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 MessageBox(SpiderWnd
, MsgWin
, szAppName
, MB_OK
| MB_ICONINFORMATION
);
205 if( IDYES
== MessageBox(SpiderWnd
, MsgDeal
, szAppName
, MB_YESNO
| MB_ICONQUESTION
) )
211 SpiderWnd
.EmptyStacks();
212 fGameStarted
= false;
216 /* Card added, check for win situation */
217 void CARDLIBPROC
StackAddProc(CardRegion
&stackobj
, const CardStack
&added
)
219 if (cardsFinished
== NUM_SPIDER_CARDS
)
225 /* Cards dropped to a stack */
226 bool CARDLIBPROC
StackDropProc(CardRegion
&stackobj
, CardStack
&dragcards
)
228 Card dragcard
= dragcards
[dragcards
.NumCards() - 1];
229 int faceup
, facedown
;
231 /* Only drop our cards on other stacks */
232 if (stackobj
.Id() == from
->Id())
237 /* If stack is empty, everything can be dropped */
238 if (stackobj
.NumCards() != 0)
240 const CardStack
&mystack
= stackobj
.GetCardStack();
242 /* Can only drop if card is 1 less */
243 if (mystack
[0].LoVal() != dragcard
.LoVal() + 1)
248 /* Check if stack complete */
249 stackobj
.GetFaceDirection(&facedown
);
250 faceup
= stackobj
.NumCards() - facedown
;
252 if (faceup
+ dragcards
.NumCards() >= NUM_ONECOLOR_CARDS
)
254 int i
, max
= NUM_ONECOLOR_CARDS
- dragcards
.NumCards() - 1;
256 /* Dragged cards have been checked to be in order, check stack cards */
257 if (stackLookingGood(mystack
, max
))
259 CardStack s
= stackobj
.GetCardStack();
262 /* Remove from card stack */
263 for (i
= 0; i
< max
+ 1; i
++)
267 /* Remove dragged cards */
269 stackobj
.SetCardStack(s
);
270 cardsFinished
+= NUM_ONECOLOR_CARDS
;
271 /* Flip top card of the dest stack */
272 TurnStackCard(stackobj
);
276 /* Flip the top card of the source stack */
277 TurnStackCard(*from
);
282 /* Create card regions */
287 /* Compute the value for yRowStackCardOffset based on the height of the card, so the card number isn't hidden on larger cards */
288 yRowStackCardOffset
= (int)(__cardheight
/ 6.7);
290 pDeck
= SpiderWnd
.CreateRegion(0, true, 0, 0, -15, 0);
291 pDeck
->SetFaceDirection(CS_FACE_DOWN
, 0);
292 pDeck
->SetEmptyImage(CS_EI_CIRC
);
293 pDeck
->SetPlacement(CS_XJUST_RIGHT
, CS_YJUST_BOTTOM
, - X_BORDER
, - Y_BORDER
);
294 pDeck
->SetDragRule(CS_DRAG_NONE
, 0);
295 pDeck
->SetDropRule(CS_DROP_NONE
, 0);
296 pDeck
->SetClickProc(DeckClickProc
);
297 pDeck
->SetDblClickProc(DeckClickProc
);
299 /* Create the row stacks */
300 for (i
= 0; i
< NUM_STACKS
; i
++)
302 pStack
[i
] = SpiderWnd
.CreateRegion(NUM_STACKS
+i
, true, 0, Y_BORDER
, 0, yRowStackCardOffset
);
303 pStack
[i
]->SetFaceDirection(CS_FACE_DOWN
, 0);
304 pos
= i
- NUM_STACKS
/2;
305 pStack
[i
]->SetPlacement(CS_XJUST_CENTER
, 0,
306 pos
* (__cardwidth
+ X_BORDER
) + 6 * X_BORDER
, 0);
307 pStack
[i
]->SetEmptyImage(CS_EI_SUNK
);
308 pStack
[i
]->SetDragRule(CS_DRAG_CALLBACK
, StackDragProc
);
309 pStack
[i
]->SetDropRule(CS_DROP_CALLBACK
, StackDropProc
);
310 pStack
[i
]->SetAddCardProc(StackAddProc
);