1 /*
2 * PROJECT: Solitaire
3 * LICENSE: See COPYING in top level directory
4 * FILE: base/applications/games/solitaire/solundo.cpp
5 * PURPOSE: Undo module for Solitaire
6 * PROGRAMMER: Tibor Lajos Füzi
7 */
8
9 #include "solitaire.h"
10
11 // source_id and destination_id store the source and destination of the cards
12 // that were moved. These ids are defined in solitaire.h and can be DECK_ID, PILE_ID,
13 // [SUIT_ID..SUIT_ID + 3], [ROW_ID..ROW_ID + NUM_ROW_STACKS - 1].
14 // -1 means that there is no action stored in the undo module.
15 static int source_id = -1;
16 static int destination_id = -1;
17
18 // Number of cards that were moved.
19 static int number_of_cards = 0;
20
21 // The score before the action was taken.
22 static int prev_score = 0;
23
24 // The number of visible pile cards before the action was taken.
25 static int prev_visible_pile_cards = 0;
26
SetUndo(int set_source_id,int set_destination_id,int set_number_of_cards,int set_prev_score,int set_prev_visible_pile_cards)27 void SetUndo(
28 int set_source_id,
29 int set_destination_id,
30 int set_number_of_cards,
31 int set_prev_score,
32 int set_prev_visible_pile_cards)
33 {
34 if ((set_source_id == set_destination_id) || (set_number_of_cards == 0))
35 return;
36
37 source_id = set_source_id;
38 destination_id = set_destination_id;
39 number_of_cards = set_number_of_cards;
40 prev_score = set_prev_score;
41 prev_visible_pile_cards = set_prev_visible_pile_cards;
42 SetUndoMenuState(true);
43 }
44
ClearUndo(void)45 void ClearUndo(void)
46 {
47 source_id = -1;
48 destination_id = -1;
49 number_of_cards = 0;
50 SetUndoMenuState(false);
51 }
52
Undo(void)53 void Undo(void)
54 {
55 CardRegion *source = NULL;
56 CardRegion *destination = NULL;
57
58 if ((source_id < 1) ||
59 (source_id > (ROW_ID + NUM_ROW_STACKS - 1)) ||
60 (destination_id < 1) ||
61 (destination_id > (ROW_ID + NUM_ROW_STACKS - 1)) ||
62 (number_of_cards < 1))
63 {
64 ClearUndo();
65 return;
66 }
67
68 if (source_id >= ROW_ID)
69 source = pRowStack[source_id - ROW_ID];
70 else if ((source_id >= SUIT_ID) && (source_id < SUIT_ID + 4))
71 source = pSuitStack[source_id - SUIT_ID];
72 else if (source_id == PILE_ID)
73 source = pPile;
74 else if (source_id == DECK_ID)
75 source = pDeck;
76
77 if (destination_id >= ROW_ID)
78 destination = pRowStack[destination_id - ROW_ID];
79 else if ((destination_id >= SUIT_ID) && (destination_id < SUIT_ID + 4))
80 destination = pSuitStack[destination_id - SUIT_ID];
81 else if (destination_id == PILE_ID)
82 destination = pPile;
83 else if (destination_id == DECK_ID)
84 destination = pDeck;
85
86 if (destination == NULL || source == NULL)
87 {
88 ClearUndo();
89 return;
90 }
91
92 // If the player clicked on the deck.
93 if (destination == pPile && source == pDeck)
94 {
95 // Put back the cards on the deck in reversed order.
96 CardStack tmp = activepile.Pop(number_of_cards);
97 tmp.Reverse();
98 source->Push(tmp);
99 // Restore the pile to be the top cards in the active pile.
100 destination->Clear();
101 if (prev_visible_pile_cards <= 1)
102 {
103 destination->SetOffsets(0,0);
104 destination->SetCardStack(activepile);
105 }
106 else
107 {
108 tmp = activepile.Top(prev_visible_pile_cards);
109 destination->SetOffsets(CS_DEFXOFF, 1);
110 destination->Push(tmp);
111 }
112 VisiblePileCards = prev_visible_pile_cards;
113 }
114
115 // If the player clicked on the empty deck.
116 else if (source == pPile && destination == pDeck)
117 {
118 // Put back all the cards from the deck to the active pile in reversed order.
119 destination->Reverse();
120 activepile.Push(destination->GetCardStack());
121 destination->Clear();
122 if (prev_visible_pile_cards <= 1)
123 {
124 source->SetOffsets(0,0);
125 source->SetCardStack(activepile);
126 }
127 else
128 {
129 CardStack tmp = activepile.Top(prev_visible_pile_cards);
130 source->SetOffsets(CS_DEFXOFF, 1);
131 source->Push(tmp);
132 }
133 VisiblePileCards = prev_visible_pile_cards;
134 }
135
136 // If the player moved one card from the pile.
137 else if (source == pPile)
138 {
139 CardStack tmp = destination->Pop(1);
140 activepile.Push(tmp);
141 if (prev_visible_pile_cards <= 1)
142 {
143 source->Push(tmp);
144 }
145 else
146 {
147 source->Clear();
148 tmp = activepile.Top(prev_visible_pile_cards);
149 source->Push(tmp);
150 source->SetOffsets(CS_DEFXOFF, 1);
151 }
152 VisiblePileCards = prev_visible_pile_cards;
153 }
154
155 // If the player moved cards between row stacks / suit stacks.
156 else
157 {
158 destination->MoveCard(source, number_of_cards, false);
159 }
160
161 lScore = prev_score;
162
163 // -2 points for the undo in standard score mode.
164 if (GetScoreMode() == SCORE_STD)
165 lScore = lScore >= 2 ? lScore - 2 : 0;
166
167 UpdateStatusBar();
168
169 SolWnd.Redraw();
170 ClearUndo();
171 }
172