From 62b7604757523f27e5f5eafe61261ac1af957e4e Mon Sep 17 00:00:00 2001
From: skomoroh <skomoroh@39dd0a4e-7c14-0410-91b3-c4f2d318f732>
Date: Thu, 23 Aug 2007 21:37:07 +0000
Subject: [PATCH] * fixed games: `Salic Law', `Four by Four' * minor bugfixes

git-svn-id: https://pysolfc.svn.sourceforge.net/svnroot/pysolfc/PySolFC/trunk@197 39dd0a4e-7c14-0410-91b3-c4f2d318f732
---
 pysollib/game.py                |  5 +-
 pysollib/games/golf.py          |  2 +
 pysollib/games/katzenschwanz.py | 87 ++++++++++++++++++++++++---------
 pysollib/games/pileon.py        |  3 +-
 pysollib/games/pyramid.py       |  2 +
 pysollib/games/spider.py        | 17 ++++---
 pysollib/stack.py               |  7 ++-
 pysollib/tile/menubar.py        | 17 ++-----
 pysollib/tile/toolbar.py        | 12 +++--
 pysollib/tk/menubar.py          | 17 ++-----
 pysollib/winsystems/common.py   |  2 -
 pysollib/winsystems/x11.py      |  6 +--
 12 files changed, 106 insertions(+), 71 deletions(-)

diff --git a/pysollib/game.py b/pysollib/game.py
index 3a2e5cad..613a32e8 100644
--- a/pysollib/game.py
+++ b/pysollib/game.py
@@ -915,9 +915,12 @@ class Game:
             if k == "gamenumber":
                 if v is None:
                     if sb: sb.updateText(gamenumber="")
+                    #self.top.wm_title("%s - %s" % (TITLE, self.getTitleName()))
                     continue
-                if isinstance(v, str):
+                if isinstance(v, basestring):
                     if sb: sb.updateText(gamenumber=v)
+                    #self.top.wm_title("%s - %s %s" % (TITLE,
+                    #                                  self.getTitleName(), v))
                     continue
             if k == "info":
                 ##print 'updateStatus info:', v
diff --git a/pysollib/games/golf.py b/pysollib/games/golf.py
index 774efd38..baf46304 100644
--- a/pysollib/games/golf.py
+++ b/pysollib/games/golf.py
@@ -878,6 +878,8 @@ class ThreeFirTrees_RowStack(Golf_RowStack):
                 return True
         return False
 
+    getBottomImage = Stack._getNoneBottomImage
+
 
 class FirTree_GameMethods:
     def _createFirTree(self, l, x0, y0):
diff --git a/pysollib/games/katzenschwanz.py b/pysollib/games/katzenschwanz.py
index 307171eb..da9d4528 100644
--- a/pysollib/games/katzenschwanz.py
+++ b/pysollib/games/katzenschwanz.py
@@ -217,13 +217,7 @@ class SalicLaw_Hint(CautiousDefaultHint):
         return score+len(r.cards), color
 
 
-class SalicLaw_Talon(OpenTalonStack):
-
-    def canDealCards(self):
-        return True
-
-    def canFlipCard(self):
-        return False
+class SalicLaw_Talon(TalonStack):
 
     def dealCards(self, sound=False):
         if len(self.cards) == 0:
@@ -237,28 +231,62 @@ class SalicLaw_Talon(OpenTalonStack):
             to_stack = rows[ri]
         else:
             to_stack = rows[ri-1]
-        ##frames = (3, 4)[ri > 4]
-        frames = 3
         if sound and not self.game.demo:
             self.game.startDealSample()
-        self.game.flipMove(self)
-        self.game.moveMove(1, self, to_stack, frames=frames)
+        self.dealToStacks(stacks=[to_stack])
         if sound and not self.game.demo:
             self.game.stopSamples()
-        self.game.leaveState(old_state)
         return 1
 
