Merge 12736:14980 from trunk
[reactos.git] / rosapps / games / solitaire / solgame.cpp
1 #include <windows.h>
2 #include <commctrl.h>
3 #include <tchar.h>
4 #include <stdio.h>
5 #include "resource.h"
6 #include "cardlib/cardlib.h"
7 //#include "../catch22lib/trace.h"
8 #include "solitaire.h"
9
10 #if 1
11 #define TRACE(s)
12 #else
13 #define TRACE(s) printf("%s(%i): %s",__FILE__,__LINE__,s)
14 #endif
15
16 CardStack activepile;
17 bool fGameStarted = false;
18
19 void NewGame(void)
20 {
21 TRACE("ENTER NewGame()\n");
22 int i, j;
23
24 SolWnd.EmptyStacks();
25
26 //create a new card-stack
27 CardStack deck;
28 deck.NewDeck();
29 deck.Shuffle();
30 activepile.Clear();
31
32 //deal to each row stack..
33 for(i = 0; i < NUM_ROW_STACKS; i++)
34 {
35 CardStack temp;
36 temp.Clear();
37
38 pRowStack[i]->SetFaceDirection(CS_FACE_DOWNUP, i);
39
40 for(j = 0; j <= i; j++)
41 {
42 temp.Push(deck.Pop());
43 }
44
45 pRowStack[i]->SetCardStack(temp);
46 }
47
48 //put the other cards onto the deck
49 pDeck->SetCardStack(deck);
50 pDeck->Update();
51
52 SolWnd.Redraw();
53
54 fGameStarted = false;
55 TRACE("EXIT NewGame()\n");
56 }
57
58 //
59 // Now follow the stack callback functions. This is where we
60 // provide the game functionality and rules
61 //
62
63 //
64 // Can only drag face-up cards
65 //
66 bool CARDLIBPROC RowStackDragProc(CardRegion &stackobj, int iNumDragCards)
67 {
68 TRACE("ENTER RowStackDragProc()\n");
69 int numfacedown;
70 int numcards;
71
72 stackobj.GetFaceDirection(&numfacedown);
73
74 numcards = stackobj.NumCards();
75
76 TRACE("EXIT RowStackDragProc()\n");
77 if(iNumDragCards <= numcards-numfacedown)
78 return true;
79 else
80 return false;
81
82 }
83
84 //
85 // Row a row-stack, we can only drop cards
86 // that are lower / different colour
87 //
88 bool CARDLIBPROC RowStackDropProc(CardRegion &stackobj, const CardStack &dragcards)
89 {
90 TRACE("ENTER RowStackDropProc()\n");
91 Card dragcard = dragcards[dragcards.NumCards() - 1];
92
93 //if we are empty, can only drop a stack with a King at bottom
94 if(stackobj.NumCards() == 0)
95 {
96 if(dragcard.LoVal() != 13)
97 {
98 TRACE("EXIT RowStackDropProc(false)\n");
99 return false;
100 }
101 }
102 else
103 {
104 const CardStack &mystack = stackobj.GetCardStack();
105
106 //can only drop if card is 1 less
107 if(mystack[0].LoVal() != dragcard.LoVal() + 1)
108 {
109 TRACE("EXIT RowStackDropProc(false)\n");
110 return false;
111 }
112
113 //can only drop if card is different colour
114 if( mystack[0].IsBlack() && !dragcard.IsRed() ||
115 !mystack[0].IsBlack() && dragcard.IsRed() )
116 {
117 TRACE("EXIT RowStackDropProc(false)\n");
118 return false;
119 }
120 }
121
122 TRACE("EXIT RowStackDropProc(true)\n");
123 return true;
124 }
125
126 //
127 // Can only drop a card onto a suit-stack if the
128 // card is 1 higher, and is the same suit
129 //
130 bool CanDrop(CardRegion &stackobj, Card card)
131 {
132 TRACE("ENTER CanDrop()\n");
133 int topval;
134
135 const CardStack &cardstack = stackobj.GetCardStack();
136
137 if(cardstack.NumCards() > 0)
138 {
139 if(card.Suit() != cardstack[0].Suit())
140 {
141 TRACE("EXIT CanDrop()\n");
142 return false;
143 }
144
145 topval = cardstack[0].LoVal();
146 }
147 else
148 {
149 topval = 0;
150 }
151
152 //make sure 1 higher
153 if(card.LoVal() != (topval + 1))
154 {
155 TRACE("EXIT CanDrop()\n");
156 return false;
157 }
158
159 TRACE("EXIT CanDrop()\n");
160 return true;
161 }
162
163 //
164 // Can only drop a card onto suit stack if it is same suit, and 1 higher
165 //
166 bool CARDLIBPROC SuitStackDropProc(CardRegion &stackobj, const CardStack &dragcards)
167 {
168 TRACE("ENTER SuitStackDropProc()\n");
169 //only drop 1 card at a time
170 if(dragcards.NumCards() != 1)
171 {
172 TRACE("EXIT SuitStackDropProc()\n");
173 return false;
174 }
175
176 bool b = CanDrop(stackobj, dragcards[0]);
177 TRACE("EXIT SuitStackDropProc()\n");
178 return b;
179 }
180
181 //
182 // Single-click on one of the row-stacks
183 // Turn the top-card over if they are all face-down
184 //
185 void CARDLIBPROC RowStackClickProc(CardRegion &stackobj, int iNumClicked)
186 {
187 TRACE("ENTER RowStackClickProc()\n");
188 int numfacedown;
189
190 stackobj.GetFaceDirection(&numfacedown);
191
192 //if all face-down, then make top card face-up
193 if(stackobj.NumCards() == numfacedown)
194 {
195 if(numfacedown > 0) numfacedown--;
196 stackobj.SetFaceDirection(CS_FACE_DOWNUP, numfacedown);
197 stackobj.Redraw();
198 }
199 TRACE("EXIT RowStackClickProc()\n");
200 }
201
202 //
203 // Find the suit-stack that can accept the specified card
204 //
205 CardRegion *FindSuitStackFromCard(Card card)
206 {
207 TRACE("ENTER FindSuitStackFromCard()\n");
208 for(int i = 0; i < 4; i++)
209 {
210 if(CanDrop(*pSuitStack[i], card))
211 {
212 TRACE("EXIT FindSuitStackFromCard()\n");
213 return pSuitStack[i];
214 }
215 }
216
217 TRACE("EXIT FindSuitStackFromCard()\n");
218 return 0;
219 }
220
221 //
222 // What happens when we add a card to one of the suit stacks?
223 // Well, nothing (it is already added), but we need to
224 // check all four stacks (not just this one) to see if
225 // the game has finished.
226 //
227 void CARDLIBPROC SuitStackAddProc(CardRegion &stackobj, const CardStack &added)
228 {
229 TRACE("ENTER SuitStackAddProc()\n");
230 bool fGameOver = true;
231
232 for(int i = 0; i < 4; i++)
233 {
234 if(pSuitStack[i]->NumCards() != 13)
235 {
236 fGameOver = false;
237 break;
238 }
239 }
240
241 if(fGameOver)
242 {
243 MessageBox(SolWnd, _T("Congratulations, you win!!"), szAppName, MB_OK | MB_ICONINFORMATION);
244
245 for(int i = 0; i < 4; i++)
246 {
247 pSuitStack[i]->Flash(11, 100);
248 }
249 }
250 TRACE("EXIT SuitStackAddProc()\n");
251 }
252
253 //
254 // Double-click on one of the row stacks
255 // The aim is to find a suit-stack to move the
256 // double-clicked card to.
257 //
258 void CARDLIBPROC RowStackDblClickProc(CardRegion &stackobj, int iNumClicked)
259 {
260 TRACE("ENTER RowStackDblClickProc()\n");
261 //can only move 1 card at a time
262 if(iNumClicked != 1)
263 {
264 TRACE("EXIT RowStackDblClickProc()\n");
265 return;
266 }
267
268 //find a suit-stack to move the card to...
269 const CardStack &cardstack = stackobj.GetCardStack();
270 CardRegion *pDest = FindSuitStackFromCard(cardstack[0]);
271
272 if(pDest != 0)
273 {
274 //stackobj.MoveCards(pDest, 1, true);
275 //use the SimulateDrag funcion, because we get the
276 //AddProc callbacks called for us on the destination stacks...
277 stackobj.SimulateDrag(pDest, 1, true);
278 }
279 TRACE("EXIT RowStackDblClickProc()\n");
280 }
281
282 //
283 // Face-up pile double-click
284 //
285 void CARDLIBPROC PileDblClickProc(CardRegion &stackobj, int iNumClicked)
286 {
287 TRACE("ENTER PileDblClickProc()\n");
288 RowStackDblClickProc(stackobj, iNumClicked);
289 TRACE("EXIT PileDblClickProc()\n");
290 }
291
292 //
293 // What happens when a card is removed from face-up pile?
294 //
295 void CARDLIBPROC PileRemoveProc(CardRegion &stackobj, int iItems)
296 {
297 TRACE("ENTER PileRemoveProc()\n");
298 //modify our "virtual" pile by removing the same card
299 //that was removed from the physical card stack
300 activepile.Pop(iItems);
301
302 //if there is just 1 card left, then modify the
303 //stack to contain ALL the face-up cards..the effect
304 //will be, the next time a card is dragged, all the
305 //previous card-triplets will be available underneath
306 if(stackobj.NumCards() == 1)
307 {
308 stackobj.SetOffsets(0,0);
309 stackobj.SetCardStack(activepile);
310 }
311 TRACE("EXIT PileRemoveProc()\n");
312 }
313
314 //
315 // Double-click on the deck
316 // Move 3 cards to the face-up pile
317 //
318 void CARDLIBPROC DeckClickProc(CardRegion &stackobj, int iNumClicked)
319 {
320 TRACE("ENTER DeckClickProc()\n");
321 CardStack cardstack = stackobj.GetCardStack();
322 CardStack pile = pPile->GetCardStack();
323
324 fGameStarted = true;
325
326 //reset the face-up pile to represent 3 cards
327 pPile->SetOffsets(CS_DEFXOFF, 1);
328
329 if(cardstack.NumCards() == 0)
330 {
331 pile.Clear();
332
333 activepile.Reverse();
334 cardstack.Push(activepile);
335 activepile.Clear();
336 }
337 else
338 {
339 int numcards = min(3, cardstack.NumCards());
340
341 //make a "visible" copy of these cards
342 CardStack temp;
343 temp = cardstack.Pop(numcards);
344 temp.Reverse();
345
346 pile.Clear();
347 pile.Push(temp);
348
349 //remove the top 3 from deck
350 activepile.Push(temp);
351 }
352
353 activepile.Print();
354
355 pDeck->SetCardStack(cardstack);
356 pPile->SetCardStack(pile);
357
358 SolWnd.Redraw();
359 TRACE("EXIT DeckClickProc()\n");
360 }