From 8c8bc6797076bb60190854e116b8a53a604c5b2e Mon Sep 17 00:00:00 2001 From: skomoroh Date: Mon, 31 Jul 2006 21:35:39 +0000 Subject: [PATCH] + 7 new games + new file: pysollib/tk/findcarddialog.py + new option: `use mouse for undo/redo' * improved Game._highlightCards * added flash to FindCardDialog git-svn-id: https://pysolfc.svn.sourceforge.net/svnroot/pysolfc/PySolFC/trunk@34 39dd0a4e-7c14-0410-91b3-c4f2d318f732 --- pysollib/actions.py | 2 + pysollib/app.py | 9 +- pysollib/game.py | 146 +++++++++++++++--- pysollib/games/algerian.py | 5 +- pysollib/games/auldlangsyne.py | 6 +- pysollib/games/bakersdozen.py | 22 +-- pysollib/games/bakersgame.py | 8 +- pysollib/games/beleagueredcastle.py | 22 +-- pysollib/games/bisley.py | 9 +- pysollib/games/braid.py | 7 +- pysollib/games/bristol.py | 9 +- pysollib/games/canfield.py | 33 ++-- pysollib/games/capricieuse.py | 7 +- pysollib/games/curdsandwhey.py | 10 +- pysollib/games/diplomat.py | 3 +- pysollib/games/fan.py | 18 +-- pysollib/games/fortythieves.py | 36 ++--- pysollib/games/freecell.py | 7 +- pysollib/games/glenwood.py | 10 +- pysollib/games/golf.py | 9 +- pysollib/games/grandfathersclock.py | 3 +- pysollib/games/gypsy.py | 14 +- pysollib/games/harp.py | 16 +- pysollib/games/headsandtails.py | 3 +- pysollib/games/katzenschwanz.py | 4 +- pysollib/games/klondike.py | 33 ++-- pysollib/games/montana.py | 4 +- pysollib/games/napoleon.py | 4 +- pysollib/games/needle.py | 3 +- pysollib/games/numerica.py | 76 +++++++++- pysollib/games/pileon.py | 5 +- pysollib/games/pyramid.py | 228 +++++++++++++++++++++++++++- pysollib/games/royalcotillion.py | 3 +- pysollib/games/spider.py | 29 ++-- pysollib/games/sultan.py | 46 +++--- pysollib/games/tournament.py | 3 +- pysollib/games/unionsquare.py | 4 +- pysollib/games/wavemotion.py | 3 +- pysollib/games/windmill.py | 7 +- pysollib/games/yukon.py | 29 +--- pysollib/games/zodiac.py | 3 +- pysollib/help.py | 6 + pysollib/pysoltk.py | 1 + pysollib/stack.py | 10 +- pysollib/tk/findcarddialog.py | 203 +++++++++++++++++++++++++ pysollib/tk/menubar.py | 8 +- pysollib/tk/tkwidget.py | 147 +----------------- 47 files changed, 802 insertions(+), 471 deletions(-) create mode 100644 pysollib/tk/findcarddialog.py diff --git a/pysollib/actions.py b/pysollib/actions.py index 93668e6b..83e20763 100644 --- a/pysollib/actions.py +++ b/pysollib/actions.py @@ -138,6 +138,7 @@ class PysolMenubarActions: splashscreen = BooleanVar(), demo_logo = BooleanVar(), sticky_mouse = BooleanVar(), + mouse_undo = BooleanVar(), negative_bottom = BooleanVar(), pause = BooleanVar(), toolbar_vars = {}, @@ -190,6 +191,7 @@ class PysolMenubarActions: tkopt.demo_logo.set(opt.demo_logo) tkopt.splashscreen.set(opt.splashscreen) tkopt.sticky_mouse.set(opt.sticky_mouse) + tkopt.mouse_undo.set(opt.mouse_undo) tkopt.negative_bottom.set(opt.negative_bottom) for w in TOOLBAR_BUTTONS: tkopt.toolbar_vars[w].set(opt.toolbar_vars[w]) diff --git a/pysollib/app.py b/pysollib/app.py index ca587f9e..993eae8c 100644 --- a/pysollib/app.py +++ b/pysollib/app.py @@ -68,7 +68,8 @@ from pysoltk import PysolStatusbar, HelpStatusbar from pysoltk import SelectCardsetByTypeDialogWithPreview from pysoltk import SelectDialogTreeData from pysoltk import TOOLBAR_BUTTONS -from help import helpAbout +from pysoltk import destroy_find_card_dialog +from help import helpAbout, destroy_help gettext = _ @@ -171,7 +172,7 @@ class Options: self.highlight_samerank_colors = (None, "#ffc000", None, "#0000ff") self.hintarrow_color = "#303030" self.highlight_not_matching_color = '#ff0000' - self.table_text_color = 0 + self.table_text_color = False # `False' is mean use default self.table_text_color_value = '#ffffff' # delays self.hint_sleep = 1.0 @@ -194,6 +195,7 @@ class Options: # self.splashscreen = True self.sticky_mouse = False + self.mouse_undo = False # use mouse for undo/redo self.negative_bottom = False self.randomize_place = False self.cache_carsets = True @@ -689,6 +691,9 @@ class Application: finally: # hide main window self.wm_withdraw() + # + destroy_find_card_dialog() + destroy_help() # update options self.opt.last_gameid = id # save options diff --git a/pysollib/game.py b/pysollib/game.py index e352d447..027a310d 100644 --- a/pysollib/game.py +++ b/pysollib/game.py @@ -180,12 +180,28 @@ class Game: if self.s.talon: assert hasattr(self.s.talon, "round") assert hasattr(self.s.talon, "max_rounds") - if self.app.debug and self.s.foundations: - ncards = 0 - for stack in self.s.foundations: - ncards += stack.cap.max_cards - if ncards != self.gameinfo.ncards: - print 'WARNING: invalid sum of foundations.max_cards:', self.__class__.__name__, ncards, self.gameinfo.ncards + if self.app.debug: + class_name = self.__class__.__name__ + if self.s.foundations: + ncards = 0 + for stack in self.s.foundations: + ncards += stack.cap.max_cards + if ncards != self.gameinfo.ncards: + print 'WARNING: invalid sum of foundations.max_cards:', \ + class_name, ncards, self.gameinfo.ncards + if self.s.rows: + from stack import AC_RowStack, SS_RowStack, RK_RowStack + r = self.s.rows[0] + for c, f in ( + (AC_RowStack, (self._shallHighlightMatch_AC, + self._shallHighlightMatch_ACW)), + (SS_RowStack, (self._shallHighlightMatch_SS, + self._shallHighlightMatch_SSW)), + (RK_RowStack, (self._shallHighlightMatch_RK, + self._shallHighlightMatch_RKW)),): + if isinstance(r, c) and not self.shallHighlightMatch in f: + print 'WARNING: shallHighlightMatch is not valid:', \ + class_name, r.__class__ # optimize regions self.optimizeRegions() # create cards @@ -739,14 +755,14 @@ class Game: def undoHandler(self, event): self._defaultHandler() - if not self.event_handled: + if self.app.opt.mouse_undo and not self.event_handled: self.app.menubar.mUndo() self.event_handled = False return EVENT_PROPAGATE def redoHandler(self, event): self._defaultHandler() - if not self.event_handled: + if self.app.opt.mouse_undo and not self.event_handled: self.app.menubar.mRedo() self.event_handled = False return EVENT_PROPAGATE @@ -1416,7 +1432,9 @@ for %d moves. ## for find_card_dialog def highlightCard(self, suit, rank): - col = self.app.opt.highlight_samerank_colors[3] + if not self.app: + return None + col = self.app.opt.highlight_samerank_colors[1] info = [] for s in self.allstacks: for c in s.cards: @@ -1438,25 +1456,59 @@ for %d moves. items = [] for s, c1, c2, color in info: assert c1 in s.cards and c2 in s.cards - sy0 = s.CARD_YOFFSET[0] - if sy0 >= 0: + tkraise = False + if c1 is c2: + # highlight single card + sx0, sy0 = s.getOffsetFor(c1) + x1, y1 = s.getPositionFor(c1) + x2, y2 = x1, y1 + else: + # highlight pile + if len(s.CARD_XOFFSET) > 1: + sx0 = 0 + else: + sx0 = s.CARD_XOFFSET[0] + if len(s.CARD_YOFFSET) > 1: + sy0 = 0 + else: + sy0 = s.CARD_YOFFSET[0] x1, y1 = s.getPositionFor(c1) x2, y2 = s.getPositionFor(c2) - if c2 is not s.cards[-1] and sy0 > 0: - y2 = y2 + sy0 - else: - y2 = y2 + self.app.images.CARDH - else: - x1, y1 = s.getPositionFor(c2) - x2, y2 = s.getPositionFor(c1) + if sx0 != 0 and sy0 == 0: + # horizontal stack y2 = y2 + self.app.images.CARDH - if c2 is not s.cards[-1]: - y1 = y1 + (self.app.images.CARDH + sy0) - x2 = x2 + self.app.images.CARDW + if c2 is s.cards[-1]: # top card + x2 = x2 + self.app.images.CARDW + else: + if sx0 > 0: + # left to right + x2 = x2 + sx0 + else: + # right to left + x1 = x1 + self.app.images.CARDW + x2 = x2 + self.app.images.CARDW + sx0 + elif sx0 == 0 and sy0 != 0: + # vertical stack + x2 = x2 + self.app.images.CARDW + if c2 is s.cards[-1]: # top card + y2 = y2 + self.app.images.CARDH + else: + if sy0 > 0: + # up to down + y2 = y2 + sy0 + else: + # down to up + y1 = y1 + self.app.images.CARDH + y2 = y2 + self.app.images.CARDH + sy0 + else: + x2 = x2 + self.app.images.CARDW + y2 = y2 + self.app.images.CARDH + tkraise = True ##print c1, c2, x1, y1, x2, y2 r = MfxCanvasRectangle(self.canvas, x1-1, y1-1, x2+1, y2+1, width=4, fill=None, outline=color) - r.tkraise(c2.item) + if tkraise: + r.tkraise(c2.item) items.append(r) if not items: return 0 @@ -1469,6 +1521,7 @@ for %d moves. self.canvas.update_idletasks() return EVENT_HANDLED else: + # remove items later return items def highlightNotMatching(self): @@ -1492,9 +1545,10 @@ for %d moves. r.delete() self.canvas.update_idletasks() - def highlightPiles(self, stackinfo, sleep=1.5): + def highlightPiles(self, sleep=1.5): stackinfo = self.getHighlightPilesStacks() if not stackinfo: + self.highlightNotMatching() return 0 col = self.app.opt.highlight_piles_colors hi = [] @@ -1503,17 +1557,61 @@ for %d moves. pile = s.getPile() if pile and len(pile) >= si[1]: hi.append((s, pile[0], pile[-1], col[1])) + if not hi: + self.highlightNotMatching() + return 0 return self._highlightCards(hi, sleep) + # + # highlight matching cards + # - ### highlight matching cards def shallHighlightMatch(self, stack1, card1, stack2, card2): return 0 + def _shallHighlightMatch_AC(self, stack1, card1, stack2, card2): + # by alternate color + return card1.color != card2.color and abs(card1.rank-card2.rank) == 1 + + def _shallHighlightMatch_ACW(self, stack1, card1, stack2, card2): + # by alternate color with wrapping (only for france games) + return (card1.color != card2.color + and ((card1.rank + 1) % 13 == card2.rank + or (card2.rank + 1) % 13 == card1.rank)) + + def _shallHighlightMatch_SS(self, stack1, card1, stack2, card2): + # by same suit + return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + + def _shallHighlightMatch_SSW(self, stack1, card1, stack2, card2): + # by same suit with wrapping (only for france games) + return (card1.suit == card2.suit + and ((card1.rank + 1) % 13 == card2.rank + or (card2.rank + 1) % 13 == card1.rank)) + + def _shallHighlightMatch_RK(self, stack1, card1, stack2, card2): + # by rank + return abs(card1.rank-card2.rank) == 1 + + def _shallHighlightMatch_RKW(self, stack1, card1, stack2, card2): + # by rank with wrapping (only for france games) + return ((card1.rank + 1) % 13 == card2.rank + or (card2.rank + 1) % 13 == card1.rank) + + # + # quick-play + # + def getQuickPlayScore(self, ncards, from_stack, to_stack): # prefer non-empty piles in to_stack return (len(to_stack.cards) != 0) + def _getSpiderQuickPlayScore(self, ncards, from_stack, to_stack): + # for spider-type stacks + if to_stack.cards: + # check suit + return int(from_stack.cards[-1].suit == to_stack.cards[-1].suit)+1 + return 0 # # Score (I really don't like scores in Patience games...) diff --git a/pysollib/games/algerian.py b/pysollib/games/algerian.py index ffab0455..17b0ae4e 100644 --- a/pysollib/games/algerian.py +++ b/pysollib/games/algerian.py @@ -114,10 +114,7 @@ class Carthage(Game): self.startDealSample() self.s.talon.dealRow(rows=self.s.reserves) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - ((card1.rank + 1) % 13 == card2.rank or - (card2.rank + 1) % 13 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SSW # /*********************************************************************** diff --git a/pysollib/games/auldlangsyne.py b/pysollib/games/auldlangsyne.py index c4f3a3b9..bcbbec16 100644 --- a/pysollib/games/auldlangsyne.py +++ b/pysollib/games/auldlangsyne.py @@ -270,8 +270,7 @@ class Interregnum(Game): def getAutoStacks(self, event=None): return ((), (), self.sg.dropstacks) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return ((card1.rank + 1) % 13 == card2.rank or (card2.rank + 1) % 13 == card1.rank) + shallHighlightMatch = Game._shallHighlightMatch_RKW def _restoreGameHook(self, game): self.base_cards = [None] * 8 @@ -488,8 +487,7 @@ class Scuffle_Talon(RedealTalonStack): def dealCards(self, sound=0, shuffle=True): if self.cards: return self.dealRowAvail(sound=sound) - RedealTalonStack.redealCards(self, frames=4, - shuffle=shuffle, sound=sound) + self.redealCards(frames=4, shuffle=shuffle, sound=sound) return self.dealRowAvail(sound=sound) diff --git a/pysollib/games/bakersdozen.py b/pysollib/games/bakersdozen.py index e4a373bb..f8c93abb 100644 --- a/pysollib/games/bakersdozen.py +++ b/pysollib/games/bakersdozen.py @@ -80,8 +80,7 @@ class CastlesInSpain(Game): self.startDealSample() self.s.talon.dealRow() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.color != card2.color and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_AC # /*********************************************************************** @@ -139,8 +138,7 @@ class BakersDozen(CastlesInSpain): def startGame(self): CastlesInSpain.startGame(self, flip=(1, 1, 1)) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank) + shallHighlightMatch = Game._shallHighlightMatch_RK # /*********************************************************************** @@ -150,8 +148,7 @@ class BakersDozen(CastlesInSpain): class SpanishPatience(BakersDozen): Foundation_Class = AC_FoundationStack - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.color != card2.color and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_AC # /*********************************************************************** @@ -252,8 +249,8 @@ class Cruel(CastlesInSpain): CastlesInSpain.startGame(self, flip=(1, 1, 1)) self.s.talon.dealRow(rows=self.s.foundations) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS + # /*********************************************************************** # // Royal Family @@ -269,8 +266,7 @@ class RoyalFamily(Cruel): # move Kings to bottom of the Talon (i.e. last cards to be dealt) return self._shuffleHookMoveToBottom(cards, lambda c: (c.rank == KING, c.suit)) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.color != card2.color and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_AC class Indefatigable(Cruel): @@ -282,8 +278,7 @@ class Indefatigable(Cruel): # move Aces to bottom of the Talon (i.e. last cards to be dealt) return self._shuffleHookMoveToBottom(cards, lambda c: (c.rank == ACE, c.suit)) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -328,8 +323,7 @@ class RippleFan(CastlesInSpain): def startGame(self): CastlesInSpain.startGame(self, flip=(1, 1, 1)) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS # register the game diff --git a/pysollib/games/bakersgame.py b/pysollib/games/bakersgame.py index 3c8bb671..119d6690 100644 --- a/pysollib/games/bakersgame.py +++ b/pysollib/games/bakersgame.py @@ -114,9 +114,7 @@ class BakersGame(Game): ##self.s.talon.dealRow(rows=(r[0], r[1], r[6], r[7])) self.s.talon.dealRow(rows=r[:4]) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -312,9 +310,7 @@ class Penguin(Game): self.startDealSample() self.s.talon.dealRow() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - ((card1.rank + 1) % 13 == card2.rank or (card2.rank + 1) % 13 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SSW def _restoreGameHook(self, game): self.base_card = self.cards[game.loadinfo.base_card_id] diff --git a/pysollib/games/beleagueredcastle.py b/pysollib/games/beleagueredcastle.py index b6b19696..9189b08d 100644 --- a/pysollib/games/beleagueredcastle.py +++ b/pysollib/games/beleagueredcastle.py @@ -126,8 +126,7 @@ class StreetsAndAlleys(Game): for i in range(3): self.s.talon.dealRowAvail() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return abs(card1.rank - card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_RK # /*********************************************************************** @@ -226,10 +225,8 @@ class Fortress(Game): for i in range(3): self.s.talon.dealRowAvail() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - ((card1.rank + 1) % 13 == card2.rank or - (card2.rank + 1) % 13 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SSW + # /*********************************************************************** # // Bastion @@ -436,8 +433,7 @@ class Zerline(Game): self.s.talon.dealRow() self.s.talon.dealCards() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return abs(card1.rank - card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_RK def getQuickPlayScore(self, ncards, from_stack, to_stack): return int(to_stack in self.s.rows) @@ -559,8 +555,7 @@ class CastleOfIndolence(Game): self.s.talon.dealRow() self.s.talon.dealRowAvail() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return abs(card1.rank - card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_RK # /*********************************************************************** @@ -637,8 +632,7 @@ class Rittenhouse(Game): def fillStack(self, stack): self.fillAll() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return abs(card1.rank - card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_RK # /*********************************************************************** @@ -688,9 +682,7 @@ class CastleMount(Lightweight): DEAL = (11, 1) RowStack_Class = Spider_SS_RowStack - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return ((card1.rank + 1) % stack1.cap.mod == card2.rank or - (card2.rank + 1) % stack1.cap.mod == card1.rank) + shallHighlightMatch = Game._shallHighlightMatch_RK def getQuickPlayScore(self, ncards, from_stack, to_stack): if to_stack.cards: diff --git a/pysollib/games/bisley.py b/pysollib/games/bisley.py index 4b06c13c..3317a297 100644 --- a/pysollib/games/bisley.py +++ b/pysollib/games/bisley.py @@ -90,8 +90,7 @@ class Bisley(Game): # move Aces to bottom of the Talon (i.e. last cards to be dealt) return self._shuffleHookMoveToBottom(cards, lambda c: (c.rank == ACE, c.suit)) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -232,15 +231,13 @@ class Realm(Game): self.s.talon.dealRow() self.s.talon.dealRowAvail() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.color != card2.color and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_AC class Mancunian(Realm): RowStack_Class = StackWrapper(UD_RK_RowStack, base_rank=NO_RANK) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_RK # register the game diff --git a/pysollib/games/braid.py b/pysollib/games/braid.py index 46f86bfb..850457ea 100644 --- a/pysollib/games/braid.py +++ b/pysollib/games/braid.py @@ -214,9 +214,7 @@ class Braid(Game): # deal first card to WasteStack self.s.talon.dealCards() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - ((card1.rank + 1) % 13 == card2.rank or (card2.rank + 1) % 13 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SSW def getHighlightPilesStacks(self): return () @@ -358,8 +356,7 @@ class Backbone(Game): 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 + shallHighlightMatch = Game._shallHighlightMatch_SS class BackbonePlus(Backbone): diff --git a/pysollib/games/bristol.py b/pysollib/games/bristol.py index f2f5d591..4fcd44d5 100644 --- a/pysollib/games/bristol.py +++ b/pysollib/games/bristol.py @@ -319,10 +319,7 @@ class NewYork(Dover): self.s.talon.dealRow() self.s.talon.fillStack() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.color != card2.color and - ((card1.rank + 1) % 13 == card2.rank or - (card2.rank + 1) % 13 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_ACW def _restoreGameHook(self, game): self.base_card = self.cards[game.loadinfo.base_card_id] @@ -356,9 +353,7 @@ class Spike(Dover): 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) + shallHighlightMatch = Game._shallHighlightMatch_AC # /*********************************************************************** diff --git a/pysollib/games/canfield.py b/pysollib/games/canfield.py index f1f4b1f9..9dfea82e 100644 --- a/pysollib/games/canfield.py +++ b/pysollib/games/canfield.py @@ -212,9 +212,7 @@ class Canfield(Game): if stack.canFlipCard(): stack.flipMove() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.color != card2.color and - ((card1.rank + 1) % 13 == card2.rank or (card2.rank + 1) % 13 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_ACW def _restoreGameHook(self, game): self.base_card = self.cards[game.loadinfo.base_card_id] @@ -277,9 +275,7 @@ class Storehouse(Canfield): self.s.talon.dealRow(rows=self.s.foundations[:3]) Canfield.startGame(self) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - ((card1.rank + 1) % 13 == card2.rank or (card2.rank + 1) % 13 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SSW def updateText(self): pass @@ -297,8 +293,7 @@ class Chameleon(Canfield): def createGame(self): Canfield.createGame(self, rows=3, max_rounds=1, num_deal=1) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return ((card1.rank + 1) % 13 == card2.rank or (card2.rank + 1) % 13 == card1.rank) + shallHighlightMatch = Game._shallHighlightMatch_RKW # /*********************************************************************** @@ -345,9 +340,7 @@ class VariegatedCanfield(Canfield): self.s.talon.dealRow(rows=self.s.foundations[:7]) Canfield.startGame(self) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.color != card2.color and - ((card1.rank + 1) == card2.rank or (card2.rank + 1) == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_AC def updateText(self): pass @@ -471,9 +464,7 @@ class Gate(Game): if from_stack: from_stack.moveMove(1, stack) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.color != card2.color and - abs(card1.rank-card2.rank) == 1) + shallHighlightMatch = Game._shallHighlightMatch_AC class LittleGate(Gate): @@ -544,8 +535,7 @@ class Doorway(LittleGate): def fillStack(self, stack): pass - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_RK # /*********************************************************************** @@ -574,8 +564,7 @@ class Minerva(Canfield): self.flipMove(self.s.reserves[0]) self.s.talon.dealCards() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.color != card2.color and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_AC def _restoreGameHook(self, game): pass @@ -631,9 +620,7 @@ class Acme(Canfield): self.s.talon.dealRow(reverse=1) self.s.talon.dealCards() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - abs(card1.rank-card2.rank) == 1) + shallHighlightMatch = Game._shallHighlightMatch_SS def updateText(self): pass @@ -703,9 +690,7 @@ class Duke(Game): self.s.talon.dealCards() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.color != card2.color and - abs(card1.rank-card2.rank) == 1) + shallHighlightMatch = Game._shallHighlightMatch_AC # /*********************************************************************** diff --git a/pysollib/games/capricieuse.py b/pysollib/games/capricieuse.py index e7beec99..c36f43bd 100644 --- a/pysollib/games/capricieuse.py +++ b/pysollib/games/capricieuse.py @@ -122,10 +122,7 @@ class Capricieuse(Game): def _shuffleHook(self, cards): return self._shuffleHookMoveToBottom(cards, lambda c: (c.deck == 0 and c.rank in (0, 12), (c.rank, c.suit)), 8) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - ((card1.rank + 1) % stack1.cap.mod == card2.rank or - (card2.rank + 1) % stack1.cap.mod == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -136,6 +133,8 @@ class Nationale(Capricieuse): Talon_Class = InitialDealTalonStack RowStack_Class = StackWrapper(UD_SS_RowStack, mod=13) + shallHighlightMatch = Game._shallHighlightMatch_SSW + # register the game registerGame(GameInfo(292, Capricieuse, "Capricieuse", diff --git a/pysollib/games/curdsandwhey.py b/pysollib/games/curdsandwhey.py index 6537ceb9..dc0825f2 100644 --- a/pysollib/games/curdsandwhey.py +++ b/pysollib/games/curdsandwhey.py @@ -323,9 +323,7 @@ class GermanPatience(Game): return True - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return ((card1.rank + 1) % 13 == card2.rank or - (card2.rank + 1) % 13 == card1.rank) + shallHighlightMatch = Game._shallHighlightMatch_RKW class BavarianPatience(GermanPatience): @@ -384,8 +382,7 @@ class TrustyTwelve(Game): def isGameWon(self): return len(self.s.talon.cards) == 0 - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_RK class KnottyNines(TrustyTwelve): @@ -410,8 +407,7 @@ class SweetSixteen(TrustyTwelve): y += l.YS+10*l.YOFFSET l.defaultStackGroups() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.color != card2.color and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_AC diff --git a/pysollib/games/diplomat.py b/pysollib/games/diplomat.py index 99469452..05e1fa8a 100644 --- a/pysollib/games/diplomat.py +++ b/pysollib/games/diplomat.py @@ -112,8 +112,7 @@ class Diplomat(Game): self.s.waste.moveMove(1, stack) self.leaveState(old_state) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank + shallHighlightMatch = Game._shallHighlightMatch_RK # /*********************************************************************** diff --git a/pysollib/games/fan.py b/pysollib/games/fan.py index 590b845c..26d81a67 100644 --- a/pysollib/games/fan.py +++ b/pysollib/games/fan.py @@ -121,9 +121,7 @@ class Fan(Game): self.startDealSample() self.s.talon.dealRow() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SS def getHighlightPilesStacks(self): return () @@ -138,8 +136,7 @@ class ScotchPatience(Fan): RowStack_Class = StackWrapper(RK_RowStack, base_rank=NO_RANK) def createGame(self): Fan.createGame(self, playcards=8) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_RK # /*********************************************************************** @@ -150,8 +147,7 @@ class Shamrocks(Fan): RowStack_Class = StackWrapper(UD_RK_RowStack, base_rank=NO_RANK, max_cards=3) def createGame(self): Fan.createGame(self, playcards=4) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_RK # /*********************************************************************** @@ -520,9 +516,7 @@ class CloverLeaf(Game): (c.rank == KING and c.suit in (2,3)), c.suit)) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - abs(card1.rank-card2.rank) == 1) + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -556,9 +550,7 @@ class BoxFan(Fan): # move Aces to bottom of the Talon (i.e. last cards to be dealt) return self._shuffleHookMoveToBottom(cards, lambda c: (c.rank == 0, c.suit)) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.color != card2.color and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_AC # /*********************************************************************** diff --git a/pysollib/games/fortythieves.py b/pysollib/games/fortythieves.py index bae783a2..fc15acc6 100644 --- a/pysollib/games/fortythieves.py +++ b/pysollib/games/fortythieves.py @@ -152,9 +152,7 @@ class FortyThieves(Game): self.s.waste.moveMove(1, stack) self.leaveState(old_state) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -358,8 +356,7 @@ class LittleForty(FortyThieves): class Streets(FortyThieves): RowStack_Class = AC_RowStack - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.color != card2.color and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_AC class Maria(Streets): @@ -458,8 +455,9 @@ class Indian(FortyThieves): FortyThieves.createGame(self, XCARDS=74) def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit != card2.suit and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + return (card1.suit != card2.suit + and (card1.rank + 1 == card2.rank + or card2.rank + 1 == card1.rank)) class Midshipman(Indian): @@ -487,8 +485,7 @@ class NapoleonsExile(FortyThieves): DEAL = (0, 4) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank + shallHighlightMatch = Game._shallHighlightMatch_RK class DoubleRail(NapoleonsExile): @@ -600,8 +597,7 @@ class Octave(Game): return False return not self.s.waste.cards - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.color != card2.color and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_AC def _autoDeal(self, sound=1): ncards = len(self.s.waste.cards) + sum([len(i.cards) for i in self.s.reserves]) @@ -667,8 +663,7 @@ class FortunesFavor(Game): self.s.waste.moveMove(1, stack) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -731,8 +726,7 @@ class Octagon(Game): if self.s.waste.cards: self.s.waste.moveMove(1, stack) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -850,8 +844,7 @@ class Junction(Game): self.s.talon.dealCards() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.color != card2.color and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_AC # /*********************************************************************** @@ -930,8 +923,7 @@ class TheSpark(Game): self.s.talon.dealCards() # deal first card to WasteStack - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -988,8 +980,7 @@ class Unlimited(Interchange): class Breakwater(Interchange): RowStack_Class = RK_RowStack - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_RK class FortyNine_RowStack(AC_RowStack): @@ -1011,8 +1002,7 @@ class FortyNine(Interchange): 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 + shallHighlightMatch = Game._shallHighlightMatch_AC # /*********************************************************************** diff --git a/pysollib/games/freecell.py b/pysollib/games/freecell.py index ff0c81dd..edc1d8d6 100644 --- a/pysollib/games/freecell.py +++ b/pysollib/games/freecell.py @@ -118,9 +118,7 @@ class FreeCell(Game): ##self.s.talon.dealRow(rows=(r[0], r[2], r[4], r[6])) self.s.talon.dealRow(rows=r[:4]) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.color != card2.color and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_AC # /*********************************************************************** @@ -539,8 +537,7 @@ class OceanTowers(TripleFreecell): self.s.talon.dealRow() self.s.talon.dealRow(rows=self.s.reserves[1:-1]) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** diff --git a/pysollib/games/glenwood.py b/pysollib/games/glenwood.py index 2564fbeb..f11c9d69 100644 --- a/pysollib/games/glenwood.py +++ b/pysollib/games/glenwood.py @@ -158,10 +158,7 @@ class Glenwood(Game): t = RANKS[self.base_rank] self.texts.info.config(text=t) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.color != card2.color - and ((card1.rank + 1) % 13 == card2.rank - or (card2.rank + 1) % 13 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_ACW def _restoreGameHook(self, game): self.base_rank = game.loadinfo.base_rank @@ -323,10 +320,7 @@ class DoubleFives(Glenwood): return self.dealCards(sound=sound) return 0 - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit - and ((card1.rank + 1) % 13 == card2.rank - or (card2.rank + 1) % 13 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SSW diff --git a/pysollib/games/golf.py b/pysollib/games/golf.py index fecb49fc..40c00933 100644 --- a/pysollib/games/golf.py +++ b/pysollib/games/golf.py @@ -174,8 +174,7 @@ class Golf(Game): return 0 return 1 - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank) + shallHighlightMatch = Game._shallHighlightMatch_RK def getHighlightPilesStacks(self): return () @@ -206,8 +205,7 @@ class DeadKingGolf(Golf): class RelaxedGolf(Golf): Waste_Class = StackWrapper(Golf_Waste, mod=13) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return ((card1.rank + 1) % 13 == card2.rank or (card2.rank + 1) % 13 == card1.rank) + shallHighlightMatch = Game._shallHighlightMatch_RKW # /*********************************************************************** @@ -666,8 +664,7 @@ class DiamondMine(Game): return False return True - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_RK # register the game diff --git a/pysollib/games/grandfathersclock.py b/pysollib/games/grandfathersclock.py index db9be246..cf4acbf8 100644 --- a/pysollib/games/grandfathersclock.py +++ b/pysollib/games/grandfathersclock.py @@ -125,8 +125,7 @@ class GrandfathersClock(Game): self.s.talon.dealRow() self.s.talon.dealRow(rows=self.s.foundations) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank + shallHighlightMatch = Game._shallHighlightMatch_RK def getHighlightPilesStacks(self): return () diff --git a/pysollib/games/gypsy.py b/pysollib/games/gypsy.py index 5e0bf563..e56d1b95 100644 --- a/pysollib/games/gypsy.py +++ b/pysollib/games/gypsy.py @@ -82,9 +82,7 @@ class Gypsy(Game): self.startDealSample() self.s.talon.dealRow() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.color != card2.color and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_AC # /*********************************************************************** @@ -327,8 +325,7 @@ class Steve(Carlton): Hint_Class = Spider_Hint RowStack_Class = Spider_SS_RowStack - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_RK def getQuickPlayScore(self, ncards, from_stack, to_stack): if to_stack.cards: @@ -389,9 +386,7 @@ class Blockade(Gypsy): self.s.talon.moveMove(1, stack) self.leaveState(old_state) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - abs(card1.rank-card2.rank) == 1) + shallHighlightMatch = Game._shallHighlightMatch_SS class PhantomBlockade(Gypsy): @@ -709,8 +704,7 @@ class Eclipse(Gypsy): self.startDealSample() self.s.talon.dealRow() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1) + shallHighlightMatch = Game._shallHighlightMatch_SS # register the game diff --git a/pysollib/games/harp.py b/pysollib/games/harp.py index 37ed6028..a859eece 100644 --- a/pysollib/games/harp.py +++ b/pysollib/games/harp.py @@ -92,9 +92,7 @@ class DoubleKlondike(Game): self.s.talon.dealRow() self.s.talon.dealCards() # deal first card to WasteStack - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.color != card2.color and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_AC # /*********************************************************************** @@ -190,8 +188,7 @@ class LadyJane(DoubleKlondike): DoubleKlondike.createGame(self, rows=10, max_rounds=2, num_deal=3) def startGame(self): DoubleKlondike.startGame(self, flip=1) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_RK def getQuickPlayScore(self, ncards, from_stack, to_stack): if to_stack.cards: return int(from_stack.cards[-1].suit == to_stack.cards[-1].suit)+1 @@ -205,8 +202,7 @@ class Inquisitor(DoubleKlondike): DoubleKlondike.createGame(self, rows=10, max_rounds=3, num_deal=3) def startGame(self): DoubleKlondike.startGame(self, flip=1) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -220,8 +216,7 @@ class Arabella(DoubleKlondike): DoubleKlondike.createGame(self, rows=13, max_rounds=1, playcards=24) def startGame(self): DoubleKlondike.startGame(self, flip=1) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_RK def getQuickPlayScore(self, ncards, from_stack, to_stack): if to_stack.cards: return int(from_stack.cards[-1].suit == to_stack.cards[-1].suit)+1 @@ -276,8 +271,7 @@ class Delivery(BigDeal): dx = self.app.images.CARDW/10 BigDeal.createGame(self, rows=12, max_rounds=1, XOFFSET=dx) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS def startGame(self): for i in range(2): diff --git a/pysollib/games/headsandtails.py b/pysollib/games/headsandtails.py index cae00cde..8829c075 100644 --- a/pysollib/games/headsandtails.py +++ b/pysollib/games/headsandtails.py @@ -129,8 +129,7 @@ class HeadsAndTails(Game): #stack.flipMove() self.leaveState(old_state) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank - card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS # register the game diff --git a/pysollib/games/katzenschwanz.py b/pysollib/games/katzenschwanz.py index 5e1227b8..e67bb150 100644 --- a/pysollib/games/katzenschwanz.py +++ b/pysollib/games/katzenschwanz.py @@ -122,9 +122,7 @@ class DerKatzenschwanz(Game): i = i + 1 self.s.talon.dealRow(rows=[self.s.rows[i]], frames=4) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.color != card2.color and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_AC # must look at cards def _getClosestStack(self, cx, cy, stacks, dragstack): diff --git a/pysollib/games/klondike.py b/pysollib/games/klondike.py index 875520bc..16c94b74 100644 --- a/pysollib/games/klondike.py +++ b/pysollib/games/klondike.py @@ -86,9 +86,7 @@ class Klondike(Game): if self.s.waste: self.s.talon.dealCards() # deal first card to WasteStack - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.color != card2.color and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_AC # /*********************************************************************** @@ -150,8 +148,9 @@ class ThumbAndPouch(Klondike): Klondike.createGame(self, max_rounds=1) def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit != card2.suit and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + return (card1.suit != card2.suit + and (card1.rank + 1 == card2.rank + or card2.rank + 1 == card1.rank)) # /*********************************************************************** @@ -172,9 +171,7 @@ class Whitehead(Klondike): def startGame(self): Klondike.startGame(self, flip=1) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -537,8 +534,7 @@ class Brigade(Raglan): self.s.talon.dealRow(rows=self.s.reserves) self.s.talon.dealRow(rows=self.s.foundations) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank) + shallHighlightMatch = Game._shallHighlightMatch_RK # /*********************************************************************** @@ -619,10 +615,7 @@ class Jane(Klondike): s.cap.update(cap.__dict__) self.saveinfo.stack_caps.append((s.id, cap)) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - ((card1.rank + 1) % 13 == card2.rank or - (card2.rank + 1) % 13 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SSW def _autoDeal(self, sound=1): return 0 @@ -817,8 +810,7 @@ class ThirtySix(Klondike): break self.s.talon.dealCards() # deal first card to WasteStack - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_RK # /*********************************************************************** @@ -869,8 +861,7 @@ class Q_C_(Klondike): self.s.waste.moveMove(1, stack) self.fillAll() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -1030,8 +1021,7 @@ class BigForty(Klondike): 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 + shallHighlightMatch = Game._shallHighlightMatch_SS class AliBaba(BigForty): @@ -1143,8 +1133,7 @@ class LuckyThirteen(Klondike): self.startDealSample() self.s.talon.dealRow() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS class LuckyPiles(LuckyThirteen): diff --git a/pysollib/games/montana.py b/pysollib/games/montana.py index 6f35d3be..39a468c2 100644 --- a/pysollib/games/montana.py +++ b/pysollib/games/montana.py @@ -222,9 +222,7 @@ class Montana(Game): def getAutoStacks(self, event=None): return (self.sg.dropstacks, (), self.sg.dropstacks) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SS def getQuickPlayScore(self, ncards, from_stack, to_stack): if from_stack.cards: diff --git a/pysollib/games/napoleon.py b/pysollib/games/napoleon.py index bd921e5c..efcc59de 100644 --- a/pysollib/games/napoleon.py +++ b/pysollib/games/napoleon.py @@ -164,9 +164,7 @@ class DerKleineNapoleon(Game): self.s.talon.dealRow(rows=self.s.rows[8:]) self.s.talon.dealBaseCards(ncards=4) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - ((card1.rank + 1) % 13 == card2.rank or (card2.rank + 1) % 13 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SSW # # game extras diff --git a/pysollib/games/needle.py b/pysollib/games/needle.py index be541857..71f5129b 100644 --- a/pysollib/games/needle.py +++ b/pysollib/games/needle.py @@ -94,8 +94,7 @@ class Needle(Game): self.s.talon.dealRow(rows=self.s.rows[:i]) self.s.talon.dealRow(rows=self.s.rows[-i:]) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.color != card2.color and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_AC def getQuickPlayScore(self, ncards, from_stack, to_stack): if to_stack in self.s.reserves: diff --git a/pysollib/games/numerica.py b/pysollib/games/numerica.py index 393fa323..cb00e699 100644 --- a/pysollib/games/numerica.py +++ b/pysollib/games/numerica.py @@ -33,7 +33,7 @@ __all__ = [] # imports -import sys +import sys, time # PySol imports from pysollib.gamedb import registerGame, GameInfo, GI @@ -103,7 +103,7 @@ class Numerica(Game): # game layout # - def createGame(self, rows=4, reserve=False): + def createGame(self, rows=4, reserve=False, max_rounds=1, waste_max_cards=1): # create layout l, s = Layout(self), self.s decks = self.gameinfo.decks @@ -131,13 +131,15 @@ class Numerica(Game): x = x + l.XS self.setRegion(s.rows, (x0-l.XS/2, y-l.CH/2, 999999, 999999)) x, y = l.XM, l.YM+l.YS+l.YS/2*int(reserve) - s.talon = WasteTalonStack(x, y, self, max_rounds=1) - if reserve: + s.talon = WasteTalonStack(x, y, self, max_rounds=max_rounds) + if reserve or waste_max_cards > 1: l.createText(s.talon, 'ne') else: l.createText(s.talon, 'n') y = y + l.YS - s.waste = WasteStack(x, y, self, max_cards=1) + s.waste = WasteStack(x, y, self, max_cards=waste_max_cards) + if waste_max_cards > 1: + l.createText(s.waste, 'ne') if reserve: s.reserves.append(self.ReserveStack_Class(l.XM, l.YM, self)) @@ -153,9 +155,7 @@ class Numerica(Game): self.startDealSample() self.s.talon.dealCards() # deal first card to WasteStack - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SS def getHighlightPilesStacks(self): return () @@ -659,6 +659,62 @@ class Strategerie(Game): self.s.talon.fillStack() +# /*********************************************************************** +# // Assembly +# // Anno Domini +# ************************************************************************/ + +class Assembly(Numerica): + Hint_Class = DefaultHint + + Foundation_Class = StackWrapper(RK_FoundationStack, suit=ANY_SUIT) + RowStack_Class = StackWrapper(RK_RowStack, max_move=1) + + def createGame(self): + Numerica.createGame(self, waste_max_cards=UNLIMITED_CARDS) + + def startGame(self): + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.dealCards() + + shallHighlightMatch = Game._shallHighlightMatch_RK + + +class AnnoDomini_Hint(DefaultHint): + def step030(self, foundations, rows, dropstacks): + pass + + +class AnnoDomini(Numerica): + Hint_Class = AnnoDomini_Hint + + Foundation_Class = StackWrapper(SS_FoundationStack, suit=ANY_SUIT, mod=13) + RowStack_Class = AC_RowStack + + def createGame(self): + Numerica.createGame(self, max_rounds=3, waste_max_cards=UNLIMITED_CARDS) + year = str(time.localtime()[0]) + i = 0 + for s in self.s.foundations: + # setup base_rank & base_suit + s.cap.suit = i + s.cap.base_suit = i + d = int(year[i]) + if d == 0: + d = JACK + s.cap.base_rank = d + i += 1 + + def startGame(self): + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.dealCards() + + shallHighlightMatch = Game._shallHighlightMatch_AC + + + # register the game registerGame(GameInfo(257, Numerica, "Numerica", @@ -689,4 +745,8 @@ registerGame(GameInfo(558, Numerica2Decks, "Numerica (2 decks)", GI.GT_NUMERICA, 2, 0, GI.SL_BALANCED)) registerGame(GameInfo(589, LastChance, "Last Chance", GI.GT_NUMERICA, 1, 0, GI.SL_BALANCED)) +registerGame(GameInfo(599, Assembly, "Assembly", + GI.GT_NUMERICA, 1, 0, GI.SL_BALANCED)) +registerGame(GameInfo(600, AnnoDomini, "Anno Domini", + GI.GT_NUMERICA, 1, 2, GI.SL_BALANCED)) diff --git a/pysollib/games/pileon.py b/pysollib/games/pileon.py index 4a079ead..636eef91 100644 --- a/pysollib/games/pileon.py +++ b/pysollib/games/pileon.py @@ -184,10 +184,7 @@ class Foursome(Game): self.leaveState(old_state) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.color != card2.color and - ((card1.rank + 1) % 13 == card2.rank or - (card2.rank + 1) % 13 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_ACW class Quartets(Foursome): diff --git a/pysollib/games/pyramid.py b/pysollib/games/pyramid.py index 68908e76..ba7ee49e 100644 --- a/pysollib/games/pyramid.py +++ b/pysollib/games/pyramid.py @@ -337,7 +337,6 @@ class Thirteen(Pyramid): class Thirteens(Pyramid): - def createGame(self): # create layout l, s = Layout(self), self.s @@ -376,6 +375,225 @@ class Thirteens(Pyramid): self.s.talon.moveMove(1, stack) self.leaveState(old_state) +# /*********************************************************************** +# // Elevens +# // Suit Elevens +# ************************************************************************/ + +class Elevens_RowStack(Giza_Reserve): + ACCEPTED_SUM = 9 + + def acceptsCards(self, from_stack, cards): + #if self.basicIsBlocked(): + # return 0 + if from_stack is self or not self.cards or len(cards) != 1: + return False + c = self.cards[-1] + return (c.face_up and cards[0].face_up + and cards[0].rank + c.rank == self.ACCEPTED_SUM) + + def clickHandler(self, event): + return OpenStack.clickHandler(self, event) + + def moveMove(self, ncards, to_stack, frames=-1, shadow=-1): + if to_stack in self.game.s.rows: + self._dropPairMove(ncards, to_stack, frames=-1, shadow=shadow) + else: + self.game.moveMove(ncards, self, to_stack, + frames=frames, shadow=shadow) + self.fillStack() + + +class Elevens_Reserve(ReserveStack): + ACCEPTED_CARDS = (JACK, QUEEN, KING) + + def acceptsCards(self, from_stack, cards): + if not ReserveStack.acceptsCards(self, from_stack, cards): + return False + c = cards[0] + if not c.rank in self.ACCEPTED_CARDS: + return False + for s in self.game.s.reserves: + if s.cards and s.cards[0].rank == c.rank: + return False + return True + + +class Elevens(Pyramid): + + RowStack_Class = Elevens_RowStack + Reserve_Class = Elevens_Reserve + + def createGame(self, rows=3, cols=3, reserves=3, texts=False): + + l, s = Layout(self), self.s + + self.setSize(l.XM+(cols+2)*l.XS, l.YM+(rows+1.5)*l.YS) + + x, y = self.width-l.XS, l.YM + s.talon = TalonStack(x, y, self) + l.createText(s.talon, 's') + x, y = self.width-l.XS, self.height-l.YS + s.foundations.append(AbstractFoundationStack(x, y, self, + suit=ANY_SUIT, max_accept=0, + max_move=0, max_cards=52)) + y = l.YM + for i in range(rows): + x = l.XM + for j in range(cols): + s.rows.append(self.RowStack_Class(x, y, self, max_accept=1)) + x += l.XS + y += l.YS + x, y = l.XM, self.height-l.YS + for i in range(reserves): + stack = self.Reserve_Class(x, y, self) + s.reserves.append(stack) + stack.CARD_XOFFSET = l.XOFFSET # for fifteens + x += l.XS + + if texts: + stack = s.reserves[0] + tx, ty, ta, tf = l.getTextAttr(stack, "n") + font = self.app.getFont("canvas_default") + stack.texts.misc = MfxCanvasText(self.canvas, tx, ty, + anchor=ta, font=font) + + l.defaultStackGroups() + + + def startGame(self): + self.startDealSample() + self.s.talon.dealRow() + + + def fillStack(self, stack): + old_state = self.enterState(self.S_FILL) + if stack in self.s.rows: + if not stack.cards and self.s.talon.cards: + self.s.talon.flipMove() + self.s.talon.moveMove(1, stack) + reserves_ncards = 0 + for s in self.s.reserves: + if s.cards: + reserves_ncards += 1 + if reserves_ncards == len(self.s.reserves): + if not self.demo: + self.playSample("droppair", priority=200) + for s in self.s.reserves: + s.moveMove(1, self.s.foundations[0], frames=4) + self.leaveState(old_state) + + +class ElevensToo(Elevens): + + def fillStack(self, stack): + old_state = self.enterState(self.S_FILL) + reserves_ncards = 0 + for s in self.s.reserves: + if s.cards: + reserves_ncards += 1 + if reserves_ncards == 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) + elif reserves_ncards == len(self.s.reserves): + if not self.demo: + self.playSample("droppair", priority=200) + for s in self.s.reserves: + s.moveMove(1, self.s.foundations[0], frames=4) + self.fillStack(stack) + self.leaveState(old_state) + + +class SuitElevens_RowStack(Elevens_RowStack): + def acceptsCards(self, from_stack, cards): + if not Elevens_RowStack.acceptsCards(self, from_stack, cards): + return False + return cards[0].suit == self.cards[0].suit + +class SuitElevens_Reserve(Elevens_Reserve): + def acceptsCards(self, from_stack, cards): + if not Elevens_Reserve.acceptsCards(self, from_stack, cards): + return False + for r in self.game.s.reserves: + if r.cards and r.cards[0].suit != cards[0].suit: + return False + return True + +class SuitElevens(Elevens): + RowStack_Class = SuitElevens_RowStack + Reserve_Class = SuitElevens_Reserve + def createGame(self): + Elevens.createGame(self, rows=3, cols=5) + + +# /*********************************************************************** +# // Fifteens +# ************************************************************************/ + +class Fifteens_RowStack(Elevens_RowStack): + ACCEPTED_SUM = 13 + def acceptsCards(self, from_stack, cards): + if not Elevens_RowStack.acceptsCards(self, from_stack, cards): + return False + return cards[0].rank < 9 and self.cards[0] < 9 + + +class Fifteens_Reserve(ReserveStack): + def updateText(self): + if self.game.preview > 1 or self.texts.misc is None: + return + t = '' + if self.cards: + ranks = [c.rank for c in self.cards] + for r in (9, JACK, QUEEN, KING): + if r in ranks: + break + else: + n = sum([i+1 for i in ranks]) + t = str(n) + self.texts.misc.config(text=t) + + +class Fifteens(Elevens): + Hint_Class = None + + RowStack_Class = Fifteens_RowStack + Reserve_Class = StackWrapper(Fifteens_Reserve, max_cards=UNLIMITED_CARDS) + + def createGame(self): + Elevens.createGame(self, rows=4, cols=4, reserves=1, texts=True) + + def _dropReserve(self): + reserve = self.s.reserves[0] + if not self.demo: + self.playSample("droppair", priority=200) + while reserve.cards: + reserve.moveMove(1, self.s.foundations[0], frames=4) + self.fillStack() + + 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: + reserve_ranks = [c.rank for c in reserve.cards] + reserve_ranks.sort() + if (9 in reserve_ranks or JACK in reserve_ranks + or QUEEN in reserve_ranks or KING in reserve_ranks): + if reserve_ranks == [9, JACK, QUEEN, KING]: + self._dropReserve() + else: + reserve_sum = sum([c.rank+1 for c in reserve.cards]) + if reserve_sum == 15: + self._dropReserve() + self.leaveState(old_state) + # register the game @@ -389,6 +607,14 @@ registerGame(GameInfo(592, Giza, "Giza", GI.GT_PAIRING_TYPE | GI.GT_OPEN, 1, 0, GI.SL_BALANCED)) registerGame(GameInfo(593, Thirteens, "Thirteens", GI.GT_PAIRING_TYPE, 1, 0, GI.SL_LUCK)) +registerGame(GameInfo(594, Elevens, "Elevens", + GI.GT_PAIRING_TYPE, 1, 0, GI.SL_LUCK)) +registerGame(GameInfo(595, ElevensToo, "Elevens Too", + GI.GT_PAIRING_TYPE, 1, 0, GI.SL_LUCK)) +registerGame(GameInfo(596, SuitElevens, "Suit Elevens", + GI.GT_PAIRING_TYPE, 1, 0, GI.SL_LUCK)) +registerGame(GameInfo(597, Fifteens, "Fifteens", + GI.GT_PAIRING_TYPE, 1, 0, GI.SL_MOSTLY_LUCK)) diff --git a/pysollib/games/royalcotillion.py b/pysollib/games/royalcotillion.py index 728ebb28..7312d08e 100644 --- a/pysollib/games/royalcotillion.py +++ b/pysollib/games/royalcotillion.py @@ -582,8 +582,7 @@ class ThreePirates(Game): 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 + shallHighlightMatch = Game._shallHighlightMatch_SS diff --git a/pysollib/games/spider.py b/pysollib/games/spider.py index 1afc39a6..db3f23c4 100644 --- a/pysollib/games/spider.py +++ b/pysollib/games/spider.py @@ -149,9 +149,7 @@ class RelaxedSpider(Game): self.startDealSample() self.s.talon.dealRow() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return ((card1.rank + 1) % stack1.cap.mod == card2.rank or - (card2.rank + 1) % stack1.cap.mod == card1.rank) + shallHighlightMatch = Game._shallHighlightMatch_RK def getQuickPlayScore(self, ncards, from_stack, to_stack): if to_stack.cards: @@ -226,6 +224,8 @@ class GroundForADivorce(RelaxedSpider): self.startDealSample() self.s.talon.dealRow() + shallHighlightMatch = Game._shallHighlightMatch_RKW + # /*********************************************************************** # // Grandmother's Game @@ -336,8 +336,7 @@ class Scorpion(RelaxedSpider): self.startDealSample() self.s.talon.dealRow() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS def getHighlightPilesStacks(self): return () @@ -350,8 +349,7 @@ class ScorpionTail(Scorpion): Foundation_Class = Spider_AC_Foundation RowStack_Class = StackWrapper(ScorpionTail_RowStack, base_rank=KING) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.color != card2.color and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_AC class DoubleScorpion(Scorpion): @@ -613,8 +611,7 @@ class Trillium(Game): self.startDealSample() self.s.talon.dealRow() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.color != card2.color and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_AC def isGameWon(self): for s in self.s.rows: @@ -641,9 +638,7 @@ class WakeRobin(Trillium): return False return True - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return abs(card1.rank-card2.rank) == 1 - + shallHighlightMatch = Game._shallHighlightMatch_RK class TripleWakeRobin(WakeRobin): @@ -703,8 +698,7 @@ class Chelicera(Game): def getHighlightPilesStacks(self): return () - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS def isGameWon(self): for s in self.s.rows: @@ -859,10 +853,7 @@ class Applegate(Game): def getHighlightPilesStacks(self): return () - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - ((card1.rank + 1) % stack1.cap.mod == card2.rank or - (card2.rank + 1) % stack1.cap.mod == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_RKW # /*********************************************************************** @@ -903,6 +894,7 @@ class GroundForADivorce3Decks(BigSpider): RowStack_Class = StackWrapper(Spider_RowStack, mod=13) def canDealCards(self): return Game.canDealCards(self) + shallHighlightMatch = Game._shallHighlightMatch_RKW class Spider4Decks(BigSpider): @@ -942,6 +934,7 @@ class GroundForADivorce4Decks(Spider4Decks): Spider4Decks.createGame(self, rows=12) def canDealCards(self): return Game.canDealCards(self) + shallHighlightMatch = Game._shallHighlightMatch_RKW # /*********************************************************************** diff --git a/pysollib/games/sultan.py b/pysollib/games/sultan.py index b1c2930e..b3363a1c 100644 --- a/pysollib/games/sultan.py +++ b/pysollib/games/sultan.py @@ -491,12 +491,13 @@ class Matrimony(Game): # /*********************************************************************** +# // Picture Patience # // Patriarchs # ************************************************************************/ -class Patriarchs(Game): +class PicturePatience(Game): - def createGame(self, max_rounds=2): + def createGame(self, max_rounds=1): l, s = Layout(self), self.s self.setSize(3*l.XM+5*l.XS, l.YM+4*l.YS) @@ -528,14 +529,7 @@ class Patriarchs(Game): l.defaultStackGroups() - def _shuffleHook(self, cards): - return self._shuffleHookMoveToTop(cards, - lambda c: (c.rank in (ACE, KING) and c.deck == 0, - (c.rank, c.suit))) - - def startGame(self): - self.s.talon.dealRow(rows=self.s.foundations, frames=0) self.startDealSample() self.s.talon.dealRow() self.s.talon.dealCards() @@ -549,6 +543,22 @@ class Patriarchs(Game): self.s.waste.moveMove(1, stack) +class Patriarchs(PicturePatience): + def createGame(self): + PicturePatience.createGame(self, max_rounds=2) + + def _shuffleHook(self, cards): + return self._shuffleHookMoveToTop(cards, + lambda c: (c.rank in (ACE, KING) and c.deck == 0, + (c.rank, c.suit))) + + def startGame(self): + self.s.talon.dealRow(rows=self.s.foundations, frames=0) + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.dealCards() + + # /*********************************************************************** # // Simplicity # ************************************************************************/ @@ -602,10 +612,7 @@ class Simplicity(Game): self.s.talon.dealCards() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.color != card2.color and - ((card1.rank + 1) % 13 == card2.rank or - (card2.rank + 1) % 13 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_ACW def _restoreGameHook(self, game): @@ -727,8 +734,7 @@ class CornerSuite(Game): self.startDealSample() self.s.talon.dealCards() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_RK # /*********************************************************************** @@ -785,9 +791,7 @@ class Marshal(Game): self.moveMove(1, self.s.talon, stack) self.leaveState(old_state) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - (abs(card1.rank-card2.rank) == 1)) + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -855,9 +859,7 @@ class RoyalAids(Game): self.s.talon.dealCards() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.color != card2.color and - (abs(card1.rank-card2.rank) == 1)) + shallHighlightMatch = Game._shallHighlightMatch_AC # register the game @@ -892,3 +894,5 @@ registerGame(GameInfo(559, Marshal, "Marshal", GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED)) registerGame(GameInfo(565, RoyalAids, "Royal Aids", GI.GT_2DECK_TYPE, 2, UNLIMITED_REDEALS, GI.SL_BALANCED)) +registerGame(GameInfo(598, PicturePatience, "Picture Patience", + GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_LUCK)) diff --git a/pysollib/games/tournament.py b/pysollib/games/tournament.py index 2e060e7c..dd22babd 100644 --- a/pysollib/games/tournament.py +++ b/pysollib/games/tournament.py @@ -229,8 +229,7 @@ class KingsdownEights(Game): 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 + shallHighlightMatch = Game._shallHighlightMatch_AC # register the game diff --git a/pysollib/games/unionsquare.py b/pysollib/games/unionsquare.py index 3cf389d4..4b912a66 100644 --- a/pysollib/games/unionsquare.py +++ b/pysollib/games/unionsquare.py @@ -138,9 +138,7 @@ class UnionSquare(Game): self.s.talon.dealRow() self.s.talon.dealCards() # deal first card to WasteStack - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SS def getHighlightPilesStacks(self): return () diff --git a/pysollib/games/wavemotion.py b/pysollib/games/wavemotion.py index 72ba5442..75e82b1a 100644 --- a/pysollib/games/wavemotion.py +++ b/pysollib/games/wavemotion.py @@ -91,8 +91,7 @@ class WaveMotion(Game): return False return True - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS # register the game diff --git a/pysollib/games/windmill.py b/pysollib/games/windmill.py index 1a49963a..fb8025d5 100644 --- a/pysollib/games/windmill.py +++ b/pysollib/games/windmill.py @@ -143,8 +143,7 @@ class Windmill(Game): elif stack in self.s.rows and self.s.waste.cards: self.s.waste.moveMove(1, stack) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank) + shallHighlightMatch = Game._shallHighlightMatch_RK def getHighlightPilesStacks(self): return () @@ -357,9 +356,7 @@ class Czarina(Corners): def _shuffleHook(self, cards): return cards - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return ((card1.rank + 1) % 13 == card2.rank or - (card2.rank + 1) % 13 == card1.rank) + shallHighlightMatch = Game._shallHighlightMatch_RKW def _restoreGameHook(self, game): self.base_card = self.cards[game.loadinfo.base_card_id] diff --git a/pysollib/games/yukon.py b/pysollib/games/yukon.py index b37dafd8..41417bc8 100644 --- a/pysollib/games/yukon.py +++ b/pysollib/games/yukon.py @@ -115,9 +115,7 @@ class Yukon(Game): def getHighlightPilesStacks(self): return () - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.color != card2.color and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_AC # /*********************************************************************** @@ -127,9 +125,7 @@ class Yukon(Game): class RussianSolitaire(Yukon): RowStack_Class = StackWrapper(Yukon_SS_RowStack, base_rank=KING) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -367,9 +363,7 @@ class DoubleYukon(Yukon): class DoubleRussianSolitaire(DoubleYukon): RowStack_Class = StackWrapper(Yukon_SS_RowStack, base_rank=KING) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -392,9 +386,7 @@ class TripleYukon(Yukon): class TripleRussianSolitaire(TripleYukon): RowStack_Class = StackWrapper(Yukon_SS_RowStack, base_rank=KING) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -443,9 +435,7 @@ class TenAcross(Yukon): self.s.talon.dealRow() self.s.talon.dealRow(rows=self.s.reserves) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return (card1.suit == card2.suit and - (card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank)) + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -538,8 +528,7 @@ class Geoffrey(Yukon): self.s.talon.dealRow() self.s.talon.dealRow(rows=self.s.rows[:4]) - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -562,8 +551,7 @@ class Queensland(Yukon): self.s.talon.dealRow() self.s.talon.dealRowAvail() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** @@ -593,8 +581,7 @@ class OutbackPatience(Yukon): 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 + shallHighlightMatch = Game._shallHighlightMatch_SS # /*********************************************************************** diff --git a/pysollib/games/zodiac.py b/pysollib/games/zodiac.py index b6cea283..c32ffe08 100644 --- a/pysollib/games/zodiac.py +++ b/pysollib/games/zodiac.py @@ -117,8 +117,7 @@ class Zodiac(Game): self.s.talon.dealCards() - def shallHighlightMatch(self, stack1, card1, stack2, card2): - return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 + shallHighlightMatch = Game._shallHighlightMatch_SS # register the game diff --git a/pysollib/help.py b/pysollib/help.py index 45ede3ea..c42f6403 100644 --- a/pysollib/help.py +++ b/pysollib/help.py @@ -169,3 +169,9 @@ def helpHTML(app, document, dir_, top=None): help_html_viewer = viewer return viewer +def destroy_help(): + try: + help_html_viewer.destroy() + except: + pass + diff --git a/pysollib/pysoltk.py b/pysollib/pysoltk.py index 28b38121..d94fca66 100644 --- a/pysollib/pysoltk.py +++ b/pysollib/pysoltk.py @@ -32,6 +32,7 @@ from tk.soundoptionsdialog import * from tk.timeoutsdialog import * from tk.colorsdialog import * from tk.fontsdialog import * +from tk.findcarddialog import * from tk.gameinfodialog import * from tk.toolbar import * from tk.statusbar import * diff --git a/pysollib/stack.py b/pysollib/stack.py index 10d386aa..8c03ad71 100644 --- a/pysollib/stack.py +++ b/pysollib/stack.py @@ -706,6 +706,14 @@ class Stack: iy = (iy + 1) % ly return (x, y) + def getOffsetFor(self, card): + model, view = self, self + if view.can_hide_cards: + return 0, 0 + lx, ly = len(view.CARD_XOFFSET), len(view.CARD_YOFFSET) + i = list(model.cards).index(card) + return view.CARD_XOFFSET[i%lx], view.CARD_YOFFSET[i%ly] + # Fully update the view of a stack - updates # hiding, card positions and stacking order. # Avoid calling this as it is rather slow. @@ -895,7 +903,7 @@ class Stack: # def __defaultClickEventHandler(self, event, handler, start_drag=0, cancel_drag=1): - self.game.event_handled = True # for Game.clickHandler + self.game.event_handled = True # for Game.undoHandler if self.game.demo: self.game.stopDemo(event) self.game.interruptSleep() diff --git a/pysollib/tk/findcarddialog.py b/pysollib/tk/findcarddialog.py new file mode 100644 index 00000000..3bd9ac14 --- /dev/null +++ b/pysollib/tk/findcarddialog.py @@ -0,0 +1,203 @@ +##---------------------------------------------------------------------------## +## +## PySol -- a Python Solitaire game +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; see the file COPYING. +## If not, write to the Free Software Foundation, Inc., +## 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +## +##---------------------------------------------------------------------------## + +__all__ = ['create_find_card_dialog', + 'connect_game_find_card_dialog', + 'destroy_find_card_dialog', + ] + +# imports +import os +import Tkinter +import traceback + +# PySol imports + +# Toolkit imports +from tkutil import after, after_cancel +from tkutil import bind, unbind_destroy, makeImage +from tkcanvas import MfxCanvas, MfxCanvasGroup, MfxCanvasImage, MfxCanvasRectangle + + +# /*********************************************************************** +# // +# ************************************************************************/ + +class FindCardDialog(Tkinter.Toplevel): + SUIT_IMAGES = {} # key: (suit, color) + RANK_IMAGES = {} # key: (rank, color) + + def __init__(self, parent, game, dir): + Tkinter.Toplevel.__init__(self) + self.title(_('Find card')) + self.wm_resizable(0, 0) + # + self.images_dir = dir + self.label_width, self.label_height = 38, 34 + self.canvas = MfxCanvas(self, bg='white') + self.canvas.pack(expand=True, fill='both') + # + self.groups = [] + self.highlight_items = None + self.connectGame(game) + # + bind(self, "WM_DELETE_WINDOW", self.destroy) + bind(self, "", self.destroy) + # + ##self.normal_timeout = 400 # in milliseconds + self.normal_timeout = int(1000*game.app.opt.highlight_samerank_sleep) + self.hidden_timeout = 200 + self.timer = None + + def createCardLabel(self, suit, rank, x0, y0): + dx, dy = self.label_width, self.label_height + dir = self.images_dir + canvas = self.canvas + group = MfxCanvasGroup(canvas) + s = 'cshd'[suit] + if suit >= 2: c = 'red' + else: c = 'black' + rect_width = 4 + x1, y1 = x0+dx-rect_width, y0+dy-rect_width + rect = MfxCanvasRectangle(self.canvas, x0, y0, x1, y1, + width=rect_width, + fill='white', outline='white') + rect.addtag(group) + # + fn = os.path.join(dir, c+'-'+str(rank)+'.gif') + rim = FindCardDialog.RANK_IMAGES.get((rank, c)) + if not rim: + rim = makeImage(file=fn) + FindCardDialog.RANK_IMAGES[(rank, c)] = rim + fn = os.path.join(dir, s+'.gif') + sim = FindCardDialog.SUIT_IMAGES.get((suit, c)) + if not sim: + sim = makeImage(file=fn) + FindCardDialog.SUIT_IMAGES[(suit, c)] = sim + # + x0 = x0+(dx-rim.width()-sim.width())/2 + x0, y0 = x0-1, y0-2 + x, y = x0, y0+(dy-rim.height())/2 + im = MfxCanvasImage(canvas, x, y, image=rim, anchor='nw') + im.addtag(group) + x, y = x0+rim.width(), y0+(dy-sim.height())/2 + im = MfxCanvasImage(canvas, x, y, image=sim, anchor='nw') + im.addtag(group) + bind(group, '', + lambda e, suit=suit, rank=rank, rect=rect: + self.enterEvent(suit, rank, rect)) + bind(group, '', + lambda e, suit=suit, rank=rank, rect=rect: + self.leaveEvent(suit, rank, rect)) + self.groups.append(group) + + def connectGame(self, game): + self.game = game + suits = game.gameinfo.suits + ranks = game.gameinfo.ranks + dx, dy = self.label_width, self.label_height + uniq_suits = [] + i = 0 + for suit in suits: + if suit in uniq_suits: + continue + uniq_suits.append(suit) + j = 0 + for rank in ranks: + x, y = dx*j+2, dy*i+2 + self.createCardLabel(suit=suit, rank=rank, x0=x, y0=y) + j += 1 + i += 1 + w, h = dx*j, dy*i + self.canvas.config(width=w, height=h) + + def enterEvent(self, suit, rank, rect): + #print 'enterEvent', suit, rank + self.highlight_items = self.game.highlightCard(suit, rank) + if not self.highlight_items: + self.highlight_items = [] + rect.config(outline='red') + if self.highlight_items: + self.timer = after(self, self.normal_timeout, self.timeoutEvent) + + def leaveEvent(self, suit, rank, rect): + #print 'leaveEvent', suit, rank + if self.highlight_items: + for i in self.highlight_items: + i.delete() + rect.config(outline='white') + #self.game.canvas.update_idletasks() + #self.canvas.update_idletasks() + if self.timer: + after_cancel(self.timer) + self.timer = None + + def timeoutEvent(self, *event): + if self.highlight_items: + state = self.highlight_items[0].cget('state') + if state in ('', 'normal'): + state = 'hidden' + self.timer = after(self, self.hidden_timeout, + self.timeoutEvent) + else: + state = 'normal' + self.timer = after(self, self.normal_timeout, + self.timeoutEvent) + for item in self.highlight_items: + item.config(state=state) + + def destroy(self, *args): + for l in self.groups: + unbind_destroy(l) + unbind_destroy(self) + if self.timer: + after_cancel(self.timer) + self.timer = None + self.wm_withdraw() + Tkinter.Toplevel.destroy(self) + + + +find_card_dialog = None + +def create_find_card_dialog(parent, game, dir): + global find_card_dialog + try: + find_card_dialog.tkraise() + except: + ##traceback.print_exc() + find_card_dialog = FindCardDialog(parent, game, dir) + +def connect_game_find_card_dialog(game): + try: + find_card_dialog.connectGame(game) + except: + pass + +def destroy_find_card_dialog(): + global find_card_dialog + try: + find_card_dialog.destroy() + except: + ##traceback.print_exc() + pass + find_card_dialog = None + diff --git a/pysollib/tk/menubar.py b/pysollib/tk/menubar.py index ea820be5..5d1bfa10 100644 --- a/pysollib/tk/menubar.py +++ b/pysollib/tk/menubar.py @@ -320,7 +320,7 @@ class PysolMenubar(PysolMenubarActions): menu.add_command(label=n_("&Demo"), command=self.mDemo, accelerator=m+"D") menu.add_command(label=n_("Demo (&all games)"), command=self.mMixedDemo) menu.add_separator() - menu.add_command(label=n_("Show descriptions od piles"), command=self.mStackDesk, accelerator="F2") + menu.add_command(label=n_("Piles description"), command=self.mStackDesk, accelerator="F2") menu = MfxMenu(self.__menubar, label=n_("&Options")) menu.add_command(label=n_("&Player options..."), command=self.mOptPlayerOptions) submenu = MfxMenu(menu, label=n_("&Automatic play")) @@ -365,6 +365,7 @@ class PysolMenubar(PysolMenubarActions): submenu.add_radiobutton(label=n_("&Slow"), variable=self.tkopt.animations, value=3, command=self.mOptAnimations) submenu.add_radiobutton(label=n_("&Very slow"), variable=self.tkopt.animations, value=4, command=self.mOptAnimations) menu.add_checkbutton(label=n_("Stick&y mouse"), variable=self.tkopt.sticky_mouse, command=self.mOptStickyMouse) + menu.add_checkbutton(label=n_("Use mouse for undo/redo"), variable=self.tkopt.mouse_undo, command=self.mOptMouseUndo) menu.add_separator() menu.add_command(label=n_("&Fonts..."), command=self.mOptFontsOptions) menu.add_command(label=n_("&Colors..."), command=self.mOptColorsOptions) @@ -408,6 +409,7 @@ class PysolMenubar(PysolMenubarActions): self._bindKey(ctrl, "q", self.mQuit) self._bindKey("", "z", self.mUndo) self._bindKey("", "BackSpace", self.mUndo) # undocumented + self._bindKey("", "KP_Enter", self.mUndo) # undocumented self._bindKey("", "r", self.mRedo) self._bindKey(ctrl, "g", self.mRestart) self._bindKey("", "space", self.mDeal) # undocumented @@ -1004,6 +1006,10 @@ class PysolMenubar(PysolMenubarActions): if self._cancelDrag(break_pause=False): return self.app.opt.sticky_mouse = self.tkopt.sticky_mouse.get() + def mOptMouseUndo(self, *event): + if self._cancelDrag(break_pause=False): return + self.app.opt.mouse_undo = self.tkopt.mouse_undo.get() + def mOptNegativeBottom(self, *event): if self._cancelDrag(): return n = self.tkopt.negative_bottom.get() diff --git a/pysollib/tk/tkwidget.py b/pysollib/tk/tkwidget.py index d5495e90..9fec16f4 100644 --- a/pysollib/tk/tkwidget.py +++ b/pysollib/tk/tkwidget.py @@ -39,13 +39,11 @@ __all__ = ['MfxMessageDialog', 'MfxTooltip', 'MfxScrolledCanvas', 'StackDesc', - 'create_find_card_dialog', - 'connect_game_find_card_dialog', - 'destroy_find_card_dialog', ] # imports -import os, sys, time, types, Tkinter +import os, sys, time, types +import Tkinter import traceback # PySol imports @@ -53,12 +51,11 @@ from pysollib.mfxutil import destruct, kwdefault, KwStruct from pysollib.mfxutil import win32api # Toolkit imports -from tkconst import tkversion from tkconst import EVENT_HANDLED, EVENT_PROPAGATE from tkutil import after, after_idle, after_cancel -from tkutil import bind, unbind_destroy, makeImage +from tkutil import bind, unbind_destroy from tkutil import makeToplevel, setTransient -from tkcanvas import MfxCanvas, MfxCanvasGroup, MfxCanvasImage, MfxCanvasRectangle +from tkcanvas import MfxCanvas # /*********************************************************************** @@ -719,139 +716,3 @@ class StackDesc: for b in self.bindings: self.label.unbind('', b) - -# /*********************************************************************** -# // -# ************************************************************************/ - -class FindCardDialog(Tkinter.Toplevel): - SUIT_IMAGES = {} # key: (suit, color) - RANK_IMAGES = {} # key: (rank, color) - - def __init__(self, parent, game, dir, title='Find card'): - Tkinter.Toplevel.__init__(self) - self.title(title) - self.wm_resizable(0, 0) - # - self.images_dir = dir - self.label_width, self.label_height = 38, 34 - self.canvas = MfxCanvas(self, bg='white') - self.canvas.pack(expand=True, fill='both') - # - self.groups = [] - self.highlight_items = None - self.connectGame(game) - # - bind(self, "WM_DELETE_WINDOW", self.destroy) - bind(self, "", self.destroy) - - def createCardLabel(self, suit, rank, x0, y0): - dx, dy = self.label_width, self.label_height - dir = self.images_dir - canvas = self.canvas - group = MfxCanvasGroup(canvas) - s = 'cshd'[suit] - if suit >= 2: c = 'red' - else: c = 'black' - rect_width = 4 - x1, y1 = x0+dx-rect_width, y0+dy-rect_width - rect = MfxCanvasRectangle(self.canvas, x0, y0, x1, y1, - width=rect_width, - fill='white', outline='white') - rect.addtag(group) - # - fn = os.path.join(dir, c+'-'+str(rank)+'.gif') - rim = FindCardDialog.RANK_IMAGES.get((rank, c)) - if not rim: - rim = makeImage(file=fn) - FindCardDialog.RANK_IMAGES[(rank, c)] = rim - fn = os.path.join(dir, s+'.gif') - sim = FindCardDialog.SUIT_IMAGES.get((suit, c)) - if not sim: - sim = makeImage(file=fn) - FindCardDialog.SUIT_IMAGES[(suit, c)] = sim - # - x0 = x0+(dx-rim.width()-sim.width())/2 - x0, y0 = x0-1, y0-2 - x, y = x0, y0+(dy-rim.height())/2 - im = MfxCanvasImage(canvas, x, y, image=rim, anchor='nw') - im.addtag(group) - x, y = x0+rim.width(), y0+(dy-sim.height())/2 - im = MfxCanvasImage(canvas, x, y, image=sim, anchor='nw') - im.addtag(group) - bind(group, '', - lambda e, suit=suit, rank=rank, rect=rect: - self.enterEvent(suit, rank, rect)) - bind(group, '', - lambda e, suit=suit, rank=rank, rect=rect: - self.leaveEvent(suit, rank, rect)) - self.groups.append(group) - - def connectGame(self, game): - self.game = game - suits = game.gameinfo.suits - ranks = game.gameinfo.ranks - dx, dy = self.label_width, self.label_height - i = 0 - for suit in suits: - j = 0 - for rank in ranks: - x, y = dx*j+2, dy*i+2 - self.createCardLabel(suit=suit, rank=rank, x0=x, y0=y) - j += 1 - i += 1 - w, h = dx*j, dy*i - self.canvas.config(width=w, height=h) - - def enterEvent(self, suit, rank, rect): - #print 'enterEvent', suit, rank - self.last_card = (suit, rank) - self.highlight_items = self.game.highlightCard(suit, rank) - if not self.highlight_items: - self.highlight_items = [] - rect.config(outline='red') - - def leaveEvent(self, suit, rank, rect): - #print 'leaveEvent', suit, rank - if self.highlight_items: - for i in self.highlight_items: - i.delete() - rect.config(outline='white') - #self.game.canvas.update_idletasks() - #self.canvas.update_idletasks() - self.last_card = None - - def destroy(self, *args): - for l in self.groups: - unbind_destroy(l) - unbind_destroy(self) - self.wm_withdraw() - Tkinter.Toplevel.destroy(self) - - - -find_card_dialog = None - -def create_find_card_dialog(parent, game, dir): - global find_card_dialog - try: - find_card_dialog.tkraise() - except: - ##traceback.print_exc() - find_card_dialog = FindCardDialog(parent, game, dir) - -def connect_game_find_card_dialog(game): - try: - find_card_dialog.connectGame(game) - except: - pass - -def destroy_find_card_dialog(): - global find_card_dialog - try: - find_card_dialog.destroy() - except: - ##traceback.print_exc() - pass - find_card_dialog = None -