+# all Aces go to the Foundations
+class SalicLaw_Talon_2(SalicLaw_Talon):
+    def dealCards(self, sound=False):
+        if len(self.cards) == 0:
+            return 0
+        if self.cards[-1].rank == ACE:
+            for f in self.game.s.foundations:
+                if not f.cards:
+                    break
+            if sound and not self.game.demo:
+                self.game.startDealSample()
+            self.dealToStacks(stacks=[f])
+            if sound and not self.game.demo:
+                self.game.stopSamples()
+            return 1
+        else:
+            return SalicLaw_Talon.dealCards(self, sound=sound)
+
+
+class SalicLaw_RowStack(OpenStack):
+    def acceptsCards(self, from_stack, cards):
+        if len(self.cards) == 1:
+            return True
+        return False
+        return OpenStack.acceptsCards(self, from_stack, cards)
+
+
+class SalicLaw_Foundation(RK_FoundationStack):
+    def acceptsCards(self, from_stack, cards):
+        if not RK_FoundationStack.acceptsCards(self, from_stack, cards):
+            return False
+        if from_stack not in self.game.s.rows:
+            return False
+        row_id = self.id + 8
+        return len(self.game.allstacks[row_id].cards) > 0
+
 
 class SalicLaw(DerKatzenschwanz):
 
     Hint_Class = SalicLaw_Hint
     Solver_Class = None
 
+    Talon_Class = SalicLaw_Talon_2
     Foundation_Classes = [
         StackWrapper(AbstractFoundationStack, max_cards=1, base_rank=QUEEN),
-        StackWrapper(RK_FoundationStack, base_rank=ACE, max_cards=11),
+        StackWrapper(SalicLaw_Foundation, max_cards=11, base_rank=ACE),
         ]
-    RowStack_Class = OpenStack
+    RowStack_Class = StackWrapper(SalicLaw_RowStack, min_cards=1,
+                                  max_accept=UNLIMITED_ACCEPTS)
 
     ROW_BASE_RANK = KING
 
@@ -301,7 +329,7 @@ class SalicLaw(DerKatzenschwanz):
             stack.CARD_YOFFSET = yoffset
             s.rows.append(stack)
             x += l.XS
-        s.talon = SalicLaw_Talon(l.XM+9*l.XS, l.YM, self)
+        s.talon = self.Talon_Class(l.XM+9*l.XS, l.YM, self)
         l.createText(s.talon, "s")
 
         # define stack-groups
@@ -317,10 +345,13 @@ class SalicLaw(DerKatzenschwanz):
                 cards.remove(c)
                 break
         cards.append(c)
+        cards = self._shuffleHookMoveToTop(cards,
+                                           lambda c: (c.rank == QUEEN, None))
         return cards
 
     def startGame(self):
         self.startDealSample()
+        self.s.talon.dealRow(self.s.foundations[:8]) # deal Queens
         self.s.talon.dealRow(self.s.rows[:1]) # deal King
 
     def isGameWon(self):
@@ -329,14 +360,6 @@ class SalicLaw(DerKatzenschwanz):
                 return False
         return True
 
-    def getAutoStacks(self, event=None):
-        if event is None:
-            # disable auto drop
-            return (self.sg.dropstacks, (), self.sg.dropstacks)
-        else:
-            # rightclickHandler
-            return (self.sg.dropstacks, self.sg.dropstacks, self.sg.dropstacks)
-
 
 # /***********************************************************************
 # // Deep
@@ -371,11 +394,24 @@ class FaerieQueen_RowStack(RK_RowStack):
 
 class FaerieQueen(SalicLaw):
 
+    Talon_Class = SalicLaw_Talon
     Foundation_Classes = [
         StackWrapper(RK_FoundationStack, max_move=0, max_cards=12)
         ]
     RowStack_Class = StackWrapper(FaerieQueen_RowStack, min_cards=1, max_move=1)
 
