From 082c64597a3d272c1c09b11972e016a8e6d4a91e Mon Sep 17 00:00:00 2001 From: skomoroh Date: Tue, 25 Jul 2006 21:13:43 +0000 Subject: [PATCH] + 6 new games + new tk util `_getHelpText' git-svn-id: file:///home/shlomif/Backup/svn-dumps/PySolFC/svnsync-repos/pysolfc/PySolFC/trunk@27 efabe8c0-fbe8-4139-b769-b5e6d273206e --- pysollib/game.py | 8 +- pysollib/gamedb.py | 10 +- pysollib/games/acesup.py | 43 +++++++- pysollib/games/beleagueredcastle.py | 2 + pysollib/games/calculation.py | 164 +++++++++++++++++++++------- pysollib/games/diplomat.py | 38 ++++++- pysollib/games/golf.py | 62 +++++++++++ pysollib/games/sultan.py | 81 ++++++++++++-- pysollib/stack.py | 16 +-- pysollib/tk/tkutil.py | 10 ++ 10 files changed, 366 insertions(+), 68 deletions(-) diff --git a/pysollib/game.py b/pysollib/game.py index 5368e64f..8f8928b0 100644 --- a/pysollib/game.py +++ b/pysollib/game.py @@ -197,6 +197,9 @@ class Game: # update display properties self.top.wm_geometry("") # cancel user-specified geometry self.canvas.setInitialSize(self.width, self.height) + if self.app.debug >= 2: + MfxCanvasRectangle(self.canvas, 0, 0, self.width, self.height, + width=2, fill=None, outline='green') # restore game geometry if self.app.opt.save_games_geometry: w, h = self.app.opt.games_geometry.get(self.id, (0, 0)) @@ -1025,8 +1028,9 @@ class Game: def setRegion(self, stacks, rect, priority=0): assert len(stacks) > 0 assert len(rect) == 4 and rect[0] < rect[2] and rect[1] < rect[3] - ##MfxCanvasRectangle(self.canvas, rect[0], rect[1], rect[2], rect[3], - ## width=2, fill=None, outline='red') + if self.app.debug >= 2: + MfxCanvasRectangle(self.canvas, rect[0], rect[1], rect[2], rect[3], + width=2, fill=None, outline='red') for s in stacks: assert s and s in self.allstacks # verify that the stack lies within the rectangle diff --git a/pysollib/gamedb.py b/pysollib/gamedb.py index c7ab0167..bde03651 100644 --- a/pysollib/gamedb.py +++ b/pysollib/gamedb.py @@ -244,17 +244,17 @@ class GI: ## 41, 42, 43, 58, 59, 92, 93, 94, 95, 96, ## 100, 105, 111, 112, 113, 130, 200, 201, ##)), - # Gnome AisleRiot 2.2.0 (we have 57 out of 73 games) + # Gnome AisleRiot 2.2.0 (we have 60 out of 70 games) # still missing: - # Clock, Cover, Diamond mine, Gay gordons, Helsinki - # Isabel, Labyrinth (!), Quatorze, Scuffle, Thieves, - # Treize, Valentine, Yeld, ??? + # Clock, Gay gordons, Helsinki, + # Isabel, Labyrinth, Quatorze, Thieves, + # Treize, Valentine, Yeld. ("Gnome AisleRiot", ( 1, 2, 8, 9, 11, 12, 19, 24, 27, 29, 31, 33, 34, 35, 36, 40, 41, 42, 43, 45, 48, 58, 59, 67, 89, 91, 92, 93, 94, 95, 96, 100, 105, 111, 112, 113, 130, 139, 144, 146, 147, 148, 200, 201, 206, 224, 225, 229, 230, 233, 257, 258, 280, 281, 282, - 283, 284, + 283, 284, 551, 552, 553, )), ## KDE Patience 0.7.3 from KDE 1.1.2 (we have 6 out of 9 games) diff --git a/pysollib/games/acesup.py b/pysollib/games/acesup.py index 5c64663a..57435e2f 100644 --- a/pysollib/games/acesup.py +++ b/pysollib/games/acesup.py @@ -42,6 +42,9 @@ from pysollib.game import Game from pysollib.layout import Layout from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint +from montecarlo import MonteCarlo_RowStack + + # /*********************************************************************** # // Aces Up # ************************************************************************/ @@ -69,6 +72,7 @@ class AcesUp_RowStack(BasicRowStack): class AcesUp(Game): + Foundation_Class = AcesUp_Foundation Talon_Class = DealRowTalonStack RowStack_Class = StackWrapper(AcesUp_RowStack, max_accept=1) @@ -92,8 +96,8 @@ class AcesUp(Game): s.rows.append(self.RowStack_Class(x, y, self)) x = x + l.XS x = x + l.XS/2 - stack = AcesUp_Foundation(x, y, self, ANY_SUIT, max_move=0, - dir=0, base_rank=ANY_RANK, max_cards=48) + stack = self.Foundation_Class(x, y, self, suit=ANY_SUIT, max_move=0, + dir=0, base_rank=ANY_RANK, max_cards=48) l.createText(stack, "ss") s.foundations.append(stack) @@ -250,6 +254,39 @@ class AcesUp5(AcesUp): return len(self.s.foundations[0].cards) == 48 +# /*********************************************************************** +# // Cover +# ************************************************************************/ + +class Cover_RowStack(MonteCarlo_RowStack): + def acceptsCards(self, from_stack, cards): + if not OpenStack.acceptsCards(self, from_stack, cards): + return False + return self.cards[-1].suit == cards[0].suit + + +class Cover(AcesUp): + Foundation_Class = StackWrapper(AbstractFoundationStack, max_accept=0) + Talon_Class = TalonStack + RowStack_Class = StackWrapper(Cover_RowStack, max_accept=1) + + FILL_STACKS_AFTER_DROP = 0 # for MonteCarlo_RowStack + + def fillStack(self, stack): + if not self.s.talon.cards: + return + self.startDealSample() + for r in self.s.rows: + if not r.cards: + self.flipMove(self.s.talon) + self.moveMove(1, self.s.talon, r) + self.stopSamples() + + + def isGameWon(self): + return len(self.s.foundations[0].cards) == 48 + + # register the game registerGame(GameInfo(903, AcesUp, "Aces Up", # was: 52 GI.GT_1DECK_TYPE, 1, 0, GI.SL_LUCK, @@ -263,3 +300,5 @@ registerGame(GameInfo(130, PerpetualMotion, "Perpetual Motion", altnames="First Law")) registerGame(GameInfo(353, AcesUp5, "Aces Up 5", GI.GT_1DECK_TYPE, 1, 0, GI.SL_LUCK)) +registerGame(GameInfo(552, Cover, "Cover", + GI.GT_1DECK_TYPE, 1, 0, GI.SL_LUCK)) diff --git a/pysollib/games/beleagueredcastle.py b/pysollib/games/beleagueredcastle.py index 9bb3b2e9..b6b19696 100644 --- a/pysollib/games/beleagueredcastle.py +++ b/pysollib/games/beleagueredcastle.py @@ -109,6 +109,8 @@ class StreetsAndAlleys(Game): s.talon = InitialDealTalonStack(x, y, self) if reserves: l.setRegion(s.rows[:4], (-999, l.YM+l.YS-l.CH/2, x1-l.CW/2, 999999)) + else: + l.setRegion(s.rows[:4], (-999, -999, x1-l.CW/2, 999999)) # default l.defaultAll() diff --git a/pysollib/games/calculation.py b/pysollib/games/calculation.py index 97ec7fd7..0ad14be1 100644 --- a/pysollib/games/calculation.py +++ b/pysollib/games/calculation.py @@ -41,7 +41,7 @@ from pysollib.stack import * from pysollib.game import Game from pysollib.layout import Layout from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint -from pysollib.pysoltk import MfxCanvasText +from pysollib.pysoltk import MfxCanvasText, getTextWidth # /*********************************************************************** # // @@ -68,13 +68,16 @@ class Calculation_Hint(DefaultHint): # ************************************************************************/ class BetsyRoss_Foundation(RK_FoundationStack): - def updateText(self): + def updateText(self, update_empty=True): if self.game.preview > 1: return if self.texts.misc: if len(self.cards) == 0: - rank = self.cap.base_rank - self.texts.misc.config(text=RANKS[rank]) + if update_empty: + rank = self.cap.base_rank + self.texts.misc.config(text=RANKS[rank]) + else: + self.texts.misc.config(text="") elif len(self.cards) == self.cap.max_cards: self.texts.misc.config(text="") else: @@ -107,42 +110,57 @@ class Calculation_RowStack(BasicRowStack): class Calculation(Game): Hint_Class = Calculation_Hint + Foundation_Class = Calculation_Foundation + RowStack_Class = StackWrapper(Calculation_RowStack, max_move=1, max_accept=1) # # game layout # - def createGame(self): - # create layout - l, s = Layout(self, TEXT_HEIGHT=40), self.s - - # set window - # (piles up to 20 cards are playable in default window size) - h = max(2*l.YS, 20*l.YOFFSET) - self.setSize(5.5*l.XS+l.XM+200, l.YM + l.YS + l.TEXT_HEIGHT + h) - - # create stacks - x0 = l.XM + l.XS * 3 / 2 - x, y = x0, l.YM - for i in range(4): - stack = Calculation_Foundation(x, y, self, base_rank=i, mod=13, dir=i+1) - s.foundations.append(stack) - stack.texts.misc = MfxCanvasText(self.canvas, - x + l.CW / 2, y + l.YS, - anchor="n", - font=self.app.getFont("canvas_default")) - x = x + l.XS + def _getHelpText(self): help = (_('''\ 1: 2 3 4 5 6 7 8 9 T J Q K 2: 4 6 8 T Q A 3 5 7 9 J K 3: 6 9 Q 2 5 8 J A 4 7 T K 4: 8 Q 3 7 J 2 6 T A 5 9 K''')) + # calculate text_width + lines = help.split('\n') + lines.sort(lambda a, b: cmp(len(a), len(b))) + max_line = lines[-1] + text_width = getTextWidth(max_line, + font=self.app.getFont("canvas_fixed")) + return help, text_width + + def createGame(self): + + # create layout + l, s = Layout(self, TEXT_HEIGHT=40), self.s + help, text_width = self._getHelpText() + text_width += 2*l.XM + + # set window + w = l.XM+5.5*l.XS+text_width + h = max(2*l.YS, 20*l.YOFFSET) + self.setSize(w, l.YM + l.YS + l.TEXT_HEIGHT + h) + + # create stacks + x0 = l.XM + l.XS * 3 / 2 + x, y = x0, l.YM + for i in range(4): + stack = self.Foundation_Class(x, y, self, + mod=13, dir=i+1, base_rank=i) + s.foundations.append(stack) + tx, ty, ta, tf = l.getTextAttr(stack, "s") + font = self.app.getFont("canvas_default") + stack.texts.misc = MfxCanvasText(self.canvas, tx, ty, + anchor=ta, font=font) + x = x + l.XS self.texts.help = MfxCanvasText(self.canvas, x + l.XM, y + l.CH / 2, text=help, anchor="w", font=self.app.getFont("canvas_fixed")) x = x0 y = l.YM + l.YS + l.TEXT_HEIGHT for i in range(4): - s.rows.append(Calculation_RowStack(x, y, self, max_move=1, max_accept=1)) + s.rows.append(self.RowStack_Class(x, y, self)) x = x + l.XS self.setRegion(s.rows, (-999, y, 999999, 999999)) x = l.XM @@ -205,10 +223,12 @@ class BetsyRoss(Calculation): def createGame(self): # create layout - l, s = Layout(self, TEXT_HEIGHT=40), self.s + l, s = Layout(self), self.s + help, text_width = self._getHelpText() + text_width += 2*l.XM # set window - self.setSize(5.5*l.XS+l.XM+200, l.YM + l.YS + l.TEXT_HEIGHT + 3*l.YS) + self.setSize(5.5*l.XS+l.XM+text_width, l.YM+3*l.YS+l.TEXT_HEIGHT) # create stacks x0 = l.XM + l.XS * 3 / 2 @@ -219,19 +239,17 @@ class BetsyRoss(Calculation): s.foundations.append(stack) x = x + l.XS x = x0 - y = l.YM + l.YS + l.TEXT_HEIGHT + y = l.YM + l.YS for i in range(4): - stack = BetsyRoss_Foundation(x, y, self, base_rank=2*i+1, mod=13, dir=i+1, - max_cards=12, max_move=0) - stack.texts.misc = MfxCanvasText(self.canvas, x + l.CW / 2, y - l.YM, - anchor="s", font=self.app.getFont("canvas_default")) + stack = BetsyRoss_Foundation(x, y, self, base_rank=2*i+1, + mod=13, dir=i+1, + max_cards=12, max_move=0) + tx, ty, ta, tf = l.getTextAttr(stack, "s") + font = self.app.getFont("canvas_default") + stack.texts.misc = MfxCanvasText(self.canvas, tx, ty, + anchor=ta, font=font) s.foundations.append(stack) x = x + l.XS - help = (_('''\ -1: 2 3 4 5 6 7 8 9 T J Q K -2: 4 6 8 T Q A 3 5 7 9 J K -3: 6 9 Q 2 5 8 J A 4 7 T K -4: 8 Q 3 7 J 2 6 T A 5 9 K''')) self.texts.help = MfxCanvasText(self.canvas, x + l.XM, y + l.CH / 2, text=help, anchor="w", font=self.app.getFont("canvas_fixed")) x = l.XM @@ -265,6 +283,76 @@ class BetsyRoss(Calculation): return cards + topcards +# /*********************************************************************** +# // One234 +# ************************************************************************/ + +class One234_Foundation(BetsyRoss_Foundation): + def canMoveCards(self, cards): + if not BetsyRoss_Foundation.canMoveCards(self, cards): + return False + return len(self.cards) > 1 + def updateText(self): + BetsyRoss_Foundation.updateText(self, update_empty=False) + + +class One234_RowStack(BasicRowStack): + ##clickHandler = BasicRowStack.doubleclickHandler + pass + + +class One234(Calculation): + Foundation_Class = One234_Foundation + RowStack_Class = StackWrapper(One234_RowStack, max_move=1, max_accept=0) + + def createGame(self): + # create layout + l, s = Layout(self, TEXT_HEIGHT=40), self.s + help, text_width = self._getHelpText() + text_width += 2*l.XM + + # set window + # (piles up to 20 cards are playable in default window size) + w = l.XM+max(4*l.XS+text_width, 8*l.XS) + h = l.YM+2*l.YS+5*l.YOFFSET+l.TEXT_HEIGHT+l.YS + self.setSize(w, h) + + # create stacks + x, y = l.XM, l.YM + for i in range(4): + stack = self.Foundation_Class(x, y, self, + mod=13, dir=i+1, base_rank=i) + s.foundations.append(stack) + tx, ty, ta, tf = l.getTextAttr(stack, "s") + font = self.app.getFont("canvas_default") + stack.texts.misc = MfxCanvasText(self.canvas, tx, ty, + anchor=ta, font=font) + x = x + l.XS + self.texts.help = MfxCanvasText(self.canvas, x + l.XM, y + l.CH / 2, text=help, + anchor="w", font=self.app.getFont("canvas_fixed")) + x, y = l.XM, l.YM+l.YS+l.TEXT_HEIGHT + for i in range(8): + s.rows.append(self.RowStack_Class(x, y, self)) + x = x + l.XS + + s.talon = InitialDealTalonStack(l.XM, self.height-l.YS, self) + + # define stack-groups + l.defaultStackGroups() + + def _shuffleHook(self, cards): + return cards + + def startGame(self): + for i in range(4): + self.s.talon.dealRow(frames=0) + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.dealRow() + self.s.talon.dealRow(rows=self.s.foundations) + + + # register the game registerGame(GameInfo(256, Calculation, "Calculation", GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_SKILL, @@ -275,4 +363,6 @@ registerGame(GameInfo(134, BetsyRoss, "Betsy Ross", GI.GT_1DECK_TYPE, 1, 2, GI.SL_MOSTLY_LUCK, altnames=("Fairest", "Four Kings", "Musical Patience", "Quadruple Alliance", "Plus Belle") )) +registerGame(GameInfo(550, One234, "One234", + GI.GT_1DECK_TYPE | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL)) diff --git a/pysollib/games/diplomat.py b/pysollib/games/diplomat.py index 8a3c7922..a5606425 100644 --- a/pysollib/games/diplomat.py +++ b/pysollib/games/diplomat.py @@ -125,12 +125,15 @@ class LadyPalk(Diplomat): # /*********************************************************************** # // Congress +# // Parliament # ************************************************************************/ class Congress(Diplomat): DEAL = (0, 1) FILL_EMPTY_ROWS = 1 + Foundation_Classes = [SS_FoundationStack, SS_FoundationStack] + # # game layout (just rearrange the stacks a little bit) # @@ -143,10 +146,13 @@ class Congress(Diplomat): self.setSize(l.XM + 7*l.XS, l.YM + 4*l.YS) # create stacks - for i in range(4): - for j in range(2): - x, y = l.XM + (4+j)*l.XS, l.YM + i*l.YS - s.foundations.append(self.Foundation_Class(x, y, self, suit=i)) + x = l.XM+4*l.XS + for fnd_cls in self.Foundation_Classes: + y = l.YM + for i in range(4): + s.foundations.append(fnd_cls(x, y, self, suit=i)) + y += l.YS + x += l.XS for i in range(4): for j in range(2): x, y = l.XM + (3+3*j)*l.XS, l.YM + i*l.YS @@ -164,6 +170,26 @@ class Congress(Diplomat): l.defaultStackGroups() +class Parliament(Congress): + + def _shuffleHook(self, cards): + # move Aces to top of the Talon (i.e. first cards to be dealt) + return self._shuffleHookMoveToTop(cards, + lambda c: (c.rank == ACE, (c.deck, c.suit))) + + def startGame(self): + self.s.talon.dealRow(rows=self.s.foundations, frames=0) + Congress.startGame(self) + + +class Wheatsheaf(Congress): + Foundation_Classes = [ + SS_FoundationStack, + StackWrapper(SS_FoundationStack, base_rank=KING, dir=-1), + ] + RowStack_Class = UD_SS_RowStack + + # /*********************************************************************** # // Rows of Four # ************************************************************************/ @@ -238,4 +264,8 @@ registerGame(GameInfo(485, Dieppe, "Dieppe", GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_SKILL)) registerGame(GameInfo(489, LittleNapoleon, "Little Napoleon", GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED)) +registerGame(GameInfo(548, Parliament, "Parliament", + GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED)) +registerGame(GameInfo(549, Wheatsheaf, "Wheatsheaf", + GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED)) diff --git a/pysollib/games/golf.py b/pysollib/games/golf.py index cd1f3432..b946c836 100644 --- a/pysollib/games/golf.py +++ b/pysollib/games/golf.py @@ -611,6 +611,65 @@ class Robert(Game): self.s.talon.dealCards() +# /*********************************************************************** +# // Diamond Mine +# ************************************************************************/ + +DIAMOND = 3 + +class DiamondMine_Foundation(AbstractFoundationStack): + pass + +class DiamondMine_RowStack(RK_RowStack): + def acceptsCards(self, from_stack, cards): + if not RK_RowStack.acceptsCards(self, from_stack, cards): + return False + if cards[0].suit == DIAMOND: + return False + if self.cards: + return self.cards[-1].suit != DIAMOND + return True + + +class DiamondMine(Game): + + def createGame(self): + l, s = Layout(self), self.s + self.setSize(l.XM+13*l.XS, l.YM+2*l.YS+15*l.YOFFSET) + + x, y = l.XM+6*l.XS, l.YM + s.foundations.append(SS_FoundationStack(x, y, self, + base_rank=ANY_RANK, suit=DIAMOND, mod=13)) + x, y = l.XM, l.YM+l.YS + for i in range(13): + s.rows.append(DiamondMine_RowStack(x, y, self)) + x += l.XS + s.talon = InitialDealTalonStack(l.XM, self.height-l.YS, self) + + l.defaultAll() + + def startGame(self): + for i in range(3): + self.s.talon.dealRow(flip=0, frames=0) + self.startDealSample() + self.s.talon.dealRow() + + def isGameWon(self): + if len(self.s.foundations[0].cards) != 13: + return False + for s in self.s.rows: + if len(s.cards) == 0: + continue + if len(s.cards) != 13: + return False + if not isSameSuitSequence(s.cards): + return False + return True + + def shallHighlightMatch(self, stack1, card1, stack2, card2): + return abs(card1.rank-card2.rank) == 1 + + # register the game registerGame(GameInfo(36, Golf, "Golf", GI.GT_GOLF, 1, 0, GI.SL_BALANCED)) @@ -633,3 +692,6 @@ registerGame(GameInfo(405, AllInARow, "All in a Row", GI.GT_GOLF | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL)) registerGame(GameInfo(432, Robert, "Robert", GI.GT_GOLF, 1, 2, GI.SL_LUCK)) +registerGame(GameInfo(551, DiamondMine, "Diamond Mine", + GI.GT_1DECK_TYPE, 1, 0, GI.SL_BALANCED)) + diff --git a/pysollib/games/sultan.py b/pysollib/games/sultan.py index c295865f..40cdc204 100644 --- a/pysollib/games/sultan.py +++ b/pysollib/games/sultan.py @@ -128,10 +128,10 @@ class Boudoir(Game): x, y = l.XM, l.YM+l.YS-l.TEXT_HEIGHT/2 s.talon = WasteTalonStack(x, y, self, max_rounds=3) - s.talon.texts.rounds = MfxCanvasText(self.canvas, - x + l.CW / 2, y - l.YM, - anchor="s", - font=self.app.getFont("canvas_default")) + tx, ty, ta, tf = l.getTextAttr(s.talon, "nn") + font=self.app.getFont("canvas_default") + s.talon.texts.rounds = MfxCanvasText(self.canvas, tx, ty, + anchor=ta, font=font) l.createText(s.talon, "s") y += l.YS+l.TEXT_HEIGHT s.waste = WasteStack(x, y, self) @@ -192,11 +192,11 @@ class CaptiveQueens(Game): x, y = l.XM, l.YM+l.TEXT_HEIGHT s.talon = WasteTalonStack(x, y, self, max_rounds=3) - s.talon.texts.rounds = MfxCanvasText(self.canvas, - x + l.CW / 2, y - l.YM, - anchor="s", - font=self.app.getFont("canvas_default")) l.createText(s.talon, "s") + tx, ty, ta, tf = l.getTextAttr(s.talon, "nn") + font = self.app.getFont("canvas_default") + s.talon.texts.rounds = MfxCanvasText(self.canvas, tx, ty, + anchor=ta, font=font) y += l.YS+l.TEXT_HEIGHT s.waste = WasteStack(x, y, self) l.createText(s.waste, "s") @@ -449,9 +449,9 @@ class Matrimony(Game): s.talon = Matrimony_Talon(l.XM, l.YM, self, max_rounds=17) l.createText(s.talon, 'se') tx, ty, ta, tf = l.getTextAttr(s.talon, "ne") + font = self.app.getFont("canvas_default") s.talon.texts.rounds = MfxCanvasText(self.canvas, tx, ty, - anchor=ta, - font=self.app.getFont("canvas_default")) + anchor=ta, font=font) x, y = l.XM+2*l.XS, l.YM for i in range(4): @@ -730,6 +730,65 @@ class CornerSuite(Game): return abs(card1.rank-card2.rank) == 1 +# /*********************************************************************** +# // Scuffle +# ************************************************************************/ + +class Scuffle_Talon(RedealTalonStack): + + def canDealCards(self): + if self.round == self.max_rounds: + return len(self.cards) != 0 + return not self.game.isGameWon() + + def dealCards(self, sound=0): + if self.cards: + return self.dealRowAvail(sound=sound) + RedealTalonStack.redealCards(self, shuffle=True, sound=sound) + return self.dealRowAvail(sound=sound) + + +class Scuffle_RowStack(BasicRowStack): + ##clickHandler = BasicRowStack.doubleclickHandler + pass + + +class Scuffle(Game): + + def createGame(self): + + l, s = Layout(self), self.s + self.setSize(l.XM+6*l.XS, l.YM+2*l.YS) + + s.talon = Scuffle_Talon(l.XM, l.YM+l.YS/2, self, max_rounds=3) + l.createText(s.talon, 's') + tx, ty, ta, tf = l.getTextAttr(s.talon, 'nn') + font = self.app.getFont('canvas_default') + s.talon.texts.rounds = MfxCanvasText(self.canvas, tx, ty, + anchor=ta, font=font) + + x, y = l.XM+2*l.XS, l.YM + for i in range(4): + s.foundations.append(RK_FoundationStack(x, y, self)) + x += l.XS + x, y = l.XM+2*l.XS, l.YM+l.YS + for i in range(4): + stack = Scuffle_RowStack(x, y, self, max_move=1) + s.rows.append(stack) + stack.CARD_XOFFSET, stack.CARD_YOFFSET = 0, 0 + x += l.XS + + l.defaultStackGroups() + + def _shuffleHook(self, cards): + return self._shuffleHookMoveToTop(cards, + lambda c: (c.rank == ACE, c.suit)) + + def startGame(self): + self.startDealSample() + self.s.talon.dealRow(rows=self.s.foundations) + self.s.talon.dealRow() + # register the game registerGame(GameInfo(330, Sultan, "Sultan", @@ -759,3 +818,5 @@ registerGame(GameInfo(438, SixesAndSevens, "Sixes and Sevens", GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_LUCK)) registerGame(GameInfo(477, CornerSuite, "Corner Suite", GI.GT_2DECK_TYPE, 1, 0, GI.SL_MOSTLY_LUCK)) +registerGame(GameInfo(553, Scuffle, "Scuffle", + GI.GT_1DECK_TYPE, 1, 2, GI.SL_MOSTLY_LUCK)) diff --git a/pysollib/stack.py b/pysollib/stack.py index f7145e42..abaf86c2 100644 --- a/pysollib/stack.py +++ b/pysollib/stack.py @@ -102,8 +102,8 @@ from pysoltk import bind, unbind_destroy from pysoltk import after, after_idle, after_cancel from pysoltk import MfxCanvasGroup, MfxCanvasImage, MfxCanvasRectangle, MfxCanvasText from pysoltk import Card +from pysoltk import getTextWidth -from tkFont import Font # /*********************************************************************** # // Let's start with some test methods for cards. @@ -1398,14 +1398,16 @@ class DealBaseCard_StackMethods: class RedealCards_StackMethods: - def redealCards(self, sound=0, shuffle=False, reverse=False, frames=4): + def redealCards(self, rows=None, sound=0, shuffle=False, reverse=False, frames=4): if sound and self.game.app.opt.animations: self.game.startDealSample() lr = len(self.game.s.rows) # move all cards to the Talon num_cards = 0 assert len(self.cards) == 0 - rows = list(self.game.s.rows)[:] + if rows is None: + rows = self.game.s.rows + rows = list(rows) if reverse: rows.reverse() for r in rows: @@ -1525,7 +1527,7 @@ class TalonStack(Stack, else: ca = None font = self.game.app.getFont("canvas_default") - text_width = Font(self.game.canvas, font).measure(_('Redeal')) + text_width = getTextWidth(_('Redeal'), font=font, root=self.game.canvas) if images.CARDW >= text_width+4 and ca: # add a redeal text above the bottom image if self.max_rounds != 1: @@ -2212,6 +2214,8 @@ class ArbitraryStack(OpenStack): def startDrag(self, event, sound=1): OpenStack.startDrag(self, event, sound=sound) + for c in self.cards[self.game.drag.index+1:]: + c.moveBy(0, -self.CARD_YOFFSET[0]) def doubleclickHandler(self, event): # flip or drop a card @@ -2231,10 +2235,6 @@ class ArbitraryStack(OpenStack): return 1 return 0 -## def moveMove(self, ncards, to_stack, frames=-1, shadow=-1): -## i = len(self.cards)-1 -## self.singleCardMove(i, to_stack, frames=frames, shadow=shadow) - def moveCardsBackHandler(self, event, drag): i = self.cards.index(drag.cards[0]) for card in self.cards[i:]: diff --git a/pysollib/tk/tkutil.py b/pysollib/tk/tkutil.py index 234b93c6..e26d8730 100644 --- a/pysollib/tk/tkutil.py +++ b/pysollib/tk/tkutil.py @@ -51,11 +51,13 @@ __all__ = ['wm_withdraw', 'loadImage', #'fillImage', 'createImage', + 'getTextWidth', ] # imports import sys, os, re import Tkinter +from tkFont import Font try: # PIL import Image @@ -398,3 +400,11 @@ def createImage(width, height, fill, outline=None): fillImage(image, fill, outline) return image + +# /*********************************************************************** +# // font utils +# ************************************************************************/ + +def getTextWidth(text, font, root=None): + return Font(root=root, font=font).measure(text) +