From 556a82c3673de371049edb527224b420ddfea346 Mon Sep 17 00:00:00 2001 From: skomoroh Date: Fri, 28 Jul 2006 21:12:37 +0000 Subject: [PATCH] + 11 new games * improved StackDesc * improved CautiousDefaultHint git-svn-id: https://pysolfc.svn.sourceforge.net/svnroot/pysolfc/PySolFC/trunk@30 39dd0a4e-7c14-0410-91b3-c4f2d318f732 --- pysollib/game.py | 2 + pysollib/games/auldlangsyne.py | 75 ++++++++++++++++-- pysollib/games/fortythieves.py | 131 ++++++++++++++++++++++++++++++- pysollib/games/gypsy.py | 18 ++++- pysollib/games/klondike.py | 27 ++++++- pysollib/games/montana.py | 12 ++- pysollib/games/royalcotillion.py | 59 ++++++++++++++ pysollib/games/spider.py | 59 ++++++++++++++ pysollib/games/sultan.py | 6 +- pysollib/games/yukon.py | 3 +- pysollib/hint.py | 6 ++ pysollib/stack.py | 8 +- pysollib/tk/tkcanvas.py | 3 +- pysollib/tk/tkwidget.py | 18 +++-- 14 files changed, 397 insertions(+), 30 deletions(-) diff --git a/pysollib/game.py b/pysollib/game.py index a36c093f..677c1655 100644 --- a/pysollib/game.py +++ b/pysollib/game.py @@ -1253,11 +1253,13 @@ for %d moves. strings=(_("&New game"), None, _("&Cancel")), image=self.app.gimages.logos[4], separatorwidth=2) elif self.gstats.updated < 0: + self.finished = True self.playSample("gamefinished", priority=1000) d = MfxMessageDialog(self.top, title=_("Game finished"), bitmap="info", text=_("\nGame finished\n"), strings=(_("&New game"), None, _("&Cancel"))) else: + self.finished = True self.playSample("gamelost", priority=1000) d = MfxMessageDialog(self.top, title=_("Game finished"), bitmap="info", text=_("\nGame finished, but not without my help...\n"), diff --git a/pysollib/games/auldlangsyne.py b/pysollib/games/auldlangsyne.py index 6e9a7164..c4f3a3b9 100644 --- a/pysollib/games/auldlangsyne.py +++ b/pysollib/games/auldlangsyne.py @@ -213,16 +213,19 @@ class Interregnum_Foundation(RK_FoundationStack): class Interregnum(Game): GAME_VERSION = 2 + Talon_Class = DealRowTalonStack + RowStack_Class = StackWrapper(BasicRowStack, max_accept=0, max_move=1) + # # game layout # - def createGame(self, rows=8): + def createGame(self, rows=8, playcards=12, texts=False): # create layout l, s = Layout(self), self.s # set window - self.setSize(l.XM + max(9,rows)*l.XS, l.YM + 5*l.YS) + self.setSize(l.XM+max(9,rows)*l.XS, l.YM+3*l.YS+playcards*l.YOFFSET) # extra settings self.base_cards = None @@ -236,9 +239,15 @@ class Interregnum(Game): s.foundations.append(Interregnum_Foundation(x, y, self, mod=13, max_move=0)) for i in range(rows): x, y, = l.XM + (2*i+8-rows)*l.XS/2, l.YM + 2*l.YS - s.rows.append(BasicRowStack(x, y, self, max_accept=0, max_move=1)) - s.talon = DealRowTalonStack(self.width-l.XS, self.height-l.YS, self) - l.createText(s.talon, "nn") + s.rows.append(self.RowStack_Class(x, y, self)) + s.talon = self.Talon_Class(self.width-l.XS, self.height-l.YS, self) + if texts: + 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) + else: + l.createText(s.talon, "nn") # define stack-groups l.defaultStackGroups() @@ -249,6 +258,7 @@ class Interregnum(Game): def startGame(self): self.startDealSample() + self.s.talon.dealRow() # deal base_cards to reserves, update foundations cap.base_rank self.base_cards = [] for i in range(8): @@ -256,8 +266,6 @@ class Interregnum(Game): self.s.foundations[i].cap.base_rank = (self.base_cards[i].rank + 1) % 13 self.flipMove(self.s.talon) self.moveMove(1, self.s.talon, self.s.reserves[i]) - # deal other cards - self.s.talon.dealRow() def getAutoStacks(self, event=None): return ((), (), self.sg.dropstacks) @@ -282,6 +290,57 @@ class Interregnum(Game): for c in self.base_cards: p.dump(c.id) + +# /*********************************************************************** +# // Primrose +# ************************************************************************/ + +class Primrose_Talon(DealRowTalonStack): + + def canDealCards(self): + if self.round == self.max_rounds and not self.cards: + return False + return not self.game.isGameWon() + + def _redeal(self): + lr = len(self.game.s.rows) + rows = self.game.s.rows + r = self.game.s.rows[self.round-1] + for i in range(len(r.cards)): + self.game.moveMove(1, r, self, frames=4) + self.game.flipMove(self) + self.game.nextRoundMove(self) + + def dealCards(self, sound=0): + if sound: + self.game.startDealSample() + if len(self.cards) == 0: + self._redeal() + if self.round == 1: + n = self.dealRowAvail(sound=0) + else: + rows = self.game.s.rows + n = self.dealRowAvail(rows=rows[self.round-2:], sound=0) + #n = 0 + while self.cards: + n += self.dealRowAvail(rows=rows, sound=0) + if sound: + self.game.stopSamples() + return n + + +class Primrose(Interregnum): + Talon_Class = StackWrapper(Primrose_Talon, max_rounds=9) + + def createGame(self): + Interregnum.createGame(self, playcards=16, texts=True) + + def startGame(self): + for i in range(11): + self.s.talon.dealRow(frames=0) + Interregnum.startGame(self) + + # /*********************************************************************** # // Colorado # ************************************************************************/ @@ -479,4 +538,6 @@ registerGame(GameInfo(553, Scuffle, "Scuffle", GI.GT_NUMERICA, 1, 2, GI.SL_MOSTLY_LUCK)) registerGame(GameInfo(560, DoubleAcquaintance, "Double Acquaintance", GI.GT_NUMERICA, 2, 2, GI.SL_BALANCED)) +registerGame(GameInfo(569, Primrose, "Primrose", + GI.GT_NUMERICA, 2, 8, GI.SL_BALANCED)) diff --git a/pysollib/games/fortythieves.py b/pysollib/games/fortythieves.py index 44e5ba4c..98990c50 100644 --- a/pysollib/games/fortythieves.py +++ b/pysollib/games/fortythieves.py @@ -353,7 +353,8 @@ class Streets(FortyThieves): def shallHighlightMatch(self, stack1, card1, stack2, card2): return (card1.color != card2.color and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + (card1.rank + 1 == card2.rank or + card2.rank + 1 == card1.rank)) class Maria(Streets): @@ -929,8 +930,120 @@ class TheSpark(Game): return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 +# /*********************************************************************** +# // Double Gold Mine +# ************************************************************************/ + +class DoubleGoldMine_RowStack(AC_RowStack): + def getBottomImage(self): + return self.game.app.images.getReserveBottom() + +class DoubleGoldMine(Streets): + + RowStack_Class = DoubleGoldMine_RowStack + + ROW_MAX_MOVE = UNLIMITED_MOVES + + def createGame(self): + Streets.createGame(self, rows=9, num_deal=3) + + def startGame(self): + self.startDealSample() + self.s.talon.dealCards() +# /*********************************************************************** +# // Interchange +# // Unlimited +# // Breakwater +# // Forty Nine +# ************************************************************************/ + +class Interchange(FortyThieves): + + RowStack_Class = StackWrapper(SS_RowStack, base_rank=KING) + + ROW_MAX_MOVE = UNLIMITED_MOVES + + def createGame(self): + FortyThieves.createGame(self, rows=7) + + def startGame(self): + for i in (0,1,2): + self.s.talon.dealRow(frames=0) + self.s.talon.dealRow(flip=0, frames=0) + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.dealCards() + + +class Unlimited(Interchange): + def createGame(self): + FortyThieves.createGame(self, rows=7, max_rounds=UNLIMITED_REDEALS) + + +class Breakwater(Interchange): + RowStack_Class = RK_RowStack + def shallHighlightMatch(self, stack1, card1, stack2, card2): + return abs(card1.rank-card2.rank) == 1 + + +class FortyNine_RowStack(AC_RowStack): + def acceptsCards(self, from_stack, cards): + if not AC_RowStack.acceptsCards(self, from_stack, cards): + return False + if self.cards: + return len(cards) == 1 + return True + + +class FortyNine(Interchange): + RowStack_Class = FortyNine_RowStack + + def startGame(self): + for i in range(6): + self.s.talon.dealRow(frames=0) + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.dealCards() + + def shallHighlightMatch(self, stack1, card1, stack2, card2): + return card1.color != card2.color and abs(card1.rank-card2.rank) == 1 + + +# /*********************************************************************** +# // Indian Patience +# ************************************************************************/ + +class IndianPatience_RowStack(Indian_RowStack): + def acceptsCards(self, from_stack, cards): + if not Indian_RowStack.acceptsCards(self, from_stack, cards): + return False + if not self.game.s.talon.cards: + return True + if self.cards: + if from_stack in self.game.s.rows and len(from_stack.cards) == 1: + return False + return len(self.cards) != 1 + return True + +class IndianPatience(Indian): + RowStack_Class = IndianPatience_RowStack + + def fillStack(self, stack): + if stack in self.s.rows and not stack.cards: + old_state = self.enterState(self.S_FILL) + if self.s.talon.cards: + if len(self.s.talon.cards) == 1: + self.s.talon.flipMove() + self.s.talon.moveMove(1, stack) + if self.s.talon.cards: + self.s.talon.flipMove() + self.s.talon.moveMove(1, stack) + if self.s.talon.cards: + self.s.talon.flipMove() + self.s.talon.moveMove(1, stack) + self.leaveState(old_state) # register the game @@ -975,8 +1088,7 @@ registerGame(GameInfo(126, RedAndBlack, "Red and Black", # was: 75 registerGame(GameInfo(113, Zebra, "Zebra", GI.GT_FORTY_THIEVES, 2, 1, GI.SL_BALANCED)) registerGame(GameInfo(69, Indian, "Indian", - GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED, - altnames=("Indian Patience",) )) + GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED)) registerGame(GameInfo(74, Midshipman, "Midshipman", GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED)) registerGame(GameInfo(198, NapoleonsExile, "Napoleon's Exile", @@ -1026,5 +1138,16 @@ registerGame(GameInfo(556, Junction, "Junction", ranks=(0, 6, 7, 8, 9, 10, 11, 12) )) registerGame(GameInfo(564, TheSpark, "The Spark", GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_LUCK)) - +registerGame(GameInfo(573, DoubleGoldMine, "Double Gold Mine", + GI.GT_NUMERICA | GI.GT_ORIGINAL, 2, 0, GI.SL_MOSTLY_SKILL)) +registerGame(GameInfo(574, Interchange, "Interchange", + GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_SKILL)) +registerGame(GameInfo(575, Unlimited, "Unlimited", + GI.GT_FORTY_THIEVES, 2, -1, GI.SL_MOSTLY_SKILL)) +registerGame(GameInfo(576, Breakwater, "Breakwater", + GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_SKILL)) +registerGame(GameInfo(577, FortyNine, "Forty Nine", + GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_SKILL)) +registerGame(GameInfo(578, IndianPatience, "Indian Patience", + GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_SKILL)) diff --git a/pysollib/games/gypsy.py b/pysollib/games/gypsy.py index 58cc2ccc..ffd27a02 100644 --- a/pysollib/games/gypsy.py +++ b/pysollib/games/gypsy.py @@ -576,12 +576,25 @@ class EternalTriangle(Hypotenuse): class RightTriangle_Talon(OpenStack, DealRowTalonStack): def __init__(self, x, y, game, max_rounds=1, num_deal=1, **cap): + kwdefault(cap, max_move=1, max_accept=1, max_cards=999999) Stack.__init__(self, x, y, game, cap=cap) self.max_rounds = max_rounds self.num_deal = num_deal self.round = 1 self.base_cards = [] # for DealBaseCard_StackMethods + def clickHandler(self, event): + if self.cards and not self.cards[-1].face_up: + return self.game.dealCards(sound=1) + return OpenStack.clickHandler(self, event) + + def canDealCards(self): + if not DealRowTalonStack.canDealCards(self): + return False + if self.cards and self.cards[-1].face_up: + return False + return True + def canFlipCard(self): return False @@ -589,10 +602,11 @@ class RightTriangle_Talon(OpenStack, DealRowTalonStack): return self.game.app.images.getReserveBottom() def getHelp(self): - return '' + return DealRowTalonStack.getHelp(self) + class RightTriangle(Hypotenuse): - Talon_Class = StackWrapper(RightTriangle_Talon, max_accept=1, max_move=1) + Talon_Class = RightTriangle_Talon def createGame(self): Gypsy.createGame(self, rows=10, playcards=24) diff --git a/pysollib/games/klondike.py b/pysollib/games/klondike.py index 518a9e8e..80d30da6 100644 --- a/pysollib/games/klondike.py +++ b/pysollib/games/klondike.py @@ -45,6 +45,8 @@ from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import KlondikeType_Hint from pysollib.pysoltk import MfxCanvasText +from canfield import CanfieldRush_Talon + # /*********************************************************************** # // Klondike @@ -1116,14 +1118,31 @@ class Boost(Klondike): # // Gold Rush # ************************************************************************/ -from canfield import CanfieldRush_Talon - class GoldRush(Klondike): Talon_Class = CanfieldRush_Talon def createGame(self): Klondike.createGame(self, max_rounds=3) +# /*********************************************************************** +# // Gold Mine +# ************************************************************************/ + +class GoldMine_RowStack(AC_RowStack): + def getBottomImage(self): + return self.game.app.images.getReserveBottom() + + +class GoldMine(Klondike): + RowStack_Class = GoldMine_RowStack + + def createGame(self): + Klondike.createGame(self, max_rounds=1, num_deal=3) + + def startGame(self): + self.startDealSample() + self.s.talon.dealCards() + # register the game registerGame(GameInfo(2, Klondike, "Klondike", @@ -1231,7 +1250,7 @@ registerGame(GameInfo(479, Saratoga, "Saratoga", registerGame(GameInfo(491, Whitehorse, "Whitehorse", GI.GT_KLONDIKE, 1, -1, GI.SL_BALANCED)) registerGame(GameInfo(518, Boost, "Boost", - GI.GT_KLONDIKE, 1, 2, GI.SL_BALANCED)) + GI.GT_KLONDIKE | GI.GT_ORIGINAL, 1, 2, GI.SL_BALANCED)) registerGame(GameInfo(522, ArticGarden, "Artic Garden", GI.GT_RAGLAN, 1, 0, GI.SL_MOSTLY_SKILL)) registerGame(GameInfo(532, GoldRush, "Gold Rush", @@ -1240,4 +1259,6 @@ registerGame(GameInfo(539, Usk, "Usk", GI.GT_KLONDIKE, 1, 1, GI.SL_BALANCED)) registerGame(GameInfo(541, BatsfordAgain, "Batsford Again", GI.GT_KLONDIKE, 2, 1, GI.SL_BALANCED)) +registerGame(GameInfo(572, GoldMine, "Gold Mine", + GI.GT_NUMERICA, 1, 0, GI.SL_MOSTLY_SKILL)) diff --git a/pysollib/games/montana.py b/pysollib/games/montana.py index 1011b931..6f35d3be 100644 --- a/pysollib/games/montana.py +++ b/pysollib/games/montana.py @@ -305,8 +305,16 @@ class RedMoon(BlueMoon): class Galary_Hint(Montana_Hint): - # TODO - shallMovePile = DefaultHint._cautiousShallMovePile + def shallMovePile(self, from_stack, to_stack, pile, rpile): + if from_stack is to_stack or not to_stack.acceptsCards(from_stack, pile): + return 0 + # now check for loops + rr = self.ClonedStack(from_stack, stackcards=rpile) + if rr.acceptsCards(to_stack, pile): + # the pile we are going to move could be moved back - + # this is dangerous as we can create endless loops... + return 0 + return 1 class Galary_RowStack(Montana_RowStack): diff --git a/pysollib/games/royalcotillion.py b/pysollib/games/royalcotillion.py index 8261a448..728ebb28 100644 --- a/pysollib/games/royalcotillion.py +++ b/pysollib/games/royalcotillion.py @@ -529,6 +529,63 @@ class Twenty(Game): self.leaveState(old_state) +# /*********************************************************************** +# // Three Pirates +# ************************************************************************/ + +class ThreePirates_Talon(DealRowTalonStack): + def dealCards(self, sound=0): + num_cards = 0 + old_state = self.game.enterState(self.game.S_DEAL) + if self.cards: + if sound and not self.game.demo: + self.game.playSample("dealwaste") + num_cards = self.dealRowAvail(rows=self.game.s.reserves, + sound=0, frames=4) + self.game.leaveState(old_state) + return num_cards + + +class ThreePirates(Game): + + def createGame(self): + l, s = Layout(self), self.s + + self.setSize(l.XM+10*l.XS, l.YM+3*l.YS+16*l.YOFFSET) + + x, y, = l.XM+l.XS, l.YM + for i in range(8): + s.foundations.append(SS_FoundationStack(x, y, self, suit=i/2)) + x = x + l.XS + + x, y, = l.XM, l.YM+l.YS + for i in range(10): + s.rows.append(SS_RowStack(x, y, self, max_move=1)) + x += l.XS + + x, y = l.XM, self.height-l.YS + s.talon = ThreePirates_Talon(x, y, self) + l.createText(s.talon, 'n') + x += l.XS + for i in (0,1,2): + stack = WasteStack(x, y, self) + s.reserves.append(stack) + l.createText(stack, 'n') + x += l.XS + + l.defaultStackGroups() + + def startGame(self): + for i in (0,1,2): + self.s.talon.dealRow(frames=0) + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.dealCards() + + def shallHighlightMatch(self, stack1, card1, stack2, card2): + return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + + # register the game registerGame(GameInfo(54, RoyalCotillion, "Royal Cotillion", @@ -553,4 +610,6 @@ registerGame(GameInfo(443, Twenty, "Twenty", GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED)) registerGame(GameInfo(465, Granada, "Granada", GI.GT_2DECK_TYPE, 2, 2, GI.SL_BALANCED)) +registerGame(GameInfo(579, ThreePirates, "Three Pirates", + GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_SKILL)) diff --git a/pysollib/games/spider.py b/pysollib/games/spider.py index a02a15a3..0ec48a5c 100644 --- a/pysollib/games/spider.py +++ b/pysollib/games/spider.py @@ -1020,6 +1020,61 @@ class FredsSpider3Decks(FredsSpider): Spidike.createGame(self, rows=13, playcards=26) +# /*********************************************************************** +# // Long Tail +# // Short Tail +# ************************************************************************/ + +class LongTail(RelaxedSpider): + + def createGame(self, rows=5, playcards=16): + l, s = Layout(self), self.s + + decks = self.gameinfo.decks + max_rows = max(2+decks*4, 2+rows) + w, h = l.XM+max_rows*l.XS, l.YM+l.YS+playcards*l.YOFFSET + self.setSize(w, h) + + x, y = l.XM, l.YM + s.talon = DealRowTalonStack(x, y, self) + l.createText(s.talon, 'ne') + + x += (max_rows-decks*4)*l.XS + for i in range(decks*4): + s.foundations.append(Spider_SS_Foundation(x, y, self)) + x += l.XS + + x, y = l.XM, l.YM+l.YS + stack = ReserveStack(x, y, self, max_cards=UNLIMITED_CARDS) + stack.CARD_XOFFSET, stack.CARD_YOFFSET = 0, l.YOFFSET + s.reserves.append(stack) + l.createText(stack, 'ne') + + x += 2*l.XS + for i in range(rows): + s.rows.append(Spider_RowStack(x, y, self)) + x += l.XS + + l.defaultStackGroups() + + + def startGame(self): + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.dealRow(rows=self.s.reserves*2) + + + def getQuickPlayScore(self, ncards, from_stack, to_stack): + if to_stack in self.s.reserves: + return 0 + return 1+RelaxedSpider.getQuickPlayScore(self, ncards, from_stack, to_stack) + + +class ShortTail(LongTail): + def createGame(self): + LongTail.createGame(self, rows=8, playcards=24) + + # register the game registerGame(GameInfo(10, RelaxedSpider, "Relaxed Spider", GI.GT_SPIDER | GI.GT_RELAXED, 2, 0, GI.SL_MOSTLY_SKILL)) @@ -1124,4 +1179,8 @@ registerGame(GameInfo(543, FarmersWife, "Farmer's Wife", GI.GT_SPIDER, 1, 0, GI.SL_MOSTLY_SKILL)) registerGame(GameInfo(544, HowTheyRun, "How They Run", GI.GT_SPIDER, 1, 0, GI.SL_MOSTLY_SKILL)) +registerGame(GameInfo(570, LongTail, "Long Tail", + GI.GT_SPIDER, 1, 0, GI.SL_MOSTLY_SKILL)) +registerGame(GameInfo(571, ShortTail, "Short Tail", + GI.GT_SPIDER | GI.GT_ORIGINAL, 2, 0, GI.SL_MOSTLY_SKILL)) diff --git a/pysollib/games/sultan.py b/pysollib/games/sultan.py index d3027ed6..19bf83dd 100644 --- a/pysollib/games/sultan.py +++ b/pysollib/games/sultan.py @@ -428,12 +428,12 @@ class Matrimony_Talon(DealRowTalonStack): if len(self.cards) == 0: self._redeal() if self.round == 1: - n = self.dealRowAvail(sound=sound) + n = self.dealRowAvail(sound=0) else: rows = self.game.s.rows[-self.round+1:] - n = self.dealRowAvail(rows=rows, sound=sound) + n = self.dealRowAvail(rows=rows, sound=0) while self.cards: - n += self.dealRowAvail(rows=self.game.s.rows, sound=sound) + n += self.dealRowAvail(rows=self.game.s.rows, sound=0) if sound: self.game.stopSamples() return n diff --git a/pysollib/games/yukon.py b/pysollib/games/yukon.py index a5ed6f67..b37dafd8 100644 --- a/pysollib/games/yukon.py +++ b/pysollib/games/yukon.py @@ -693,6 +693,7 @@ registerGame(GameInfo(525, Queensland, "Queensland", registerGame(GameInfo(526, OutbackPatience, "Outback Patience", GI.GT_YUKON, 1, 0, GI.SL_BALANCED)) registerGame(GameInfo(530, RussianSpider, "Russian Spider", - GI.GT_SPIDER, 1, 0, GI.SL_BALANCED)) + GI.GT_SPIDER, 1, 0, GI.SL_BALANCED, + altnames=('Ukrainian Solitaire',) )) registerGame(GameInfo(531, DoubleRussianSpider, "Double Russian Spider", GI.GT_SPIDER | GI.GT_ORIGINAL, 2, 0, GI.SL_BALANCED)) diff --git a/pysollib/hint.py b/pysollib/hint.py index 35d47170..d24c747d 100644 --- a/pysollib/hint.py +++ b/pysollib/hint.py @@ -215,6 +215,9 @@ class AbstractHint(HintInterface): def _cautiousShallMovePile(self, from_stack, to_stack, pile, rpile): if from_stack is to_stack or not to_stack.acceptsCards(from_stack, pile): return 0 + # + if len(rpile) == 0: + return 1 # now check for loops rr = self.ClonedStack(from_stack, stackcards=rpile) if rr.acceptsCards(to_stack, pile): @@ -228,6 +231,9 @@ class AbstractHint(HintInterface): if from_stack is to_stack or not to_stack.acceptsCards(from_stack, pile): return 0 if self.level >= 2: + # + if len(rpile) == 0: + return 1 # now check for loops rr = self.ClonedStack(from_stack, stackcards=rpile) if rr.acceptsCards(to_stack, pile): diff --git a/pysollib/stack.py b/pysollib/stack.py index 6ac0ae51..ebc599d9 100644 --- a/pysollib/stack.py +++ b/pysollib/stack.py @@ -1956,6 +1956,10 @@ class FreeCell_SS_RowStack(SS_RowStack): class Spider_AC_RowStack(AC_RowStack): def _isAcceptableSequence(self, cards): return isRankSequence(cards, self.cap.mod, self.cap.dir) + def getHelp(self): + if self.cap.dir > 0: return _('Tableau. Build up regardless of suit. Sequences of cards in alternate color can be moved as a unit.') + elif self.cap.dir < 0: return _('Tableau. Build down regardless of suit. Sequences of cards in alternate color can be moved as a unit.') + else: return _('Tableau. Build by same rank.') # A Spider_SameSuit_RowStack builds down by rank and suit, # but accepts sequences that match by rank only. @@ -1963,8 +1967,8 @@ class Spider_SS_RowStack(SS_RowStack): def _isAcceptableSequence(self, cards): return isRankSequence(cards, self.cap.mod, self.cap.dir) def getHelp(self): - if self.cap.dir > 0: return _('Tableau. Build up regardless of suit.') - elif self.cap.dir < 0: return _('Tableau. Build down regardless of suit.') + if self.cap.dir > 0: return _('Tableau. Build up regardless of suit. Sequences of cards in the same suit can be moved as a unit.') + elif self.cap.dir < 0: return _('Tableau. Build down regardless of suit. Sequences of cards in the same suit can be moved as a unit.') else: return _('Tableau. Build by same rank.') # A Yukon_AlternateColor_RowStack builds down by rank and alternate color, diff --git a/pysollib/tk/tkcanvas.py b/pysollib/tk/tkcanvas.py index 4d4df201..6a9b3d3d 100644 --- a/pysollib/tk/tkcanvas.py +++ b/pysollib/tk/tkcanvas.py @@ -148,7 +148,8 @@ class MfxCanvas(Tkinter.Canvas): self.__tileimage = image if stretch: # - id = self._x_create("image", 0, 0, image=image, anchor="nw") + id = self._x_create("image", -self.xmargin, -self.ymargin, + image=image, anchor="nw") self.tag_lower(id) # also see tag_lower above self.__tiles.append(id) else: diff --git a/pysollib/tk/tkwidget.py b/pysollib/tk/tkwidget.py index 5c8503e3..1b24da9c 100644 --- a/pysollib/tk/tkwidget.py +++ b/pysollib/tk/tkwidget.py @@ -680,6 +680,7 @@ class StackDesc: self.game = game self.stack = stack self.canvas = game.canvas + self.bindings = [] font = game.app.getFont('canvas_small') ##print self.app.cardset.CARDW, self.app.images.CARDW @@ -690,22 +691,29 @@ class StackDesc: if text: frame = Tkinter.Frame(self.canvas, highlightthickness=1, highlightbackground='black') + self.frame = frame label = Tkinter.Message(frame, font=font, text=text, width=cardw-8, - fg='#000000', bg='#ffffe0') + fg='#000000', bg='#ffffe0', bd=1) label.pack() self.label = label self.id = self.canvas.create_window(x, y, window=frame, anchor='n') - self.binding = label.bind('', self.buttonPressEvent) + self.bindings.append(label.bind('', self._buttonPressEvent)) + ##self.bindings.append(label.bind('', self._enterEvent)) else: self.id = None - def buttonPressEvent(self, *event): - self.game.deleteStackDesc() + def _buttonPressEvent(self, *event): + ##self.game.deleteStackDesc() + self.frame.tkraise() + + def _enterEvent(self, *event): + self.frame.tkraise() def delete(self): if self.id: self.canvas.delete(self.id) - self.label.unbind('', self.binding) + for b in self.bindings: + self.label.unbind('', b)