+    def _shuffleHook(self, cards):
+        for c in cards[:]:
+            if c.rank == KING:
+                cards.remove(c)
+                break
+        cards.append(c)
+        return cards
+
+    def startGame(self):
+        self.startDealSample()
+        self.s.talon.dealRow(self.s.rows[:1]) # deal King
+
     def isGameWon(self):
         if self.s.talon.cards:
             return False
@@ -405,6 +441,7 @@ class Intrigue_RowStack(OpenStack):
 
 class Intrigue(SalicLaw):
 
+    Talon_Class = SalicLaw_Talon
     Foundation_Classes = [
         StackWrapper(RK_FoundationStack, base_rank=5, max_cards=6),
         StackWrapper(RK_FoundationStack, base_rank=4, max_cards=6, dir=-1, mod=13),
@@ -421,6 +458,10 @@ class Intrigue(SalicLaw):
         cards.append(c)
         return cards
 
+    def startGame(self):
+        self.startDealSample()
+        self.s.talon.dealRow(self.s.rows[:1]) # deal King
+
     def isGameWon(self):
         if self.s.talon.cards:
             return False
diff --git a/pysollib/games/pileon.py b/pysollib/games/pileon.py
index 89214aeb..bad14e55 100644
--- a/pysollib/games/pileon.py
+++ b/pysollib/games/pileon.py
@@ -273,7 +273,7 @@ class FourByFour(Game):
         x += 3.5*l.XS
         s.foundations.append(FourByFour_Foundation(x, y, self,
                              suit=ANY_SUIT, base_rank=ANY_RANK, max_cards=52,
-                             max_accept=1, max_move=0))
+                             max_accept=1, max_move=0, mod=13))
         stack = s.foundations[0]
         tx, ty, ta, tf = l.getTextAttr(stack, 'ne')
         font = self.app.getFont('canvas_default')
@@ -316,6 +316,7 @@ class FourByFour(Game):
             if n == 0:
                 n = 4*decks
                 r = (r+1) % f.cap.mod
+            r = r % 13
             r = RANKS[r]
             t = '%s (%d)' % (r, n)
         f.texts.misc.config(text=t)
diff --git a/pysollib/games/pyramid.py b/pysollib/games/pyramid.py
index 74a14ac2..70ff8173 100644
--- a/pysollib/games/pyramid.py
+++ b/pysollib/games/pyramid.py
@@ -155,6 +155,8 @@ class Pyramid_RowStack(Pyramid_StackMethods, OpenStack):
             return 1
         return OpenStack.clickHandler(self, event)
 
+    getBottomImage = Stack._getNoneBottomImage
+
 
 # /***********************************************************************
 # // Pyramid
diff --git a/pysollib/games/spider.py b/pysollib/games/spider.py
index 4c25dfe4..aae21dc0 100644
--- a/pysollib/games/spider.py
+++ b/pysollib/games/spider.py
@@ -534,7 +534,7 @@ class Cicely(Game):
         l, s = Layout(self), self.s
 
         # set window
-        w, h = l.XM+10*l.XS, l.YM+max(5*l.YS, 2*l.YS+16*l.YOFFSET)
+        w, h = l.XM+11*l.XS, l.YM+max(5*l.YS, 2*l.YS+16*l.YOFFSET)
         self.setSize(w, h)
 
         # create stacks
@@ -542,24 +542,25 @@ class Cicely(Game):
         for i in range(4):
             s.foundations.append(SS_FoundationStack(x, y, self, suit=i))
             y += l.YS
-        x, y = l.XM+9*l.XS, l.YM+l.YS
+        x, y = l.XM+10*l.XS, l.YM+l.YS
         for i in range(4):
             s.foundations.append(SS_FoundationStack(x, y, self, suit=i, base_rank=KING, dir=-1))
             y += l.YS
-        x, y = l.XM+l.XS, l.YM
+        x, y = l.XM+1.5*l.XS, l.YM
         for i in range(8):
             s.reserves.append(ReserveStack(x, y, self))
             x += l.XS
