diff --git a/html-src/rules/relaxedclock.html b/html-src/rules/relaxedclock.html new file mode 100644 index 000000000..c9c77fa7f --- /dev/null +++ b/html-src/rules/relaxedclock.html @@ -0,0 +1,14 @@ +
+One-Deck game type. 1 deck. No redeals. + +
+Move all cards to the correct pile in the tableau, before the fourth +king is revealed, and the extra pile you drew a card from is filled. + +
+Just like Clock, +but once per game, after all four kings have been revealed, you are +allowed to take a face-down card from another pile and continue playing. diff --git a/pysollib/gamedb.py b/pysollib/gamedb.py index 8c49fc2d3..c5667d045 100644 --- a/pysollib/gamedb.py +++ b/pysollib/gamedb.py @@ -575,7 +575,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, 915)) + tuple(range(11017, 11020)) + + ('dev', tuple(range(906, 916)) + tuple(range(11017, 11020)) + tuple(range(22303, 22311)) + tuple(range(22353, 22361))), ) diff --git a/pysollib/games/grandfathersclock.py b/pysollib/games/grandfathersclock.py index e045d3b05..dfbef43f9 100644 --- a/pysollib/games/grandfathersclock.py +++ b/pysollib/games/grandfathersclock.py @@ -25,6 +25,7 @@ from pysollib.gamedb import GI, GameInfo, registerGame from pysollib.hint import CautiousDefaultHint, DefaultHint from pysollib.layout import Layout +from pysollib.mygettext import _ from pysollib.pysoltk import MfxCanvasText from pysollib.stack import \ AC_FoundationStack, \ @@ -488,6 +489,7 @@ def _autoDeal(self, sound=True): # ************************************************************************ # * Clock +# * Relaxed Clock # ************************************************************************ class Clock_RowStack(RK_RowStack): @@ -500,8 +502,25 @@ def _numFaceDown(self): ncards += 1 return ncards + def clickHandler(self, event): + game = self.game + if game.s.rows[12].cards[-1].rank == KING \ + and game.DrawsLeft > 0 and not self.cards[-1].face_up: + old_state = game.enterState(game.S_FILL) + game.flipMove(self) + game.saveStateMove(2 | 16) + game.playSample("move", priority=10) + game.moveMove(1, self, game.s.rows[12]) + game.DrawsLeft -= 1 + game.saveStateMove(1 | 16) + game.leaveState(old_state) + game.finishMove() + else: + return RK_RowStack.clickHandler(self, event) + def acceptsCards(self, from_stack, cards): - return cards[0].rank == self.id + return cards[0].rank == self.id or \ + (self.cards[-1].face_up and self.cards[-1].rank == KING) def moveMove(self, ncards, to_stack, frames=-1, shadow=-1): self._swapPairMove(ncards, to_stack, frames=-1, shadow=0) @@ -512,15 +531,17 @@ def _swapPairMove(self, n, other_stack, frames=-1, shadow=-1): old_state = game.enterState(game.S_FILL) swap = game.s.internals[0] ncards = other_stack._numFaceDown() + for i in range(ncards): game.moveMove(n, other_stack, swap, frames=0) game.moveMove(n, self, other_stack, frames=0) - for i in range(ncards): - game.moveMove(n, swap, other_stack, frames=0) - game.flipMove(other_stack) - game.moveMove(n, other_stack, self) - if is_king: - self._moveKingToBottom() + if ncards > 0: + for i in range(ncards): + game.moveMove(n, swap, other_stack, frames=0) + game.flipMove(other_stack) + game.moveMove(n, other_stack, self) + if is_king: + self._moveKingToBottom() game.leaveState(old_state) def _moveKingToBottom(self): @@ -549,6 +570,9 @@ def _fillStack(self): def canFlipCard(self): return False + def getHelp(self): + return _('Tableau. Build by same rank.') + class Clock(Game): RowStack_Class = Clock_RowStack @@ -556,6 +580,9 @@ class Clock(Game): HAS_WASTE = False + Draws = 0 + DrawsLeft = 0 + def createGame(self): # create layout l, s = Layout(self), self.s @@ -641,6 +668,7 @@ def createGame(self): l.defaultStackGroups() def startGame(self): + self.DrawsLeft = self.Draws for i in range(3): self.s.talon.dealRow(frames=0, flip=False) self.startDealSample() @@ -650,16 +678,49 @@ def startGame(self): def isGameWon(self): for r in self.s.rows: - if not r.cards[-1].face_up: + if len(r.cards) != 4 or not r.cards[-1].face_up: return False return True + def _restoreGameHook(self, game): + if self.Draws > 0: + self.DrawsLeft = game.loadinfo.DrawsLeft + + def _loadGameHook(self, p): + if self.Draws > 0: + self.loadinfo.addattr(DrawsLeft=p.load()) + + def _saveGameHook(self, p): + if self.Draws > 0: + DrawsLeft = self.DrawsLeft + p.dump(DrawsLeft) + + def setState(self, state): + # restore saved vars (from undo/redo) + self.DrawsLeft = state[0] + for s in self.s.foundations: + s.cap.DrawsLeft = state[0] + break + + def getState(self): + # save vars (for undo/redo) + return [self.DrawsLeft] + def getHighlightPilesStacks(self): return () def getAutoStacks(self, event=None): return (), (), () + def getStuck(self): + if self.DrawsLeft > 0: + return True + return Game.getStuck(self) + + +class RelaxedClock(Clock): + Draws = 1 + # ************************************************************************ # * German Clock @@ -715,3 +776,6 @@ def getAutoStacks(self, event=None): registerGame(GameInfo(827, GermanClock, "German Clock", GI.GT_1DECK_TYPE, 1, 1, GI.SL_MOSTLY_LUCK, altnames=("Die Uhr",))) +registerGame(GameInfo(915, RelaxedClock, "Relaxed Clock", + GI.GT_1DECK_TYPE | GI.GT_RELAXED, 1, 0, GI.SL_LUCK, + altnames=("Watch")))