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: file:///home/shlomif/Backup/svn-dumps/PySolFC/svnsync-repos/pysolfc/PySolFC/trunk@29 efabe8c0-fbe8-4139-b769-b5e6d273206e
This commit is contained in:
parent
8e2cc715a9
commit
3814cf1cd4
21 changed files with 460 additions and 98 deletions
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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.')
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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])
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue