https://git.reactos.org/?p=reactos.git;a=commitdiff;h=9dff498b21da9e6b60bd1…
commit 9dff498b21da9e6b60bd12d1d14de5f411382ff4
Author: Tibor Lajos Füzi <tibor.fuzi(a)gmail.com>
AuthorDate: Sun Feb 28 22:31:19 2021 +0100
Commit: GitHub <noreply(a)github.com>
CommitDate: Sun Feb 28 22:31:19 2021 +0100
[SOLITAIRE] Add undo feature & fix occasionally invisible cards (#3422)
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.
---
base/applications/games/solitaire/CMakeLists.txt | 1 +
base/applications/games/solitaire/lang/bg-BG.rc | 1 +
base/applications/games/solitaire/lang/ca-ES.rc | 1 +
base/applications/games/solitaire/lang/cs-CZ.rc | 1 +
base/applications/games/solitaire/lang/de-DE.rc | 1 +
base/applications/games/solitaire/lang/el-GR.rc | 1 +
base/applications/games/solitaire/lang/en-US.rc | 1 +
base/applications/games/solitaire/lang/es-ES.rc | 1 +
base/applications/games/solitaire/lang/eu-ES.rc | 1 +
base/applications/games/solitaire/lang/fr-FR.rc | 1 +
base/applications/games/solitaire/lang/he-IL.rc | 1 +
base/applications/games/solitaire/lang/hu-HU.rc | 1 +
base/applications/games/solitaire/lang/id-ID.rc | 1 +
base/applications/games/solitaire/lang/it-IT.rc | 1 +
base/applications/games/solitaire/lang/ja-JP.rc | 1 +
base/applications/games/solitaire/lang/ko-KR.rc | 1 +
base/applications/games/solitaire/lang/lt-LT.rc | 1 +
base/applications/games/solitaire/lang/nl-NL.rc | 1 +
base/applications/games/solitaire/lang/no-NO.rc | 1 +
base/applications/games/solitaire/lang/pl-PL.rc | 1 +
base/applications/games/solitaire/lang/pt-BR.rc | 1 +
base/applications/games/solitaire/lang/ro-RO.rc | 1 +
base/applications/games/solitaire/lang/ru-RU.rc | 1 +
base/applications/games/solitaire/lang/sk-SK.rc | 1 +
base/applications/games/solitaire/lang/sq-AL.rc | 1 +
base/applications/games/solitaire/lang/sv-SE.rc | 1 +
base/applications/games/solitaire/lang/th-TH.rc | 1 +
base/applications/games/solitaire/lang/tr-TR.rc | 1 +
base/applications/games/solitaire/lang/uk-UA.rc | 1 +
base/applications/games/solitaire/lang/zh-CN.rc | 1 +
base/applications/games/solitaire/lang/zh-TW.rc | 1 +
base/applications/games/solitaire/resource.h | 11 +-
base/applications/games/solitaire/solcreate.cpp | 2 -
base/applications/games/solitaire/solgame.cpp | 50 +++++--
base/applications/games/solitaire/solitaire.cpp | 20 ++-
base/applications/games/solitaire/solitaire.h | 7 +
base/applications/games/solitaire/solundo.cpp | 171 +++++++++++++++++++++++
37 files changed, 276 insertions(+), 16 deletions(-)
diff --git a/base/applications/games/solitaire/CMakeLists.txt
b/base/applications/games/solitaire/CMakeLists.txt
index a0f083774ad..a229418320a 100644
--- a/base/applications/games/solitaire/CMakeLists.txt
+++ b/base/applications/games/solitaire/CMakeLists.txt
@@ -2,6 +2,7 @@
list(APPEND SOURCE
solcreate.cpp
solgame.cpp
+ solundo.cpp
solitaire.cpp
solitaire.h)
diff --git a/base/applications/games/solitaire/lang/bg-BG.rc
b/base/applications/games/solitaire/lang/bg-BG.rc
index a19f9edf2cf..2b8a79bf8b5 100644
--- a/base/applications/games/solitaire/lang/bg-BG.rc
+++ b/base/applications/games/solitaire/lang/bg-BG.rc
@@ -71,6 +71,7 @@ BEGIN
BEGIN
MENUITEM "&Раздаване\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "&Тесте...", IDM_GAME_DECK
MENUITEM "&Настройки...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/ca-ES.rc
b/base/applications/games/solitaire/lang/ca-ES.rc
index 1a8a0d1f68f..231eb5589b3 100644
--- a/base/applications/games/solitaire/lang/ca-ES.rc
+++ b/base/applications/games/solitaire/lang/ca-ES.rc
@@ -71,6 +71,7 @@ BEGIN
BEGIN
MENUITEM "R&eparteix\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "&Barallar...", IDM_GAME_DECK
MENUITEM "&Opcions...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/cs-CZ.rc
b/base/applications/games/solitaire/lang/cs-CZ.rc
index 58060af83ad..bb61acd6295 100644
--- a/base/applications/games/solitaire/lang/cs-CZ.rc
+++ b/base/applications/games/solitaire/lang/cs-CZ.rc
@@ -69,6 +69,7 @@ BEGIN
BEGIN
MENUITEM "&Rozdat\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "Rub& karet...", IDM_GAME_DECK
MENUITEM "&Možnosti...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/de-DE.rc
b/base/applications/games/solitaire/lang/de-DE.rc
index 331096f604a..3211c65648b 100644
--- a/base/applications/games/solitaire/lang/de-DE.rc
+++ b/base/applications/games/solitaire/lang/de-DE.rc
@@ -71,6 +71,7 @@ BEGIN
BEGIN
MENUITEM "&Karten geben\t F2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "&Deckblatt...", IDM_GAME_DECK
MENUITEM "&Optionen...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/el-GR.rc
b/base/applications/games/solitaire/lang/el-GR.rc
index 7dbaa6e8450..08707ffce52 100644
--- a/base/applications/games/solitaire/lang/el-GR.rc
+++ b/base/applications/games/solitaire/lang/el-GR.rc
@@ -71,6 +71,7 @@ BEGIN
BEGIN
MENUITEM "&Deal\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "De&ck...", IDM_GAME_DECK
MENUITEM "&Επιλογές...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/en-US.rc
b/base/applications/games/solitaire/lang/en-US.rc
index 46abfe30d90..b8111ee7e2b 100644
--- a/base/applications/games/solitaire/lang/en-US.rc
+++ b/base/applications/games/solitaire/lang/en-US.rc
@@ -71,6 +71,7 @@ BEGIN
BEGIN
MENUITEM "&Deal\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "De&ck...", IDM_GAME_DECK
MENUITEM "&Options...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/es-ES.rc
b/base/applications/games/solitaire/lang/es-ES.rc
index 3a3222a558f..16d1944faa8 100644
--- a/base/applications/games/solitaire/lang/es-ES.rc
+++ b/base/applications/games/solitaire/lang/es-ES.rc
@@ -73,6 +73,7 @@ BEGIN
BEGIN
MENUITEM "&Repartir\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "&Barajas...", IDM_GAME_DECK
MENUITEM "&Opciones...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/eu-ES.rc
b/base/applications/games/solitaire/lang/eu-ES.rc
index 8a3c97956b4..064f283d75e 100644
--- a/base/applications/games/solitaire/lang/eu-ES.rc
+++ b/base/applications/games/solitaire/lang/eu-ES.rc
@@ -71,6 +71,7 @@ BEGIN
BEGIN
MENUITEM "&Banatu\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "&Barajak...", IDM_GAME_DECK
MENUITEM "&Aukerak...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/fr-FR.rc
b/base/applications/games/solitaire/lang/fr-FR.rc
index f1f874719cd..2f81611d373 100644
--- a/base/applications/games/solitaire/lang/fr-FR.rc
+++ b/base/applications/games/solitaire/lang/fr-FR.rc
@@ -71,6 +71,7 @@ BEGIN
BEGIN
MENUITEM "&Donne\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "&Jeux...", IDM_GAME_DECK
MENUITEM "&Options...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/he-IL.rc
b/base/applications/games/solitaire/lang/he-IL.rc
index 49129736df4..dda42542783 100644
--- a/base/applications/games/solitaire/lang/he-IL.rc
+++ b/base/applications/games/solitaire/lang/he-IL.rc
@@ -73,6 +73,7 @@ BEGIN
BEGIN
MENUITEM "&חלק\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "ח&פיסה...", IDM_GAME_DECK
MENUITEM "&אפשרויות", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/hu-HU.rc
b/base/applications/games/solitaire/lang/hu-HU.rc
index 2dad6759ef1..13633305d71 100644
--- a/base/applications/games/solitaire/lang/hu-HU.rc
+++ b/base/applications/games/solitaire/lang/hu-HU.rc
@@ -71,6 +71,7 @@ BEGIN
BEGIN
MENUITEM "&Osztás\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Visszavonás", IDM_GAME_UNDO, GRAYED
MENUITEM "&Hátlap...", IDM_GAME_DECK
MENUITEM "&Beállítások...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/id-ID.rc
b/base/applications/games/solitaire/lang/id-ID.rc
index a2af672ed89..b877e5ae7a1 100644
--- a/base/applications/games/solitaire/lang/id-ID.rc
+++ b/base/applications/games/solitaire/lang/id-ID.rc
@@ -71,6 +71,7 @@ BEGIN
BEGIN
MENUITEM "&Main Baru\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "&Dek...", IDM_GAME_DECK
MENUITEM "&Pilihan...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/it-IT.rc
b/base/applications/games/solitaire/lang/it-IT.rc
index c767ebff5ea..845f574e154 100644
--- a/base/applications/games/solitaire/lang/it-IT.rc
+++ b/base/applications/games/solitaire/lang/it-IT.rc
@@ -72,6 +72,7 @@ BEGIN
BEGIN
MENUITEM "&Dai carte\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "Maz&zo...", IDM_GAME_DECK
MENUITEM "O&pzioni...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/ja-JP.rc
b/base/applications/games/solitaire/lang/ja-JP.rc
index cba2e976ac1..fc8bd2fa945 100644
--- a/base/applications/games/solitaire/lang/ja-JP.rc
+++ b/base/applications/games/solitaire/lang/ja-JP.rc
@@ -70,6 +70,7 @@ BEGIN
BEGIN
MENUITEM "カードを配る(&D)\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "カードの装飾(&C)...", IDM_GAME_DECK
MENUITEM "オプション(&O)...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/ko-KR.rc
b/base/applications/games/solitaire/lang/ko-KR.rc
index b59f7841038..5c16be49a6b 100644
--- a/base/applications/games/solitaire/lang/ko-KR.rc
+++ b/base/applications/games/solitaire/lang/ko-KR.rc
@@ -65,6 +65,7 @@ BEGIN
BEGIN
MENUITEM "새 게임(&D)\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "덱(&C)...", IDM_GAME_DECK /* FIXME: is 덱 correct? */
MENUITEM "옵션(&O)...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/lt-LT.rc
b/base/applications/games/solitaire/lang/lt-LT.rc
index 38b9219d929..dbb674c3857 100644
--- a/base/applications/games/solitaire/lang/lt-LT.rc
+++ b/base/applications/games/solitaire/lang/lt-LT.rc
@@ -71,6 +71,7 @@ BEGIN
BEGIN
MENUITEM "&Dalinti\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "&Malka...", IDM_GAME_DECK
MENUITEM "&Nuostatos...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/nl-NL.rc
b/base/applications/games/solitaire/lang/nl-NL.rc
index d8bed184acd..6e71cd9fc59 100644
--- a/base/applications/games/solitaire/lang/nl-NL.rc
+++ b/base/applications/games/solitaire/lang/nl-NL.rc
@@ -71,6 +71,7 @@ BEGIN
BEGIN
MENUITEM "&Delen\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "&Kaarten...", IDM_GAME_DECK
MENUITEM "&Opties...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/no-NO.rc
b/base/applications/games/solitaire/lang/no-NO.rc
index c9c9e259436..79600a528cb 100644
--- a/base/applications/games/solitaire/lang/no-NO.rc
+++ b/base/applications/games/solitaire/lang/no-NO.rc
@@ -63,6 +63,7 @@ BEGIN
BEGIN
MENUITEM "&Del ut\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "Kort&stokk...", IDM_GAME_DECK
MENUITEM "&Valg...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/pl-PL.rc
b/base/applications/games/solitaire/lang/pl-PL.rc
index bb046fb80e4..af7615ff881 100644
--- a/base/applications/games/solitaire/lang/pl-PL.rc
+++ b/base/applications/games/solitaire/lang/pl-PL.rc
@@ -73,6 +73,7 @@ BEGIN
BEGIN
MENUITEM "&Rozdaj\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "&Talia...", IDM_GAME_DECK
MENUITEM "&Opcje...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/pt-BR.rc
b/base/applications/games/solitaire/lang/pt-BR.rc
index b51054578cb..6f8563bc8a2 100644
--- a/base/applications/games/solitaire/lang/pt-BR.rc
+++ b/base/applications/games/solitaire/lang/pt-BR.rc
@@ -65,6 +65,7 @@ BEGIN
BEGIN
MENUITEM "&Novo Jogo\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "Baralho...", IDM_GAME_DECK
MENUITEM "&Opções...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/ro-RO.rc
b/base/applications/games/solitaire/lang/ro-RO.rc
index fdffea90cae..4e14430b7a2 100644
--- a/base/applications/games/solitaire/lang/ro-RO.rc
+++ b/base/applications/games/solitaire/lang/ro-RO.rc
@@ -73,6 +73,7 @@ BEGIN
BEGIN
MENUITEM "Rundă &nouă\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "Culoare &dorsală…", IDM_GAME_DECK
MENUITEM "&Opțiuni…", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/ru-RU.rc
b/base/applications/games/solitaire/lang/ru-RU.rc
index 3e97b0c859e..047ce7487f8 100644
--- a/base/applications/games/solitaire/lang/ru-RU.rc
+++ b/base/applications/games/solitaire/lang/ru-RU.rc
@@ -65,6 +65,7 @@ BEGIN
BEGIN
MENUITEM "Н&овая игра\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "&Обложки...", IDM_GAME_DECK
MENUITEM "&Настройки...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/sk-SK.rc
b/base/applications/games/solitaire/lang/sk-SK.rc
index 69f57b46f90..11a33849c43 100644
--- a/base/applications/games/solitaire/lang/sk-SK.rc
+++ b/base/applications/games/solitaire/lang/sk-SK.rc
@@ -72,6 +72,7 @@ BEGIN
BEGIN
MENUITEM "&Rozdať\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "&Balíček...", IDM_GAME_DECK
MENUITEM "&Možnosti...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/sq-AL.rc
b/base/applications/games/solitaire/lang/sq-AL.rc
index 1e2f3b00af7..02400e87f51 100644
--- a/base/applications/games/solitaire/lang/sq-AL.rc
+++ b/base/applications/games/solitaire/lang/sq-AL.rc
@@ -72,6 +72,7 @@ BEGIN
BEGIN
MENUITEM "&Ndaj Letrat\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "Pa&ko...", IDM_GAME_DECK
MENUITEM "&Opsione...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/sv-SE.rc
b/base/applications/games/solitaire/lang/sv-SE.rc
index c1d15301f1d..d548ee8670f 100644
--- a/base/applications/games/solitaire/lang/sv-SE.rc
+++ b/base/applications/games/solitaire/lang/sv-SE.rc
@@ -63,6 +63,7 @@ BEGIN
BEGIN
MENUITEM "&Ge\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "&Kortlek...", IDM_GAME_DECK
MENUITEM "&Alternativ...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/th-TH.rc
b/base/applications/games/solitaire/lang/th-TH.rc
index ebabeab9946..c5e8486224e 100644
--- a/base/applications/games/solitaire/lang/th-TH.rc
+++ b/base/applications/games/solitaire/lang/th-TH.rc
@@ -71,6 +71,7 @@ BEGIN
BEGIN
MENUITEM "แ&จกไพ่\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "แ&ต่งไพ่...", IDM_GAME_DECK
MENUITEM "&ตัวเลือก...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/tr-TR.rc
b/base/applications/games/solitaire/lang/tr-TR.rc
index e53de0d0f4f..57ce217bffd 100644
--- a/base/applications/games/solitaire/lang/tr-TR.rc
+++ b/base/applications/games/solitaire/lang/tr-TR.rc
@@ -72,6 +72,7 @@ BEGIN
BEGIN
MENUITEM "&Dağıt\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "D&esteler...", IDM_GAME_DECK
MENUITEM "&Seçenekler...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/uk-UA.rc
b/base/applications/games/solitaire/lang/uk-UA.rc
index 299492e8022..c65482340e7 100644
--- a/base/applications/games/solitaire/lang/uk-UA.rc
+++ b/base/applications/games/solitaire/lang/uk-UA.rc
@@ -71,6 +71,7 @@ BEGIN
BEGIN
MENUITEM "&Роздати карти\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "&Колода...", IDM_GAME_DECK
MENUITEM "Па&раметри...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/zh-CN.rc
b/base/applications/games/solitaire/lang/zh-CN.rc
index 5487ba8b1ca..18e8a067444 100644
--- a/base/applications/games/solitaire/lang/zh-CN.rc
+++ b/base/applications/games/solitaire/lang/zh-CN.rc
@@ -71,6 +71,7 @@ BEGIN
BEGIN
MENUITEM "发牌(&D)\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "背面图案(&C)...", IDM_GAME_DECK
MENUITEM "选项(&O)...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/lang/zh-TW.rc
b/base/applications/games/solitaire/lang/zh-TW.rc
index ff8c2410ed8..8cc1aa8225b 100644
--- a/base/applications/games/solitaire/lang/zh-TW.rc
+++ b/base/applications/games/solitaire/lang/zh-TW.rc
@@ -71,6 +71,7 @@ BEGIN
BEGIN
MENUITEM "發牌(&D)\tF2", IDM_GAME_NEW
MENUITEM SEPARATOR
+ MENUITEM "&Undo", IDM_GAME_UNDO, GRAYED
MENUITEM "背面圖案(&C)...", IDM_GAME_DECK
MENUITEM "選項(&O)...", IDM_GAME_OPTIONS
MENUITEM SEPARATOR
diff --git a/base/applications/games/solitaire/resource.h
b/base/applications/games/solitaire/resource.h
index 0b221bc4f9c..680ec9fbb51 100644
--- a/base/applications/games/solitaire/resource.h
+++ b/base/applications/games/solitaire/resource.h
@@ -8,11 +8,12 @@
/* Menu */
#define IDM_GAME_NEW 1001
-#define IDM_GAME_DECK 1002
-#define IDM_GAME_OPTIONS 1003
-#define IDM_GAME_EXIT 1004
-#define IDM_HELP_CONTENTS 1005
-#define IDM_HELP_ABOUT 1006
+#define IDM_GAME_UNDO 1002
+#define IDM_GAME_DECK 1003
+#define IDM_GAME_OPTIONS 1004
+#define IDM_GAME_EXIT 1005
+#define IDM_HELP_CONTENTS 1006
+#define IDM_HELP_ABOUT 1007
/* Dialogs */
#define IDD_OPTIONS 1200
diff --git a/base/applications/games/solitaire/solcreate.cpp
b/base/applications/games/solitaire/solcreate.cpp
index 00d29d856d6..64af9b11ba6 100644
--- a/base/applications/games/solitaire/solcreate.cpp
+++ b/base/applications/games/solitaire/solcreate.cpp
@@ -5,8 +5,6 @@ CardRegion *pPile;
CardRegion *pSuitStack[4];
CardRegion *pRowStack[NUM_ROW_STACKS];
-extern CardStack activepile;
-
HBITMAP hbmBitmap;
HDC hdcBitmap;
int yRowStackCardOffset;
diff --git a/base/applications/games/solitaire/solgame.cpp
b/base/applications/games/solitaire/solgame.cpp
index f1322647dba..19219b8f9f4 100644
--- a/base/applications/games/solitaire/solgame.cpp
+++ b/base/applications/games/solitaire/solgame.cpp
@@ -10,6 +10,7 @@ extern TCHAR MsgWin[128];
extern TCHAR MsgDeal[128];
CardStack activepile;
+int VisiblePileCards;
int LastId;
bool fGameStarted = false;
bool bAutoroute = false;
@@ -53,6 +54,7 @@ void NewGame(void)
deck.NewDeck();
deck.Shuffle();
activepile.Clear();
+ VisiblePileCards = 0;
//deal to each row stack..
for(i = 0; i < NUM_ROW_STACKS; i++)
@@ -85,6 +87,7 @@ void NewGame(void)
dwPrevMode = GetScoreMode();
UpdateStatusBar();
+ ClearUndo();
TRACE("EXIT NewGame()\n");
@@ -160,6 +163,8 @@ bool CARDLIBPROC RowStackDropProc(CardRegion &stackobj, CardStack
&dragcards)
fGameStarted = true;
+ SetUndo(LastId, stackobj.Id(), dragcards.NumCards(), lScore, VisiblePileCards);
+
if (LastId == PILE_ID)
{
if (GetScoreMode() == SCORE_STD)
@@ -245,6 +250,8 @@ bool CARDLIBPROC SuitStackDropProc(CardRegion &stackobj, CardStack
&dragcards)
if (b)
{
+ SetUndo(LastId, stackobj.Id(), 1, lScore, VisiblePileCards);
+
if ((LastId == PILE_ID) || (LastId >= ROW_ID))
{
if (GetScoreMode() == SCORE_VEGAS)
@@ -300,6 +307,7 @@ void CARDLIBPROC RowStackClickProc(CardRegion &stackobj, int
iNumClicked)
lScore = lScore + 5;
UpdateStatusBar();
}
+ ClearUndo();
}
LastId = stackobj.Id();
@@ -363,6 +371,7 @@ void CARDLIBPROC SuitStackAddProc(CardRegion &stackobj, const
CardStack &added)
}
UpdateStatusBar();
+ ClearUndo();
MessageBox(SolWnd, MsgWin, szAppName, MB_OK | MB_ICONINFORMATION);
@@ -450,6 +459,22 @@ void CARDLIBPROC PileDblClickProc(CardRegion &stackobj, int
iNumClicked)
TRACE("EXIT PileDblClickProc()\n");
}
+//
+// Fix for the 3-card play when only 1 card left on the pile.
+//
+void FixIfOneCardLeft(void)
+{
+ // If there is just 1 card left, then modify the
+ // stack to contain ALL the face-up cards. The effect
+ // will be, the next time a card is dragged, all the
+ // previous card-triplets will be available underneath.
+ if ((dwOptions & OPTION_THREE_CARDS) && pPile->NumCards() == 1)
+ {
+ pPile->SetOffsets(0, 0);
+ pPile->SetCardStack(activepile);
+ }
+}
+
//
// What happens when a card is removed from face-up pile?
//
@@ -462,16 +487,13 @@ void CARDLIBPROC PileRemoveProc(CardRegion &stackobj, int
iItems)
//modify our "virtual" pile by removing the same card
//that was removed from the physical card stack
activepile.Pop(iItems);
-
- //if there is just 1 card left, then modify the
- //stack to contain ALL the face-up cards..the effect
- //will be, the next time a card is dragged, all the
- //previous card-triplets will be available underneath
- if(stackobj.NumCards() == 1)
+ if ((dwOptions & OPTION_THREE_CARDS) && (VisiblePileCards > 1))
{
- stackobj.SetOffsets(0,0);
- stackobj.SetCardStack(activepile);
+ --VisiblePileCards;
}
+
+ FixIfOneCardLeft();
+
TRACE("EXIT PileRemoveProc()\n");
}
@@ -506,10 +528,13 @@ void CARDLIBPROC DeckClickProc(CardRegion &stackobj, int
iNumClicked)
activepile.Reverse();
cardstack.Push(activepile);
activepile.Clear();
+ SetUndo(PILE_ID, DECK_ID, cardstack.NumCards(), lScore,
VisiblePileCards);
+ VisiblePileCards = 0;
}
}
else if (GetScoreMode() == SCORE_STD)
{
+ SetUndo(PILE_ID, DECK_ID, activepile.NumCards(), lScore, VisiblePileCards);
if ((dwWasteCount >= dwWasteTreshold) && (activepile.NumCards() !=
0))
{
if (dwOptions & OPTION_THREE_CARDS)
@@ -523,6 +548,7 @@ void CARDLIBPROC DeckClickProc(CardRegion &stackobj, int
iNumClicked)
activepile.Reverse();
cardstack.Push(activepile);
activepile.Clear();
+ VisiblePileCards = 0;
UpdateStatusBar();
}
@@ -533,6 +559,8 @@ void CARDLIBPROC DeckClickProc(CardRegion &stackobj, int
iNumClicked)
activepile.Reverse();
cardstack.Push(activepile);
activepile.Clear();
+ SetUndo(PILE_ID, DECK_ID, cardstack.NumCards(), lScore, VisiblePileCards);
+ VisiblePileCards = 0;
}
dwWasteCount++;
@@ -541,6 +569,8 @@ void CARDLIBPROC DeckClickProc(CardRegion &stackobj, int
iNumClicked)
{
int numcards = min((dwOptions & OPTION_THREE_CARDS) ? 3 : 1,
cardstack.NumCards());
+ SetUndo(DECK_ID, PILE_ID, numcards, lScore, VisiblePileCards);
+
//make a "visible" copy of these cards
CardStack temp;
temp = cardstack.Pop(numcards);
@@ -553,6 +583,8 @@ void CARDLIBPROC DeckClickProc(CardRegion &stackobj, int
iNumClicked)
//remove the top 3 from deck
activepile.Push(temp);
+
+ VisiblePileCards = numcards;
}
activepile.Print();
@@ -560,6 +592,8 @@ void CARDLIBPROC DeckClickProc(CardRegion &stackobj, int
iNumClicked)
pDeck->SetCardStack(cardstack);
pPile->SetCardStack(pile);
+ FixIfOneCardLeft();
+
SolWnd.Redraw();
TRACE("EXIT DeckClickProc()\n");
}
diff --git a/base/applications/games/solitaire/solitaire.cpp
b/base/applications/games/solitaire/solitaire.cpp
index 84895cb5701..529f6ba56e9 100644
--- a/base/applications/games/solitaire/solitaire.cpp
+++ b/base/applications/games/solitaire/solitaire.cpp
@@ -12,6 +12,7 @@ DWORD dwAppStartTime;
HWND hwndMain;
HWND hwndStatus;
HINSTANCE hInstance;
+HMENU hGameMenu;
TCHAR szAppName[128];
TCHAR szScore[64];
@@ -178,6 +179,18 @@ void SetPlayTimer(void)
}
}
+void SetUndoMenuState(bool enable)
+{
+ if (enable)
+ {
+ EnableMenuItem(hGameMenu, IDM_GAME_UNDO, MF_BYCOMMAND | MF_ENABLED);
+ }
+ else
+ {
+ EnableMenuItem(hGameMenu, IDM_GAME_UNDO, MF_BYCOMMAND | MF_GRAYED);
+ }
+}
+
//
// Main entry point
//
@@ -248,6 +261,8 @@ int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE hPrev, LPTSTR
szCmdLine, int iCm
hwndMain = hwnd;
+ hGameMenu = GetSubMenu(GetMenu(hwndMain), 0);
+
UpdateStatusBar();
ShowWindow(hwnd, iCmdShow);
@@ -706,6 +721,10 @@ LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM
lParam)
NewGame();
return 0;
+ case IDM_GAME_UNDO:
+ Undo();
+ return 0;
+
case IDM_GAME_DECK:
ShowDeckOptionsDlg(hwnd);
return 0;
@@ -753,4 +772,3 @@ LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM
lParam)
}
-
diff --git a/base/applications/games/solitaire/solitaire.h
b/base/applications/games/solitaire/solitaire.h
index 9905ec51a9a..2254b7abb58 100644
--- a/base/applications/games/solitaire/solitaire.h
+++ b/base/applications/games/solitaire/solitaire.h
@@ -54,15 +54,18 @@ void NewGame(void);
#define Y_BORDERWITHFRAME 20
#define Y_ROWSTACK_BORDER 32
extern int yRowStackCardOffset;
+extern int VisiblePileCards;
extern CardRegion *pDeck;
extern CardRegion *pPile;
extern CardRegion *pSuitStack[];
extern CardRegion *pRowStack[];
+extern CardStack activepile;
extern void UpdateStatusBar(void);
extern void SetPlayTimer(void);
extern int GetScoreMode(void);
+extern void SetUndoMenuState(bool enable);
bool CARDLIBPROC RowStackDragProc(CardRegion &stackobj, int iNumCards);
bool CARDLIBPROC RowStackDropProc(CardRegion &stackobj, CardStack &dragcards);
@@ -80,5 +83,9 @@ void CARDLIBPROC PileClickProc(CardRegion &stackobj, int
iNumClicked);
void CARDLIBPROC PileRemoveProc(CardRegion &stackobj, int iRemoved);
+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);
+void ClearUndo(void);
+void Undo(void);
+
#endif /* _SOL_PCH_ */
diff --git a/base/applications/games/solitaire/solundo.cpp
b/base/applications/games/solitaire/solundo.cpp
new file mode 100644
index 00000000000..ef509255889
--- /dev/null
+++ b/base/applications/games/solitaire/solundo.cpp
@@ -0,0 +1,171 @@
+/*
+ * 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();
+}