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 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 45 void ClearUndo(void) 46 { 47 source_id = -1; 48 destination_id = -1; 49 number_of_cards = 0; 50 SetUndoMenuState(false); 51 } 52 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