2 * PROJECT: Spider Solitaire
3 * LICENSE: See COPYING in top level directory
4 * FILE: base/applications/games/spider/spigame.cpp
5 * PURPOSE: Spider Solitaire game functions
6 * PROGRAMMER: Gregor Schneider
11 #define NUM_DECK_CARDS 5
12 #define NUM_SMALLER_STACKS 4
13 #define NUM_CARD_COLORS 4
14 #define NUM_ONECOLOR_CARDS 13
15 #define NUM_STD_CARDS 52
16 #define NUM_SPIDER_CARDS 104
21 CardRegion
*pStack
[NUM_STACKS
];
22 bool fGameStarted
= false;
23 int yRowStackCardOffset
;
25 extern TCHAR MsgDeal
[];
26 extern TCHAR MsgWin
[];
28 CardStack
CreatePlayDeck()
31 int i
, colors
= 1, num
= 0;
35 case IDC_DIF_ONECOLOR
:
38 case IDC_DIF_TWOCOLORS
:
41 case IDC_DIF_FOURCOLORS
:
45 for (i
= 0; i
< NUM_SPIDER_CARDS
; i
++)
47 num
+= NUM_CARD_COLORS
/ colors
;
48 Card
newCard(num
% NUM_STD_CARDS
);
49 newStack
.Push(newCard
);
57 /* First four stack with five, all other with 4 */
59 CardStack fakeDeck
, temp
;
61 SpiderWnd
.EmptyStacks();
63 /* Create a new card-deck, fake deck */
64 deck
= CreatePlayDeck();
69 /* Reset progress value */
72 /* Deal to each stack */
73 for (i
= 0; i
< NUM_STACKS
; i
++)
76 if (i
== NUM_SMALLER_STACKS
)
80 for (j
= 0; j
<= covCards
; j
++)
82 temp
.Push(deck
.Pop(1));
84 pStack
[i
]->SetFaceDirection(CS_FACE_DOWNUP
, covCards
);
85 pStack
[i
]->SetCardStack(temp
);
87 /* Deal five fake cards to the deck */
88 pDeck
->SetCardStack(fakeDeck
.Pop(5));
94 bool stackLookingGood(const CardStack
&mystack
, int numChecks
)
97 for (i
= 0; i
< numChecks
; i
++)
99 if (mystack
[i
].LoVal() != mystack
[i
+ 1].LoVal() - 1)
103 if (mystack
[i
].Suit() != mystack
[i
+ 1].Suit())
111 /* Card to be turned from a stack */
112 void TurnStackCard(CardRegion
&stackobj
)
116 stackobj
.GetFaceDirection(&numfacedown
);
117 if (stackobj
.NumCards() <= numfacedown
)
119 if (numfacedown
> 0) numfacedown
--;
120 stackobj
.SetFaceDirection(CS_FACE_DOWNUP
, numfacedown
);
125 /* Click on the deck */
126 void CARDLIBPROC
DeckClickProc(CardRegion
&stackobj
, int NumDragCards
)
128 CardStack temp
, fakeDeck
= pDeck
->GetCardStack();
131 if (fakeDeck
.NumCards() != 0 && deck
.NumCards() != 0)
133 int i
, facedown
, faceup
;
134 /* Add one card to every stack */
135 for (i
= 0; i
< NUM_STACKS
; i
++)
137 temp
= pStack
[i
]->GetCardStack();
138 temp
.Push(deck
.Pop());
140 /* Check if we accidentally finished a row */
141 pStack
[i
]->GetFaceDirection(&facedown
);
142 faceup
= temp
.NumCards() - facedown
;
143 if (faceup
>= NUM_ONECOLOR_CARDS
)
145 /* Check stack finished, remove cards if so */
146 if (stackLookingGood(temp
, NUM_ONECOLOR_CARDS
- 1))
149 for (j
= 0; j
< NUM_ONECOLOR_CARDS
; j
++)
153 cardsFinished
+= NUM_ONECOLOR_CARDS
;
154 pStack
[i
]->SetCardStack(temp
);
155 /* Turn now topmost card */
156 TurnStackCard(*pStack
[i
]);
159 pStack
[i
]->SetCardStack(temp
);
161 /* Remove one card from the fake ones */
162 pDeck
->SetCardStack(fakeDeck
.Pop(fakeDeck
.NumCards() - 1));
168 /* Cards dragged from a stack */
169 bool CARDLIBPROC
StackDragProc(CardRegion
&stackobj
, int numDragCards
)
171 int numfacedown
, numcards
;
173 stackobj
.GetFaceDirection(&numfacedown
);
174 numcards
= stackobj
.NumCards();
176 /* Only cards facing up */
177 if (numDragCards
<= numcards
- numfacedown
)
179 const CardStack
&mystack
= stackobj
.GetCardStack();
180 /* Don't allow to drag unsuited cards */
181 if (!stackLookingGood(mystack
, numDragCards
- 1))
185 /* Remember where the cards come from */
195 /* Game finished successfully */
198 SpiderWnd
.EmptyStacks();
200 MessageBox(SpiderWnd
, MsgWin
, szAppName
, MB_OK
| MB_ICONINFORMATION
);
201 if( IDYES
== MessageBox(SpiderWnd
, MsgDeal
, szAppName
, MB_YESNO
| MB_ICONQUESTION
) )
207 fGameStarted
= false;
211 /* Card added, check for win situation */
212 void CARDLIBPROC
StackAddProc(CardRegion
&stackobj
, const CardStack
&added
)
214 if (cardsFinished
== NUM_SPIDER_CARDS
)
220 /* Cards dropped to a stack */
221 bool CARDLIBPROC
StackDropProc(CardRegion
&stackobj
, CardStack
&dragcards
)
223 Card dragcard
= dragcards
[dragcards
.NumCards() - 1];
224 int faceup
, facedown
;
226 /* Only drop our cards on other stacks */
227 if (stackobj
.Id() == from
->Id())
232 /* If stack is empty, everything can be dropped */
233 if (stackobj
.NumCards() != 0)
235 const CardStack
&mystack
= stackobj
.GetCardStack();
237 /* Can only drop if card is 1 less */
238 if (mystack
[0].LoVal() != dragcard
.LoVal() + 1)
243 /* Check if stack complete */
244 stackobj
.GetFaceDirection(&facedown
);
245 faceup
= stackobj
.NumCards() - facedown
;
247 if (faceup
+ dragcards
.NumCards() >= NUM_ONECOLOR_CARDS
)
249 int i
, max
= NUM_ONECOLOR_CARDS
- dragcards
.NumCards() - 1;
251 /* Dragged cards have been checked to be in order, check stack cards */
252 if (mystack
[0].Suit() == dragcard
.Suit() &&
253 stackLookingGood(mystack
, max
))
255 CardStack s
= stackobj
.GetCardStack();
258 /* Remove from card stack */
259 for (i
= 0; i
< max
+ 1; i
++)
263 /* Remove dragged cards */
265 stackobj
.SetCardStack(s
);
266 cardsFinished
+= NUM_ONECOLOR_CARDS
;
267 /* Flip top card of the dest stack */
268 TurnStackCard(stackobj
);
272 /* Flip the top card of the source stack */
273 TurnStackCard(*from
);
278 /* Create card regions */
283 /* Compute the value for yRowStackCardOffset based on the height of the card, so the card number and suite isn't hidden on larger cards except Ace */
284 yRowStackCardOffset
= (int)(__cardheight
/ 6.4);
286 pDeck
= SpiderWnd
.CreateRegion(0, true, 0, 0, -15, 0);
287 pDeck
->SetFaceDirection(CS_FACE_DOWN
, 0);
288 pDeck
->SetEmptyImage(CS_EI_CIRC
);
289 pDeck
->SetPlacement(CS_XJUST_RIGHT
, CS_YJUST_BOTTOM
, - X_BORDER
, - Y_BORDER
);
290 pDeck
->SetDragRule(CS_DRAG_NONE
, 0);
291 pDeck
->SetDropRule(CS_DROP_NONE
, 0);
292 pDeck
->SetClickReleaseProc(DeckClickProc
);
294 /* Create the row stacks */
295 for (i
= 0; i
< NUM_STACKS
; i
++)
297 pStack
[i
] = SpiderWnd
.CreateRegion(NUM_STACKS
+i
, true, 0, Y_BORDER
, 0, yRowStackCardOffset
);
298 pStack
[i
]->SetFaceDirection(CS_FACE_DOWN
, 0);
299 pos
= i
- NUM_STACKS
/2;
300 pStack
[i
]->SetPlacement(CS_XJUST_CENTER
, 0,
301 pos
* (__cardwidth
+ X_BORDER
) + 6 * X_BORDER
, 0);
302 pStack
[i
]->SetEmptyImage(CS_EI_SUNK
);
303 pStack
[i
]->SetDragRule(CS_DRAG_CALLBACK
, StackDragProc
);
304 pStack
[i
]->SetDropRule(CS_DROP_CALLBACK
, StackDropProc
);
305 pStack
[i
]->SetAddCardProc(StackAddProc
);