-        x, y = l.XM+l.XS, l.YM+l.YS
+        x, y = l.XM+1.5*l.XS, l.YM+l.YS
         for i in range(8):
             s.rows.append(UD_SS_RowStack(x, y, self))
             x += l.XS
         s.talon = Cicely_Talon(l.XM, l.YM, self)
-        l.setRegion(s.rows, (l.XM+l.XS-l.CW/2, l.YM+l.YS-l.CH/2,
-                             w-l.XS-l.CW/2, 999999))
+        l.createText(s.talon, "ne")
+        l.setRegion(s.rows, (l.XM+1.5*l.XS-l.CW/2, l.YM+l.YS-l.CH/2,
+                             w-1.5*l.XS-l.CW/2, 999999))
 
-        # default
-        l.defaultAll()
+        # define stack-groups
+        l.defaultStackGroups()
 
 
     def startGame(self):
diff --git a/pysollib/stack.py b/pysollib/stack.py
index 628f21f3..b2127fc3 100644
--- a/pysollib/stack.py
+++ b/pysollib/stack.py
@@ -298,6 +298,7 @@ class Stack:
         view.canvas = game.canvas
         view.CARD_XOFFSET = 0
         view.CARD_YOFFSET = 0
+        view.INIT_CARD_YOFFSET = 0      # for reallocateCards
         view.group = MfxCanvasGroup(view.canvas)
         view.shrink_face_down = 1
         ##view.group.move(view.x, view.y)
@@ -676,7 +677,7 @@ class Stack:
 
     def resetGame(self):
         # Called when starting a new game.
-        pass
+        self.CARD_YOFFSET = self.INIT_CARD_YOFFSET
 
     def __repr__(self):
         # Return a string for debug print statements.
@@ -868,6 +869,7 @@ class Stack:
 
     def reallocateCards(self):
         # change CARD_YOFFSET if a cards is off-screen
+        # returned False if CARD_YOFFSET is not changed, otherwise True
         if not self.game.app.opt.squeeze_stacks:
             return False
         if TOOLKIT != 'tk':
@@ -878,7 +880,7 @@ class Stack:
             return False
         if self.CARD_YOFFSET[0] <= 0:
             return False
-        if len(self.cards) <= 1:
+        if len(self.cards) <= 8:        # XXX
             return False
         if not self.canvas.winfo_ismapped():
             return False
