ReactOS  0.4.12-dev-18-gf469aca
solgame.cpp
Go to the documentation of this file.
1 #include "solitaire.h"
2 
3 #if 1
4 #define TRACE(s)
5 #else
6 #define TRACE(s) printf("%s(%i): %s",__FILE__,__LINE__,s)
7 #endif
8 
9 extern TCHAR MsgWin[128];
10 extern TCHAR MsgDeal[128];
11 
13 int LastId;
14 bool fGameStarted = false;
15 bool bAutoroute = false;
16 
17 void NewGame(void)
18 {
19  TRACE("ENTER NewGame()\n");
20  int i, j;
21 
22  if (GetScoreMode() == SCORE_VEGAS)
23  {
25  lScore = lScore - 52;
26  else
27  lScore = -52;
28 
30  dwWasteTreshold = 2;
31  else
32  dwWasteTreshold = 0;
33 
34  }
35  else
36  {
38  dwWasteTreshold = 3;
39  else
40  dwWasteTreshold = 0;
41 
42  lScore = 0;
43  }
44 
45  dwTime = 0;
46  dwWasteCount = 0;
47  LastId = 0;
48 
50 
51  //create a new card-stack
53  deck.NewDeck();
54  deck.Shuffle();
55  activepile.Clear();
56 
57  //deal to each row stack..
58  for(i = 0; i < NUM_ROW_STACKS; i++)
59  {
61  temp.Clear();
62 
64 
65  for(j = 0; j <= i; j++)
66  {
67  temp.Push(deck.Pop());
68  }
69 
70  pRowStack[i]->SetCardStack(temp);
71  }
72 
73  //put the other cards onto the deck
74  pDeck->SetCardStack(deck);
75  pDeck->Update();
76 
77  // For the 1-card-mode, all cards need to be completely overlapped
79  pPile->SetOffsets(0, 0);
80 
81  SolWnd.Redraw();
82 
83  fGameStarted = false;
84 
86 
88 
89  TRACE("EXIT NewGame()\n");
90 
91 }
92 
93 //
94 // Now follow the stack callback functions. This is where we
95 // provide the game functionality and rules
96 //
97 
98 //
99 // Can only drag face-up cards
100 //
101 bool CARDLIBPROC RowStackDragProc(CardRegion &stackobj, int iNumDragCards)
102 {
103  TRACE("ENTER RowStackDragProc()\n");
104  int numfacedown;
105  int numcards;
106 
107  SetPlayTimer();
108 
109  stackobj.GetFaceDirection(&numfacedown);
110 
111  numcards = stackobj.NumCards();
112 
113  TRACE("EXIT RowStackDragProc()\n");
114  if(iNumDragCards <= numcards-numfacedown)
115  return true;
116  else
117  return false;
118 
119 }
120 
121 //
122 // Row a row-stack, we can only drop cards
123 // that are lower / different colour
124 //
126 {
127  TRACE("ENTER RowStackDropProc()\n");
128  Card dragcard = dragcards[dragcards.NumCards() - 1];
129 
130  SetPlayTimer();
131 
132  //if we are empty, can only drop a stack with a King at bottom
133  if(stackobj.NumCards() == 0)
134  {
135  if(dragcard.LoVal() != 13)
136  {
137  TRACE("EXIT RowStackDropProc(false)\n");
138  return false;
139  }
140  }
141  else
142  {
143  const CardStack &mystack = stackobj.GetCardStack();
144 
145  //can only drop if card is 1 less
146  if(mystack[0].LoVal() != dragcard.LoVal() + 1)
147  {
148  TRACE("EXIT RowStackDropProc(false)\n");
149  return false;
150  }
151 
152  //can only drop if card is different colour
153  if( (mystack[0].IsBlack() && !dragcard.IsRed()) ||
154  (!mystack[0].IsBlack() && dragcard.IsRed()) )
155  {
156  TRACE("EXIT RowStackDropProc(false)\n");
157  return false;
158  }
159  }
160 
161  fGameStarted = true;
162 
163  if (LastId == PILE_ID)
164  {
165  if (GetScoreMode() == SCORE_STD)
166  {
167  lScore = lScore + 5;
168  }
169  }
170  else if ((LastId >= SUIT_ID) && (LastId <= SUIT_ID + 3))
171  {
172  if (GetScoreMode() == SCORE_STD)
173  {
174  lScore = lScore >= 15 ? lScore - 15 : 0;
175  }
176  else if (GetScoreMode() == SCORE_VEGAS)
177  {
178  lScore = lScore >= -47 ? lScore - 5 : -52;
179  }
180  }
181 
182  UpdateStatusBar();
183 
184  TRACE("EXIT RowStackDropProc(true)\n");
185  return true;
186 }
187 
188 //
189 // Can only drop a card onto a suit-stack if the
190 // card is 1 higher, and is the same suit
191 //
192 bool CanDrop(CardRegion &stackobj, Card card)
193 {
194  TRACE("ENTER CanDrop()\n");
195  int topval;
196 
197  const CardStack &cardstack = stackobj.GetCardStack();
198 
199  SetPlayTimer();
200 
201  if(cardstack.NumCards() > 0)
202  {
203  if(card.Suit() != cardstack[0].Suit())
204  {
205  TRACE("EXIT CanDrop()\n");
206  return false;
207  }
208 
209  topval = cardstack[0].LoVal();
210  }
211  else
212  {
213  topval = 0;
214  }
215 
216  //make sure 1 higher
217  if(card.LoVal() != (topval + 1))
218  {
219  TRACE("EXIT CanDrop()\n");
220  return false;
221  }
222 
223  TRACE("EXIT CanDrop()\n");
224  return true;
225 }
226 
227 //
228 // Can only drop a card onto suit stack if it is same suit, and 1 higher
229 //
231 {
232  TRACE("ENTER SuitStackDropProc()\n");
233 
234  SetPlayTimer();
235 
236  //only drop 1 card at a time
237  if (!bAutoroute && dragcards.NumCards() != 1)
238  {
239  TRACE("EXIT SuitStackDropProc()\n");
240  return false;
241  }
242 
243  bool b = CanDrop(stackobj, dragcards[0]);
244  TRACE("EXIT SuitStackDropProc()\n");
245 
246  if (b)
247  {
248  if ((LastId == PILE_ID) || (LastId >= ROW_ID))
249  {
250  if (GetScoreMode() == SCORE_VEGAS)
251  {
252  lScore = lScore + 5;
253  }
254  else if (GetScoreMode() == SCORE_STD)
255  {
256  lScore = lScore + 10;
257  }
258 
259  UpdateStatusBar();
260  }
261  }
262 
263  return b;
264 }
265 
266 //
267 // Single-click on one of the suit-stacks
268 //
269 void CARDLIBPROC SuitStackClickProc(CardRegion &stackobj, int iNumClicked)
270 {
271  TRACE("ENTER SuitStackClickProc()\n");
272 
273  fGameStarted = true;
274 
275  LastId = stackobj.Id();
276 
277  TRACE("EXIT SuitStackClickProc()\n");
278 }
279 
280 //
281 // Single-click on one of the row-stacks
282 // Turn the top-card over if they are all face-down
283 //
284 void CARDLIBPROC RowStackClickProc(CardRegion &stackobj, int iNumClicked)
285 {
286  TRACE("ENTER RowStackClickProc()\n");
287  int numfacedown;
288 
289  stackobj.GetFaceDirection(&numfacedown);
290 
291  //if all face-down, then make top card face-up
292  if(stackobj.NumCards() == numfacedown)
293  {
294  if(numfacedown > 0) numfacedown--;
295  stackobj.SetFaceDirection(CS_FACE_DOWNUP, numfacedown);
296  stackobj.Redraw();
297 
298  if (GetScoreMode() == SCORE_STD)
299  {
300  lScore = lScore + 5;
301  UpdateStatusBar();
302  }
303  }
304 
305  LastId = stackobj.Id();
306 
307  fGameStarted = true;
308 
309  TRACE("EXIT RowStackClickProc()\n");
310 }
311 
312 //
313 // Find the suit-stack that can accept the specified card
314 //
316 {
317  TRACE("ENTER FindSuitStackFromCard()\n");
318 
319  for(int i = 0; i < 4; i++)
320  {
321  if(CanDrop(*pSuitStack[i], card))
322  {
323  TRACE("EXIT FindSuitStackFromCard()\n");
324  return pSuitStack[i];
325  }
326  }
327 
328  TRACE("EXIT FindSuitStackFromCard()\n");
329  return 0;
330 }
331 
332 //
333 // What happens when we add a card to one of the suit stacks?
334 // Well, nothing (it is already added), but we need to
335 // check all four stacks (not just this one) to see if
336 // the game has finished.
337 //
338 void CARDLIBPROC SuitStackAddProc(CardRegion &stackobj, const CardStack &added)
339 {
340  TRACE("ENTER SuitStackAddProc()\n");
341  bool fGameOver = true;
342 
343  SetPlayTimer();
344 
345  for(int i = 0; i < 4; i++)
346  {
347  if(pSuitStack[i]->NumCards() != 13)
348  {
349  fGameOver = false;
350 
351  break;
352  }
353  }
354 
355  if(fGameOver)
356  {
358  PlayTimer = 0;
359 
361  {
362  lScore = lScore + (700000 / dwTime);
363  }
364 
365  UpdateStatusBar();
366 
368 
369  for(int i = 0; i < 4; i++)
370  {
371  pSuitStack[i]->Flash(11, 100);
372  }
373 
375  {
376  NewGame();
377  }
378  else
379  {
381 
382  fGameStarted = false;
383  }
384  }
385 
386  TRACE("EXIT SuitStackAddProc()\n");
387 }
388 
389 //
390 // Double-click on one of the row stacks
391 // The aim is to find a suit-stack to move the
392 // double-clicked card to.
393 //
394 void CARDLIBPROC RowStackDblClickProc(CardRegion &stackobj, int iNumClicked)
395 {
396  TRACE("ENTER RowStackDblClickProc()\n");
397 
398  SetPlayTimer();
399 
400  //can only move 1 card at a time
401  if(iNumClicked != 1)
402  {
403  TRACE("EXIT RowStackDblClickProc()\n");
404  return;
405  }
406 
407  //find a suit-stack to move the card to...
408  const CardStack &cardstack = stackobj.GetCardStack();
409  CardRegion *pDest = FindSuitStackFromCard(cardstack[0]);
410 
411  if(pDest != 0)
412  {
413  fGameStarted = true;
414  SetPlayTimer();
415 
416  //stackobj.MoveCards(pDest, 1, true);
417  //use the SimulateDrag function, because we get the
418  //AddProc callbacks called for us on the destination stacks...
419  bAutoroute = true;
420  stackobj.SimulateDrag(pDest, 1, true);
421  bAutoroute = false;
422  }
423  TRACE("EXIT RowStackDblClickProc()\n");
424 }
425 
426 //
427 // Face-up pile single-click
428 //
429 void CARDLIBPROC PileClickProc(CardRegion &stackobj, int iNumClicked)
430 {
431  TRACE("ENTER SuitStackClickProc()\n");
432 
433  fGameStarted = true;
434 
435  LastId = stackobj.Id();
436 
437  TRACE("EXIT SuitStackClickProc()\n");
438 }
439 
440 //
441 // Face-up pile double-click
442 //
443 void CARDLIBPROC PileDblClickProc(CardRegion &stackobj, int iNumClicked)
444 {
445  TRACE("ENTER PileDblClickProc()\n");
446 
447  SetPlayTimer();
448 
449  RowStackDblClickProc(stackobj, iNumClicked);
450  TRACE("EXIT PileDblClickProc()\n");
451 }
452 
453 //
454 // What happens when a card is removed from face-up pile?
455 //
456 void CARDLIBPROC PileRemoveProc(CardRegion &stackobj, int iItems)
457 {
458  TRACE("ENTER PileRemoveProc()\n");
459 
460  SetPlayTimer();
461 
462  //modify our "virtual" pile by removing the same card
463  //that was removed from the physical card stack
464  activepile.Pop(iItems);
465 
466  //if there is just 1 card left, then modify the
467  //stack to contain ALL the face-up cards..the effect
468  //will be, the next time a card is dragged, all the
469  //previous card-triplets will be available underneath
470  if(stackobj.NumCards() == 1)
471  {
472  stackobj.SetOffsets(0,0);
473  stackobj.SetCardStack(activepile);
474  }
475  TRACE("EXIT PileRemoveProc()\n");
476 }
477 
478 //
479 // Double-click on the deck
480 // Move 3 cards to the face-up pile
481 //
482 void CARDLIBPROC DeckClickProc(CardRegion &stackobj, int iNumClicked)
483 {
484  TRACE("ENTER DeckClickProc()\n");
485 
486  SetPlayTimer();
487 
488  CardStack cardstack = stackobj.GetCardStack();
489  CardStack pile = pPile->GetCardStack();
490 
491  fGameStarted = true;
492  SetPlayTimer();
493 
494  //reset the face-up pile to represent 3 cards
497 
498  if(cardstack.NumCards() == 0)
499  {
500  if (GetScoreMode() == SCORE_VEGAS)
501  {
503  {
504  pile.Clear();
505 
506  activepile.Reverse();
507  cardstack.Push(activepile);
508  activepile.Clear();
509  }
510  }
511  else if (GetScoreMode() == SCORE_STD)
512  {
513  if ((dwWasteCount >= dwWasteTreshold) && (activepile.NumCards() != 0))
514  {
515  if (dwOptions & OPTION_THREE_CARDS)
516  lScore = lScore >= 20 ? lScore - 20 : 0;
517  else
518  lScore = lScore >= 100 ? lScore - 100 : 0;
519  }
520 
521  pile.Clear();
522 
523  activepile.Reverse();
524  cardstack.Push(activepile);
525  activepile.Clear();
526 
527  UpdateStatusBar();
528  }
529  else
530  {
531  pile.Clear();
532 
533  activepile.Reverse();
534  cardstack.Push(activepile);
535  activepile.Clear();
536  }
537 
538  dwWasteCount++;
539  }
540  else
541  {
542  int numcards = min((dwOptions & OPTION_THREE_CARDS) ? 3 : 1, cardstack.NumCards());
543 
544  //make a "visible" copy of these cards
545  CardStack temp;
546  temp = cardstack.Pop(numcards);
547  temp.Reverse();
548 
549  if(dwOptions & OPTION_THREE_CARDS)
550  pile.Clear();
551 
552  pile.Push(temp);
553 
554  //remove the top 3 from deck
555  activepile.Push(temp);
556  }
557 
558  activepile.Print();
559 
560  pDeck->SetCardStack(cardstack);
561  pPile->SetCardStack(pile);
562 
563  SolWnd.Redraw();
564  TRACE("EXIT DeckClickProc()\n");
565 }
void Print()
Definition: cardstack.cpp:222
DWORD dwOptions
Definition: solitaire.cpp:23
int Suit() const
Definition: card.h:54
bool CARDLIBPROC SuitStackDropProc(CardRegion &stackobj, CardStack &dragcards)
Definition: solgame.cpp:230
#define OPTION_KEEP_SCORE
Definition: solitaire.h:13
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble const GLfloat const GLdouble const GLfloat GLenum GLint GLint GLint GLint GLint GLint j
Definition: glfuncs.h:98
void CARDLIBPROC PileRemoveProc(CardRegion &stackobj, int iItems)
Definition: solgame.cpp:456
void SetFaceDirection(UINT uDirType, int nOption)
Definition: cardregion.cpp:258
void CARDLIBPROC SuitStackAddProc(CardRegion &stackobj, const CardStack &added)
Definition: solgame.cpp:338
#define IDYES
Definition: winuser.h:829
HWND hwndMain
Definition: solitaire.cpp:12
long lScore
Definition: solitaire.cpp:29
const CardStack & GetCardStack()
Definition: cardregion.cpp:399
#define SUIT_ID
Definition: solitaire.h:41
CardRegion * FindSuitStackFromCard(Card card)
Definition: solgame.cpp:315
bool CARDLIBPROC RowStackDropProc(CardRegion &stackobj, CardStack &dragcards)
Definition: solgame.cpp:125
void EmptyStacks(void)
Definition: cardwindow.cpp:607
void Clear()
Definition: cardstack.cpp:37
void Push(const Card card)
Definition: cardstack.cpp:83
CardRegion * pDeck
Definition: solcreate.cpp:3
bool SimulateDrag(CardRegion *pDestStack, int nNumCards, bool fAnimate)
Definition: cardregion.cpp:636
CardRegion * pSuitStack[4]
Definition: solcreate.cpp:5
UINT_PTR PlayTimer
Definition: solitaire.cpp:30
void CARDLIBPROC SuitStackClickProc(CardRegion &stackobj, int iNumClicked)
Definition: solgame.cpp:269
void Redraw()
void CARDLIBPROC RowStackClickProc(CardRegion &stackobj, int iNumClicked)
Definition: solgame.cpp:284
void Flash(int count, int timeout)
Definition: cardregion.cpp:322
#define ROW_ID
Definition: solitaire.h:42
void NewGame(void)
Definition: solgame.cpp:17
void Redraw(void)
Definition: cardwindow.cpp:553
int GetScoreMode(void)
Definition: solitaire.cpp:128
TCHAR MsgWin[128]
Definition: solitaire.cpp:21
void NewDeck()
Definition: cardstack.cpp:42
GLenum GLclampf GLint i
Definition: glfuncs.h:14
#define IDT_PLAYTIMER
Definition: solitaire.h:33
#define MB_YESNO
Definition: winuser.h:811
void Update()
Definition: cardregion.cpp:207
void Reverse()
Definition: cardstack.cpp:73
#define MB_ICONQUESTION
Definition: winuser.h:783
#define b
Definition: ke_i.h:79
#define PILE_ID
Definition: solitaire.h:40
DWORD dwTime
Definition: solitaire.cpp:25
char TCHAR
Definition: xmlstorage.h:189
bool bAutoroute
Definition: solgame.cpp:15
#define NUM_ROW_STACKS
Definition: solitaire.h:38
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define TRACE(s)
Definition: solgame.cpp:4
void CARDLIBPROC DeckClickProc(CardRegion &stackobj, int iNumClicked)
Definition: solgame.cpp:482
void Shuffle()
Definition: cardstack.cpp:50
void CARDLIBPROC RowStackDblClickProc(CardRegion &stackobj, int iNumClicked)
Definition: solgame.cpp:394
void SetPlayTimer(void)
Definition: solitaire.cpp:170
DWORD dwPrevMode
Definition: solitaire.cpp:28
#define CS_DEFXOFF
Definition: cardlib.h:23
void CARDLIBPROC PileClickProc(CardRegion &stackobj, int iNumClicked)
Definition: solgame.cpp:429
int NumCards() const
Definition: cardregion.cpp:544
Card Pop()
Definition: cardstack.cpp:127
#define OPTION_THREE_CARDS
Definition: solitaire.h:11
bool IsRed() const
Definition: card.h:94
#define MB_ICONINFORMATION
Definition: winuser.h:796
BOOL WINAPI KillTimer(_In_opt_ HWND, _In_ UINT_PTR)
CardStack activepile
Definition: solgame.cpp:12
#define MessageBox
Definition: winuser.h:5688
static stack_node_t temp
Definition: rpn.c:18
int LastId
Definition: solgame.cpp:13
void SetCardStack(const CardStack &cs)
Definition: cardregion.cpp:390
void SetOffsets(int x, int y)
Definition: cardregion.cpp:228
TCHAR szAppName[128]
Definition: solitaire.cpp:16
Definition: card.h:27
bool fGameStarted
Definition: solgame.cpp:14
#define CS_FACE_DOWNUP
Definition: cardlib.h:53
int LoVal() const
Definition: card.h:59
#define min(a, b)
Definition: monoChain.cc:55
CardStack deck
Definition: spigame.cpp:18
#define MB_OK
Definition: winuser.h:784
bool CanDrop(CardRegion &stackobj, Card card)
Definition: solgame.cpp:192
void CARDLIBPROC PileDblClickProc(CardRegion &stackobj, int iNumClicked)
Definition: solgame.cpp:443
VOID UpdateStatusBar(WCHAR wch)
Definition: charmap.c:262
DWORD dwWasteCount
Definition: solitaire.cpp:26
TCHAR MsgDeal[128]
Definition: solitaire.cpp:22
#define CARDLIBPROC
Definition: cardlib.h:13
#define SCORE_STD
Definition: solitaire.h:45
#define OPTION_SHOW_TIME
Definition: solitaire.h:12
UINT GetFaceDirection(int *pnOption)
Definition: cardregion.cpp:273
#define SCORE_VEGAS
Definition: solitaire.h:46
CardRegion * pRowStack[NUM_ROW_STACKS]
Definition: solcreate.cpp:6
int NumCards() const
Definition: cardstack.h:14
DWORD dwWasteTreshold
Definition: solitaire.cpp:27
bool CARDLIBPROC RowStackDragProc(CardRegion &stackobj, int iNumDragCards)
Definition: solgame.cpp:101
CardWindow SolWnd
Definition: solitaire.cpp:32
CardRegion * pPile
Definition: solcreate.cpp:4