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

+ new file pysollib/games/grandduchess.py

+ 7 new games
* misc. improvements


git-svn-id: https://pysolfc.svn.sourceforge.net/svnroot/pysolfc/PySolFC/trunk@28 39dd0a4e-7c14-0410-91b3-c4f2d318f732
This commit is contained in:
skomoroh 2006-07-26 21:10:13 +00:00
parent 602ccc743f
commit 06ac5b6386
13 changed files with 495 additions and 166 deletions

View file

@ -688,6 +688,8 @@ class Application:
else: else:
self.requestCompatibleCardsetType(self.nextgame.id) self.requestCompatibleCardsetType(self.nextgame.id)
finally: finally:
# hide main window
self.wm_withdraw()
# update options # update options
self.opt.last_gameid = id self.opt.last_gameid = id
# save options # save options

View file

@ -22,6 +22,7 @@ import fortythieves
import freecell import freecell
import glenwood import glenwood
import golf import golf
import grandduchess
import grandfathersclock import grandfathersclock
import gypsy import gypsy
import harp import harp

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
@ -41,6 +40,8 @@ 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
# /*********************************************************************** # /***********************************************************************
# // Tam O'Shanter # // Tam O'Shanter
@ -48,26 +49,40 @@ from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
class TamOShanter(Game): class TamOShanter(Game):
Talon_Class = DealRowTalonStack Talon_Class = DealRowTalonStack
Foundation_Class = RK_FoundationStack
RowStack_Class = StackWrapper(BasicRowStack, max_move=1, max_accept=0) RowStack_Class = StackWrapper(BasicRowStack, max_move=1, max_accept=0)
def createGame(self): def createGame(self, rows=4, texts=False, yoffset=None):
# create layout # create layout
l, s = Layout(self), self.s l, s = Layout(self), self.s
# set window # set window
self.setSize(l.XM + 6*l.XS, l.YM + 4*l.YS) if yoffset is None:
yoffset = l.YOFFSET
max_rows = max(rows, 4*self.gameinfo.decks)
self.setSize(l.XM+(2+max_rows)*l.XS, l.YM+2*l.YS+12*yoffset)
# create stacks # create stacks
x, y, = l.XM, l.YM if texts:
x, y, = l.XM, l.YM+l.YS/2
else:
x, y, = l.XM, l.YM
s.talon = self.Talon_Class(x, y, self) s.talon = self.Talon_Class(x, y, self)
l.createText(s.talon, "ss") l.createText(s.talon, "ss")
if texts:
tx, ty, ta, tf = l.getTextAttr(s.talon, 'nn')
font = self.app.getFont('canvas_default')
s.talon.texts.rounds = MfxCanvasText(self.canvas, tx, ty,
anchor=ta, font=font)
x, y = l.XM+2*l.XS, l.YM x, y = l.XM+2*l.XS, l.YM
for i in range(4): for i in range(4*self.gameinfo.decks):
s.foundations.append(RK_FoundationStack(x, y, self)) s.foundations.append(self.Foundation_Class(x, y, self, suit=i%4))
x += l.XS x += l.XS
x, y = l.XM+2*l.XS, l.YM+l.YS x, y = l.XM+2*l.XS, l.YM+l.YS
for i in range(4): for i in range(rows):
s.rows.append(self.RowStack_Class(x, y, self)) stack = self.RowStack_Class(x, y, self)
s.rows.append(stack)
stack.CARD_YOFFSET = yoffset
x += l.XS x += l.XS
# define stack-groups # define stack-groups
@ -345,25 +360,15 @@ class Colorado(Game):
# // Amazons # // Amazons
# ************************************************************************/ # ************************************************************************/
class Amazons_Talon(DealRowTalonStack): class Amazons_Talon(RedealTalonStack):
def canDealCards(self): def canDealCards(self):
## FIXME: this is to avoid loops in the demo
if self.game.demo and self.game.moves.index >= 100:
return False
if self.round == self.max_rounds:
return False
return not self.game.isGameWon() return not self.game.isGameWon()
def dealCards(self, sound=0): def dealCards(self, sound=0):
self.game.startDealSample()
if not self.cards: if not self.cards:
self.game.nextRoundMove(self) RedealTalonStack.redealCards(self, frames=4, sound=sound)
n = self._moveAllToTalon() return self.dealRowAvail(sound=sound)
self.game.stopSamples()
return n
n = self.dealRowAvail()
self.game.stopSamples()
return n
def dealRowAvail(self, rows=None, flip=1, reverse=0, frames=-1, sound=0): def dealRowAvail(self, rows=None, flip=1, reverse=0, frames=-1, sound=0):
if rows is None: if rows is None:
@ -373,19 +378,9 @@ class Amazons_Talon(DealRowTalonStack):
if len(f.cards) < 7: if len(f.cards) < 7:
rows.append(self.game.s.rows[i]) rows.append(self.game.s.rows[i])
i += 1 i += 1
return DealRowTalonStack.dealRowAvail(self, rows=rows, flip=flip, return RedealTalonStack.dealRowAvail(self, rows=rows, flip=flip,
reverse=reverse, frames=frames, sound=sound) reverse=reverse, frames=frames, sound=sound)
def _moveAllToTalon(self):
# move all cards to the Talon
num_cards = 0
for r in self.game.s.rows:
for i in range(len(r.cards)):
num_cards += 1
self.game.moveMove(1, r, self, frames=4)
self.game.flipMove(self)
return num_cards
class Amazons_Foundation(AbstractFoundationStack): class Amazons_Foundation(AbstractFoundationStack):
def acceptsCards(self, from_stack, cards): def acceptsCards(self, from_stack, cards):
@ -407,80 +402,60 @@ class Amazons_Foundation(AbstractFoundationStack):
return i == j return i == j
class Amazons(Game): class Amazons(AuldLangSyne):
Talon_Class = StackWrapper(Amazons_Talon, max_rounds=-1)
def createGame(self): Foundation_Class = StackWrapper(Amazons_Foundation, max_cards=7)
# create layout
l, s = Layout(self), self.s
# set window
self.setSize(l.XM + 6*l.XS, l.YM + 4*l.YS)
# create stacks
x, y, = l.XM, l.YM
s.talon = Amazons_Talon(x, y, self, max_rounds=-1)
l.createText(s.talon, "ss")
x, y = l.XM+2*l.XS, l.YM
for i in range(4):
s.foundations.append(Amazons_Foundation(x, y, self, suit=i, max_cards=7))
x += l.XS
x, y = l.XM+2*l.XS, l.YM+l.YS
for i in range(4):
s.rows.append(BasicRowStack(x, y, self, max_move=1, max_accept=0))
x += l.XS
# define stack-groups
l.defaultStackGroups()
def _shuffleHook(self, cards):
return cards
def startGame(self): def startGame(self):
self.startDealSample() self.startDealSample()
self.s.talon.dealRow() self.s.talon.dealRow()
def getAutoStacks(self, event=None):
return ((), (), self.sg.dropstacks)
# /*********************************************************************** # /***********************************************************************
# // Scuffle
# // Acquaintance # // Acquaintance
# ************************************************************************/ # ************************************************************************/
class Acquaintance_Talon(TalonStack): # TalonStack class Scuffle_Talon(RedealTalonStack):
def canDealCards(self): def canDealCards(self):
if self.round == self.max_rounds and not self.cards: if self.round == self.max_rounds:
return False return len(self.cards) != 0
return not self.game.isGameWon() return not self.game.isGameWon()
def _redeal(self): def dealCards(self, sound=0, shuffle=True):
# move all cards to the Talon if self.cards:
lr = len(self.game.s.rows) return self.dealRowAvail(sound=sound)
num_cards = 0 RedealTalonStack.redealCards(self, frames=4,
assert len(self.cards) == 0 shuffle=shuffle, sound=sound)
rows = self.game.s.rows return self.dealRowAvail(sound=sound)
for r in rows:
for i in range(len(r.cards)):
num_cards = num_cards + 1
self.game.moveMove(1, r, self, frames=4)
self.game.flipMove(self)
assert len(self.cards) == num_cards
if num_cards == 0: # game already finished
return
self.game.nextRoundMove(self)
class Scuffle(AuldLangSyne):
Talon_Class = StackWrapper(Scuffle_Talon, max_rounds=3)
def createGame(self):
AuldLangSyne.createGame(self, texts=True, yoffset=0)
class Acquaintance_Talon(Scuffle_Talon):
def dealCards(self, sound=0): def dealCards(self, sound=0):
if sound: Scuffle_Talon.dealCards(self, sound=sound, shuffle=False)
self.game.startDealSample()
if len(self.cards) == 0:
self._redeal()
n = self.dealRowAvail(sound=sound)
if sound:
self.game.stopSamples()
return n
class Acquaintance(AuldLangSyne): class Acquaintance(AuldLangSyne):
Talon_Class = StackWrapper(Acquaintance_Talon, max_rounds=3) Talon_Class = StackWrapper(Acquaintance_Talon, max_rounds=3)
def createGame(self, texts=False, yoffset=None):
AuldLangSyne.createGame(self, texts=True)
class DoubleAcquaintance(AuldLangSyne):
Talon_Class = StackWrapper(Acquaintance_Talon, max_rounds=3)
def createGame(self):
AuldLangSyne.createGame(self, rows=8, texts=True)
# register the game # register the game
@ -500,4 +475,8 @@ registerGame(GameInfo(406, Amazons, "Amazons",
)) ))
registerGame(GameInfo(490, Acquaintance, "Acquaintance", registerGame(GameInfo(490, Acquaintance, "Acquaintance",
GI.GT_NUMERICA, 1, 2, GI.SL_BALANCED)) GI.GT_NUMERICA, 1, 2, GI.SL_BALANCED))
registerGame(GameInfo(553, Scuffle, "Scuffle",
GI.GT_NUMERICA, 1, 2, GI.SL_MOSTLY_LUCK))
registerGame(GameInfo(560, DoubleAcquaintance, "Double Acquaintance",
GI.GT_NUMERICA, 2, 2, GI.SL_BALANCED))

