From 3eafc6253cca3a6a406f85b77bb9bed1366b95f6 Mon Sep 17 00:00:00 2001 From: skomoroh Date: Sat, 9 Dec 2006 22:09:39 +0000 Subject: [PATCH] + 2 new games * improved tile/toolbar git-svn-id: https://pysolfc.svn.sourceforge.net/svnroot/pysolfc/PySolFC/trunk@108 39dd0a4e-7c14-0410-91b3-c4f2d318f732 --- pysollib/games/camelot.py | 67 ++++++++++++++++++++ pysollib/games/pileon.py | 123 +++++++++++++++++++++++++++++++++++++ pysollib/tile/menubar.py | 21 ------- pysollib/tile/tkutil.py | 15 +++-- pysollib/tile/toolbar.py | 124 +++++--------------------------------- 5 files changed, 214 insertions(+), 136 deletions(-) diff --git a/pysollib/games/camelot.py b/pysollib/games/camelot.py index 02378c6b..da28142a 100644 --- a/pysollib/games/camelot.py +++ b/pysollib/games/camelot.py @@ -573,6 +573,71 @@ class GrandmammasPatience(Game): +# /*********************************************************************** +# // Double Line +# ************************************************************************/ + +class DoubleLine_RowStack(BasicRowStack): + def acceptsCards(self, from_stack, cards): + if not BasicRowStack.acceptsCards(self, from_stack, cards): + return 0 + # this stack accepts any one card from the Waste pile + return from_stack is self.game.s.waste + + def getHelp(self): + return _('Tableau. Build regardless of rank and suit.') + + +class DoubleLine(Game): + + def createGame(self): + + l, s = Layout(self), self.s + h0 = l.YS+3*l.YOFFSET + self.setSize(l.XM+10*l.XS, l.YM+l.YS+l.TEXT_HEIGHT+2*h0) + + x, y = l.XM, l.YM + s.talon = WasteTalonStack(x, y, self, max_rounds=1) + l.createText(s.talon, 's') + x += l.XS + s.waste = WasteStack(x, y, self) + l.createText(s.waste, 's') + + x += l.XS + for i in range(4): + s.foundations.append(SS_FoundationStack(x, y, self, suit=i%4)) + x += l.XS + for i in range(4): + s.foundations.append(SS_FoundationStack(x, y, self, suit=i, + base_rank=KING, dir=-1)) + x += l.XS + + y = l.YM+l.YS+l.TEXT_HEIGHT + for i in range(2): + x = l.XM + for j in range(10): + s.rows.append(DoubleLine_RowStack(x, y, self, max_cards=2, + max_move=1, max_accept=1, base_rank=NO_RANK)) + x += l.XS + y += h0 + + l.defaultStackGroups() + + def startGame(self): + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.dealCards() + + def fillStack(self, stack): + if stack in self.s.rows and not stack.cards: + old_state = self.enterState(self.S_FILL) + if not self.s.waste.cards: + self.s.talon.dealCards() + if self.s.waste.cards: + self.s.waste.moveMove(1, stack) + self.leaveState(old_state) + + # register the game registerGame(GameInfo(280, Camelot, "Camelot", GI.GT_1DECK_TYPE, 1, 0, GI.SL_BALANCED)) @@ -584,5 +649,7 @@ registerGame(GameInfo(623, PrincessPatience, "Princess Patience", GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED)) registerGame(GameInfo(622, GrandmammasPatience, "Grandmamma's Patience", GI.GT_NUMERICA, 2, 0, GI.SL_MOSTLY_SKILL)) +registerGame(GameInfo(702, DoubleLine, "Double Line", + GI.GT_NUMERICA, 2, 0, GI.SL_BALANCED)) diff --git a/pysollib/games/pileon.py b/pysollib/games/pileon.py index e7df1948..6f05c127 100644 --- a/pysollib/games/pileon.py +++ b/pysollib/games/pileon.py @@ -41,6 +41,8 @@ from pysollib.stack import * from pysollib.game import Game from pysollib.layout import Layout from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint +from pysollib.pysoltk import MfxCanvasText + # /*********************************************************************** # // PileOn @@ -202,6 +204,125 @@ class Quartets(Foursome): self.s.talon.dealRowAvail() +# /*********************************************************************** +# // Four by Four +# ************************************************************************/ + +class FourByFour_Hint(DefaultHint): + + def _getMovePileScore(self, score, color, r, t, pile, rpile): + self.bonus_color = color + if len(t.cards) == 0: + return 0, color + return score + 1000 - len(r.cards), color + + def _getDropCardScore(self, score, color, r, t, ncards): + # drop immediately + return 93000, color + + +class FourByFour_Foundation(AbstractFoundationStack): + + def _getNumSameCards(self): + rank = self.cards[-1].rank + n = 1 + for i in range(2,5): + if len(self.cards) < i: + break + if self.cards[-i].rank != rank: + break + n += 1 + return n + + def _getDir(self): + if len(self.cards) < 4: + return 0 + if isRankSequence(self.cards[-4:], dir=0): + return 1 + return 0 + + def acceptsCards(self, from_stack, cards): + if not AbstractFoundationStack.acceptsCards(self, from_stack, cards): + return False + dir = self._getDir() + return (self.cards[-1].rank+dir) % 13 == cards[0].rank + + if len(self.cards) < 4: + return cards[0].rank == self.cards[-1].rank + if isRankSequence(self.cards[-4:], dir=0): + return (cards[0].rank+1) % 13 == self.cards[-1].rank + return cards[0].rank == self.cards[-1].rank + + def getHelp(self): + return _('Foundation. Build up regardless of suit.') + + +class FourByFour_RowStack(UD_RK_RowStack): + def getBottomImage(self): + return self.game.app.images.getReserveBottom() + + +class FourByFour(Game): + Hint_Class = FourByFour_Hint + + def createGame(self): + + l, s = Layout(self), self.s + self.setSize(l.XM+7*l.XS, l.YM+2*l.YS+20*l.YOFFSET) + + x, y = l.XM, l.YM + s.talon = WasteTalonStack(y, x, self, max_rounds=1) + l.createText(s.talon, 's') + x += l.XS + s.waste = WasteStack(x, y, self) + l.createText(s.waste, 's') + + 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)) + stack = s.foundations[0] + tx, ty, ta, tf = l.getTextAttr(stack, 'ne') + font = self.app.getFont('canvas_default') + stack.texts.misc = MfxCanvasText(self.canvas, tx, ty, + anchor=ta, font=font) + + x, y = l.XM+3*l.XS, l.YM+l.YS + for i in range(4): + s.rows.append(FourByFour_RowStack(x, y, self, mod=13)) + x += l.XS + + l.defaultStackGroups() + + + def startGame(self): + self.startDealSample() + self.s.talon.dealRow(rows=self.s.foundations) + self.s.talon.dealCards() + + def updateText(self): + if self.preview > 1: + return + f = self.s.foundations[0] + if not f.cards: + return + if len(f.cards) == 52: + t = '' + else: + n = f._getNumSameCards() + n = 4-n + r = f.cards[-1].rank + if n == 0: + n = 4 + r = (r+1)%13 + r = RANKS[r] + t = '%s (%d)' % (r, n) + f.texts.misc.config(text=t) + + shallHighlightMatch = Game._shallHighlightMatch_RKW + + + # register the game registerGame(GameInfo(41, PileOn, "PileOn", GI.GT_1DECK_TYPE | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL, @@ -214,5 +335,7 @@ registerGame(GameInfo(554, Foursome, "Foursome", GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_SKILL)) registerGame(GameInfo(555, Quartets, "Quartets", GI.GT_1DECK_TYPE | GI.GT_OPEN | GI.GT_ORIGINAL, 1, 0, GI.SL_MOSTLY_SKILL)) +registerGame(GameInfo(703, FourByFour, "Four by Four", + GI.GT_1DECK_TYPE, 1, 0, GI.SL_BALANCED)) diff --git a/pysollib/tile/menubar.py b/pysollib/tile/menubar.py index c06e8cf8..8f07105c 100644 --- a/pysollib/tile/menubar.py +++ b/pysollib/tile/menubar.py @@ -82,16 +82,6 @@ def createToolbarMenu(menubar, menu): submenu.add_radiobutton(label=name, variable=menubar.tkopt.toolbar_style, value=f, command=menubar.mOptToolbarStyle) - -## submenu = MfxMenu(menu, label=n_('Relief'), tearoff=tearoff) -## submenu.add_radiobutton(label=n_('Flat'), -## variable=menubar.tkopt.toolbar_relief, -## value=Tkinter.FLAT, -## command=menubar.mOptToolbarRelief) -## submenu.add_radiobutton(label=n_('Raised'), -## variable=menubar.tkopt.toolbar_relief, -## value=Tkinter.RAISED, -## command=menubar.mOptToolbarRelief) submenu = MfxMenu(menu, label=n_('Compound'), tearoff=tearoff) for comp, label in COMPOUNDS: submenu.add_radiobutton( @@ -1201,10 +1191,6 @@ class PysolMenubar(PysolMenubarActions): ##if self._cancelDrag(break_pause=False): return self.setToolbarSize(self.tkopt.toolbar_size.get()) - def mOptToolbarRelief(self, *event): - ##if self._cancelDrag(break_pause=False): return - self.setToolbarRelief(self.tkopt.toolbar_relief.get()) - def mOptToolbarConfig(self, w): self.toolbarConfig(w, self.tkopt.toolbar_vars[w].get()) @@ -1297,13 +1283,6 @@ class PysolMenubar(PysolMenubarActions): self.game.updateStatus(player=self.app.opt.player) self.top.update_idletasks() - def setToolbarRelief(self, relief): - if self._cancelDrag(break_pause=False): return - self.app.opt.toolbar_relief = relief - self.tkopt.toolbar_relief.set(relief) # update radiobutton - self.app.toolbar.setRelief(relief) - self.top.update_idletasks() - def toolbarConfig(self, w, v): if self._cancelDrag(break_pause=False): return self.app.opt.toolbar_vars[w] = v diff --git a/pysollib/tile/tkutil.py b/pysollib/tile/tkutil.py index 1ee01d76..aa0a918c 100644 --- a/pysollib/tile/tkutil.py +++ b/pysollib/tile/tkutil.py @@ -447,17 +447,22 @@ def load_theme(app, top, theme): color = style.lookup('.', 'background') if color: try: - ##top.tk.call("tk_setPalette", color) top.tk_setPalette(color) ##top.option_add('*background', color) + pass except: traceback.print_exc() pass - color = style.lookup('.', 'background', 'active') - if color: - top.option_add('*Menu.activeBackground', color) + if os.name == 'posix': + color = style.lookup('.', 'background', 'active') + if color: + top.option_add('*Menu.activeBackground', color) + elif os.name == 'nt': + ##top.option_add('*Menu.foreground', 'black') + top.option_add('*Menu.activeBackground', '#08246b') + top.option_add('*Menu.activeForeground', 'white') if theme == 'winnative': - style.configure('Toolbutton', padding=1) + style.configure('Toolbutton', padding=2) #if 'xpnative' in all_themes: # theme = 'xpnative' font = app.opt.fonts['default'] diff --git a/pysollib/tile/toolbar.py b/pysollib/tile/toolbar.py index b227520f..d361d37b 100644 --- a/pysollib/tile/toolbar.py +++ b/pysollib/tile/toolbar.py @@ -76,10 +76,10 @@ class AbstractToolbarButton: if self.visible and not force: return self.visible = True - if orient == Tkinter.HORIZONTAL: + if orient == 'horizontal': padx, pady = 0, 2 if os.name == 'nt': - padx, pady = 0, 0 + padx, pady = 2, 2 self.grid(row=0, column=self.position, padx=padx, pady=pady, @@ -87,7 +87,7 @@ class AbstractToolbarButton: else: padx, pady = 2, 0 if os.name == 'nt': - padx, pady = 0, 0 + padx, pady = 2, 2 self.grid(row=self.position, column=0, padx=padx, pady=pady, @@ -123,15 +123,15 @@ class ToolbarSeparator(Tkinter.Separator): if self.visible and not force: return self.visible = True - padx = 4 - pady = 4 - if orient == Tkinter.HORIZONTAL: + if orient == 'horizontal': + padx, pady = 4, 6 self.config(orient='vertical') self.grid(row=0, column=self.position, padx=padx, pady=pady, sticky='nsew') else: + padx, pady = 4, 6 self.config(orient='horizontal') self.grid(row=self.position, column=0, @@ -142,40 +142,6 @@ class ToolbarSeparator(Tkinter.Separator): self.visible = False self.grid_forget() -class ToolbarSeparator__(Tkinter.Frame): - def __init__(self, parent, toolbar, position, **kwargs): - Tkinter.Frame.__init__(self, parent, **kwargs) - self.toolbar = toolbar - self.position = position - self.visible = False - def show(self, orient, force=False): - if self.visible and not force: - return - self.visible = True - width = 4 - height = 4 - padx = 6 - pady = 6 - if orient == Tkinter.HORIZONTAL: - self.config(width=width, height=height) - self.grid(row=0, - column=self.position, - padx=padx, pady=pady, - sticky='ns') - else: - self.config(width=height, height=width) - self.grid(row=self.position, - column=0, - padx=pady, pady=padx, - sticky='ew') - def hide(self): - if not self.visible: return - self.visible = False - self.grid_forget() - -class ToolbarFlatSeparator(ToolbarSeparator): - pass - class ToolbarLabel(Tkinter.Message): def __init__(self, parent, toolbar, toolbar_name, position, **kwargs): Tkinter.Message.__init__(self, parent, **kwargs) @@ -187,9 +153,10 @@ class ToolbarLabel(Tkinter.Message): if self.visible and not force: return self.visible = True - padx = 4 - pady = 4 - if orient == Tkinter.HORIZONTAL: + padx, pady = 4, 4 + if os.name == 'nt': + padx, pady = 6, 6 + if orient == 'horizontal': self.grid(row=0, column=self.position, padx=padx, pady=pady, @@ -217,7 +184,6 @@ class PysolToolbar(PysolToolbarActions): PysolToolbarActions.__init__(self) self.top = top - self._setRelief(relief) self.side = -1 self._tooltips = [] self._widgets = [] @@ -225,12 +191,8 @@ class PysolToolbar(PysolToolbarActions): self.size = size self.compound = compound self.orient='horizontal' - self.label_padx = 4 - self.label_pady = 4 - self.button_pad = 2 # - #self.frame = Tkinter.Frame(top, class_='Toolbar') - self.frame = Tk.Frame(top) + self.frame = Tkinter.Frame(top, class_='Toolbar') # for l, f, t in ( (n_("New"), self.mNewGame, _("New game")), @@ -257,7 +219,6 @@ class PysolToolbar(PysolToolbarActions): else: self._createButton(l, f, tooltip=t) - #~sep = self._createFlatSeparator() position=len(self._widgets) self.frame.rowconfigure(position, weight=1) self.frame.columnconfigure(position, weight=1) @@ -271,12 +232,10 @@ class PysolToolbar(PysolToolbarActions): # self.setCompound(compound, force=True) # Change the look of the frame to match the platform look - # (see also setRelief) if os.name == 'posix': - ##self.frame.config(bd=1, relief=self.frame_relief) pass elif os.name == "nt": - self.frame.config(bd=2, relief=self.frame_relief, padx=2, pady=2) + self.frame.config(relief='groove') else: pass @@ -298,38 +257,14 @@ class PysolToolbar(PysolToolbarActions): # prev_visible = None for w in self._widgets: - if w.__class__ is ToolbarSeparator: - if prev_visible is None or prev_visible.__class__ is ToolbarSeparator: + if isinstance(w, ToolbarSeparator): + if prev_visible is None or isinstance(prev_visible, ToolbarSeparator): w.hide() else: w.show(orient=self.orient) - elif w.__class__ is ToolbarFlatSeparator: - if prev_visible.__class__ is ToolbarSeparator: - prev_visible.hide() if w.visible: prev_visible = w - def _setRelief(self, relief): - if type(relief) is types.IntType: - relief = ('raised', 'flat')[relief] - elif relief in ('raised', 'flat'): - pass - else: - relief = 'flat' - self.button_relief = relief - if relief == 'raised': - self.frame_relief = 'flat' - self.separator_relief = 'flat' - if os.name == 'nt': - self.frame_relief = 'groove' - else: - self.frame_relief = 'raised' - self.separator_relief = 'sunken' - if os.name == 'nt': - self.frame_relief = 'groove' - self.separator_relief = 'groove' - return relief - # util def _loadImage(self, name): file = os.path.join(self.dir, name) @@ -354,20 +289,6 @@ class PysolToolbar(PysolToolbarActions): self._widgets.append(sep) return sep - def _createFlatSeparator(self): - position=len(self._widgets) - sep = ToolbarFlatSeparator(self.frame, - position=position, - toolbar=self, - width=5, - takefocus=0, - relief='flat') - sep.show(orient=self.orient) - self.frame.rowconfigure(position, weight=1) - self.frame.columnconfigure(position, weight=1) - self._widgets.append(sep) - return sep - def _createButton(self, label, command, check=False, tooltip=None): name = label.lower() image = self._loadImage(name) @@ -517,23 +438,6 @@ class PysolToolbar(PysolToolbarActions): self.setCompound(self.compound, force=True) return 1 - def setRelief(self, relief): - return True - if self.button_relief == relief: - return False - self._setRelief(relief) - self.frame.config(relief=self.frame_relief) - for w in self._widgets: - bd = relief == 'flat' and 1 or 2 - if isinstance(w, ToolbarButton): - w.config(relief=self.button_relief, bd=bd) - elif isinstance(w, ToolbarCheckbutton): - w.config(relief=self.button_relief, bd=bd) - w.config(offrelief=self.button_relief) - elif w.__class__ is ToolbarSeparator: # not ToolbarFlatSeparator - w.config(relief=self.separator_relief) - return True - def setCompound(self, compound, force=False): if not force and self.compound == compound: return False