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();
130 int i
, j
, facedown
, faceup
;
132 if (fakeDeck
.NumCards() != 0 && deck
.NumCards() != 0)
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))
148 for (j
= 0; j
< NUM_ONECOLOR_CARDS
; j
++)
152 cardsFinished
+= NUM_ONECOLOR_CARDS
;
153 pStack
[i
]->SetCardStack(temp
);
154 /* Turn now topmost card */
155 TurnStackCard(*pStack
[i
]);
158 pStack
[i
]->SetCardStack(temp
);
160 /* Remove one card from the fake ones */
161 pDeck
->SetCardStack(fakeDeck
.Pop(fakeDeck
.NumCards() - 1));
167 /* Cards dragged from a stack */
168 bool CARDLIBPROC
StackDragProc(CardRegion
&stackobj
, int numDragCards
)
170 int numfacedown
, numcards
;
172 stackobj
.GetFaceDirection(&numfacedown
);
173 numcards
= stackobj
.NumCards();
175 /* Only cards facing up */
176 if (numDragCards
<= numcards
- numfacedown
)
178 const CardStack
&mystack
= stackobj
.GetCardStack();
179 /* Don't allow to drag unsuited cards */
180 if (!stackLookingGood(mystack
, numDragCards
- 1))
184 /* Remember where the cards come from */
194 /* Game finished successfully */
197 SpiderWnd
.EmptyStacks();
199 MessageBox(SpiderWnd
, MsgWin
, szAppName
, MB_OK
| MB_ICONINFORMATION
);
200 if( IDYES
== MessageBox(SpiderWnd
, MsgDeal
, szAppName
, MB_YESNO
| MB_ICONQUESTION
) )
206 fGameStarted
= false;
210 /* Card added, check for win situation */
211 void CARDLIBPROC
StackAddProc(CardRegion
&stackobj
, const CardStack
&added
)
213 if (cardsFinished
== NUM_SPIDER_CARDS
)
219 /* Cards dropped to a stack */
220 bool CARDLIBPROC
StackDropProc(CardRegion
&stackobj
, CardStack
&dragcards
)
222 Card dragcard
= dragcards
[dragcards
.NumCards() - 1];
223 int faceup
, facedown
;
225 /* Only drop our cards on other stacks */
226 if (stackobj
.Id() == from
->Id())
231 /* If stack is empty, everything can be dropped */
232 if (stackobj
.NumCards() != 0)
234 const CardStack
&mystack
= stackobj
.GetCardStack();
236 /* Can only drop if card is 1 less */
237 if (mystack
[0].LoVal() != dragcard
.LoVal() + 1)
242 /* Check if stack complete */
243 stackobj
.GetFaceDirection(&facedown
);
244 faceup
= stackobj
.NumCards() - facedown
;
246 if (faceup
+ dragcards
.NumCards() >= NUM_ONECOLOR_CARDS
)
248 int i
, max
= NUM_ONECOLOR_CARDS
- dragcards
.NumCards() - 1;
250 /* Dragged cards have been checked to be in order, check stack cards */
251 if (stackLookingGood(mystack
, max
))
253 CardStack s
= stackobj
.GetCardStack();
256 /* Remove from card stack */
257 for (i
= 0; i
< max
+ 1; i
++)
261 /* Remove dragged cards */
263 stackobj
.SetCardStack(s
);
264 cardsFinished
+= NUM_ONECOLOR_CARDS
;
265 /* Flip top card of the dest stack */
266 TurnStackCard(stackobj
);
270 /* Flip the top card of the source stack */
271 TurnStackCard(*from
);
276 /* Create card regions */
281 /* Compute the value for yRowStackCardOffset based on the height of the card, so the card number isn't hidden on larger cards */
282 yRowStackCardOffset
= (int)(__cardheight
/ 6.7);
284 pDeck
= SpiderWnd
.CreateRegion(0, true, 0, 0, -15, 0);
285 pDeck
->SetFaceDirection(CS_FACE_DOWN
, 0);
286 pDeck
->SetEmptyImage(CS_EI_CIRC
);
287 pDeck
->SetPlacement(CS_XJUST_RIGHT
, CS_YJUST_BOTTOM
, - X_BORDER
, - Y_BORDER
);
288 pDeck
->SetDragRule(CS_DRAG_NONE
, 0);
289 pDeck
->SetDropRule(CS_DROP_NONE
, 0);
290 pDeck
->SetClickReleaseProc(DeckClickProc
);
292 /* Create the row stacks */
293 for (i
= 0; i
< NUM_STACKS
; i
++)
295 pStack
[i
] = SpiderWnd
.CreateRegion(NUM_STACKS
+i
, true, 0, Y_BORDER
, 0, yRowStackCardOffset
);
296 pStack
[i
]->SetFaceDirection(CS_FACE_DOWN
, 0);
297 pos
= i
- NUM_STACKS
/2;
298 pStack
[i
]->SetPlacement(CS_XJUST_CENTER
, 0,
299 pos
* (__cardwidth
+ X_BORDER
) + 6 * X_BORDER
, 0);
300 pStack
[i
]->SetEmptyImage(CS_EI_SUNK
);
301 pStack
[i
]->SetDragRule(CS_DRAG_CALLBACK
, StackDragProc
);
302 pStack
[i
]->SetDropRule(CS_DROP_CALLBACK
, StackDropProc
);
303 pStack
[i
]->SetAddCardProc(StackAddProc
);