View file

@ -107,10 +107,12 @@ class FortyThieves(Game):
s.talon = WasteTalonStack(x, y, self, max_rounds=max_rounds, num_deal=num_deal) s.talon = WasteTalonStack(x, y, self, max_rounds=max_rounds, num_deal=num_deal)
l.createText(s.talon, "n") l.createText(s.talon, "n")
if max_rounds > 1: if max_rounds > 1:
tx, ty, ta, tf = l.getTextAttr(s.talon, "nn")
font = self.app.getFont("canvas_default")
s.talon.texts.rounds = MfxCanvasText(self.canvas, s.talon.texts.rounds = MfxCanvasText(self.canvas,
x + l.CW / 2, y - l.TEXT_HEIGHT, tx, ty-l.TEXT_MARGIN,
anchor="s", anchor=ta,
font=self.app.getFont("canvas_default")) font=font)
x = x - l.XS x = x - l.XS
s.waste = WasteStack(x, y, self) s.waste = WasteStack(x, y, self)
s.waste.CARD_XOFFSET = -l.XOFFSET s.waste.CARD_XOFFSET = -l.XOFFSET
@ -799,6 +801,55 @@ class Waterloo(FortyThieves):
return 0 return 0
# /***********************************************************************
# // Junction
# ************************************************************************/
from gypsy import DieRussische_Foundation
class Junction(Game):
def createGame(self, rows=7):
l, s = Layout(self), self.s
self.setSize(l.XM+10*l.XS, l.YM+3*l.YS+12*l.YOFFSET)
y = l.YM
for i in range(2):
x = l.XM+2*l.XS
for j in range(8):
s.foundations.append(DieRussische_Foundation(x, y, self,
suit=j%4, max_cards=8))
x += l.XS
y += l.YS
x, y = l.XM+(10-rows)*l.XS/2, l.YM+2*l.YS
for i in range(rows):
s.rows.append(AC_RowStack(x, y, self))
x += l.XS
x, y = l.XM, l.YM
s.talon = WasteTalonStack(x, y, self, max_rounds=1)
l.createText(s.talon, 'ne')
y += l.YS
s.waste = WasteStack(x, y, self)
l.createText(s.waste, 'ne')
l.defaultStackGroups()
def startGame(self):
self.startDealSample()
self.s.talon.dealRow()
self.s.talon.dealCards()
def shallHighlightMatch(self, stack1, card1, stack2, card2):
return card1.color != card2.color and abs(card1.rank-card2.rank) == 1
# register the game # register the game
registerGame(GameInfo(13, FortyThieves, "Forty Thieves", registerGame(GameInfo(13, FortyThieves, "Forty Thieves",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_SKILL, GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_SKILL,
@ -887,5 +938,8 @@ registerGame(GameInfo(529, SanJuanHill, "San Juan Hill",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED)) GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(540, Waterloo, "Waterloo", registerGame(GameInfo(540, Waterloo, "Waterloo",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED)) GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(556, Junction, "Junction",
GI.GT_FORTY_THIEVES, 4, 0, GI.SL_MOSTLY_SKILL,
ranks=(0, 6, 7, 8, 9, 10, 11, 12) ))

View file

@ -0,0 +1,139 @@
##---------------------------------------------------------------------------##
##
## PySol -- a Python Solitaire game
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; see the file COPYING.
## If not, write to the Free Software Foundation, Inc.,
## 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
##
##---------------------------------------------------------------------------##
__all__ = []
# imports
import sys
# PySol imports
from pysollib.gamedb import registerGame, GameInfo, GI
from pysollib.util import *
from pysollib.mfxutil import kwdefault
from pysollib.stack import *
from pysollib.game import Game
from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText
# /***********************************************************************
# // Grand Duchess
# ************************************************************************/
class GrandDuchess_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):
rows = self.game.s.rows
reserves = self.game.s.reserves
if not self.cards:
RedealTalonStack.redealCards(self, rows=rows+reserves, sound=0)
if sound and not self.game.demo:
self.game.startDealSample()
num_cards = 0
if self.round != 4:
num_cards += self.dealRowAvail(rows=[reserves[0]], flip=0)
num_cards += self.dealRowAvail()
if self.round != 4:
num_cards += self.dealRowAvail(rows=[reserves[1]], flip=0)
if not self.cards:
for s in reserves:
self.game.flipAllMove(s)
if sound and not self.game.demo:
self.game.stopSamples()
return num_cards
class GrandDuchess_Reserve(ArbitraryStack):
def canFlipCard(self):
return False
class GrandDuchess(Game):
#
# game layout
#
def createGame(self):
# create layout
l, s = Layout(self), self.s
# set window
w, h = l.XM+9*l.XS, l.YM+2*l.YS+18*l.YOFFSET
self.setSize(w, h)
# create stacks
x, y = l.XM, l.YM
for i in range(4):
s.foundations.append(SS_FoundationStack(x, y, self, suit=i))
x += l.XS
for i in range(4):
s.foundations.append(SS_FoundationStack(x, y, self,
suit=i, base_rank=KING, dir=-1))
x += l.XS
x, y = l.XM+2*l.XS, l.YM+l.YS
for i in range(4):
stack = BasicRowStack(x, y, self, max_move=1, max_accept=0)
stack.CARD_YOFFSET = l.YOFFSET
s.rows.append(stack)
x += l.XS
x, y = l.XM, l.YM+l.YS
s.reserves.append(GrandDuchess_Reserve(x, y, self))
x, y = l.XM+7*l.XS, l.YM+l.YS
s.reserves.append(GrandDuchess_Reserve(x, y, self))
x, y = self.width-l.XS, self.height-l.YS
s.talon = GrandDuchess_Talon(x, y, self, max_rounds=4)
l.createText(s.talon, 'n')
tx, ty, ta, tf = l.getTextAttr(s.talon, "nn")
font = self.app.getFont("canvas_default")
s.talon.texts.rounds = MfxCanvasText(self.canvas,
tx, ty-l.TEXT_MARGIN,
anchor=ta, font=font)
# define stack-groups
l.defaultStackGroups()
#
# game overrides
#
def startGame(self):
self.startDealSample()
self.s.talon.dealRow(rows=[self.s.reserves[0]], flip=0)
self.s.talon.dealRow()
self.s.talon.dealRow(rows=[self.s.reserves[1]], flip=0)
def getAutoStacks(self, event=None):
return ((), (), self.sg.dropstacks)
registerGame(GameInfo(557, GrandDuchess, "Grand Duchess",
GI.GT_2DECK_TYPE, 2, 3))

View file

@ -356,7 +356,8 @@ class AgnesSorel(Klondike):
def shallHighlightMatch(self, stack1, card1, stack2, card2): def shallHighlightMatch(self, stack1, card1, stack2, card2):
return (card1.color == card2.color and return (card1.color == card2.color and
((card1.rank + 1) % 13 == card2.rank or (card2.rank + 1) % 13 == card1.rank)) ((card1.rank + 1) % 13 == card2.rank or
(card2.rank + 1) % 13 == card1.rank))
# /*********************************************************************** # /***********************************************************************
@ -638,7 +639,8 @@ class Jane(Klondike):
def shallHighlightMatch(self, stack1, card1, stack2, card2): def shallHighlightMatch(self, stack1, card1, stack2, card2):
return (card1.suit == card2.suit and return (card1.suit == card2.suit and
((card1.rank + 1) % 13 == card2.rank or (card2.rank + 1) % 13 == card1.rank)) ((card1.rank + 1) % 13 == card2.rank or
(card2.rank + 1) % 13 == card1.rank))
def _autoDeal(self, sound=1): def _autoDeal(self, sound=1):
return 0 return 0

View file

@ -106,29 +106,33 @@ class Numerica(Game):
def createGame(self, rows=4): def createGame(self, rows=4):
# create layout # create layout
l, s = Layout(self), self.s l, s = Layout(self), self.s
decks = self.gameinfo.decks
foundations = 4*decks
# set window # set window
# (piles up to 20 cards are playable in default window size) # (piles up to 20 cards are playable in default window size)
h = max(2*l.YS, 20*l.YOFFSET) h = max(2*l.YS, 20*l.YOFFSET)
self.setSize(l.XM+(1.5+rows)*l.XS+l.XM, l.YM + l.YS + h) max_rows = max(rows, foundations)
self.setSize(l.XM+(1.5+max_rows)*l.XS+l.XM, l.YM + l.YS + h)
# create stacks # create stacks
x0 = l.XM + l.XS * 3 / 2 x0 = l.XM + l.XS * 3 / 2
x, y = x0 + (rows-4)*l.XS/2, l.YM if decks == 1:
for i in range(4): x = x0 + (rows-4)*l.XS/2
else:
x = x0
y = l.YM
for i in range(foundations):
s.foundations.append(self.Foundation_Class(x, y, self, suit=i)) s.foundations.append(self.Foundation_Class(x, y, self, suit=i))
x = x + l.XS x = x + l.XS
x, y = x0, l.YM + l.YS x, y = x0, l.YM + l.YS
for i in range(rows): for i in range(rows):
s.rows.append(self.RowStack_Class(x, y, self)) s.rows.append(self.RowStack_Class(x, y, self))
x = x + l.XS x = x + l.XS
self.setRegion(s.rows, (x0 - l.XS / 2, y, 999999, 999999)) self.setRegion(s.rows, (x0-l.XS/2, y-l.CH/2, 999999, 999999))
x = l.XM x = l.XM
s.talon = WasteTalonStack(x, y, self, max_rounds=1) s.talon = WasteTalonStack(x, y, self, max_rounds=1)
s.talon.texts.ncards = MfxCanvasText(self.canvas, l.createText(s.talon, 'n')
x + l.CW / 2, y - l.YM,
anchor="s",
font=self.app.getFont("canvas_default"))
y = y + l.YS y = y + l.YS
s.waste = WasteStack(x, y, self, max_cards=1) s.waste = WasteStack(x, y, self, max_cards=1)
@ -153,6 +157,11 @@ class Numerica(Game):
return () return ()
class Numerica2Decks(Numerica):
def createGame(self):
Numerica.createGame(self, rows=6)
# /*********************************************************************** # /***********************************************************************
# // Lady Betty # // Lady Betty
# ************************************************************************/ # ************************************************************************/
@ -642,3 +651,7 @@ registerGame(GameInfo(435, Shifting, "Shifting",
GI.GT_NUMERICA, 1, 0, GI.SL_BALANCED)) GI.GT_NUMERICA, 1, 0, GI.SL_BALANCED))
registerGame(GameInfo(472, Strategerie, "Strategerie", registerGame(GameInfo(472, Strategerie, "Strategerie",
GI.GT_NUMERICA, 1, 0, GI.SL_MOSTLY_SKILL)) GI.GT_NUMERICA, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(558, Numerica2Decks, "Numerica (2 decks)",
GI.GT_NUMERICA, 2, 0, GI.SL_BALANCED))

View file

@ -43,7 +43,7 @@ from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
# /*********************************************************************** # /***********************************************************************
# // # // PileOn
# ************************************************************************/ # ************************************************************************/
class PileOn_RowStack(RK_RowStack): class PileOn_RowStack(RK_RowStack):
@ -127,10 +127,81 @@ class SmallPileOn(PileOn):
PLAYCARDS = 4 PLAYCARDS = 4
class PileOn2Decks(PileOn): ## class PileOn2Decks(PileOn):
TWIDTH = 4 ## TWIDTH = 4
NSTACKS = 15 ## NSTACKS = 15
PLAYCARDS = 8 ## PLAYCARDS = 8
## registerGame(GameInfo(341, PileOn2Decks, "PileOn (2 decks)",
## GI.GT_2DECK_TYPE | GI.GT_OPEN,, 2, 0))
# /***********************************************************************
# // Foursome
# // Quartets
# ************************************************************************/
class Foursome(Game):
Hint_Class = CautiousDefaultHint
Talon_Class = DealRowTalonStack
def createGame(self, rows=6, texts=True):
l, s = Layout(self), self.s
max_rows = max(6, rows)
self.setSize(l.XM+max_rows*l.XS, l.YM+3*l.YS+13*l.YOFFSET)
x, y = l.XM+(max_rows-6)*l.XS/2, l.YM
for i in range(4):
s.reserves.append(ReserveStack(x, y, self))
x += l.XS
x = l.XM+(max_rows-1)*l.XS
s.foundations.append(AbstractFoundationStack(x, y, self,
suit=ANY_SUIT, max_cards=52, max_accept=0))
x, y = l.XM, l.YM+l.YS
for i in range(rows):
s.rows.append(UD_AC_RowStack(x, y, self, mod=13))
x += l.XS
s.talon = self.Talon_Class(self.width-l.XS, self.height-l.YS, self)
if texts:
l.createText(s.talon, 'n')
l.defaultStackGroups()
def startGame(self):
self.startDealSample()
self.s.talon.dealRow(rows=self.s.reserves)
self.s.talon.dealRow()
def fillStack(self, stack):
if not self.s.reserves[0].cards:
return
rank = self.s.reserves[0].cards[0].rank
for r in self.s.reserves[1:]:
if not r.cards or r.cards[0].rank != rank:
return
old_state = self.enterState(self.S_FILL)
self.playSample("droppair", priority=200)
for r in self.s.reserves:
self.moveMove(1, r, self.s.foundations[0], frames=4)
self.flipMove(self.s.foundations[0])
self.leaveState(old_state)
def shallHighlightMatch(self, stack1, card1, stack2, card2):
return (card1.color != card2.color and
((card1.rank + 1) % 13 == card2.rank or
(card2.rank + 1) % 13 == card1.rank))
class Quartets(Foursome):
Talon_Class = InitialDealTalonStack
def createGame(self):
Foursome.createGame(self, rows=8, texts=False)
def startGame(self):
for i in range(5):
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow()
self.s.talon.dealRowAvail()
# register the game # register the game
@ -141,7 +212,9 @@ registerGame(GameInfo(289, SmallPileOn, "Small PileOn",
GI.GT_1DECK_TYPE | GI.GT_OPEN | GI.GT_ORIGINAL, 1, 0, GI.SL_MOSTLY_SKILL, GI.GT_1DECK_TYPE | GI.GT_OPEN | GI.GT_ORIGINAL, 1, 0, GI.SL_MOSTLY_SKILL,
ranks=(0, 5, 6, 7, 8, 9, 10, 11, 12), ranks=(0, 5, 6, 7, 8, 9, 10, 11, 12),
rules_filename = "pileon.html")) rules_filename = "pileon.html"))
## registerGame(GameInfo(341, PileOn2Decks, "PileOn (2 decks)", registerGame(GameInfo(554, Foursome, "Foursome",
## GI.GT_2DECK_TYPE | GI.GT_OPEN,, 2, 0)) GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(555, Quartets, "Quartets",
GI.GT_1DECK_TYPE | GI.GT_OPEN | GI.GT_ORIGINAL, 1, 0, GI.SL_MOSTLY_SKILL))

