1
0
Fork 0
mirror of https://github.com/shlomif/PySolFC.git synced 2025-04-05 00:02:29 -04:00

+ 6 new games

+ new action: `show descript. of piles'; new class: StackDesc
* Stack.getHelp: rename `Row' -> `Tableau'
* misc. improvements


git-svn-id: https://pysolfc.svn.sourceforge.net/svnroot/pysolfc/PySolFC/trunk@29 39dd0a4e-7c14-0410-91b3-c4f2d318f732
This commit is contained in:
skomoroh 2006-07-27 21:25:30 +00:00
parent 06ac5b6386
commit 3c6df76c7a
21 changed files with 460 additions and 98 deletions

View file

@ -501,7 +501,6 @@ class Application:
self.toolbar = None self.toolbar = None
self.canvas = None self.canvas = None
self.statusbar = None self.statusbar = None
self.cardsets_cache = {}
# #
self.game = None self.game = None
self.dataloader = None self.dataloader = None
@ -521,6 +520,7 @@ class Application:
self.progress_images = [] self.progress_images = []
self.cardset_manager = CardsetManager() self.cardset_manager = CardsetManager()
self.cardset = None # current cardset self.cardset = None # current cardset
self.cardsets_cache = {}
self.tabletile_manager = TileManager() self.tabletile_manager = TileManager()
self.tabletile_index = 0 # current table tile self.tabletile_index = 0 # current table tile
self.sample_manager = SampleManager() self.sample_manager = SampleManager()

View file

