mirror of
https://github.com/reactos/reactos.git
synced 2025-01-07 14:51:00 +00:00
172 lines
4.9 KiB
C++
172 lines
4.9 KiB
C++
|
/*
|
||
|
* PROJECT: Solitaire
|
||
|
* LICENSE: See COPYING in top level directory
|
||
|
* FILE: base/applications/games/solitaire/solundo.cpp
|
||
|
* PURPOSE: Undo module for Solitaire
|
||
|
* PROGRAMMER: Tibor Lajos Füzi
|
||
|
*/
|
||
|
|
||
|
#include "solitaire.h"
|
||
|
|
||
|
// source_id and destination_id store the source and destination of the cards
|
||
|
// that were moved. These ids are defined in solitaire.h and can be DECK_ID, PILE_ID,
|
||
|
// [SUIT_ID..SUIT_ID + 3], [ROW_ID..ROW_ID + NUM_ROW_STACKS - 1].
|
||
|
// -1 means that there is no action stored in the undo module.
|
||
|
static int source_id = -1;
|
||
|
static int destination_id = -1;
|
||
|
|
||
|
// Number of cards that were moved.
|
||
|
static int number_of_cards = 0;
|
||
|
|
||
|
// The score before the action was taken.
|
||
|
static int prev_score = 0;
|
||
|
|
||
|
// The number of visible pile cards before the action was taken.
|
||
|
static int prev_visible_pile_cards = 0;
|
||
|
|
||
|
void SetUndo(
|
||
|
int set_source_id,
|
||
|
int set_destination_id,
|
||
|
int set_number_of_cards,
|
||
|
int set_prev_score,
|
||
|
int set_prev_visible_pile_cards)
|
||
|
{
|
||
|
if ((set_source_id == set_destination_id) || (set_number_of_cards == 0))
|
||
|
return;
|
||
|
|
||
|
source_id = set_source_id;
|
||
|
destination_id = set_destination_id;
|
||
|
number_of_cards = set_number_of_cards;
|
||
|
prev_score = set_prev_score;
|
||
|
prev_visible_pile_cards = set_prev_visible_pile_cards;
|
||
|
SetUndoMenuState(true);
|
||
|
}
|
||
|
|
||
|
void ClearUndo(void)
|
||
|
{
|
||
|
source_id = -1;
|
||
|
destination_id = -1;
|
||
|
number_of_cards = 0;
|
||
|
SetUndoMenuState(false);
|
||
|
}
|
||
|
|
||
|
void Undo(void)
|
||
|
{
|
||
|
CardRegion *source = NULL;
|
||
|
CardRegion *destination = NULL;
|
||
|
|
||
|
if ((source_id < 1) ||
|
||
|
(source_id > (ROW_ID + NUM_ROW_STACKS - 1)) ||
|
||
|
(destination_id < 1) ||
|
||
|
(destination_id > (ROW_ID + NUM_ROW_STACKS - 1)) ||
|
||
|
(number_of_cards < 1))
|
||
|
{
|
||
|
ClearUndo();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (source_id >= ROW_ID)
|
||
|
source = pRowStack[source_id - ROW_ID];
|
||
|
else if ((source_id >= SUIT_ID) && (source_id < SUIT_ID + 4))
|
||
|
source = pSuitStack[source_id - SUIT_ID];
|
||
|
else if (source_id == PILE_ID)
|
||
|
source = pPile;
|
||
|
else if (source_id == DECK_ID)
|
||
|
source = pDeck;
|
||
|
|
||
|
if (destination_id >= ROW_ID)
|
||
|
destination = pRowStack[destination_id - ROW_ID];
|
||
|
else if ((destination_id >= SUIT_ID) && (destination_id < SUIT_ID + 4))
|
||
|
destination = pSuitStack[destination_id - SUIT_ID];
|
||
|
else if (destination_id == PILE_ID)
|
||
|
destination = pPile;
|
||
|
else if (destination_id == DECK_ID)
|
||
|
destination = pDeck;
|
||
|
|
||
|
if (destination == NULL || source == NULL)
|
||
|
{
|
||
|
ClearUndo();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// If the player clicked on the deck.
|
||
|
if (destination == pPile && source == pDeck)
|
||
|
{
|
||
|
// Put back the cards on the deck in reversed order.
|
||
|
CardStack tmp = activepile.Pop(number_of_cards);
|
||
|
tmp.Reverse();
|
||
|
source->Push(tmp);
|
||
|
// Restore the pile to be the top cards in the active pile.
|
||
|
destination->Clear();
|
||
|
if (prev_visible_pile_cards <= 1)
|
||
|
{
|
||
|
destination->SetOffsets(0,0);
|
||
|
destination->SetCardStack(activepile);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tmp = activepile.Top(prev_visible_pile_cards);
|
||
|
destination->SetOffsets(CS_DEFXOFF, 1);
|
||
|
destination->Push(tmp);
|
||
|
}
|
||
|
VisiblePileCards = prev_visible_pile_cards;
|
||
|
}
|
||
|
|
||
|
// If the player clicked on the empty deck.
|
||
|
else if (source == pPile && destination == pDeck)
|
||
|
{
|
||
|
// Put back all the cards from the deck to the active pile in reversed order.
|
||
|
destination->Reverse();
|
||
|
activepile.Push(destination->GetCardStack());
|
||
|
destination->Clear();
|
||
|
if (prev_visible_pile_cards <= 1)
|
||
|
{
|
||
|
source->SetOffsets(0,0);
|
||
|
source->SetCardStack(activepile);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CardStack tmp = activepile.Top(prev_visible_pile_cards);
|
||
|
source->SetOffsets(CS_DEFXOFF, 1);
|
||
|
source->Push(tmp);
|
||
|
}
|
||
|
VisiblePileCards = prev_visible_pile_cards;
|
||
|
}
|
||
|
|
||
|
// If the player moved one card from the pile.
|
||
|
else if (source == pPile)
|
||
|
{
|
||
|
CardStack tmp = destination->Pop(1);
|
||
|
activepile.Push(tmp);
|
||
|
if (prev_visible_pile_cards <= 1)
|
||
|
{
|
||
|
source->Push(tmp);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
source->Clear();
|
||
|
tmp = activepile.Top(prev_visible_pile_cards);
|
||
|
source->Push(tmp);
|
||
|
source->SetOffsets(CS_DEFXOFF, 1);
|
||
|
}
|
||
|
VisiblePileCards = prev_visible_pile_cards;
|
||
|
}
|
||
|
|
||
|
// If the player moved cards between row stacks / suit stacks.
|
||
|
else
|
||
|
{
|
||
|
destination->MoveCard(source, number_of_cards, false);
|
||
|
}
|
||
|
|
||
|
lScore = prev_score;
|
||
|
|
||
|
// -2 points for the undo in standard score mode.
|
||
|
if (GetScoreMode() == SCORE_STD)
|
||
|
lScore = lScore >= 2 ? lScore - 2 : 0;
|
||
|
|
||
|
UpdateStatusBar();
|
||
|
|
||
|
SolWnd.Redraw();
|
||
|
ClearUndo();
|
||
|
}
|