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
18 #define NUM_DECK_CARDS 5
19 #define NUM_SMALLER_STACKS 4
20 #define NUM_CARD_COLORS 4
21 #define NUM_ONECOLOR_CARDS 13
22 #define NUM_STD_CARDS 52
23 #define NUM_SPIDER_CARDS 104
28 CardRegion
*pStack
[NUM_STACKS
];
29 bool fGameStarted
= false;
30 int yRowStackCardOffset
;
32 extern TCHAR MsgDeal
[];
33 extern TCHAR MsgWin
[];
35 CardStack
CreatePlayDeck()
38 int i
, colors
= 1, num
= 0;
42 case IDC_DIF_ONECOLOR
:
45 case IDC_DIF_TWOCOLORS
:
48 case IDC_DIF_FOURCOLORS
:
52 for (i
= 0; i
< NUM_SPIDER_CARDS
; i
++)
54 num
+= NUM_CARD_COLORS
/ colors
;
55 Card
newCard(num
% NUM_STD_CARDS
);
56 newStack
.Push(newCard
);
64 /* First four stack with five, all other with 4 */
66 CardStack fakeDeck
, temp
;
68 SpiderWnd
.EmptyStacks();
70 /* Create a new card-deck, fake deck */
71 deck
= CreatePlayDeck();
76 /* Reset progress value */
79 /* Deal to each stack */
80 for (i
= 0; i
< NUM_STACKS
; i
++)
83 if (i
== NUM_SMALLER_STACKS
)
87 for (j
= 0; j
<= covCards
; j
++)
89 temp
.Push(deck
.Pop(1));
91 pStack
[i
]->SetFaceDirection(CS_FACE_DOWNUP
, covCards
);
92 pStack
[i
]->SetCardStack(temp
);
94 /* Deal five fake cards to the deck */
95 pDeck
->SetCardStack(fakeDeck
.Pop(5));
101 bool stackLookingGood(const CardStack
&mystack
, int numChecks
)
104 for (i
= 0; i
< numChecks
; i
++)
106 if (mystack
[i
].LoVal() != mystack
[i
+ 1].LoVal() - 1)
110 if (mystack
[i
].Suit() != mystack
[i
+ 1].Suit())
118 /* Card to be turned from a stack */
119 void TurnStackCard(CardRegion
&stackobj
)
123 stackobj
.GetFaceDirection(&numfacedown
);
124 if (stackobj
.NumCards() <= numfacedown
)
126 if (numfacedown
> 0) numfacedown
--;
127 stackobj
.SetFaceDirection(CS_FACE_DOWNUP
, numfacedown
);
132 /* Click on the deck */
133 void CARDLIBPROC
DeckClickProc(CardRegion
&stackobj
, int NumDragCards
)
135 CardStack temp
, fakeDeck
= pDeck
->GetCardStack();
137 int i
, j
, facedown
, faceup
;
139 if (fakeDeck
.NumCards() != 0 && deck
.NumCards() != 0)
141 /* Add one card to every stack */
142 for (i
= 0; i
< NUM_STACKS
; i
++)
144 temp
= pStack
[i
]->GetCardStack();
145 temp
.Push(deck
.Pop());
147 /* Check if we accidentally finished a row */
148 pStack
[i
]->GetFaceDirection(&facedown
);
149 faceup
= temp
.NumCards() - facedown
;
150 if (faceup
>= NUM_ONECOLOR_CARDS
)
152 /* Check stack finished, remove cards if so */
153 if (stackLookingGood(temp
, NUM_ONECOLOR_CARDS
- 1))
155 for (j
= 0; j
< NUM_ONECOLOR_CARDS
; j
++)
159 cardsFinished
+= NUM_ONECOLOR_CARDS
;
160 pStack
[i
]->SetCardStack(temp
);
161 /* Turn now topmost card */
162 TurnStackCard(*pStack
[i
]);
165 pStack
[i
]->SetCardStack(temp
);
167 /* Remove one card from the fake ones */
168 pDeck
->SetCardStack(fakeDeck
.Pop(fakeDeck
.NumCards() - 1));
174 /* Cards dragged from a stack */
175 bool CARDLIBPROC
StackDragProc(CardRegion
&stackobj
, int numDragCards
)
177 int numfacedown
, numcards
;
179 stackobj
.GetFaceDirection(&numfacedown
);
180 numcards
= stackobj
.NumCards();
182 /* Only cards facing up */
183 if (numDragCards
<= numcards
- numfacedown
)
185 const CardStack
&mystack
= stackobj
.GetCardStack();
186 /* Don't allow to drag unsuited cards */
187 if (!stackLookingGood(mystack
, numDragCards
- 1))
191 /* Remember where the cards come from */
201 /* Game finished successfully */
204 SpiderWnd
.EmptyStacks();
206 MessageBox(SpiderWnd
, MsgWin
, szAppName
, MB_OK
| MB_ICONINFORMATION
);
207 if( IDYES
== MessageBox(SpiderWnd
, MsgDeal
, szAppName
, MB_YESNO
| MB_ICONQUESTION
) )
213 fGameStarted
= false;
217 /* Card added, check for win situation */
218 void CARDLIBPROC
StackAddProc(CardRegion
&stackobj
, const CardStack
&added
)
220 if (cardsFinished
== NUM_SPIDER_CARDS
)
226 /* Cards dropped to a stack */
227 bool CARDLIBPROC
StackDropProc(CardRegion
&stackobj
, CardStack
&dragcards
)
229 Card dragcard
= dragcards
[dragcards
.NumCards() - 1];
230 int faceup
, facedown
;
232 /* Only drop our cards on other stacks */
233 if (stackobj
.Id() == from
->Id())
238 /* If stack is empty, everything can be dropped */
239 if (stackobj
.NumCards() != 0)
241 const CardStack
&mystack
= stackobj
.GetCardStack();
243 /* Can only drop if card is 1 less */
244 if (mystack
[0].LoVal() != dragcard
.LoVal() + 1)
249 /* Check if stack complete */
250 stackobj
.GetFaceDirection(&facedown
);
251 faceup
= stackobj
.NumCards() - facedown
;
253 if (faceup
+ dragcards
.NumCards() >= NUM_ONECOLOR_CARDS
)
255 int i
, max
= NUM_ONECOLOR_CARDS
- dragcards
.NumCards() - 1;
257 /* Dragged cards have been checked to be in order, check stack cards */
258 if (stackLookingGood(mystack
, max
))
260 CardStack s
= stackobj
.GetCardStack();
263 /* Remove from card stack */
264 for (i
= 0; i
< max
+ 1; i
++)
268 /* Remove dragged cards */
270 stackobj
.SetCardStack(s
);
271 cardsFinished
+= NUM_ONECOLOR_CARDS
;
272 /* Flip top card of the dest stack */
273 TurnStackCard(stackobj
);
277 /* Flip the top card of the source stack */
278 TurnStackCard(*from
);
283 /* Create card regions */
288 /* Compute the value for yRowStackCardOffset based on the height of the card, so the card number isn't hidden on larger cards */
289 yRowStackCardOffset
= (int)(__cardheight
/ 6.7);
291 pDeck
= SpiderWnd
.CreateRegion(0, true, 0, 0, -15, 0);
292 pDeck
->SetFaceDirection(CS_FACE_DOWN
, 0);
293 pDeck
->SetEmptyImage(CS_EI_CIRC
);
294 pDeck
->SetPlacement(CS_XJUST_RIGHT
, CS_YJUST_BOTTOM
, - X_BORDER
, - Y_BORDER
);
295 pDeck
->SetDragRule(CS_DRAG_NONE
, 0);
296 pDeck
->SetDropRule(CS_DROP_NONE
, 0);
297 pDeck
->SetClickProc(DeckClickProc
);
298 pDeck
->SetDblClickProc(DeckClickProc
);
300 /* Create the row stacks */
301 for (i
= 0; i
< NUM_STACKS
; i
++)
303 pStack
[i
] = SpiderWnd
.CreateRegion(NUM_STACKS
+i
, true, 0, Y_BORDER
, 0, yRowStackCardOffset
);
304 pStack
[i
]->SetFaceDirection(CS_FACE_DOWN
, 0);
305 pos
= i
- NUM_STACKS
/2;
306 pStack
[i
]->SetPlacement(CS_XJUST_CENTER
, 0,
307 pos
* (__cardwidth
+ X_BORDER
) + 6 * X_BORDER
, 0);
308 pStack
[i
]->SetEmptyImage(CS_EI_SUNK
);
309 pStack
[i
]->SetDragRule(CS_DRAG_CALLBACK
, StackDragProc
);
310 pStack
[i
]->SetDropRule(CS_DROP_CALLBACK
, StackDropProc
);
311 pStack
[i
]->SetAddCardProc(StackAddProc
);