@ -116,6 +116,7 @@ class Game:
self.cards = [] self.cards = []
self.stackmap = {} # dict with (x,y) tuples as key self.stackmap = {} # dict with (x,y) tuples as key
self.allstacks = [] self.allstacks = []
self.stackdesc_list = []
self.demo_logo = None self.demo_logo = None
self.pause_logo = None self.pause_logo = None
self.s = Struct( # stacks self.s = Struct( # stacks
@ -701,6 +702,7 @@ class Game:
if break_pause and self.pause: if break_pause and self.pause:
self.doPause() self.doPause()
self.interruptSleep() self.interruptSleep()
self.deleteStackDesc()
if self.busy: return 1 if self.busy: return 1
if self.drag.stack: if self.drag.stack:
self.drag.stack.cancelDrag() self.drag.stack.cancelDrag()
@ -715,12 +717,14 @@ class Game:
self.app.menubar.disableMenus() self.app.menubar.disableMenus()
# #
# UI & graphics support # UI & graphics support
# #
def clickHandler(self, *args): def clickHandler(self, *args):
self.interruptSleep() self.interruptSleep()
self.deleteStackDesc()
if self.demo: if self.demo:
self.stopDemo() self.stopDemo()
return EVENT_PROPAGATE return EVENT_PROPAGATE
@ -793,7 +797,7 @@ class Game:
def _unmapHandler(self, event): def _unmapHandler(self, event):
# pause game if root window has been iconified # pause game if root window has been iconified
if event.widget is self.top and not self.pause: if event.widget is self.top and not self.pause:
self.doPause() self.app.menubar.mPause()
# #
@ -2461,6 +2465,29 @@ in the current implementation.''' % version
if kw.has_key('help') and self.app.opt.helpbar: if kw.has_key('help') and self.app.opt.helpbar:
self.app.helpbar.updateText(info=kw['help']) self.app.helpbar.updateText(info=kw['help'])
#
# Piles descriptions
#
def showStackDesc(self):
from pysoltk import StackDesc
from stack import InitialDealTalonStack
sd_list = []
for s in self.allstacks:
sd = (s.__class__.__name__, s.cap.base_rank, s.cap.dir)
if sd in sd_list:
# one of each uniq pile
continue
if isinstance(s, InitialDealTalonStack):
continue
self.stackdesc_list.append(StackDesc(self, s))
sd_list.append(sd)
def deleteStackDesc(self):
if self.stackdesc_list:
for sd in self.stackdesc_list:
sd.delete()
self.stackdesc_list = []
# #
# subclass hooks # subclass hooks

View file

@ -154,7 +154,7 @@ class Strategy_RowStack(BasicRowStack):
return self.game.app.images.getReserveBottom() return self.game.app.images.getReserveBottom()
def getHelp(self): def getHelp(self):
return _('Row. Build regardless of rank and suit.') return _('Tableau. Build regardless of rank and suit.')
class Strategy(Game): class Strategy(Game):

View file

@ -101,7 +101,7 @@ class Calculation_RowStack(BasicRowStack):
return self.game.app.images.getReserveBottom() return self.game.app.images.getReserveBottom()
def getHelp(self): def getHelp(self):
return _('Row. Build regardless of rank and suit.') return _('Tableau. Build regardless of rank and suit.')
# /*********************************************************************** # /***********************************************************************

View file

@ -57,7 +57,7 @@ class CurdsAndWhey_RowStack(BasicRowStack):
return isSameSuitSequence(cards) or isRankSequence(cards, dir=0) return isSameSuitSequence(cards) or isRankSequence(cards, dir=0)
def getHelp(self): def getHelp(self):
return _('Row. Build down by suit or of the same rank.') return _('Tableau. Build down by suit or of the same rank.')
class CurdsAndWhey(Game): class CurdsAndWhey(Game):

View file

@ -41,6 +41,7 @@ from pysollib.stack import *
from pysollib.game import Game from pysollib.game import Game
from pysollib.layout import Layout from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText
from fortythieves import FortyThieves_Hint from fortythieves import FortyThieves_Hint
from spider import Spider_Hint from spider import Spider_Hint
@ -138,7 +139,7 @@ class Congress(Diplomat):
# game layout (just rearrange the stacks a little bit) # game layout (just rearrange the stacks a little bit)
# #
def createGame(self): def createGame(self, max_rounds=1):
# create layout # create layout
l, s = Layout(self), self.s l, s = Layout(self), self.s
@ -160,11 +161,18 @@ class Congress(Diplomat):
stack.CARD_YOFFSET = 0 stack.CARD_YOFFSET = 0
s.rows.append(stack) s.rows.append(stack)
x, y, = l.XM, l.YM x, y, = l.XM, l.YM
s.talon = WasteTalonStack(x, y, self, max_rounds=1) s.talon = WasteTalonStack(x, y, self, max_rounds=max_rounds)
l.createText(s.talon, "ss") l.createText(s.talon, "ss")
x = x + l.XS x = x + l.XS
s.waste = WasteStack(x, y, self) s.waste = WasteStack(x, y, self)
l.createText(s.waste, "ss") l.createText(s.waste, "ss")
if max_rounds > 1:
tx, ty, ta, tf = l.getTextAttr(s.waste, "ne")
font = self.app.getFont("canvas_default")
s.talon.texts.rounds = MfxCanvasText(self.canvas,
tx, ty,
anchor=ta,
font=font)
# define stack-groups # define stack-groups
l.defaultStackGroups() l.defaultStackGroups()
@ -251,6 +259,22 @@ class LittleNapoleon(Diplomat):
return 0 return 0
# /***********************************************************************
# // Twin Queens
# ************************************************************************/
class TwinQueens(Congress):
Foundation_Classes = [
StackWrapper(SS_FoundationStack, base_rank=KING, mod=13),
StackWrapper(SS_FoundationStack, base_rank=KING, mod=13),
]
RowStack_Class = StackWrapper(SS_RowStack, max_move=1)
def createGame(self):
Congress.createGame(self, max_rounds=2)
# register the game # register the game
registerGame(GameInfo(149, Diplomat, "Diplomat", registerGame(GameInfo(149, Diplomat, "Diplomat",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED)) GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED))
@ -268,4 +292,6 @@ registerGame(GameInfo(548, Parliament, "Parliament",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED)) GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(549, Wheatsheaf, "Wheatsheaf", registerGame(GameInfo(549, Wheatsheaf, "Wheatsheaf",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED)) GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(563, TwinQueens, "Twin Queens",
GI.GT_FORTY_THIEVES, 2, 1, GI.SL_MOSTLY_SKILL))

View file

@ -32,7 +32,6 @@
__all__ = [] __all__ = []
# imports # imports
import sys
# PySol imports # PySol imports
from pysollib.gamedb import registerGame, GameInfo, GI from pysollib.gamedb import registerGame, GameInfo, GI
@ -43,6 +42,9 @@ from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText from pysollib.pysoltk import MfxCanvasText
from gypsy import DieRussische_Foundation
# /*********************************************************************** # /***********************************************************************
# // # //
# ************************************************************************/ # ************************************************************************/
@ -440,7 +442,7 @@ class Indian_RowStack(SequenceRowStack):
def _isSequence(self, cards): def _isSequence(self, cards):
return isAnySuitButOwnSequence(cards, self.cap.mod, self.cap.dir) return isAnySuitButOwnSequence(cards, self.cap.mod, self.cap.dir)
def getHelp(self): def getHelp(self):
return _('Row. Build down in any suit but the same.') return _('Tableau. Build down in any suit but the same.')
class Indian(FortyThieves): class Indian(FortyThieves):
@ -805,8 +807,6 @@ class Waterloo(FortyThieves):
# // Junction # // Junction
# ************************************************************************/ # ************************************************************************/
from gypsy import DieRussische_Foundation
class Junction(Game): class Junction(Game):
def createGame(self, rows=7): def createGame(self, rows=7):
@ -849,6 +849,89 @@ class Junction(Game):
return card1.color != card2.color and abs(card1.rank-card2.rank) == 1 return card1.color != card2.color and abs(card1.rank-card2.rank) == 1
# /***********************************************************************
# // The Spark
# ************************************************************************/
class TheSpark_Talon(TalonStack):
def canDealCards(self):
return len(self.cards) > 0
def dealCards(self, sound=0):
old_state = self.game.enterState(self.game.S_DEAL)
num_cards = 0
if self.cards:
if sound and not self.game.demo:
self.game.playSample("dealwaste")
for i in range(self.num_deal):
for r in self.game.s.reserves:
if not self.cards:
break
self.game.flipMove(self)
self.game.moveMove(1, self, r, frames=4, shadow=0)
num_cards += 1
self.game.leaveState(old_state)
return num_cards
class TheSpark(Game):
Hint_Class = CautiousDefaultHint
def createGame(self):
l, s = Layout(self), self.s
w, h = l.XM+8*l.XS, l.YM+4*l.YS
self.setSize(w, h)
x, y = l.XM, l.YM
for i in range(8):
s.foundations.append(SS_FoundationStack(x, y, self,
suit=i/2, base_rank=KING, mod=13))
x += l.XS
x, y = l.XM, l.YM+l.YS
s.talon = TheSpark_Talon(x, y, self, max_rounds=1, num_deal=3)
l.createText(s.talon, 'se')
y += l.YS
for i in (0,1):
stack = WasteStack(x, y, self)
s.reserves.append(stack)
l.createText(stack, 'se')
y += l.YS
y = l.YM+l.YS*3/2
for i in range(2):
x = l.XM+2*l.XS
for j in range(6):
stack = SS_RowStack(x, y, self, max_move=1)
stack.CARD_XOFFSET, stack.CARD_YOFFSET = 0, 0
s.rows.append(stack)
x += l.XS
y += l.YS
l.defaultStackGroups()
def _shuffleHook(self, cards):
# move Aces to top of the Talon (i.e. first cards to be dealt)
return self._shuffleHookMoveToTop(cards,
lambda c: (c.rank == KING, 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() # deal first card to WasteStack
def shallHighlightMatch(self, stack1, card1, stack2, card2):
return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1
# register the game # register the game
registerGame(GameInfo(13, FortyThieves, "Forty Thieves", registerGame(GameInfo(13, FortyThieves, "Forty Thieves",
@ -941,5 +1024,7 @@ registerGame(GameInfo(540, Waterloo, "Waterloo",
registerGame(GameInfo(556, Junction, "Junction", registerGame(GameInfo(556, Junction, "Junction",
GI.GT_FORTY_THIEVES, 4, 0, GI.SL_MOSTLY_SKILL, GI.GT_FORTY_THIEVES, 4, 0, GI.SL_MOSTLY_SKILL,
ranks=(0, 6, 7, 8, 9, 10, 11, 12) )) ranks=(0, 6, 7, 8, 9, 10, 11, 12) ))
registerGame(GameInfo(564, TheSpark, "The Spark",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_LUCK))

View file

@ -111,7 +111,7 @@ class Golf_RowStack(BasicRowStack):
def clickHandler(self, event): def clickHandler(self, event):
return self.doubleclickHandler(event) return self.doubleclickHandler(event)
def getHelp(self): def getHelp(self):
return _('Row. No building.') return _('Tableau. No building.')
# /*********************************************************************** # /***********************************************************************
@ -411,7 +411,7 @@ class BlackHole_RowStack(ReserveStack):
def clickHandler(self, event): def clickHandler(self, event):
return self.doubleclickHandler(event) return self.doubleclickHandler(event)
def getHelp(self): def getHelp(self):
return _('Row. No building.') return _('Tableau. No building.')
class BlackHole(Game): class BlackHole(Game):

View file

@ -539,13 +539,68 @@ class Elba(Gypsy):
class Millie(Gypsy): class Millie(Gypsy):
Layout_Method = Layout.klondikeLayout Layout_Method = Layout.klondikeLayout
RowStack_Class = AC_RowStack
def startGame(self): def startGame(self):
self.startDealSample() self.startDealSample()
self.s.talon.dealRow() self.s.talon.dealRow()
# /***********************************************************************
# // Hypotenuse
# // Eternal Triangle
# // Right Triangle
# ************************************************************************/
class Hypotenuse(Gypsy):
Layout_Method = Layout.klondikeLayout
RowStack_Class = KingAC_RowStack
def createGame(self):
Gypsy.createGame(self, rows=10, playcards=24)
def startGame(self, flip=0, reverse=1):
for i in range(1, 10):
self.s.talon.dealRow(rows=self.s.rows[:i], flip=0, frames=0)
self.startDealSample()
self.s.talon.dealRow()
class EternalTriangle(Hypotenuse):
def startGame(self, flip=0, reverse=1):
for i in range(1, 10):
self.s.talon.dealRow(rows=self.s.rows[i:], frames=0)
self.startDealSample()
self.s.talon.dealRow()
class RightTriangle_Talon(OpenStack, DealRowTalonStack):
def __init__(self, x, y, game, max_rounds=1, num_deal=1, **cap):
Stack.__init__(self, x, y, game, cap=cap)
self.max_rounds = max_rounds
self.num_deal = num_deal
self.round = 1
self.base_cards = [] # for DealBaseCard_StackMethods
def canFlipCard(self):
return False
def getBottomImage(self):
return self.game.app.images.getReserveBottom()
def getHelp(self):
return ''
class RightTriangle(Hypotenuse):
Talon_Class = StackWrapper(RightTriangle_Talon, max_accept=1, max_move=1)
def createGame(self):
Gypsy.createGame(self, rows=10, playcards=24)
self.sg.dropstacks.append(self.s.talon)
self.sg.openstacks.append(self.s.talon)
self.sg.reservestacks.append(self.s.talon)
# register the game # register the game
registerGame(GameInfo(1, Gypsy, "Gypsy", registerGame(GameInfo(1, Gypsy, "Gypsy",
GI.GT_GYPSY, 2, 0, GI.SL_MOSTLY_SKILL)) GI.GT_GYPSY, 2, 0, GI.SL_MOSTLY_SKILL))
@ -593,4 +648,11 @@ registerGame(GameInfo(487, Millie, "Millie",
GI.GT_GYPSY, 2, 0, GI.SL_BALANCED)) GI.GT_GYPSY, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(498, Steve, "Steve", registerGame(GameInfo(498, Steve, "Steve",
GI.GT_GYPSY, 2, 0, GI.SL_BALANCED)) GI.GT_GYPSY, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(566, Hypotenuse, "Hypotenuse",
GI.GT_GYPSY, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(567, EternalTriangle, "Eternal Triangle",
GI.GT_GYPSY, 2, 0, GI.SL_MOSTLY_SKILL,
altnames=('Lobachevsky',) ))
registerGame(GameInfo(568, RightTriangle, "Right Triangle",
GI.GT_GYPSY, 2, 0, GI.SL_MOSTLY_SKILL))

View file

@ -224,12 +224,14 @@ class Arabella(DoubleKlondike):
# ************************************************************************/ # ************************************************************************/
class BigDeal(DoubleKlondike): class BigDeal(DoubleKlondike):
def createGame(self, rows=12, max_rounds=2): RowStack_Class = KingAC_RowStack
def createGame(self, rows=12, max_rounds=2, XOFFSET=0):
l, s = Layout(self), self.s l, s = Layout(self), self.s
self.setSize(l.XM+(rows+2)*l.XS, l.YM+8*l.YS) self.setSize(l.XM+(rows+2)*l.XS, l.YM+8*l.YS)
x, y = l.XM, l.YM x, y = l.XM, l.YM
for i in range(rows): for i in range(rows):
s.rows.append(AC_RowStack(x, y, self, base_rank=KING)) s.rows.append(self.RowStack_Class(x, y, self))
x += l.XS x += l.XS
for i in range(2): for i in range(2):
y = l.YM y = l.YM
@ -242,16 +244,39 @@ class BigDeal(DoubleKlondike):
l.createText(s.talon, 'n') l.createText(s.talon, 'n')
x += l.XS x += l.XS
s.waste = WasteStack(x, y, self) s.waste = WasteStack(x, y, self)
s.waste.CARD_XOFFSET = XOFFSET
l.createText(s.waste, 'n') l.createText(s.waste, 'n')
if max_rounds > 1: if max_rounds > 1:
tx, ty, ta, tf = l.getTextAttr(s.talon, 'nn') tx, ty, ta, tf = l.getTextAttr(s.talon, 'nn')
ty -= 2*l.TEXT_MARGIN ty -= l.TEXT_MARGIN
font = self.app.getFont('canvas_default') font = self.app.getFont('canvas_default')
s.talon.texts.rounds = MfxCanvasText(self.canvas, tx, ty, anchor=ta, font=font) s.talon.texts.rounds = MfxCanvasText(self.canvas, tx, ty,
anchor=ta, font=font)
self.setRegion(s.rows, (-999, -999, l.XM+rows*l.XS-l.CW/2, 999999), priority=1) self.setRegion(s.rows, (-999, -999, l.XM+rows*l.XS-l.CW/2, 999999), priority=1)
l.defaultStackGroups() l.defaultStackGroups()
# /***********************************************************************
# // Delivery
# ************************************************************************/
class Delivery(BigDeal):
RowStack_Class = StackWrapper(SS_RowStack, max_move=1)
def createGame(self):
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
def startGame(self):
for i in range(2):
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow()
self.s.talon.dealCards() # deal first card to WasteStack
# register the game # register the game
registerGame(GameInfo(21, DoubleKlondike, "Double Klondike", registerGame(GameInfo(21, DoubleKlondike, "Double Klondike",
@ -277,4 +302,6 @@ registerGame(GameInfo(497, Arabella, "Arabella",
GI.GT_KLONDIKE, 3, 0, GI.SL_BALANCED)) GI.GT_KLONDIKE, 3, 0, GI.SL_BALANCED))
registerGame(GameInfo(545, BigDeal, "Big Deal", registerGame(GameInfo(545, BigDeal, "Big Deal",
GI.GT_KLONDIKE | GI.GT_ORIGINAL, 4, 1, GI.SL_BALANCED)) GI.GT_KLONDIKE | GI.GT_ORIGINAL, 4, 1, GI.SL_BALANCED))
registerGame(GameInfo(562, Delivery, "Delivery",
GI.GT_FORTY_THIEVES | GI.GT_ORIGINAL, 4, 0, GI.SL_BALANCED))

View file

@ -145,7 +145,7 @@ class ThumbAndPouch_RowStack(SequenceRowStack):
def _isSequence(self, cards): def _isSequence(self, cards):
return isAnySuitButOwnSequence(cards, self.cap.mod, self.cap.dir) return isAnySuitButOwnSequence(cards, self.cap.mod, self.cap.dir)
def getHelp(self): def getHelp(self):
return _('Row. Build down in any suit but the same.') return _('Tableau. Build down in any suit but the same.')
class ThumbAndPouch(Klondike): class ThumbAndPouch(Klondike):

View file

@ -86,8 +86,8 @@ class Numerica_RowStack(BasicRowStack):
return self.game.app.images.getReserveBottom() return self.game.app.images.getReserveBottom()
def getHelp(self): def getHelp(self):
##return _('Row. Accepts any one card from the Waste.') ##return _('Tableau. Accepts any one card from the Waste.')
return _('Row. Build regardless of rank and suit.') return _('Tableau. Build regardless of rank and suit.')
# /*********************************************************************** # /***********************************************************************
@ -233,8 +233,8 @@ class PussInTheCorner_RowStack(BasicRowStack):
def getBottomImage(self): def getBottomImage(self):
return self.game.app.images.getReserveBottom() return self.game.app.images.getReserveBottom()
def getHelp(self): def getHelp(self):
##return _('Row. Accepts any one card from the Waste.') ##return _('Tableau. Accepts any one card from the Waste.')
return _('Row. Build regardless of rank and suit.') return _('Tableau. Build regardless of rank and suit.')
class PussInTheCorner(Numerica): class PussInTheCorner(Numerica):
@ -587,7 +587,7 @@ class Strategerie_RowStack(BasicRowStack):
return self.game.app.images.getReserveBottom() return self.game.app.images.getReserveBottom()
def getHelp(self): def getHelp(self):
return _('Row. Build regardless of rank and suit.') return _('Tableau. Build regardless of rank and suit.')
class Strategerie_ReserveStack(ReserveStack): class Strategerie_ReserveStack(ReserveStack):

View file

@ -146,22 +146,22 @@ class Foursome(Game):
def createGame(self, rows=6, texts=True): def createGame(self, rows=6, texts=True):
l, s = Layout(self), self.s l, s = Layout(self), self.s
max_rows = max(6, rows) max_rows = max(8, rows)
self.setSize(l.XM+max_rows*l.XS, l.YM+3*l.YS+13*l.YOFFSET) self.setSize(l.XM+max_rows*l.XS, l.YM+2*l.YS+13*l.YOFFSET)
x, y = l.XM+(max_rows-6)*l.XS/2, l.YM x, y = l.XM+l.XS*(max_rows-4)/2, l.YM
for i in range(4): for i in range(4):
s.reserves.append(ReserveStack(x, y, self)) s.reserves.append(ReserveStack(x, y, self))
x += l.XS x += l.XS
x = l.XM+(max_rows-1)*l.XS x = l.XM+(max_rows-1)*l.XS
s.foundations.append(AbstractFoundationStack(x, y, self, s.foundations.append(AbstractFoundationStack(x, y, self,
suit=ANY_SUIT, max_cards=52, max_accept=0)) suit=ANY_SUIT, max_cards=52, max_accept=0))
x, y = l.XM, l.YM+l.YS x, y = l.XM+l.XS*(max_rows-rows)/2, l.YM+l.YS
for i in range(rows): for i in range(rows):
s.rows.append(UD_AC_RowStack(x, y, self, mod=13)) s.rows.append(UD_AC_RowStack(x, y, self, mod=13))
x += l.XS x += l.XS
s.talon = self.Talon_Class(self.width-l.XS, self.height-l.YS, self) s.talon = self.Talon_Class(l.XM, l.YM, self)
if texts: if texts:
l.createText(s.talon, 'n') l.createText(s.talon, 'ne')
l.defaultStackGroups() l.defaultStackGroups()
def startGame(self): def startGame(self):

View file

@ -233,21 +233,6 @@ class Alhambra_RowStack(UD_SS_RowStack):
return self.game.app.images.getReserveBottom() return self.game.app.images.getReserveBottom()
class Alhambra_Talon__(RedealTalonStack):
def canDealCards(self):
if self.round == self.max_rounds:
return len(self.cards) != 0
return not self.game.isGameWon()
def dealCards(self, sound=0):
if self.cards:
return self.dealRowAvail(sound=sound)
RedealTalonStack.redealCards(self, frames=0,
shuffle=False, sound=sound)
return self.dealRowAvail(sound=sound)
class Alhambra_Talon(DealRowTalonStack): class Alhambra_Talon(DealRowTalonStack):
def canDealCards(self): def canDealCards(self):
r_cards = sum([len(r.cards) for r in self.game.s.rows]) r_cards = sum([len(r.cards) for r in self.game.s.rows])

View file

@ -746,22 +746,23 @@ class Marshal(Game):
def createGame(self): def createGame(self):
l, s = Layout(self), self.s l, s = Layout(self), self.s
self.setSize(l.XM+8*l.XS, l.YM+5*l.YS) self.setSize(l.XM+9*l.XS, l.YM+5*l.YS)
x, y = l.XM, l.YM x, y = l.XM, l.YM
for i in range(4): for i in range(4):
s.foundations.append(SS_FoundationStack(x, y, self, suit=i)) s.foundations.append(SS_FoundationStack(x, y, self, suit=i))
x += l.XS y += l.YS
x, y = self.width-l.XS, l.YM
for i in range(4): for i in range(4):
s.foundations.append(SS_FoundationStack(x, y, self, s.foundations.append(SS_FoundationStack(x, y, self,
suit=i, base_rank=KING, dir=-1)) suit=i, base_rank=KING, dir=-1))
x += l.XS y += l.YS
x, y = l.XM, l.YM+l.YS x, y = (self.width-l.XS)/2, self.height-l.YS
s.talon = TalonStack(x, y, self) s.talon = DealRowTalonStack(x, y, self)
l.createText(s.talon, 'se') l.createText(s.talon, 'se')
y = l.YM+l.YS y = l.YM
for i in range(4): for i in range(4):
x = l.XM+2*l.XS x = l.XM+l.XS*3/2
for j in range(6): for j in range(6):
stack = UD_SS_RowStack(x, y, self, base_rank=NO_RANK) stack = UD_SS_RowStack(x, y, self, base_rank=NO_RANK)
s.rows.append(stack) s.rows.append(stack)
@ -788,6 +789,75 @@ class Marshal(Game):
(abs(card1.rank-card2.rank) == 1)) (abs(card1.rank-card2.rank) == 1))
# /***********************************************************************
# // Royal Aids
# ************************************************************************/
class RoyalAids_RowStack(KingAC_RowStack):
def getBottomImage(self):
return self.game.app.images.getReserveBottom()
class RoyalAids(Game):
Hint_Class = CautiousDefaultHint
def createGame(self):
l, s = Layout(self), self.s
self.setSize(l.XM+8*l.XS, l.YM+4*l.YS)
x0 = l.XM+1.5*l.XS
for k in (0,1):
suit = 0
for i, j in ((1,0), (0,0.5), (2,0.5), (1,1)):
x, y = x0+i*l.XS, l.YM+j*l.YS
s.foundations.append(AC_FoundationStack(x, y, self, suit=suit))
suit += 1
x0 += 3.5*l.XS
x, y = l.XM, l.YM+l.YS
s.talon = WasteTalonStack(x, y, self, max_rounds=UNLIMITED_REDEALS)
l.createText(s.talon, 'se')
y += l.YS
s.waste = WasteStack(x, y, self)
l.createText(s.waste, 'se')
x, y = l.XM+4*l.XS, l.YM+2*l.YS
for i in (0,1):
stack = RoyalAids_RowStack(x, y, self, max_move=1)
s.rows.append(stack)
stack.CARD_XOFFSET, stack.CARD_YOFFSET = 0, 0
x += l.XS
x, y = l.XM+3*l.XS, l.YM+3*l.YS
for i in range(4):
stack = BasicRowStack(x, y, self)
s.reserves.append(stack)
stack.CARD_XOFFSET, stack.CARD_YOFFSET = 0, 0
x += l.XS
l.defaultStackGroups()
def _shuffleHook(self, cards):
return self._shuffleHookMoveToTop(cards,
lambda c: (c.rank == ACE, (c.deck, c.suit)))
def startGame(self):
self.s.talon.dealRow(rows=self.s.foundations, frames=0)
for i in range(6):
self.s.talon.dealRow(rows=self.s.reserves, frames=0)
self.startDealSample()
for i in range(4):
self.s.talon.dealRow(rows=self.s.reserves)
self.s.talon.dealCards()
def shallHighlightMatch(self, stack1, card1, stack2, card2):
return (card1.color != card2.color and
(abs(card1.rank-card2.rank) == 1))
# register the game # register the game
registerGame(GameInfo(330, Sultan, "Sultan", registerGame(GameInfo(330, Sultan, "Sultan",
@ -819,3 +889,5 @@ registerGame(GameInfo(477, CornerSuite, "Corner Suite",
GI.GT_2DECK_TYPE, 1, 0, GI.SL_MOSTLY_LUCK)) GI.GT_2DECK_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
registerGame(GameInfo(559, Marshal, "Marshal", registerGame(GameInfo(559, Marshal, "Marshal",
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED)) 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))

View file

@ -77,6 +77,7 @@ class Windmill(Game):
] ]
RowStack_Class = Windmill_RowStack RowStack_Class = Windmill_RowStack
FOUNDATIONS_LAYOUT = ((1,0.6), (3,0.6), (1,3.4), (3,3.4))
ROWS_LAYOUT = ((2,0), (2,1), (0,2), (1,2), (3,2), (4,2), (2,3), (2,4)) ROWS_LAYOUT = ((2,0), (2,1), (0,2), (1,2), (3,2), (4,2), (2,3), (2,4))
FILL_STACK = True FILL_STACK = True
@ -84,12 +85,14 @@ class Windmill(Game):
# game layout # game layout
# #
def createGame(self): def createGame(self, card_x_space=20):
# create layout # create layout
l, s = Layout(self, card_x_space=20), self.s l, s = Layout(self, card_x_space=card_x_space), self.s
# set window # set window
self.setSize(7*l.XS+l.XM, 5*l.YS+l.YM+l.YM) max_x = max([i[0] for i in self.FOUNDATIONS_LAYOUT+self.ROWS_LAYOUT])
max_y = max([i[1] for i in self.FOUNDATIONS_LAYOUT+self.ROWS_LAYOUT])
self.setSize((3+max_x)*l.XS+l.XM, (1+max_y)*l.YS+l.YM+l.YM)
# create stacks # create stacks
x = l.XM x = l.XM
@ -109,7 +112,7 @@ class Windmill(Game):
fnd_cls = self.Foundation_Classes[0] fnd_cls = self.Foundation_Classes[0]
s.foundations.append(fnd_cls(x, y, self)) s.foundations.append(fnd_cls(x, y, self))
fnd_cls = self.Foundation_Classes[1] fnd_cls = self.Foundation_Classes[1]
for d in ((1,0.6), (3,0.6), (1,3.4), (3,3.4)): for d in self.FOUNDATIONS_LAYOUT:
x, y = x0 + d[0] * l.XS, y0 + d[1] * l.YS x, y = x0 + d[0] * l.XS, y0 + d[1] * l.YS
s.foundations.append(fnd_cls(x, y, self)) s.foundations.append(fnd_cls(x, y, self))
@ -158,22 +161,38 @@ class DutchSolitaire_RowStack(UD_RK_RowStack):
class DutchSolitaire(Windmill): class DutchSolitaire(Windmill):
Foundation_Classes = [ Foundation_Classes = [
StackWrapper(BlackHole_Foundation, suit=ANY_SUIT, mod=13, max_cards=UNLIMITED_CARDS), StackWrapper(BlackHole_Foundation, suit=ANY_SUIT, mod=13,
StackWrapper(BlackHole_Foundation, suit=ANY_SUIT, mod=13, max_cards=UNLIMITED_CARDS), max_cards=UNLIMITED_CARDS, min_cards=1),
StackWrapper(BlackHole_Foundation, suit=ANY_SUIT, mod=13,
max_cards=UNLIMITED_CARDS, min_cards=1),
] ]
RowStack_Class = DutchSolitaire_RowStack RowStack_Class = DutchSolitaire_RowStack
##ROWS_LAYOUT = ((2,0), (2,1), (0,2), (1,2), (3,2), (4,2), (2,3), (2,4)) FOUNDATIONS_LAYOUT = ((1,1), (3,1), (1,3), (3,3))
ROWS_LAYOUT = ((2,0), (2,1), (1,2), (3,2), (2,3), (2,4)) ROWS_LAYOUT = ((2,0.5), (-0.5,2), (0.5,2), (3.5,2), (4.5,2), (2,3.5))
FILL_STACK = False FILL_STACK = False
def createGame(self):
Windmill.createGame(self, card_x_space=10)
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
return cards # move 5 Aces to top of the Talon (i.e. first cards to be dealt)
def select_cards(c):
if c.rank == ACE:
if c.suit in (0, 1):
return True, c.suit
if c.suit == 3 and c.deck == 0:
return True, c.suit
return False, None
return self._shuffleHookMoveToTop(cards, select_cards)
def startGame(self): def startGame(self):
self.s.talon.dealRow(rows=self.s.foundations, frames=0)
for i in range(8):
self.s.talon.dealRow(frames=0)
self.startDealSample() self.startDealSample()
#self.s.talon.dealRow(rows=(self.s.foundations[0],)) self.s.talon.dealRow()
#self.s.talon.dealRow() self.s.talon.dealRow()
self.s.talon.dealCards() # deal first card to WasteStack self.s.talon.dealCards() # deal first card to WasteStack
def getAutoStacks(self, event=None): def getAutoStacks(self, event=None):

View file

@ -140,7 +140,7 @@ class Moosehide_RowStack(Yukon_AC_RowStack):
def _isSequence(self, c1, c2): def _isSequence(self, c1, c2):
return (c1.suit != c2.suit and c1.rank == c2.rank+1) return (c1.suit != c2.suit and c1.rank == c2.rank+1)
def getHelp(self): def getHelp(self):
return _('Row. Build down in any suit but the same, can move any face-up cards regardless of sequence.') return _('Tableau. Build down in any suit but the same, can move any face-up cards regardless of sequence.')
class Moosehide(Yukon): class Moosehide(Yukon):
RowStack_Class = StackWrapper(Moosehide_RowStack, base_rank=KING) RowStack_Class = StackWrapper(Moosehide_RowStack, base_rank=KING)
@ -199,7 +199,7 @@ class Alaska_RowStack(Yukon_SS_RowStack):
((c1.rank + self.cap.dir) % self.cap.mod == c2.rank or ((c1.rank + self.cap.dir) % self.cap.mod == c2.rank or
(c2.rank + self.cap.dir) % self.cap.mod == c1.rank)) (c2.rank + self.cap.dir) % self.cap.mod == c1.rank))
def getHelp(self): def getHelp(self):
return _('Row. Build up or down by suit, can move any face-up cards regardless of sequence.') return _('Tableau. Build up or down by suit, can move any face-up cards regardless of sequence.')
class Alaska(RussianSolitaire): class Alaska(RussianSolitaire):
@ -216,7 +216,7 @@ class Roslin_RowStack(Yukon_AC_RowStack):
((c1.rank + self.cap.dir) % self.cap.mod == c2.rank or ((c1.rank + self.cap.dir) % self.cap.mod == c2.rank or
(c2.rank + self.cap.dir) % self.cap.mod == c1.rank)) (c2.rank + self.cap.dir) % self.cap.mod == c1.rank))
def getHelp(self): def getHelp(self):
return _('Row. Build up or down by alternate color, can move any face-up cards regardless of sequence.') return _('Tableau. Build up or down by alternate color, can move any face-up cards regardless of sequence.')
class Roslin(Yukon): class Roslin(Yukon):

View file

@ -500,7 +500,7 @@ class Layout:
if rows < maxrows: x += (maxrows-rows) * XS/2 if rows < maxrows: x += (maxrows-rows) * XS/2
##y += YM * (3 - foundrows) ##y += YM * (3 - foundrows)
y += text_height y += text_height
self.setRegion(self.s.rows, (-999, y - YM / 2, 999999, 999999)) self.setRegion(self.s.rows, (-999, y-CH/2, 999999, 999999))
for i in range(rows): for i in range(rows):
self.s.rows.append(S(x, y)) self.s.rows.append(S(x, y))
x = x + XS x = x + XS

View file

@ -1556,8 +1556,8 @@ class TalonStack(Stack,
##round = _('Round #%d.') % self.round ##round = _('Round #%d.') % self.round
return _('Talon.')+' '+nredeals ##+' '+round return _('Talon.')+' '+nredeals ##+' '+round
def getBaseCard(self): #def getBaseCard(self):
return self._getBaseCard() # return self._getBaseCard()
# A single click deals one card to each of the RowStacks. # A single click deals one card to each of the RowStacks.
@ -1777,6 +1777,9 @@ class AbstractFoundationStack(OpenStack):
if len(self.cards) == self.cap.max_cards: if len(self.cards) == self.cap.max_cards:
self.game.closeStackMove(self) self.game.closeStackMove(self)
def getHelp(self):
return _('Foundation.')
# A SameSuit_FoundationStack is the typical Foundation stack. # A SameSuit_FoundationStack is the typical Foundation stack.
# It builds up in rank and suit. # It builds up in rank and suit.
@ -1874,7 +1877,7 @@ class BasicRowStack(OpenStack):
def getHelp(self): def getHelp(self):
if self.cap.max_accept == 0: if self.cap.max_accept == 0:
return _('Row. No building.') return _('Tableau. No building.')
return '' return ''
#def getBaseCard(self): #def getBaseCard(self):
@ -1904,9 +1907,9 @@ class AC_RowStack(SequenceRowStack):
def _isSequence(self, cards): def _isSequence(self, cards):
return isAlternateColorSequence(cards, self.cap.mod, self.cap.dir) return isAlternateColorSequence(cards, self.cap.mod, self.cap.dir)
def getHelp(self): def getHelp(self):
if self.cap.dir > 0: return _('Row. Build up by alternate color.') if self.cap.dir > 0: return _('Tableau. Build up by alternate color.')
elif self.cap.dir < 0: return _('Row. Build down by alternate color.') elif self.cap.dir < 0: return _('Tableau. Build down by alternate color.')
else: return _('Row. Build by same rank.') else: return _('Tableau. Build by same rank.')
# A SameColor_RowStack builds down by rank and same color. # A SameColor_RowStack builds down by rank and same color.
# e.g. Klondike # e.g. Klondike
@ -1914,27 +1917,27 @@ class SC_RowStack(SequenceRowStack):
def _isSequence(self, cards): def _isSequence(self, cards):
return isSameColorSequence(cards, self.cap.mod, self.cap.dir) return isSameColorSequence(cards, self.cap.mod, self.cap.dir)
def getHelp(self): def getHelp(self):
if self.cap.dir > 0: return _('Row. Build up by color.') if self.cap.dir > 0: return _('Tableau. Build up by color.')
elif self.cap.dir < 0: return _('Row. Build down by color.') elif self.cap.dir < 0: return _('Tableau. Build down by color.')
else: return _('Row. Build by same rank.') else: return _('Tableau. Build by same rank.')
# A SameSuit_RowStack builds down by rank and suit. # A SameSuit_RowStack builds down by rank and suit.
class SS_RowStack(SequenceRowStack): class SS_RowStack(SequenceRowStack):
def _isSequence(self, cards): def _isSequence(self, cards):
return isSameSuitSequence(cards, self.cap.mod, self.cap.dir) return isSameSuitSequence(cards, self.cap.mod, self.cap.dir)
def getHelp(self): def getHelp(self):
if self.cap.dir > 0: return _('Row. Build up by suit.') if self.cap.dir > 0: return _('Tableau. Build up by suit.')
elif self.cap.dir < 0: return _('Row. Build down by suit.') elif self.cap.dir < 0: return _('Tableau. Build down by suit.')
else: return _('Row. Build by same rank.') else: return _('Tableau. Build by same rank.')
# A Rank_RowStack builds down by rank ignoring suit. # A Rank_RowStack builds down by rank ignoring suit.
class RK_RowStack(SequenceRowStack): class RK_RowStack(SequenceRowStack):
def _isSequence(self, cards): def _isSequence(self, cards):
return isRankSequence(cards, self.cap.mod, self.cap.dir) return isRankSequence(cards, self.cap.mod, self.cap.dir)
def getHelp(self): def getHelp(self):
if self.cap.dir > 0: return _('Row. Build up regardless of suit.') if self.cap.dir > 0: return _('Tableau. Build up regardless of suit.')
elif self.cap.dir < 0: return _('Row. Build down regardless of suit.') elif self.cap.dir < 0: return _('Tableau. Build down regardless of suit.')
else: return _('Row. Build by same rank.') else: return _('Tableau. Build by same rank.')
# A Freecell_AlternateColor_RowStack # A Freecell_AlternateColor_RowStack
class FreeCell_AC_RowStack(AC_RowStack): class FreeCell_AC_RowStack(AC_RowStack):
@ -1960,9 +1963,9 @@ class Spider_SS_RowStack(SS_RowStack):
def _isAcceptableSequence(self, cards): def _isAcceptableSequence(self, cards):
return isRankSequence(cards, self.cap.mod, self.cap.dir) return isRankSequence(cards, self.cap.mod, self.cap.dir)
def getHelp(self): def getHelp(self):
if self.cap.dir > 0: return _('Row. Build up regardless of suit.') if self.cap.dir > 0: return _('Tableau. Build up regardless of suit.')
elif self.cap.dir < 0: return _('Row. Build down regardless of suit.') elif self.cap.dir < 0: return _('Tableau. Build down regardless of suit.')
else: return _('Row. Build by same rank.') else: return _('Tableau. Build by same rank.')
# A Yukon_AlternateColor_RowStack builds down by rank and alternate color, # A Yukon_AlternateColor_RowStack builds down by rank and alternate color,
# but can move any face-up cards regardless of sequence. # but can move any face-up cards regardless of sequence.
@ -1983,10 +1986,12 @@ class Yukon_AC_RowStack(BasicRowStack):
return 1 return 1
def getHelp(self): def getHelp(self):
if self.cap.dir > 0: return _('Row. Build up by alternate color, can move any face-up cards regardless of sequence.') if self.cap.dir > 0: return _('Tableau. Build up by alternate color, can move any face-up cards regardless of sequence.')
elif self.cap.dir < 0: return _('Row. Build down by alternate color, can move any face-up cards regardless of sequence.') elif self.cap.dir < 0: return _('Tableau. Build down by alternate color, can move any face-up cards regardless of sequence.')
else: return _('Row. Build by same rank, can move any face-up cards regardless of sequence.') else: return _('Tableau. Build by same rank, can move any face-up cards regardless of sequence.')
def getBaseCard(self):
return self._getBaseCard()
# A Yukon_SameSuit_RowStack builds down by rank and suit, # A Yukon_SameSuit_RowStack builds down by rank and suit,
# but can move any face-up cards regardless of sequence. # but can move any face-up cards regardless of sequence.
@ -1994,9 +1999,9 @@ class Yukon_SS_RowStack(Yukon_AC_RowStack):
def _isSequence(self, c1, c2): def _isSequence(self, c1, c2):
return (c1.rank + self.cap.dir) % self.cap.mod == c2.rank and c1.suit == c2.suit return (c1.rank + self.cap.dir) % self.cap.mod == c2.rank and c1.suit == c2.suit
def getHelp(self): def getHelp(self):
if self.cap.dir > 0: return _('Row. Build up by suit, can move any face-up cards regardless of sequence.') if self.cap.dir > 0: return _('Tableau. Build up by suit, can move any face-up cards regardless of sequence.')
elif self.cap.dir < 0: return _('Row. Build down by suit, can move any face-up cards regardless of sequence.') elif self.cap.dir < 0: return _('Tableau. Build down by suit, can move any face-up cards regardless of sequence.')
else: return _('Row. Build by same rank, can move any face-up cards regardless of sequence.') else: return _('Tableau. Build by same rank, can move any face-up cards regardless of sequence.')
# #
# King-versions of some of the above stacks: they accepts only Kings or # King-versions of some of the above stacks: they accepts only Kings or
@ -2028,7 +2033,7 @@ class UD_SC_RowStack(SequenceRowStack):
return (isSameColorSequence(cards, self.cap.mod, 1) or return (isSameColorSequence(cards, self.cap.mod, 1) or
isSameColorSequence(cards, self.cap.mod, -1)) isSameColorSequence(cards, self.cap.mod, -1))
def getHelp(self): def getHelp(self):
return _('Row. Build up or down by color.') return _('Tableau. Build up or down by color.')
# up or down by alternate color # up or down by alternate color
class UD_AC_RowStack(SequenceRowStack): class UD_AC_RowStack(SequenceRowStack):
@ -2039,7 +2044,7 @@ class UD_AC_RowStack(SequenceRowStack):
return (isAlternateColorSequence(cards, self.cap.mod, 1) or return (isAlternateColorSequence(cards, self.cap.mod, 1) or
isAlternateColorSequence(cards, self.cap.mod, -1)) isAlternateColorSequence(cards, self.cap.mod, -1))
def getHelp(self): def getHelp(self):
return _('Row. Build up or down by alternate color.') return _('Tableau. Build up or down by alternate color.')
# up or down by suit # up or down by suit
class UD_SS_RowStack(SequenceRowStack): class UD_SS_RowStack(SequenceRowStack):
@ -2050,7 +2055,7 @@ class UD_SS_RowStack(SequenceRowStack):
return (isSameSuitSequence(cards, self.cap.mod, 1) or return (isSameSuitSequence(cards, self.cap.mod, 1) or
isSameSuitSequence(cards, self.cap.mod, -1)) isSameSuitSequence(cards, self.cap.mod, -1))
def getHelp(self): def getHelp(self):
return _('Row. Build up or down by suit.') return _('Tableau. Build up or down by suit.')
# up or down by rank ignoring suit # up or down by rank ignoring suit
class UD_RK_RowStack(SequenceRowStack): class UD_RK_RowStack(SequenceRowStack):
@ -2061,7 +2066,7 @@ class UD_RK_RowStack(SequenceRowStack):
return (isRankSequence(cards, self.cap.mod, 1) or return (isRankSequence(cards, self.cap.mod, 1) or
isRankSequence(cards, self.cap.mod, -1)) isRankSequence(cards, self.cap.mod, -1))
def getHelp(self): def getHelp(self):
return _('Row. Build up or down regardless of suit.') return _('Tableau. Build up or down regardless of suit.')

View file

@ -37,7 +37,7 @@
__all__ = ['PysolMenubar'] __all__ = ['PysolMenubar']
# imports # imports
import math, os, re, sys, types import math, os, re, types
import Tkinter, tkColorChooser, tkFileDialog import Tkinter, tkColorChooser, tkFileDialog
# PySol imports # PySol imports
@ -318,6 +318,8 @@ class PysolMenubar(PysolMenubarActions):
menu.add_separator() menu.add_separator()
menu.add_command(label=n_("&Demo"), command=self.mDemo, accelerator=m+"D") 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_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 = MfxMenu(self.__menubar, label=n_("&Options")) menu = MfxMenu(self.__menubar, label=n_("&Options"))
menu.add_command(label=n_("&Player options..."), command=self.mOptPlayerOptions) menu.add_command(label=n_("&Player options..."), command=self.mOptPlayerOptions)
submenu = MfxMenu(menu, label=n_("&Automatic play")) submenu = MfxMenu(menu, label=n_("&Automatic play"))
@ -425,8 +427,8 @@ class PysolMenubar(PysolMenubarActions):
self._bindKey("", "Print", self.mScreenshot) self._bindKey("", "Print", self.mScreenshot)
self._bindKey(ctrl, "u", self.mPlayNextMusic) # undocumented self._bindKey(ctrl, "u", self.mPlayNextMusic) # undocumented
self._bindKey("", "p", self.mPause) self._bindKey("", "p", self.mPause)
self._bindKey("", "Pause", self.mPause) self._bindKey("", "Pause", self.mPause) # undocumented
self._bindKey("", "Escape", self.mIconify) self._bindKey("", "Escape", self.mIconify) # undocumented
# ASD and LKJ # ASD and LKJ
self._bindKey("", "a", self.mDrop) self._bindKey("", "a", self.mDrop)
self._bindKey(ctrl, "a", self.mDrop1) self._bindKey(ctrl, "a", self.mDrop1)
@ -436,6 +438,8 @@ class PysolMenubar(PysolMenubarActions):
self._bindKey(ctrl, "l", self.mDrop1) self._bindKey(ctrl, "l", self.mDrop1)
self._bindKey("", "k", self.mUndo) self._bindKey("", "k", self.mUndo)
self._bindKey("", "j", self.mDeal) self._bindKey("", "j", self.mDeal)
self._bindKey("", "F2", self.mStackDesk)
# #
self._bindKey("", "slash", self.mGameInfo) # undocumented, devel self._bindKey("", "slash", self.mGameInfo) # undocumented, devel
@ -1053,5 +1057,14 @@ class PysolMenubar(PysolMenubarActions):
self.app.toolbar.config(w, v) self.app.toolbar.config(w, v)
self.top.update_idletasks() self.top.update_idletasks()
#
# stacks descriptions
#
def mStackDesk(self, *event):
if self.game.stackdesc_list:
self.game.deleteStackDesc()
else:
if self._cancelDrag(break_pause=True): return
self.game.showStackDesc()

View file

@ -38,6 +38,7 @@ __all__ = ['MfxMessageDialog',
'MfxSimpleEntry', 'MfxSimpleEntry',
'MfxTooltip', 'MfxTooltip',
'MfxScrolledCanvas', 'MfxScrolledCanvas',
'StackDesc',
] ]
# imports # imports
@ -669,3 +670,43 @@ class MfxScrolledCanvas:
return self._yview('moveto', 1) return self._yview('moveto', 1)
# /***********************************************************************
# //
# ************************************************************************/
class StackDesc:
def __init__(self, game, stack):
self.game = game
self.stack = stack
self.canvas = game.canvas
font = game.app.getFont('canvas_small')
##print self.app.cardset.CARDW, self.app.images.CARDW
cardw = game.app.images.CARDW
x, y = stack.x+cardw/2, stack.y
text = stack.getHelp()+'\n'+stack.getBaseCard()
text = text.strip()
if text:
frame = Tkinter.Frame(self.canvas, highlightthickness=1,
highlightbackground='black')
label = Tkinter.Message(frame, font=font, text=text, width=cardw-8,
fg='#000000', bg='#ffffe0')
label.pack()
self.label = label
self.id = self.canvas.create_window(x, y, window=frame, anchor='n')
self.binding = label.bind('<ButtonPress>', self.buttonPressEvent)
else:
self.id = None
def buttonPressEvent(self, *event):
self.game.deleteStackDesc()
def delete(self):
if self.id:
self.canvas.delete(self.id)
self.label.unbind('<ButtonPress>', self.binding)