mirror of
https://github.com/reactos/reactos.git
synced 2025-01-06 06:20:13 +00:00
9dff498b21
Two issues are addressed: CORE-2189: missing undo feature Works the same way as solitaire in windows xp: - only 1 action can be undone; - the player gets -2 points in standard score mode; - the undo action resets when the player clicks on a row stack to turn the top card. CORE-11148: invisible cards This happens in 3-card mode, when only 1 card left in the deck. The fix for this is to modify the pile stack to contain all the face-up cards. It was actually already in the code somewhere else, so I turned it into a separate function.
171 lines
4.9 KiB
C++
171 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();
|
|
}
|