@@ -1735,6 +1737,7 @@ class TalonStack(Stack,
         self.resetGame()
 
     def resetGame(self):
+        Stack.resetGame(self)
         self.round = 1
         self.base_cards = []        # for DealBaseCard_StackMethods
 
diff --git a/pysollib/tile/menubar.py b/pysollib/tile/menubar.py
index 2c53e499..9e0834b7 100644
--- a/pysollib/tile/menubar.py
+++ b/pysollib/tile/menubar.py
@@ -888,22 +888,13 @@ class PysolMenubar(PysolMenubarActions):
 
 
     def updateRecentGamesMenu(self, gameids):
-        # delete all entries
         submenu = self.__menupath[".menubar.file.recentgames"][2]
-        submenu.delete(0, "last")
-        # insert games
-        cb = (25, self.__cb_max) [ len(gameids) > 4 * 25 ]
-        i = 0
+        games = []
         for id in gameids:
             gi = self.app.getGameInfo(id)
-            if not gi:
-                continue
-            columnbreak = i > 0 and (i % cb) == 0
-            submenu.add_radiobutton(command=self.mSelectGame,
-                                    variable=self.tkopt.gameid,
-                                    columnbreak=columnbreak,
-                                    value=gi.id, label=gi.name)
-            i = i + 1
+            if gi:
+                games.append(gi)
+        self.updateGamesMenu(submenu, games)
 
     def updateBookmarkMenuState(self):
         state = self._getEnabledState
diff --git a/pysollib/tile/toolbar.py b/pysollib/tile/toolbar.py
index 9000afdd..917dd418 100644
--- a/pysollib/tile/toolbar.py
+++ b/pysollib/tile/toolbar.py
@@ -278,6 +278,8 @@ class PysolToolbar(PysolToolbarActions):
 
     def _createDisabledButtonImage(self, tkim):
         # grayscale and light-up image
+        if not tkim:
+            return None
         im = tkim._pil_image
         dis_im = ImageOps.grayscale(im)
         ##color = '#ffffff'
@@ -292,14 +294,14 @@ class PysolToolbar(PysolToolbarActions):
 
     def _setButtonImage(self, button, name):
         image = self._loadImage(name)
-        if Image: # ??? and WIN_SYSTEM != 'aqua':
+        setattr(self, name + "_image", image)
+        if Image: # XXX: and WIN_SYSTEM != 'aqua':
             dis_image = self._createDisabledButtonImage(image)
-            setattr(self, name + "_disabled_image", dis_image)
-            setattr(self, name + "_image", image)
-            button.config(image=(image, 'disabled', dis_image))
+            if dis_image:
+                setattr(self, name + "_disabled_image", dis_image)
+                button.config(image=(image, 'disabled', dis_image))
         else:
             image = self._loadImage(name)
-            setattr(self, name + "_image", image)
             button.config(image=image)
 
     def _createButton(self, label, command, check=False, tooltip=None):
diff --git a/pysollib/tk/menubar.py b/pysollib/tk/menubar.py
index 7a9307de..e4e3dc75 100644
--- a/pysollib/tk/menubar.py
+++ b/pysollib/tk/menubar.py
@@ -889,22 +889,13 @@ class PysolMenubar(PysolMenubarActions):
 
 
     def updateRecentGamesMenu(self, gameids):
-        # delete all entries
         submenu = self.__menupath[".menubar.file.recentgames"][2]
-        submenu.delete(0, "last")
-        # insert games
-        cb = (25, self.__cb_max) [ len(gameids) > 4 * 25 ]
-        i = 0
+        games = []
         for id in gameids:
             gi = self.app.getGameInfo(id)
-            if not gi:
-                continue
-            columnbreak = i > 0 and (i % cb) == 0
-            submenu.add_radiobutton(command=self.mSelectGame,
-                                    variable=self.tkopt.gameid,
-                                    columnbreak=columnbreak,
-                                    value=gi.id, label=gi.name)
-            i = i + 1
+            if gi:
+                games.append(gi)
+        self.updateGamesMenu(submenu, games)
 
     def updateBookmarkMenuState(self):
         state = self._getEnabledState
diff --git a/pysollib/winsystems/common.py b/pysollib/winsystems/common.py
index 9d38ef89..5556afae 100644
--- a/pysollib/winsystems/common.py
+++ b/pysollib/winsystems/common.py
@@ -76,8 +76,6 @@ def get_font_name(font):
             traceback.print_exc()
     else:
         fa = f.actual()
-        if fa['size'] > 0:
-            fa['size'] = -fa['size']
         font_name = (fa['family'],
                      fa['size'],
                      fa['slant'],
diff --git a/pysollib/winsystems/x11.py b/pysollib/winsystems/x11.py
index 61c68713..96937e96 100644
--- a/pysollib/winsystems/x11.py
+++ b/pysollib/winsystems/x11.py
@@ -111,7 +111,7 @@ def init_root_window(root, app):
             # use font from xrdb
             fn = get_font_name(font)
             if fn:
-                root.option_add('*font', font)
+                ##root.option_add('*font', font)
                 style.configure('.', font=font)
                 app.opt.fonts['default'] = fn
                 # treeview heading
@@ -154,8 +154,8 @@ def init_root_window(root, app):
             fn = get_font_name(font)
             app.opt.fonts['default'] = fn
         else:
-            root.option_add('*font', 'helvetica -12', 60)
-            app.opt.fonts['default'] = ('helvetica', -12,
+            root.option_add('*font', 'helvetica 12', 60)
+            app.opt.fonts['default'] = ('helvetica', 12,
                                         'roman', 'normal')