View file

@ -222,11 +222,32 @@ class Kingdom(RoyalCotillion):
# // Granada # // Granada
# ************************************************************************/ # ************************************************************************/
class Alhambra_Hint(CautiousDefaultHint):
def _getDropCardScore(self, score, color, r, t, ncards):
return 93000, color
class Alhambra_RowStack(UD_SS_RowStack): class Alhambra_RowStack(UD_SS_RowStack):
def getBottomImage(self): def getBottomImage(self):
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])
@ -259,7 +280,7 @@ class Alhambra_Talon(DealRowTalonStack):
class Alhambra(Game): class Alhambra(Game):
Hint_Class = CautiousDefaultHint Hint_Class = Alhambra_Hint
def createGame(self, rows=1): def createGame(self, rows=1):
# create layout # create layout

View file

@ -731,64 +731,63 @@ class CornerSuite(Game):
# /*********************************************************************** # /***********************************************************************
# // Scuffle # // Marshal
# ************************************************************************/ # ************************************************************************/
class Scuffle_Talon(RedealTalonStack): class Marshal_Hint(CautiousDefaultHint):
def _getDropCardScore(self, score, color, r, t, ncards):
def canDealCards(self): return 93000, color
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, shuffle=True, sound=sound)
return self.dealRowAvail(sound=sound)
class Scuffle_RowStack(BasicRowStack): class Marshal(Game):
##clickHandler = BasicRowStack.doubleclickHandler
pass
Hint_Class = Marshal_Hint
class Scuffle(Game):
def createGame(self): def createGame(self):
l, s = Layout(self), self.s l, s = Layout(self), self.s
self.setSize(l.XM+6*l.XS, l.YM+2*l.YS) self.setSize(l.XM+8*l.XS, l.YM+5*l.YS)
s.talon = Scuffle_Talon(l.XM, l.YM+l.YS/2, self, max_rounds=3) x, y = l.XM, l.YM
l.createText(s.talon, 's')
tx, ty, ta, tf = l.getTextAttr(s.talon, 'nn')
font = self.app.getFont('canvas_default')
s.talon.texts.rounds = MfxCanvasText(self.canvas, tx, ty,
anchor=ta, font=font)
x, y = l.XM+2*l.XS, l.YM
for i in range(4): for i in range(4):
s.foundations.append(RK_FoundationStack(x, y, self)) s.foundations.append(SS_FoundationStack(x, y, self, suit=i))
x += l.XS x += l.XS
x, y = l.XM+2*l.XS, l.YM+l.YS
for i in range(4): for i in range(4):
stack = Scuffle_RowStack(x, y, self, max_move=1) s.foundations.append(SS_FoundationStack(x, y, self,
s.rows.append(stack) suit=i, base_rank=KING, dir=-1))
stack.CARD_XOFFSET, stack.CARD_YOFFSET = 0, 0
x += l.XS x += l.XS
x, y = l.XM, l.YM+l.YS
s.talon = TalonStack(x, y, self)
l.createText(s.talon, 'se')
y = l.YM+l.YS
for i in range(4):
x = l.XM+2*l.XS
for j in range(6):
stack = UD_SS_RowStack(x, y, self, base_rank=NO_RANK)
s.rows.append(stack)
stack.CARD_XOFFSET, stack.CARD_YOFFSET = 0, 0
x += l.XS
y += l.YS
l.defaultStackGroups() l.defaultStackGroups()
def _shuffleHook(self, cards):
return self._shuffleHookMoveToTop(cards,
lambda c: (c.rank == ACE, c.suit))
def startGame(self): def startGame(self):
self.startDealSample() self.startDealSample()
self.s.talon.dealRow(rows=self.s.foundations)
self.s.talon.dealRow() self.s.talon.dealRow()
def fillStack(self, stack):
if stack in self.s.rows and not stack.cards:
if self.s.talon.cards:
old_state = self.enterState(self.S_FILL)
self.flipMove(self.s.talon)
self.moveMove(1, self.s.talon, stack)
self.leaveState(old_state)
def shallHighlightMatch(self, stack1, card1, stack2, card2):
return (card1.suit == card2.suit and
(abs(card1.rank-card2.rank) == 1))
# register the game # register the game
registerGame(GameInfo(330, Sultan, "Sultan", registerGame(GameInfo(330, Sultan, "Sultan",
@ -818,5 +817,5 @@ registerGame(GameInfo(438, SixesAndSevens, "Sixes and Sevens",
GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_LUCK)) GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_LUCK))
registerGame(GameInfo(477, CornerSuite, "Corner Suite", 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(553, Scuffle, "Scuffle", registerGame(GameInfo(559, Marshal, "Marshal",
GI.GT_1DECK_TYPE, 1, 2, GI.SL_MOSTLY_LUCK)) GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))

View file

@ -42,6 +42,9 @@ 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 golf import BlackHole_Foundation
# /*********************************************************************** # /***********************************************************************
# // # //
# ************************************************************************/ # ************************************************************************/
@ -63,10 +66,18 @@ class Windmill_RowStack(ReserveStack):
# /*********************************************************************** # /***********************************************************************
# // Windmill # // Windmill
# // Dutch Solitaire
# ************************************************************************/ # ************************************************************************/
class Windmill(Game): class Windmill(Game):
Foundation_Classes = [
StackWrapper(Windmill_Foundation, mod=13, min_cards=1, max_cards=52),
StackWrapper(Windmill_Foundation, base_rank=KING, dir=-1),
]
RowStack_Class = Windmill_RowStack
ROWS_LAYOUT = ((2,0), (2,1), (0,2), (1,2), (3,2), (4,2), (2,3), (2,4))
FILL_STACK = True FILL_STACK = True
# #
@ -89,16 +100,18 @@ class Windmill(Game):
s.waste = WasteStack(x, y, self) s.waste = WasteStack(x, y, self)
l.createText(s.waste, "ss") l.createText(s.waste, "ss")
x0, y0 = x + l.XS, y x0, y0 = x + l.XS, y
for d in ((2,0), (2,1), (0,2), (1,2), (3,2), (4,2), (2,3), (2,4)): for d in self.ROWS_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.rows.append(Windmill_RowStack(x, y, self)) stack = self.RowStack_Class(x, y, self)
s.rows.append(stack)
stack.CARD_XOFFSET, stack.CARD_YOFFSET = 0, 0
x, y = x0 + 2 * l.XS, y0 + 2 * l.YS x, y = x0 + 2 * l.XS, y0 + 2 * l.YS
s.foundations.append(Windmill_Foundation(x, y, self, fnd_cls = self.Foundation_Classes[0]
mod=13, min_cards=1, max_cards=52)) s.foundations.append(fnd_cls(x, y, self))
fnd_cls = self.Foundation_Classes[1]
for d in ((1,0.6), (3,0.6), (1,3.4), (3,3.4)): for d in ((1,0.6), (3,0.6), (1,3.4), (3,3.4)):
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(Windmill_Foundation(x, y, self, s.foundations.append(fnd_cls(x, y, self))
base_rank=KING, dir=-1))
# define stack-groups # define stack-groups
l.defaultStackGroups() l.defaultStackGroups()
@ -138,6 +151,34 @@ class Windmill(Game):
return ((), (), ()) return ((), (), ())
class DutchSolitaire_RowStack(UD_RK_RowStack):
def getBottomImage(self):
return self.game.app.images.getReserveBottom()
class DutchSolitaire(Windmill):
Foundation_Classes = [
StackWrapper(BlackHole_Foundation, suit=ANY_SUIT, mod=13, max_cards=UNLIMITED_CARDS),
StackWrapper(BlackHole_Foundation, suit=ANY_SUIT, mod=13, max_cards=UNLIMITED_CARDS),
]
RowStack_Class = DutchSolitaire_RowStack
##ROWS_LAYOUT = ((2,0), (2,1), (0,2), (1,2), (3,2), (4,2), (2,3), (2,4))
ROWS_LAYOUT = ((2,0), (2,1), (1,2), (3,2), (2,3), (2,4))
FILL_STACK = False
def _shuffleHook(self, cards):
return cards
def startGame(self):
self.startDealSample()
#self.s.talon.dealRow(rows=(self.s.foundations[0],))
#self.s.talon.dealRow()
self.s.talon.dealCards() # deal first card to WasteStack
def getAutoStacks(self, event=None):
return (self.sg.dropstacks, self.sg.dropstacks, self.sg.dropstacks)
# /*********************************************************************** # /***********************************************************************
# // Napoleon's Tomb # // Napoleon's Tomb
@ -330,4 +371,6 @@ registerGame(GameInfo(483, Czarina, "Czarina",
GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_LUCK)) GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
registerGame(GameInfo(484, FourSeasons, "Four Seasons", registerGame(GameInfo(484, FourSeasons, "Four Seasons",
GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_LUCK)) GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
registerGame(GameInfo(561, DutchSolitaire, "Dutch Solitaire",
GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_SKILL))

View file

@ -121,9 +121,10 @@ class Layout:
##self.RIGHT_MARGIN = layout_x_margin-layout_card_x_space ##self.RIGHT_MARGIN = layout_x_margin-layout_card_x_space
##self.BOTTOM_MARGIN = layout_y_margin-layout_card_y_space ##self.BOTTOM_MARGIN = layout_y_margin-layout_card_y_space
self.TEXT_MARGIN = 10
##self.TEXT_HEIGHT = 30
font = game.app.getFont("canvas_default") font = game.app.getFont("canvas_default")
##self.TEXT_MARGIN = 10
self.TEXT_MARGIN = font[1]
##self.TEXT_HEIGHT = 30
self.TEXT_HEIGHT = 18+font[1] self.TEXT_HEIGHT = 18+font[1]
self.__dict__.update(kw) self.__dict__.update(kw)
@ -150,29 +151,30 @@ class Layout:
def getTextAttr(self, stack, anchor): def getTextAttr(self, stack, anchor):
x, y = 0, 0 x, y = 0, 0
delta_x, delta_y = 4, 4
if stack is not None: if stack is not None:
x, y = stack.x, stack.y x, y = stack.x, stack.y
if anchor == "n": if anchor == "n":
return (x+self.CW/2, y-4, "s", "%d") return (x+self.CW/2, y-delta_y, "s", "%d")
if anchor == "nn": if anchor == "nn":
return (x+self.CW/2, y-self.TEXT_MARGIN, "s", "%d") return (x+self.CW/2, y-self.TEXT_MARGIN, "s", "%d")
if anchor == "s": if anchor == "s":
return (x+self.CW/2, y+self.CH+4, "n", "%d") return (x+self.CW/2, y+self.CH+delta_y, "n", "%d")
if anchor == "ss": if anchor == "ss":
return (x+self.CW/2, y+self.CH+self.TEXT_MARGIN, "n", "%d") return (x+self.CW/2, y+self.CH+self.TEXT_MARGIN, "n", "%d")
if anchor == "nw": if anchor == "nw":
return (x-self.TEXT_MARGIN, y, "ne", "%d") return (x-delta_x, y, "ne", "%d")
if anchor == "sw": if anchor == "sw":
return (x-self.TEXT_MARGIN, y+self.CH, "se", "%d") return (x-delta_x, y+self.CH, "se", "%d")
f = "%2d" f = "%2d"
if self.game.gameinfo.decks > 1: if self.game.gameinfo.decks > 1:
f = "%3d" f = "%3d"
if anchor == "ne": if anchor == "ne":
return (x+self.CW+self.TEXT_MARGIN, y, "nw", f) return (x+self.CW+delta_x, y, "nw", f)
if anchor == "se": if anchor == "se":
return (x+self.CW+self.TEXT_MARGIN, y+self.CH, "sw", f) return (x+self.CW+delta_x, y+self.CH, "sw", f)
if anchor == "e": if anchor == "e":
return (x+self.CW+self.TEXT_MARGIN, y+self.CH/2, "w", f) return (x+self.CW+delta_x, y+self.CH/2, "w", f)
raise Exception, anchor raise Exception, anchor
def createText(self, stack, anchor, dx=0, dy=0, text_format=""): def createText(self, stack, anchor, dx=0, dy=0, text_format=""):

View file

@ -1398,7 +1398,8 @@ class DealBaseCard_StackMethods:
class RedealCards_StackMethods: class RedealCards_StackMethods:
def redealCards(self, rows=None, sound=0, shuffle=False, reverse=False, frames=4): def redealCards(self, rows=None, sound=0,
shuffle=False, reverse=False, frames=0):
if sound and self.game.app.opt.animations: if sound and self.game.app.opt.animations:
self.game.startDealSample() self.game.startDealSample()
lr = len(self.game.s.rows) lr = len(self.game.s.rows)
@ -1413,7 +1414,7 @@ class RedealCards_StackMethods:
for r in rows: for r in rows:
for i in range(len(r.cards)): for i in range(len(r.cards)):
num_cards += 1 num_cards += 1
self.game.moveMove(1, r, self, frames=0) self.game.moveMove(1, r, self, frames=frames)
if self.cards[-1].face_up: if self.cards[-1].face_up:
self.game.flipMove(self) self.game.flipMove(self)
assert len(self.cards) == num_cards assert len(self.cards) == num_cards
@ -1798,11 +1799,11 @@ class SS_FoundationStack(AbstractFoundationStack):
# A Rank_FoundationStack builds up in rank and ignores color and suit. # A Rank_FoundationStack builds up in rank and ignores color and suit.
class RK_FoundationStack(SS_FoundationStack): class RK_FoundationStack(SS_FoundationStack):
def __init__(self, x, y, game, suit=ANY_SUIT, **cap): def __init__(self, x, y, game, suit=ANY_SUIT, **cap):
apply(SS_FoundationStack.__init__, (self, x, y, game, suit), cap) apply(SS_FoundationStack.__init__, (self, x, y, game, ANY_SUIT), cap)
def assertStack(self): def assertStack(self):
SS_FoundationStack.assertStack(self) SS_FoundationStack.assertStack(self)
assert self.cap.suit == ANY_SUIT ##assert self.cap.suit == ANY_SUIT
assert self.cap.color == ANY_COLOR assert self.cap.color == ANY_COLOR
def getHelp(self): def getHelp(self):