diff --git a/html-src/rules/kingsway.html b/html-src/rules/kingsway.html
new file mode 100644
index 00000000..0eaaa59e
--- /dev/null
+++ b/html-src/rules/kingsway.html
@@ -0,0 +1,29 @@
+
King's Way
+
+Golf type. 2 decks. 1 redeal.
+
+
Object
+
+Move all cards except the kings to the waste stack.
+
+
Rules
+
+Deal the eight kings to eight tableau piles. Then, deal five cards on
+top of each king - the bottom-most one face-down and the others face-up.
+
+Deal cards from the talon one at a time. You can move cards from the
+tableau to build the waste stack up or down by alternate color. Kings
+cannot be moved to the waste stack.
+
+There is an additional reserve pile. Aces from the waste stack (not the
+tableau) may be moved to this reserve. This reserve controls a single
+redeal - when the talon is empty, you can take one card from the bottom
+of the tableau for each card in the reserve, and use these cards to
+build a new talon. You can only do this once.
+
+The game is won if all cards are moved to the waste pile, except for the
+immovable kings.
+
+
Notes
+
+Autodrop is disabled for this game.
diff --git a/po/de_pysol.po b/po/de_pysol.po
index 4cc098a3..24492e4e 100644
--- a/po/de_pysol.po
+++ b/po/de_pysol.po
@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: PySol 0.0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-12-10 10:19-0500\n"
-"PO-Revision-Date: 2024-06-30 10:00-0400\n"
+"PO-Revision-Date: 2024-07-04 17:03-0400\n"
"Last-Translator: H. Schaekel \n"
"Language-Team: German\n"
"Language: de\n"
@@ -2367,6 +2367,9 @@ msgstr "Basiskarte - Ass oder König."
msgid "Waste. Build up or down regardless of suit."
msgstr "Zwischentalon. Hoch oder Runter unabhängig der Farbe zu erstelle."
+msgid "Waste. Build up or down by alternate color."
+msgstr ""
+
#: pysollib/games/klondike.py:125
#, python-format
msgid "Balance $%d"
diff --git a/po/fr_pysol.po b/po/fr_pysol.po
index 00341c35..5d0d31b2 100644
--- a/po/fr_pysol.po
+++ b/po/fr_pysol.po
@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: 1.02\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-12-10 10:19-0500\n"
-"PO-Revision-Date: 2024-06-30 09:59-0400\n"
+"PO-Revision-Date: 2024-07-04 17:03-0400\n"
"Last-Translator: Eric Rausch \n"
"Language-Team: French\n"
"Language: fr\n"
@@ -2407,6 +2407,9 @@ msgstr "Carte de départ - As ou Roi."
msgid "Waste. Build up or down regardless of suit."
msgstr "Défausse. Croissant ou décroissant indépendamment de l'enseigne."
+msgid "Waste. Build up or down by alternate color."
+msgstr ""
+
#: pysollib/games/klondike.py:125
#, python-format
msgid "Balance $%d"
diff --git a/po/it_pysol.po b/po/it_pysol.po
index 27d38502..e077362c 100644
--- a/po/it_pysol.po
+++ b/po/it_pysol.po
@@ -12,7 +12,7 @@ msgstr ""
"Project-Id-Version: it_pysol\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-12-10 10:19-0500\n"
-"PO-Revision-Date: 2024-06-30 09:59-0400\n"
+"PO-Revision-Date: 2024-07-04 17:03-0400\n"
"Last-Translator: Giuliano Colla \n"
"Language-Team: Italiano \n"
"Language: it\n"
@@ -2415,6 +2415,9 @@ msgstr "Carta Base - Asso o Re"
msgid "Waste. Build up or down regardless of suit."
msgstr "Pozzo: Sequenza crescente o decrescente indipendentemente dal seme"
+msgid "Waste. Build up or down by alternate color."
+msgstr ""
+
#: pysollib/games/klondike.py:125
#, python-format
msgid "Balance $%d"
diff --git a/po/pl_pysol.po b/po/pl_pysol.po
index e5768ebd..bc846de3 100644
--- a/po/pl_pysol.po
+++ b/po/pl_pysol.po
@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: PySolFC\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-12-10 10:19-0500\n"
-"PO-Revision-Date: 2024-06-30 09:58-0400\n"
+"PO-Revision-Date: 2024-07-04 17:03-0400\n"
"Last-Translator: Jerzy Trzeciak \n"
"Language-Team: Polish \n"
"Language: pl\n"
@@ -2421,6 +2421,9 @@ msgstr "Karta bazowa - As lub Król."
msgid "Waste. Build up or down regardless of suit."
msgstr "Zrzut. Układaj w górę lub w dół niezależnie od koloru."
+msgid "Waste. Build up or down by alternate color."
+msgstr ""
+
#: pysollib/games/klondike.py:125
#, python-format
msgid "Balance $%d"
diff --git a/po/pt_BR_pysol.po b/po/pt_BR_pysol.po
index bbf8c9c3..623af9ba 100644
--- a/po/pt_BR_pysol.po
+++ b/po/pt_BR_pysol.po
@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-12-10 10:19-0500\n"
-"PO-Revision-Date: 2024-06-30 09:58-0400\n"
+"PO-Revision-Date: 2024-07-04 17:04-0400\n"
"Last-Translator: Matheus Knack \n"
"Language-Team: \n"
"Language: pt_BR\n"
@@ -2429,6 +2429,9 @@ msgid "Waste. Build up or down regardless of suit."
msgstr ""
"Descarte. Construa crescente ou descrescente independentemente de naipe."
+msgid "Waste. Build up or down by alternate color."
+msgstr ""
+
#: pysollib/games/klondike.py:125
#, python-format
msgid "Balance $%d"
diff --git a/po/pysol.pot b/po/pysol.pot
index 9f527269..ffb30e3c 100644
--- a/po/pysol.pot
+++ b/po/pysol.pot
@@ -2254,6 +2254,9 @@ msgstr ""
msgid "Waste. Build up or down regardless of suit."
msgstr ""
+msgid "Waste. Build up or down by alternate color."
+msgstr ""
+
#: pysollib/games/klondike.py:125
#, python-format
msgid "Balance $%d"
diff --git a/po/ru_pysol.po b/po/ru_pysol.po
index e58ec416..1cab798d 100644
--- a/po/ru_pysol.po
+++ b/po/ru_pysol.po
@@ -7,7 +7,7 @@ msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-12-10 10:19-0500\n"
-"PO-Revision-Date: 2024-06-30 09:58-0400\n"
+"PO-Revision-Date: 2024-07-04 17:04-0400\n"
"Last-Translator: Skomoroh \n"
"Language-Team: Russian \n"
"Language: ru\n"
@@ -2414,6 +2414,9 @@ msgstr "Базовая карта - Туз или Король."
msgid "Waste. Build up or down regardless of suit."
msgstr "Сброс. Складывать по возрастанию или убыванию не считаясь с мастью."
+msgid "Waste. Build up or down by alternate color."
+msgstr ""
+
#: pysollib/games/klondike.py:125
#, python-format
msgid "Balance $%d"
diff --git a/pysollib/gamedb.py b/pysollib/gamedb.py
index e8cb04c1..350ea561 100644
--- a/pysollib/gamedb.py
+++ b/pysollib/gamedb.py
@@ -604,7 +604,7 @@ class GI:
tuple(range(13168, 13170)) + tuple(range(18000, 18005)) +
tuple(range(19000, 19012)) + tuple(range(22303, 22311)) +
tuple(range(22353, 22361))),
- ('dev', tuple(range(961, 965))),
+ ('dev', tuple(range(961, 966))),
)
# deprecated - the correct way is to or a GI.GT_XXX flag
diff --git a/pysollib/games/golf.py b/pysollib/games/golf.py
index c175af5a..a74d1c72 100644
--- a/pysollib/games/golf.py
+++ b/pysollib/games/golf.py
@@ -136,8 +136,12 @@ class Golf_RowStack(BasicRowStack):
class Golf(Game):
Solver_Class = BlackHoleSolverWrapper(preset='golf', base_rank=0,
queens_on_kings=True)
+ Talon_Class = Golf_Talon
Waste_Class = Golf_Waste
Hint_Class = Golf_Hint
+ Reserve_Class = None
+
+ ROUNDS = 1
#
# game layout
@@ -161,13 +165,18 @@ class Golf(Game):
x, y = layout.XM + layout.XS // 2, layout.YM
for i in range(columns):
s.rows.append(Golf_RowStack(x, y, self))
- x = x + layout.XS
+ x += layout.XS
x, y = layout.XM, self.height - layout.YS
- s.talon = Golf_Talon(x, y, self, max_rounds=1)
+ s.talon = self.Talon_Class(x, y, self, max_rounds=self.ROUNDS)
layout.createText(s.talon, "n")
- x = x + layout.XS
+ x += layout.XS
s.waste = self.Waste_Class(x, y, self)
- s.waste.CARD_XOFFSET = layout.XOFFSET
+ if self.Reserve_Class is None:
+ s.waste.CARD_XOFFSET = layout.XOFFSET
+ else:
+ x += layout.XS
+ s.reserves.append(self.Reserve_Class(x, y, self))
+ layout.createText(s.reserves[0], "n")
layout.createText(s.waste, "n")
# the Waste is also our only Foundation in this game
s.foundations.append(s.waste)
@@ -176,6 +185,9 @@ class Golf(Game):
self.sg.openstacks = [s.waste]
self.sg.talonstacks = [s.talon]
self.sg.dropstacks = s.rows
+ if self.Reserve_Class is not None:
+ self.sg.openstacks += s.reserves
+ self.sg.reservestacks = s.reserves
#
# game overrides
@@ -228,7 +240,9 @@ class Thieves(Golf):
# ************************************************************************
-# *
+# * Dead King Golf
+# * Relaxed Golf
+# * Double Putt
# ************************************************************************
class DeadKingGolf(Golf):
@@ -259,6 +273,110 @@ class DoublePutt(DoubleGolf):
shallHighlightMatch = Game._shallHighlightMatch_RKW
+# ************************************************************************
+# * King's Way
+# ************************************************************************
+
+class KingsWay_Talon(Golf_Talon):
+ def _redeal(self):
+ game = self.game
+ num_redeal = len(game.s.reserves[0].cards)
+ # TODO: I know there's a better way to do this.
+ while len(game.s.waste.cards) > 0:
+ game.moveMove(1, self.waste, game.s.reserves[0], frames=0)
+ for i in range(num_redeal):
+ game.moveMove(1, game.s.reserves[0], self, frames=0)
+ if self.cards[-1].face_up:
+ game.flipMove(self)
+ while len(game.s.reserves[0].cards) > num_redeal:
+ game.moveMove(1, game.s.reserves[0], self.waste, frames=0)
+ self.game.nextRoundMove(self)
+ self.dealCards()
+
+ def canDealCards(self):
+ return (len(self.cards) > 0
+ or (self.round == 1 and len(self.cards) == 0
+ and len(self.game.s.reserves[0].cards) > 0))
+
+ def dealCards(self, sound=False):
+ if self.cards:
+ return WasteTalonStack.dealCards(self, sound=sound)
+ if sound:
+ self.game.startDealSample()
+ self._redeal()
+ if sound:
+ self.game.stopSamples()
+ return
+
+
+class KingsWay_Waste(Golf_Waste):
+
+ def __init__(self, x, y, game, **cap):
+ kwdefault(cap, max_move=1, max_accept=1)
+ WasteStack.__init__(self, x, y, game, **cap)
+
+ def acceptsCards(self, from_stack, cards):
+ if self.cards[-1].color == cards[0].color:
+ return False
+ if cards[0].rank == KING:
+ return False
+ return Golf_Waste.acceptsCards(self, from_stack, cards)
+
+ def moveMove(self, ncards, to_stack, frames=-1, shadow=-1):
+ WasteStack.moveMove(self, ncards, to_stack, frames=frames,
+ shadow=shadow)
+ self.game.s.talon.dealCards()
+
+ def rightclickHandler(self, event):
+ if self.cards and self.cards[-1].rank == ACE:
+ self.playMoveMove(1, self.game.s.reserves[0])
+
+ def getHelp(self):
+ return _('Waste. Build up or down by alternate color.')
+
+
+class KingsWay_Reserve(ReserveStack):
+
+ def getBottomImage(self):
+ return self.game.app.images.getLetter(ACE)
+
+ def acceptsCards(self, from_stack, cards):
+ return from_stack == self.game.s.waste and cards[0].rank == ACE
+
+
+class KingsWay(Golf):
+ Solver_Class = None
+
+ Talon_Class = KingsWay_Talon
+ Waste_Class = KingsWay_Waste
+ Reserve_Class = StackWrapper(KingsWay_Reserve, max_accept=1)
+
+ ROUNDS = 2
+
+ def createGame(self):
+ Golf.createGame(self, 8)
+
+ def _shuffleHook(self, cards):
+ return self._shuffleHookMoveToTop(cards,
+ lambda c: (c.rank == KING, None))
+
+ def startGame(self):
+ self.s.talon.dealRow(rows=self.s.rows, frames=0)
+ self.s.talon.dealRow(rows=self.s.rows, flip=0, frames=0)
+ for i in range(2):
+ self.s.talon.dealRow(rows=self.s.rows, frames=0)
+ self.startDealSample()
+ for i in range(2):
+ self.s.talon.dealRow(rows=self.s.rows)
+ self.s.talon.dealCards() # deal first card to WasteStack
+
+ def isGameWon(self):
+ for r in self.s.rows:
+ if len(r.cards) != 1:
+ return False
+ return True
+
+
# ************************************************************************
# * Elevator - Relaxed Golf in a Pyramid layout
# ************************************************************************
@@ -1562,3 +1680,5 @@ registerGame(GameInfo(941, BinaryStar, "Binary Star",
registerGame(GameInfo(959, DoubleUintah, "Double Uintah",
GI.GT_GOLF, 2, UNLIMITED_REDEALS,
GI.SL_MOSTLY_LUCK))
+registerGame(GameInfo(965, KingsWay, "King's Way",
+ GI.GT_GOLF, 2, 1, GI.SL_MOSTLY_LUCK))