From b42a43fb0fea823a7a402804c00bef31e7b91f2a Mon Sep 17 00:00:00 2001 From: Joe R Date: Sun, 11 Feb 2024 21:19:05 -0500 Subject: [PATCH] Added Eighteens game. --- html-src/rules/eighteens.html | 22 ++++++++++ html-src/rules/fifteens.html | 2 +- pysollib/gamedb.py | 2 +- pysollib/games/pyramid.py | 82 ++++++++++++++++++++++++++++++++++- 4 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 html-src/rules/eighteens.html diff --git a/html-src/rules/eighteens.html b/html-src/rules/eighteens.html new file mode 100644 index 0000000000..12cc203320 --- /dev/null +++ b/html-src/rules/eighteens.html @@ -0,0 +1,22 @@ +

Eighteens

+

+Pairing game type. 2 decks. No redeal. + +

Object

+

+Move all cards to the single foundation. + +

Rules

+

+Twelve cards are dealt to the tableau. Cards are removed in groups of four, +consisting of one face card, and three cards of different ranks that total +18 - this is done by moving all four cards to a special reserve pile. Aces +are removed singly. After each set is removed, the empty spaces are filled +from the talon. +

+The game is won if all cards have been discarded. + +

Notes

+

+ +Autodrop is disabled for this game. diff --git a/html-src/rules/fifteens.html b/html-src/rules/fifteens.html index fb46f741af..f3c43047c6 100644 --- a/html-src/rules/fifteens.html +++ b/html-src/rules/fifteens.html @@ -9,7 +9,7 @@

Object

Rules

Sixteen cards are dealt to the tableau. Pairs of cards that are both ranked 9 -ore lower that total fifteen can be moved to the foundation, and the spaces +or lower that total fifteen can be moved to the foundation, and the spaces are filled from the talon. Larger groups of cards that total 15 can also be discarded by moving all of them to a special reserve pile.

diff --git a/pysollib/gamedb.py b/pysollib/gamedb.py index e4f80dc462..0f90d8ed2b 100644 --- a/pysollib/gamedb.py +++ b/pysollib/gamedb.py @@ -594,7 +594,7 @@ def _callback(gi, gt=game_type): ('fc-2.20', tuple(range(855, 897))), ('fc-2.21', tuple(range(897, 900)) + tuple(range(11014, 11017)) + tuple(range(13160, 13163)) + (16682,)), - ('dev', tuple(range(906, 950)) + tuple(range(11017, 11020)) + + ('dev', tuple(range(906, 951)) + tuple(range(11017, 11020)) + tuple(range(5600, 5624)) + tuple(range(18000, 18005)) + tuple(range(22303, 22311)) + tuple(range(22353, 22361))), ) diff --git a/pysollib/games/pyramid.py b/pysollib/games/pyramid.py index e6f9f8fcb5..af7bf49bc0 100644 --- a/pysollib/games/pyramid.py +++ b/pysollib/games/pyramid.py @@ -538,6 +538,7 @@ class Elevens(Pyramid): RowStack_Class = Elevens_RowStack Reserve_Class = Elevens_Reserve + Foundation_Class = AbstractFoundationStack Talon_Class = AutoDealTalonStack Waste_Class = None @@ -562,7 +563,7 @@ def createGame(self, rows=3, cols=3, reserves=3, maxpiles=-1, texts=False): y += layout.YS s.waste = self.Waste_Class(x, y, self) x, y = self.width-layout.XS, self.height-layout.YS - s.foundations.append(AbstractFoundationStack(x, y, self, + s.foundations.append(self.Foundation_Class(x, y, self, suit=ANY_SUIT, max_accept=0, max_move=0, max_cards=52 * self.gameinfo.decks)) layout.createText(s.foundations[0], 'n') @@ -836,6 +837,82 @@ def fillStack(self, stack=None): self.leaveState(old_state) +# ************************************************************************ +# * Eighteens +# ************************************************************************ + +class Eighteens_RowStack(Elevens_RowStack): + + def acceptsCards(self, from_stack, cards): + return False + + def clickHandler(self, event): + game = self.game + if self.cards and self.cards[0].rank == 0: + game.playSample("autodrop", priority=20) + self.playMoveMove(1, game.s.foundations[0], sound=False) + self.fillStack() + return True + + return False + + +class Eighteens_Reserve(ReserveStack): + def acceptsCards(self, from_stack, cards): + for c in self.cards: + if c.rank == cards[0].rank: + return False + return True + + def updateText(self): + if self.game.preview > 1 or self.texts.misc is None: + return + t = '' + if self.cards: + t = 0 + for c in self.cards: + if c.rank < JACK: + t += c.rank + 1 + self.texts.misc.config(text=t) + + +class Eighteens_Foundation(AbstractFoundationStack): + def acceptsCards(self, from_stack, cards): + if not AbstractFoundationStack.acceptsCards(self, from_stack, cards): + return False + # We accept any aces. + return cards[0].rank == 0 + + +class Eighteens(Fifteens): + RowStack_Class = Eighteens_RowStack + Reserve_Class = StackWrapper(Eighteens_Reserve, max_cards=4) + Foundation_Class = StackWrapper(Eighteens_Foundation, max_accept=1) + + def createGame(self): + Elevens.createGame(self, rows=3, cols=4, reserves=1, texts=True) + + def fillStack(self, stack=None): + old_state = self.enterState(self.S_FILL) + reserve = self.s.reserves[0] + if len(reserve.cards) == 0: + for r in self.s.rows: + if not r.cards and self.s.talon.cards: + self.s.talon.flipMove() + self.s.talon.moveMove(1, r) + else: + facecards = 0 + reserve_sum = 0 + for c in reserve.cards: + if c.rank < JACK: + reserve_sum += c.rank + 1 + else: + facecards += 1 + if reserve_sum == 18 and facecards == 1: + self._dropReserve() + self.leaveState(old_state) + + # ************************************************************************ # * Neptune # ************************************************************************ @@ -1733,3 +1810,6 @@ def fillStack(self, stack): altnames=('Acht Karten',))) registerGame(GameInfo(937, TheLuckyNumber, "The Lucky Number", GI.GT_PAIRING_TYPE, 2, 0, GI.SL_LUCK)) +registerGame(GameInfo(950, Eighteens, "Eighteens", + GI.GT_PAIRING_TYPE, 2, 0, GI.SL_MOSTLY_LUCK, + altnames=("Steel Wheels",)))