mirror of
https://github.com/shlomif/PySolFC.git
synced 2025-04-05 00:02:29 -04:00
Compare commits
9 commits
4711919942
...
6bc5b53995
Author | SHA1 | Date | |
---|---|---|---|
|
6bc5b53995 | ||
|
dd42ac10ea | ||
|
d6ca6d226b | ||
|
e4e2e99031 | ||
|
054c0f0368 | ||
|
487d1c52f3 | ||
|
6852bb40ff | ||
|
6006e0f4c0 | ||
|
68138c7284 |
27 changed files with 306 additions and 53 deletions
|
@ -2,7 +2,7 @@
|
||||||
image: Visual Studio 2022
|
image: Visual Studio 2022
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- PYTHON: "C:\\Python312"
|
- PYTHON: "C:\\Python313"
|
||||||
# Shamelessly taken from https://github.com/plicease/Dist-Zilla-PluginBundle-Author-Plicease/blob/master/.appveyor.yml
|
# Shamelessly taken from https://github.com/plicease/Dist-Zilla-PluginBundle-Author-Plicease/blob/master/.appveyor.yml
|
||||||
# Thanks!
|
# Thanks!
|
||||||
install:
|
install:
|
||||||
|
|
15
html-src/rules/colours.html
Normal file
15
html-src/rules/colours.html
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<h1>Colours</h1>
|
||||||
|
<p>
|
||||||
|
Numerica type. 1 deck. No redeal.
|
||||||
|
|
||||||
|
<h3>Object</h3>
|
||||||
|
<p>
|
||||||
|
Move all cards to the foundations.
|
||||||
|
|
||||||
|
<h3>Quick Description</h3>
|
||||||
|
<p>
|
||||||
|
Like <a href="ladybetty.html">Lady Betty</a>,
|
||||||
|
but the foundations are built up by same color, and
|
||||||
|
wrap from king to ace. At the start of the game, a
|
||||||
|
two through five are dealt to the foundations, in
|
||||||
|
alternating colors.
|
12
html-src/rules/littleishido.html
Normal file
12
html-src/rules/littleishido.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<h1>Little Ishido</h1>
|
||||||
|
<p>
|
||||||
|
Ishido game type. 2 decks. No redeal.
|
||||||
|
|
||||||
|
<h3>Object</h3>
|
||||||
|
<p>
|
||||||
|
Move all tiles to the playing area.
|
||||||
|
|
||||||
|
<h3>Quick Description</h3>
|
||||||
|
<p>
|
||||||
|
Like <a href='ishido.html'>Ishido</a>, but with four colors and symbols,
|
||||||
|
and a 6X8 grid. The initial tiles are placed in the four corners only.
|
14
html-src/rules/littleishidorelaxed.html
Normal file
14
html-src/rules/littleishidorelaxed.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<h1>Little Ishido Relaxed</h1>
|
||||||
|
<p>
|
||||||
|
Ishido game type. 2 decks. No redeal.
|
||||||
|
|
||||||
|
<h3>Object</h3>
|
||||||
|
<p>
|
||||||
|
Move all tiles to the playing area.
|
||||||
|
|
||||||
|
<h3>Quick Description</h3>
|
||||||
|
<p>
|
||||||
|
Like <a href='ishido.html'>Ishido</a>, but with four colors and symbols,
|
||||||
|
and a 6X8 grid. The initial tiles are placed in the four corners only.
|
||||||
|
Also, there are no restrictions when placing a tile next to two or more
|
||||||
|
other tiles - they just have to match the color or symbol of each.
|
|
@ -4370,6 +4370,9 @@ msgstr "Aktuelle Sitzung"
|
||||||
msgid "Log"
|
msgid "Log"
|
||||||
msgstr "Protokoll"
|
msgstr "Protokoll"
|
||||||
|
|
||||||
|
msgid "Demo Log"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
||||||
msgid "Full log"
|
msgid "Full log"
|
||||||
msgstr "Volles Protokoll"
|
msgstr "Volles Protokoll"
|
||||||
|
@ -5171,6 +5174,9 @@ msgstr "Kommentare..."
|
||||||
msgid "Log..."
|
msgid "Log..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Demo Log..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/ui/tktile/menubar.py:427
|
#: pysollib/ui/tktile/menubar.py:427
|
||||||
msgid "D&emo statistics..."
|
msgid "D&emo statistics..."
|
||||||
msgstr "D&emo Statistiken..."
|
msgstr "D&emo Statistiken..."
|
||||||
|
|
|
@ -4421,6 +4421,9 @@ msgstr "Session en cours"
|
||||||
msgid "Log"
|
msgid "Log"
|
||||||
msgstr "Journal"
|
msgstr "Journal"
|
||||||
|
|
||||||
|
msgid "Demo Log"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
||||||
msgid "Full log"
|
msgid "Full log"
|
||||||
msgstr "Journal complet"
|
msgstr "Journal complet"
|
||||||
|
@ -5222,6 +5225,9 @@ msgstr "&Commentaires..."
|
||||||
msgid "Log..."
|
msgid "Log..."
|
||||||
msgstr "Journal..."
|
msgstr "Journal..."
|
||||||
|
|
||||||
|
msgid "Demo Log..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/ui/tktile/menubar.py:427
|
#: pysollib/ui/tktile/menubar.py:427
|
||||||
msgid "D&emo statistics..."
|
msgid "D&emo statistics..."
|
||||||
msgstr "Statistiques d&émo..."
|
msgstr "Statistiques d&émo..."
|
||||||
|
|
|
@ -4485,6 +4485,9 @@ msgstr "Questa sessione"
|
||||||
msgid "Log"
|
msgid "Log"
|
||||||
msgstr "Log"
|
msgstr "Log"
|
||||||
|
|
||||||
|
msgid "Demo Log"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
||||||
msgid "Full log"
|
msgid "Full log"
|
||||||
msgstr "Log completo"
|
msgstr "Log completo"
|
||||||
|
@ -5288,6 +5291,9 @@ msgstr "&Commenti..."
|
||||||
msgid "Log..."
|
msgid "Log..."
|
||||||
msgstr "Log..."
|
msgstr "Log..."
|
||||||
|
|
||||||
|
msgid "Demo Log..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/ui/tktile/menubar.py:427
|
#: pysollib/ui/tktile/menubar.py:427
|
||||||
msgid "D&emo statistics..."
|
msgid "D&emo statistics..."
|
||||||
msgstr "Statistiche d&emo..."
|
msgstr "Statistiche d&emo..."
|
||||||
|
|
|
@ -4438,6 +4438,9 @@ msgstr "Bieżąca sesja"
|
||||||
msgid "Log"
|
msgid "Log"
|
||||||
msgstr "Log"
|
msgstr "Log"
|
||||||
|
|
||||||
|
msgid "Demo Log"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
||||||
msgid "Full log"
|
msgid "Full log"
|
||||||
msgstr "Kompletny log"
|
msgstr "Kompletny log"
|
||||||
|
@ -5242,6 +5245,9 @@ msgstr "Komentarze..."
|
||||||
msgid "Log..."
|
msgid "Log..."
|
||||||
msgstr "Log..."
|
msgstr "Log..."
|
||||||
|
|
||||||
|
msgid "Demo Log..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/ui/tktile/menubar.py:427
|
#: pysollib/ui/tktile/menubar.py:427
|
||||||
msgid "D&emo statistics..."
|
msgid "D&emo statistics..."
|
||||||
msgstr "D&emo statystyk..."
|
msgstr "D&emo statystyk..."
|
||||||
|
|
|
@ -4444,6 +4444,9 @@ msgstr "Sessão atual"
|
||||||
msgid "Log"
|
msgid "Log"
|
||||||
msgstr "registro"
|
msgstr "registro"
|
||||||
|
|
||||||
|
msgid "Demo Log"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
||||||
msgid "Full log"
|
msgid "Full log"
|
||||||
msgstr "Registro completo"
|
msgstr "Registro completo"
|
||||||
|
@ -5244,6 +5247,9 @@ msgstr "&Comentários..."
|
||||||
msgid "Log..."
|
msgid "Log..."
|
||||||
msgstr "Registro"
|
msgstr "Registro"
|
||||||
|
|
||||||
|
msgid "Demo Log..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/ui/tktile/menubar.py:427
|
#: pysollib/ui/tktile/menubar.py:427
|
||||||
msgid "D&emo statistics..."
|
msgid "D&emo statistics..."
|
||||||
msgstr "Estatísticas de D&emo..."
|
msgstr "Estatísticas de D&emo..."
|
||||||
|
|
|
@ -4224,6 +4224,9 @@ msgstr ""
|
||||||
msgid "Log"
|
msgid "Log"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Demo Log"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
||||||
msgid "Full log"
|
msgid "Full log"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -4974,6 +4977,9 @@ msgstr ""
|
||||||
msgid "Log..."
|
msgid "Log..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Demo Log..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/ui/tktile/menubar.py:427
|
#: pysollib/ui/tktile/menubar.py:427
|
||||||
msgid "D&emo statistics..."
|
msgid "D&emo statistics..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
@ -4494,6 +4494,9 @@ msgstr "Текущая сессия"
|
||||||
msgid "Log"
|
msgid "Log"
|
||||||
msgstr "Лог"
|
msgstr "Лог"
|
||||||
|
|
||||||
|
msgid "Demo Log"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
||||||
msgid "Full log"
|
msgid "Full log"
|
||||||
msgstr "Полный лог"
|
msgstr "Полный лог"
|
||||||
|
@ -5311,6 +5314,9 @@ msgstr "&Комментарии..."
|
||||||
msgid "Log..."
|
msgid "Log..."
|
||||||
msgstr "Лог..."
|
msgstr "Лог..."
|
||||||
|
|
||||||
|
msgid "Demo Log..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/ui/tktile/menubar.py:427
|
#: pysollib/ui/tktile/menubar.py:427
|
||||||
msgid "D&emo statistics..."
|
msgid "D&emo statistics..."
|
||||||
msgstr "Статистика демо..."
|
msgstr "Статистика демо..."
|
||||||
|
|
|
@ -115,18 +115,13 @@ class Statistics:
|
||||||
game.GAME_VERSION)
|
game.GAME_VERSION)
|
||||||
# full log
|
# full log
|
||||||
if status >= 0:
|
if status >= 0:
|
||||||
if player is None:
|
if player not in self.prev_games:
|
||||||
# demo
|
self.prev_games[player] = []
|
||||||
ret = self.updateGameStat(player, game, status)
|
self.prev_games[player].append(log)
|
||||||
else:
|
if player not in self.all_prev_games:
|
||||||
# player
|
self.all_prev_games[player] = []
|
||||||
if player not in self.prev_games:
|
self.all_prev_games[player].append(log)
|
||||||
self.prev_games[player] = []
|
ret = self.updateGameStat(player, game, status)
|
||||||
self.prev_games[player].append(log)
|
|
||||||
if player not in self.all_prev_games:
|
|
||||||
self.all_prev_games[player] = []
|
|
||||||
self.all_prev_games[player].append(log)
|
|
||||||
ret = self.updateGameStat(player, game, status)
|
|
||||||
# session log
|
# session log
|
||||||
if player not in self.session_games:
|
if player not in self.session_games:
|
||||||
self.session_games[player] = []
|
self.session_games[player] = []
|
||||||
|
|
|
@ -595,13 +595,12 @@ class GI:
|
||||||
tuple(range(19000, 19012)) + tuple(range(22303, 22311)) +
|
tuple(range(19000, 19012)) + tuple(range(22303, 22311)) +
|
||||||
tuple(range(22353, 22361))),
|
tuple(range(22353, 22361))),
|
||||||
('fc-3.1', tuple(range(961, 971))),
|
('fc-3.1', tuple(range(961, 971))),
|
||||||
('dev', tuple(range(971, 972))),
|
('dev', tuple(range(971, 973)) + tuple(range(18005, 18007))),
|
||||||
)
|
)
|
||||||
|
|
||||||
# deprecated - the correct way is to or a GI.GT_XXX flag
|
# deprecated - the correct way is to or a GI.GT_XXX flag
|
||||||
# in the registerGame() call
|
# in the registerGame() call
|
||||||
_CHILDREN_GAMES = [16, 33, 55, 90, 91, 96, 97, 176, 328, 329, 862, 865,
|
_CHILDREN_GAMES = []
|
||||||
886, 903, ]
|
|
||||||
|
|
||||||
_OPEN_GAMES = []
|
_OPEN_GAMES = []
|
||||||
|
|
||||||
|
|
|
@ -504,7 +504,7 @@ class MaineCoon(TabbyCat):
|
||||||
|
|
||||||
# register the game
|
# register the game
|
||||||
registerGame(GameInfo(903, AcesUp, "Aces Up", # was: 52
|
registerGame(GameInfo(903, AcesUp, "Aces Up", # was: 52
|
||||||
GI.GT_1DECK_TYPE, 1, 0, GI.SL_LUCK,
|
GI.GT_1DECK_TYPE | GI.GT_CHILDREN, 1, 0, GI.SL_LUCK,
|
||||||
altnames=("Aces High", "Drivel", "Discard")))
|
altnames=("Aces High", "Drivel", "Discard")))
|
||||||
registerGame(GameInfo(206, Fortunes, "Fortunes",
|
registerGame(GameInfo(206, Fortunes, "Fortunes",
|
||||||
GI.GT_1DECK_TYPE, 1, 0, GI.SL_LUCK))
|
GI.GT_1DECK_TYPE, 1, 0, GI.SL_LUCK))
|
||||||
|
@ -514,7 +514,7 @@ registerGame(GameInfo(130, PerpetualMotion, "Perpetual Motion",
|
||||||
GI.GT_1DECK_TYPE, 1, -1, GI.SL_MOSTLY_LUCK,
|
GI.GT_1DECK_TYPE, 1, -1, GI.SL_MOSTLY_LUCK,
|
||||||
altnames=("First Law", "Narcotic")))
|
altnames=("First Law", "Narcotic")))
|
||||||
registerGame(GameInfo(353, AcesUp5, "Aces Up 5",
|
registerGame(GameInfo(353, AcesUp5, "Aces Up 5",
|
||||||
GI.GT_1DECK_TYPE, 1, 0, GI.SL_LUCK))
|
GI.GT_1DECK_TYPE | GI.GT_CHILDREN, 1, 0, GI.SL_LUCK))
|
||||||
registerGame(GameInfo(552, Cover, "Cover",
|
registerGame(GameInfo(552, Cover, "Cover",
|
||||||
GI.GT_1DECK_TYPE, 1, 0, GI.SL_LUCK))
|
GI.GT_1DECK_TYPE, 1, 0, GI.SL_LUCK))
|
||||||
registerGame(GameInfo(583, FiringSquad, "Firing Squad",
|
registerGame(GameInfo(583, FiringSquad, "Firing Squad",
|
||||||
|
|
|
@ -105,6 +105,7 @@ class StrictEiffelTower(EiffelTower):
|
||||||
|
|
||||||
# register the game
|
# register the game
|
||||||
registerGame(GameInfo(16, EiffelTower, "Eiffel Tower",
|
registerGame(GameInfo(16, EiffelTower, "Eiffel Tower",
|
||||||
GI.GT_PAIRING_TYPE, 2, 0, GI.SL_MOSTLY_LUCK))
|
GI.GT_PAIRING_TYPE | GI.GT_CHILDREN, 2, 0,
|
||||||
|
GI.SL_MOSTLY_LUCK))
|
||||||
# registerGame(GameInfo(801, StrictEiffelTower, "Strict Eiffel Tower",
|
# registerGame(GameInfo(801, StrictEiffelTower, "Strict Eiffel Tower",
|
||||||
# GI.GT_PAIRING_TYPE, 2, 0))
|
# GI.GT_PAIRING_TYPE, 2, 0))
|
||||||
|
|
|
@ -776,11 +776,11 @@ registerGame(GameInfo(697, BigBen, "Big Ben",
|
||||||
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED,
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED,
|
||||||
altnames=("Father Time")))
|
altnames=("Father Time")))
|
||||||
registerGame(GameInfo(737, Clock, "Clock",
|
registerGame(GameInfo(737, Clock, "Clock",
|
||||||
GI.GT_1DECK_TYPE, 1, 0, GI.SL_LUCK,
|
GI.GT_1DECK_TYPE | GI.GT_CHILDREN, 1, 0, GI.SL_LUCK,
|
||||||
altnames=("Travellers", "Sundial")))
|
altnames=("Travellers", "Sundial")))
|
||||||
registerGame(GameInfo(827, GermanClock, "German Clock",
|
registerGame(GameInfo(827, GermanClock, "German Clock",
|
||||||
GI.GT_1DECK_TYPE, 1, 1, GI.SL_MOSTLY_LUCK,
|
GI.GT_1DECK_TYPE, 1, 1, GI.SL_MOSTLY_LUCK,
|
||||||
altnames=("Die Uhr",)))
|
altnames=("Die Uhr",)))
|
||||||
registerGame(GameInfo(915, RelaxedClock, "Relaxed Clock",
|
registerGame(GameInfo(915, RelaxedClock, "Relaxed Clock",
|
||||||
GI.GT_1DECK_TYPE | GI.GT_RELAXED, 1, 0, GI.SL_LUCK,
|
GI.GT_1DECK_TYPE | GI.GT_RELAXED | GI.GT_CHILDREN, 1, 0,
|
||||||
altnames=("Watch")))
|
GI.SL_LUCK, altnames=("Watch")))
|
||||||
|
|
|
@ -170,5 +170,5 @@ registerGame(GameInfo(774, HitOrMiss, "Hit or Miss",
|
||||||
GI.GT_1DECK_TYPE, 1, VARIABLE_REDEALS,
|
GI.GT_1DECK_TYPE, 1, VARIABLE_REDEALS,
|
||||||
GI.SL_LUCK, altnames=("Roll Call",)))
|
GI.SL_LUCK, altnames=("Roll Call",)))
|
||||||
registerGame(GameInfo(865, HitOrMissUnlimited, "Hit or Miss Unlimited",
|
registerGame(GameInfo(865, HitOrMissUnlimited, "Hit or Miss Unlimited",
|
||||||
GI.GT_1DECK_TYPE, 1, UNLIMITED_REDEALS,
|
GI.GT_1DECK_TYPE | GI.GT_CHILDREN, 1, UNLIMITED_REDEALS,
|
||||||
GI.SL_LUCK))
|
GI.SL_LUCK))
|
||||||
|
|
|
@ -1640,7 +1640,8 @@ registerGame(GameInfo(66, Eastcliff, "Eastcliff",
|
||||||
registerGame(GameInfo(224, Easthaven, "Easthaven",
|
registerGame(GameInfo(224, Easthaven, "Easthaven",
|
||||||
GI.GT_GYPSY, 1, 0, GI.SL_MOSTLY_LUCK))
|
GI.GT_GYPSY, 1, 0, GI.SL_MOSTLY_LUCK))
|
||||||
registerGame(GameInfo(33, Westcliff, "Westcliff",
|
registerGame(GameInfo(33, Westcliff, "Westcliff",
|
||||||
GI.GT_KLONDIKE, 1, 0, GI.SL_MOSTLY_LUCK))
|
GI.GT_KLONDIKE | GI.GT_CHILDREN, 1, 0,
|
||||||
|
GI.SL_MOSTLY_LUCK))
|
||||||
registerGame(GameInfo(225, Westhaven, "Westhaven",
|
registerGame(GameInfo(225, Westhaven, "Westhaven",
|
||||||
GI.GT_GYPSY, 1, 0, GI.SL_BALANCED))
|
GI.GT_GYPSY, 1, 0, GI.SL_BALANCED))
|
||||||
registerGame(GameInfo(107, PasSeul, "Pas Seul",
|
registerGame(GameInfo(107, PasSeul, "Pas Seul",
|
||||||
|
|
|
@ -1118,15 +1118,16 @@ registerGame(GameInfo(216, MonteCarlo2Decks, "Monte Carlo (2 Decks)",
|
||||||
registerGame(GameInfo(212, Weddings, "Weddings",
|
registerGame(GameInfo(212, Weddings, "Weddings",
|
||||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
|
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
|
||||||
registerGame(GameInfo(90, SimpleCarlo, "Simple Carlo",
|
registerGame(GameInfo(90, SimpleCarlo, "Simple Carlo",
|
||||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
|
GI.GT_PAIRING_TYPE | GI.GT_CHILDREN, 1, 0,
|
||||||
|
GI.SL_MOSTLY_LUCK))
|
||||||
registerGame(GameInfo(91, SimplePairs, "Simple Pairs",
|
registerGame(GameInfo(91, SimplePairs, "Simple Pairs",
|
||||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_LUCK,
|
GI.GT_PAIRING_TYPE | GI.GT_CHILDREN, 1, 0,
|
||||||
altnames=("Jamestown", "Pirate Gold", "Treasure Hunt",
|
GI.SL_LUCK, altnames=("Jamestown", "Pirate Gold",
|
||||||
"Hunter")))
|
"Treasure Hunt", "Hunter")))
|
||||||
registerGame(GameInfo(92, Neighbour, "Neighbour",
|
registerGame(GameInfo(92, Neighbour, "Neighbour",
|
||||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
|
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
|
||||||
registerGame(GameInfo(96, Fourteen, "Fourteen",
|
registerGame(GameInfo(96, Fourteen, "Fourteen",
|
||||||
GI.GT_PAIRING_TYPE | GI.GT_OPEN, 1, 0,
|
GI.GT_PAIRING_TYPE | GI.GT_OPEN | GI.GT_CHILDREN, 1, 0,
|
||||||
GI.SL_MOSTLY_LUCK, altnames=("Fourteen Out",
|
GI.SL_MOSTLY_LUCK, altnames=("Fourteen Out",
|
||||||
"Fourteen Puzzle",
|
"Fourteen Puzzle",
|
||||||
"Take Fourteen")))
|
"Take Fourteen")))
|
||||||
|
@ -1137,12 +1138,13 @@ registerGame(GameInfo(152, DerLetzteMonarch, "The Last Monarch",
|
||||||
GI.GT_1DECK_TYPE | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL,
|
GI.GT_1DECK_TYPE | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL,
|
||||||
altnames=("Der letzte Monarch",)))
|
altnames=("Der letzte Monarch",)))
|
||||||
registerGame(GameInfo(328, TheWish, "The Wish",
|
registerGame(GameInfo(328, TheWish, "The Wish",
|
||||||
GI.GT_PAIRING_TYPE | GI.GT_STRIPPED, 1, 0,
|
GI.GT_PAIRING_TYPE | GI.GT_STRIPPED | GI.GT_CHILDREN,
|
||||||
GI.SL_MOSTLY_LUCK, ranks=(0, 6, 7, 8, 9, 10, 11, 12)))
|
1, 0, GI.SL_MOSTLY_LUCK,
|
||||||
|
ranks=(0, 6, 7, 8, 9, 10, 11, 12)))
|
||||||
registerGame(GameInfo(329, TheWishOpen, "The Wish (Open)",
|
registerGame(GameInfo(329, TheWishOpen, "The Wish (Open)",
|
||||||
GI.GT_PAIRING_TYPE | GI.GT_OPEN | GI.GT_ORIGINAL |
|
GI.GT_PAIRING_TYPE | GI.GT_OPEN | GI.GT_ORIGINAL |
|
||||||
GI.GT_STRIPPED, 1, 0, GI.SL_MOSTLY_SKILL,
|
GI.GT_STRIPPED | GI.GT_CHILDREN, 1, 0,
|
||||||
ranks=(0, 6, 7, 8, 9, 10, 11, 12),
|
GI.SL_MOSTLY_SKILL, ranks=(0, 6, 7, 8, 9, 10, 11, 12),
|
||||||
rules_filename="thewish.html"))
|
rules_filename="thewish.html"))
|
||||||
registerGame(GameInfo(368, Vertical, "Vertical",
|
registerGame(GameInfo(368, Vertical, "Vertical",
|
||||||
GI.GT_PAIRING_TYPE | GI.GT_OPEN, 1, 0,
|
GI.GT_PAIRING_TYPE | GI.GT_OPEN, 1, 0,
|
||||||
|
@ -1162,8 +1164,8 @@ registerGame(GameInfo(810, Quatorze, "Quatorze",
|
||||||
registerGame(GameInfo(829, BlockTen, "Block Ten",
|
registerGame(GameInfo(829, BlockTen, "Block Ten",
|
||||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_LUCK))
|
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_LUCK))
|
||||||
registerGame(GameInfo(862, SimpleTens, "Simple Tens",
|
registerGame(GameInfo(862, SimpleTens, "Simple Tens",
|
||||||
GI.GT_PAIRING_TYPE | GI.GT_STRIPPED, 1, 0, GI.SL_LUCK,
|
GI.GT_PAIRING_TYPE | GI.GT_STRIPPED | GI.GT_CHILDREN,
|
||||||
ranks=(0, 1, 2, 3, 4, 5, 6, 7, 8),
|
1, 0, GI.SL_LUCK, ranks=(0, 1, 2, 3, 4, 5, 6, 7, 8),
|
||||||
altnames=("Add Up Tens",)))
|
altnames=("Add Up Tens",)))
|
||||||
registerGame(GameInfo(867, DoubleFourteen, "Double Fourteen",
|
registerGame(GameInfo(867, DoubleFourteen, "Double Fourteen",
|
||||||
GI.GT_PAIRING_TYPE | GI.GT_OPEN, 2, 0,
|
GI.GT_PAIRING_TYPE | GI.GT_OPEN, 2, 0,
|
||||||
|
|
|
@ -41,6 +41,7 @@ from pysollib.stack import \
|
||||||
RK_FoundationStack, \
|
RK_FoundationStack, \
|
||||||
RK_RowStack, \
|
RK_RowStack, \
|
||||||
ReserveStack, \
|
ReserveStack, \
|
||||||
|
SC_FoundationStack, \
|
||||||
SS_FoundationStack, \
|
SS_FoundationStack, \
|
||||||
Stack, \
|
Stack, \
|
||||||
StackWrapper, \
|
StackWrapper, \
|
||||||
|
@ -176,6 +177,7 @@ class Numerica2Decks(Numerica):
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
# * Lady Betty
|
# * Lady Betty
|
||||||
# * Last Chance
|
# * Last Chance
|
||||||
|
# * Colours
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
|
|
||||||
class LadyBetty(Numerica):
|
class LadyBetty(Numerica):
|
||||||
|
@ -215,6 +217,40 @@ class LastChance(LadyBetty):
|
||||||
self.s.talon.dealCards()
|
self.s.talon.dealCards()
|
||||||
|
|
||||||
|
|
||||||
|
class Colours(LadyBetty):
|
||||||
|
Foundation_Class = StackWrapper(SC_FoundationStack, mod=13, suit=ANY_SUIT)
|
||||||
|
|
||||||
|
def startGame(self):
|
||||||
|
self.startDealSample()
|
||||||
|
self.s.talon.dealRow(rows=self.s.foundations)
|
||||||
|
self.s.talon.dealCards() # deal first card to WasteStack
|
||||||
|
|
||||||
|
def _shuffleHook(self, cards):
|
||||||
|
# prepare first cards
|
||||||
|
topcards = [None] * 4
|
||||||
|
evencolor = -1
|
||||||
|
oddcolor = -1
|
||||||
|
for c in cards[:]:
|
||||||
|
if 0 < c.rank <= 4 and topcards[c.rank - 1] is None:
|
||||||
|
if c.rank % 2 == 0:
|
||||||
|
if evencolor != -1 and c.color != evencolor:
|
||||||
|
continue
|
||||||
|
if oddcolor != -1 and c.color == oddcolor:
|
||||||
|
continue
|
||||||
|
evencolor = c.color
|
||||||
|
elif c.rank % 2 == 1:
|
||||||
|
if oddcolor != -1 and c.color != oddcolor:
|
||||||
|
continue
|
||||||
|
if evencolor != -1 and c.color == evencolor:
|
||||||
|
continue
|
||||||
|
oddcolor = c.color
|
||||||
|
|
||||||
|
topcards[c.rank - 1] = c
|
||||||
|
cards.remove(c)
|
||||||
|
topcards.reverse()
|
||||||
|
return cards + topcards
|
||||||
|
|
||||||
|
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
# * Puss in the Corner
|
# * Puss in the Corner
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
|
@ -1460,3 +1496,5 @@ registerGame(GameInfo(931, TheBogey, "The Bogey",
|
||||||
GI.GT_1DECK_TYPE, 1, -1, GI.SL_BALANCED))
|
GI.GT_1DECK_TYPE, 1, -1, GI.SL_BALANCED))
|
||||||
registerGame(GameInfo(958, NinetyOne, "Ninety-One",
|
registerGame(GameInfo(958, NinetyOne, "Ninety-One",
|
||||||
GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_SKILL))
|
GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_SKILL))
|
||||||
|
registerGame(GameInfo(972, Colours, "Colours",
|
||||||
|
GI.GT_NUMERICA, 1, 0, GI.SL_BALANCED))
|
||||||
|
|
|
@ -1573,13 +1573,14 @@ registerGame(GameInfo(54, RoyalCotillion, "Royal Cotillion",
|
||||||
GI.GT_2DECK_TYPE, 2, 0, GI.SL_LUCK,
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_LUCK,
|
||||||
altnames=("Lords and Ladies",)))
|
altnames=("Lords and Ladies",)))
|
||||||
registerGame(GameInfo(55, OddAndEven, "Odd and Even",
|
registerGame(GameInfo(55, OddAndEven, "Odd and Even",
|
||||||
GI.GT_2DECK_TYPE, 2, 1, GI.SL_LUCK))
|
GI.GT_2DECK_TYPE | GI.GT_CHILDREN, 2, 1, GI.SL_LUCK))
|
||||||
registerGame(GameInfo(143, Kingdom, "Kingdom",
|
registerGame(GameInfo(143, Kingdom, "Kingdom",
|
||||||
GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_LUCK))
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_LUCK))
|
||||||
registerGame(GameInfo(234, Alhambra, "Alhambra",
|
registerGame(GameInfo(234, Alhambra, "Alhambra",
|
||||||
GI.GT_2DECK_TYPE, 2, 2, GI.SL_BALANCED))
|
GI.GT_2DECK_TYPE, 2, 2, GI.SL_BALANCED))
|
||||||
registerGame(GameInfo(97, Carpet, "Carpet",
|
registerGame(GameInfo(97, Carpet, "Carpet",
|
||||||
GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
|
GI.GT_1DECK_TYPE | GI.GT_CHILDREN, 1, 0,
|
||||||
|
GI.SL_MOSTLY_LUCK))
|
||||||
registerGame(GameInfo(391, BritishConstitution, "British Constitution",
|
registerGame(GameInfo(391, BritishConstitution, "British Constitution",
|
||||||
GI.GT_2DECK_TYPE | GI.GT_STRIPPED, 2, 0, GI.SL_BALANCED,
|
GI.GT_2DECK_TYPE | GI.GT_STRIPPED, 2, 0, GI.SL_BALANCED,
|
||||||
ranks=list(range(11)), # without Queens and Kings
|
ranks=list(range(11)), # without Queens and Kings
|
||||||
|
|
|
@ -99,6 +99,9 @@ class Ishido(Game):
|
||||||
STRICT_FOUR_WAYS = True
|
STRICT_FOUR_WAYS = True
|
||||||
SCORING = False
|
SCORING = False
|
||||||
|
|
||||||
|
COLS = 12
|
||||||
|
ROWS = 8
|
||||||
|
|
||||||
#
|
#
|
||||||
# game layout
|
# game layout
|
||||||
#
|
#
|
||||||
|
@ -115,13 +118,13 @@ class Ishido(Game):
|
||||||
|
|
||||||
w2 = max(2 * l.XS, x)
|
w2 = max(2 * l.XS, x)
|
||||||
# set window
|
# set window
|
||||||
w, h = w2 + l.XM * 2 + l.CW * 12, l.YM * 2 + l.CH * 8
|
w, h = w2 + l.XM * 2 + l.CW * self.COLS, l.YM * 2 + l.CH * self.ROWS
|
||||||
self.setSize(w, h)
|
self.setSize(w, h)
|
||||||
|
|
||||||
# Create rows
|
# Create rows
|
||||||
for j in range(8):
|
for j in range(self.ROWS):
|
||||||
x, y = w2 + l.XM, l.YM + l.CH * j
|
x, y = w2 + l.XM, l.YM + l.CH * j
|
||||||
for i in range(12):
|
for i in range(self.COLS):
|
||||||
s.rows.append(self.RowStack_Class(x, y, self))
|
s.rows.append(self.RowStack_Class(x, y, self))
|
||||||
x = x + l.CW
|
x = x + l.CW
|
||||||
|
|
||||||
|
@ -269,17 +272,17 @@ class Ishido(Game):
|
||||||
|
|
||||||
def getAdjacent(self, playSpace):
|
def getAdjacent(self, playSpace):
|
||||||
adjacentRows = []
|
adjacentRows = []
|
||||||
if playSpace % 12 != 11:
|
if playSpace % self.COLS != self.COLS - 1:
|
||||||
adjacentRows.append(self.s.rows[playSpace + 1])
|
adjacentRows.append(self.s.rows[playSpace + 1])
|
||||||
|
|
||||||
if playSpace % 12 != 0:
|
if playSpace % self.COLS != 0:
|
||||||
adjacentRows.append(self.s.rows[playSpace - 1])
|
adjacentRows.append(self.s.rows[playSpace - 1])
|
||||||
|
|
||||||
if playSpace + 12 < 96:
|
if playSpace + self.COLS < (self.COLS * self.ROWS):
|
||||||
adjacentRows.append(self.s.rows[playSpace + 12])
|
adjacentRows.append(self.s.rows[playSpace + self.COLS])
|
||||||
|
|
||||||
if playSpace - 12 > -1:
|
if playSpace - self.COLS > -1:
|
||||||
adjacentRows.append(self.s.rows[playSpace - 12])
|
adjacentRows.append(self.s.rows[playSpace - self.COLS])
|
||||||
|
|
||||||
return adjacentRows
|
return adjacentRows
|
||||||
|
|
||||||
|
@ -301,10 +304,46 @@ class IshidoScored(Ishido):
|
||||||
SCORING = True
|
SCORING = True
|
||||||
|
|
||||||
|
|
||||||
|
class LittleIshido(Ishido):
|
||||||
|
ROWS = 6
|
||||||
|
COLS = 8
|
||||||
|
|
||||||
|
def startGame(self):
|
||||||
|
self.score = 0
|
||||||
|
self.fourways = 0
|
||||||
|
self.moveMove(1, self.s.talon, self.s.rows[0], frames=0)
|
||||||
|
self.s.rows[0].flipMove()
|
||||||
|
self.moveMove(1, self.s.talon, self.s.rows[7], frames=0)
|
||||||
|
self.s.rows[7].flipMove()
|
||||||
|
self.moveMove(1, self.s.talon, self.s.rows[40], frames=0)
|
||||||
|
self.s.rows[40].flipMove()
|
||||||
|
self.moveMove(1, self.s.talon, self.s.rows[47], frames=0)
|
||||||
|
self.s.rows[47].flipMove()
|
||||||
|
self.s.talon.fillStack()
|
||||||
|
|
||||||
|
def _shuffleHook(self, cards):
|
||||||
|
# prepare first cards
|
||||||
|
symbols = []
|
||||||
|
colors = []
|
||||||
|
topcards = []
|
||||||
|
for c in cards[:]:
|
||||||
|
if c.suit not in colors and c.rank not in symbols:
|
||||||
|
topcards.append(c)
|
||||||
|
cards.remove(c)
|
||||||
|
symbols.append(c.rank)
|
||||||
|
colors.append(c.suit)
|
||||||
|
if len(colors) >= 4 or len(symbols) >= 4:
|
||||||
|
break
|
||||||
|
return cards + topcards
|
||||||
|
|
||||||
|
class LittleIshidoRelaxed(LittleIshido):
|
||||||
|
STRICT_FOUR_WAYS = False
|
||||||
|
|
||||||
|
|
||||||
def r(id, gameclass, name, decks, redeals, skill_level,
|
def r(id, gameclass, name, decks, redeals, skill_level,
|
||||||
game_type=GI.GT_ISHIDO):
|
game_type=GI.GT_ISHIDO, colors=6):
|
||||||
gi = GameInfo(id, gameclass, name, game_type, decks, redeals, skill_level,
|
gi = GameInfo(id, gameclass, name, game_type, decks, redeals, skill_level,
|
||||||
ranks=list(range(6)), suits=list(range(6)),
|
ranks=list(range(colors)), suits=list(range(colors)),
|
||||||
category=GI.GC_ISHIDO)
|
category=GI.GC_ISHIDO)
|
||||||
registerGame(gi)
|
registerGame(gi)
|
||||||
return gi
|
return gi
|
||||||
|
@ -316,3 +355,6 @@ r(18002, FreeIshido, 'Free Ishido', 2, 0, GI.SL_MOSTLY_SKILL)
|
||||||
r(18003, FreeIshidoRelaxed, 'Free Ishido Relaxed', 2, 0, GI.SL_MOSTLY_SKILL)
|
r(18003, FreeIshidoRelaxed, 'Free Ishido Relaxed', 2, 0, GI.SL_MOSTLY_SKILL)
|
||||||
r(18004, IshidoScored, 'Ishido Scored', 2, 0, GI.SL_MOSTLY_SKILL,
|
r(18004, IshidoScored, 'Ishido Scored', 2, 0, GI.SL_MOSTLY_SKILL,
|
||||||
game_type=GI.GT_ISHIDO | GI.GT_SCORE)
|
game_type=GI.GT_ISHIDO | GI.GT_SCORE)
|
||||||
|
r(18005, LittleIshido, 'Little Ishido', 2, 0, GI.SL_MOSTLY_SKILL, colors=4)
|
||||||
|
r(18006, LittleIshidoRelaxed, 'Little Ishido Relaxed', 2, 0,
|
||||||
|
GI.SL_MOSTLY_SKILL, colors=4)
|
||||||
|
|
|
@ -392,12 +392,12 @@ class MemorySequence(Memory24):
|
||||||
|
|
||||||
# register the game
|
# register the game
|
||||||
registerGame(GameInfo(886, Memory16, "Memory 16",
|
registerGame(GameInfo(886, Memory16, "Memory 16",
|
||||||
GI.GT_MEMORY | GI.GT_SCORE, 2, 0, GI.SL_SKILL,
|
GI.GT_MEMORY | GI.GT_SCORE | GI.GT_CHILDREN, 2, 0,
|
||||||
category=GI.GC_MATCHING,
|
GI.SL_SKILL, category=GI.GC_MATCHING,
|
||||||
suits=(), ranks=(), trumps=list(range(8))))
|
suits=(), ranks=(), trumps=list(range(8))))
|
||||||
registerGame(GameInfo(176, Memory24, "Memory 24",
|
registerGame(GameInfo(176, Memory24, "Memory 24",
|
||||||
GI.GT_MEMORY | GI.GT_SCORE, 2, 0, GI.SL_SKILL,
|
GI.GT_MEMORY | GI.GT_SCORE | GI.GT_CHILDREN, 2, 0,
|
||||||
category=GI.GC_MATCHING,
|
GI.SL_SKILL, category=GI.GC_MATCHING,
|
||||||
suits=(), ranks=(), trumps=list(range(12))))
|
suits=(), ranks=(), trumps=list(range(12))))
|
||||||
registerGame(GameInfo(219, Memory30, "Memory 30",
|
registerGame(GameInfo(219, Memory30, "Memory 30",
|
||||||
GI.GT_MEMORY | GI.GT_SCORE, 2, 0, GI.SL_SKILL,
|
GI.GT_MEMORY | GI.GT_SCORE, 2, 0, GI.SL_SKILL,
|
||||||
|
|
|
@ -26,6 +26,8 @@ import os
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from pysollib.mfxutil import destruct
|
from pysollib.mfxutil import destruct
|
||||||
|
@ -996,6 +998,72 @@ class FreeCellSolver_Hint(Base_Solver_Hint):
|
||||||
-1
|
-1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def calcBoardXML(self):
|
||||||
|
from io import StringIO
|
||||||
|
from xml.sax.saxutils import XMLGenerator
|
||||||
|
game = self.game
|
||||||
|
self.board = ''
|
||||||
|
is_simple_simon = self._isSimpleSimon()
|
||||||
|
b = []
|
||||||
|
for s in game.s.foundations:
|
||||||
|
if s.cards:
|
||||||
|
b.append(s.cards[0 if is_simple_simon else -1])
|
||||||
|
assert len(b) == 0
|
||||||
|
|
||||||
|
b = []
|
||||||
|
for s in game.s.reserves:
|
||||||
|
b.append((s.cards[-1]) if s.cards else None)
|
||||||
|
assert all(x is None for x in b)
|
||||||
|
|
||||||
|
nextid = 1
|
||||||
|
ids = {}
|
||||||
|
out = StringIO("")
|
||||||
|
xmler = XMLGenerator(out=out, encoding='UTF-8')
|
||||||
|
xmler.startDocument()
|
||||||
|
xmler.startElement(name='state', attrs={})
|
||||||
|
for row_idx, s in enumerate(game.s.rows):
|
||||||
|
moveattrs = []
|
||||||
|
moveattrs.append(('pile', 'store{}'.format(row_idx)))
|
||||||
|
moveattrs.append(('position', '{}'.format(0)))
|
||||||
|
moveattrs.sort()
|
||||||
|
dmoveattrs = OrderedDict(moveattrs)
|
||||||
|
|
||||||
|
xmler.startElement(name='move', attrs=dmoveattrs)
|
||||||
|
b = []
|
||||||
|
for c in s.cards:
|
||||||
|
cardattrs = []
|
||||||
|
cs = self.card2str1(c)
|
||||||
|
if cs in ids:
|
||||||
|
this_id = ids[cs]
|
||||||
|
else:
|
||||||
|
this_id = nextid
|
||||||
|
nextid += 1
|
||||||
|
ids[cs] = this_id
|
||||||
|
cardattrs.append(('id', '{}'.format(this_id)))
|
||||||
|
this_rank = [
|
||||||
|
"ace", "two", "three", "four", "five", "six", "seven",
|
||||||
|
"eight", "nine", "ten", "jack", "queen", "king"
|
||||||
|
][c.rank]
|
||||||
|
cardattrs.append(('rank', '{}'.format(this_rank)))
|
||||||
|
this_suit = [
|
||||||
|
"clubs", "spades", "hearts", "diamonds",
|
||||||
|
][c.suit]
|
||||||
|
cardattrs.append(('suit', '{}'.format(this_suit)))
|
||||||
|
cardattrs.append(('turn', '{}'.format("face-up")))
|
||||||
|
cardattrs.sort()
|
||||||
|
dcardattrs = OrderedDict(cardattrs)
|
||||||
|
|
||||||
|
xmler.startElement(name='card', attrs=dcardattrs)
|
||||||
|
if not c.face_up:
|
||||||
|
cs = '<%s>' % cs
|
||||||
|
xmler.endElement(name='card')
|
||||||
|
xmler.endElement(name='move')
|
||||||
|
xmler.endElement(name='state')
|
||||||
|
xmler.endDocument()
|
||||||
|
|
||||||
|
ret = out.getvalue()
|
||||||
|
return ret
|
||||||
|
|
||||||
def calcBoardString(self):
|
def calcBoardString(self):
|
||||||
game = self.game
|
game = self.game
|
||||||
self.board = ''
|
self.board = ''
|
||||||
|
|
|
@ -377,7 +377,7 @@ class TreeFormatter(PysolStatsFormatter):
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
def writeLog(self, player, prev_games, sort_by='date'):
|
def writeLog(self, player, prev_games, sort_by='date'):
|
||||||
if not player or not prev_games:
|
if not prev_games:
|
||||||
return 0
|
return 0
|
||||||
num_rows = 0
|
num_rows = 0
|
||||||
results = self.getLogResults(player, prev_games)
|
results = self.getLogResults(player, prev_games)
|
||||||
|
@ -520,6 +520,8 @@ class LogDialog(MfxDialog):
|
||||||
|
|
||||||
kw = self.initKw(kw)
|
kw = self.initKw(kw)
|
||||||
title = _('Log')
|
title = _('Log')
|
||||||
|
if player is None:
|
||||||
|
title = _('Demo Log')
|
||||||
MfxDialog.__init__(self, parent, title, kw.resizable, kw.default)
|
MfxDialog.__init__(self, parent, title, kw.resizable, kw.default)
|
||||||
|
|
||||||
self.top.wm_minsize(400, 200)
|
self.top.wm_minsize(400, 200)
|
||||||
|
|
|
@ -620,6 +620,9 @@ class PysolMenubarTkCommon:
|
||||||
menu.add_command(
|
menu.add_command(
|
||||||
label=n_("Log..."),
|
label=n_("Log..."),
|
||||||
command=lambda: self.mPlayerStats(mode=103))
|
command=lambda: self.mPlayerStats(mode=103))
|
||||||
|
menu.add_command(
|
||||||
|
label=n_("Demo Log..."),
|
||||||
|
command=lambda: self.mPlayerStats(mode=1103))
|
||||||
menu.add_separator()
|
menu.add_separator()
|
||||||
menu.add_command(
|
menu.add_command(
|
||||||
label=n_("&Comments..."),
|
label=n_("&Comments..."),
|
||||||
|
|
|
@ -50,6 +50,24 @@ class ImportFileTests(unittest.TestCase):
|
||||||
def _successful_import(self, fn, want_s, blurb):
|
def _successful_import(self, fn, want_s, blurb):
|
||||||
self.assertEqual(self._calc_hint(fn).calcBoardString(), want_s, blurb)
|
self.assertEqual(self._calc_hint(fn).calcBoardString(), want_s, blurb)
|
||||||
|
|
||||||
|
def _successful_import__XML_test(self, fn, expected_regex, blurb):
|
||||||
|
hint = self._calc_hint(fn)
|
||||||
|
xml_output = hint.calcBoardXML()
|
||||||
|
# import sys
|
||||||
|
# print(xml_output, file=sys.stderr)
|
||||||
|
self.assertRegex(
|
||||||
|
text=xml_output, expected_regex=expected_regex, msg=blurb)
|
||||||
|
|
||||||
|
def test_import_XML(self):
|
||||||
|
return self._successful_import__XML_test(
|
||||||
|
fn='tests/unit/data/with-10-for-rank.txt',
|
||||||
|
expected_regex=(
|
||||||
|
'''<state><move pile="store0" position="0">'''
|
||||||
|
'''<card id="[0-9]+" rank="four"'''
|
||||||
|
''' suit="clubs" turn="face-up"></card>'''
|
||||||
|
),
|
||||||
|
blurb='xml import worked')
|
||||||
|
|
||||||
def test_import(self):
|
def test_import(self):
|
||||||
return self._successful_import('tests/unit/data/with-10-for-rank.txt',
|
return self._successful_import('tests/unit/data/with-10-for-rank.txt',
|
||||||
'''FC: - - - -
|
'''FC: - - - -
|
||||||
|
|
Loading…
Add table
Reference in a new issue