1
0
Fork 0
mirror of https://github.com/shlomif/PySolFC.git synced 2025-04-05 00:02:29 -04:00
This commit is contained in:
Shlomi Fish 2017-04-17 21:22:28 +03:00
parent 7d6c4cf58e
commit 8573e23829
6 changed files with 235 additions and 150 deletions

View file

@ -1,15 +1,28 @@
from pysollib.gamedb import registerGame, GameInfo, GI from pysollib.gamedb import registerGame, GameInfo, GI
from pysollib.util import *
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 DefaultHint
from pysollib.pysoltk import MfxCanvasText, get_text_width from pysollib.pysoltk import MfxCanvasText, get_text_width
from pysollib.mygettext import _
from pysollib.util import ANY_SUIT, KING, \
RANKS
from pysollib.stack import \
BasicRowStack, \
DealRowTalonStack, \
InitialDealTalonStack, \
RK_FoundationStack, \
Stack, \
WasteStack, \
WasteTalonStack, \
StackWrapper
# ************************************************************************ # ************************************************************************
# * # *
# ************************************************************************ # ************************************************************************
class Calculation_Hint(DefaultHint): class Calculation_Hint(DefaultHint):
# FIXME: demo logic is a complete nonsense # FIXME: demo logic is a complete nonsense
def _getMoveWasteScore(self, score, color, r, t, pile, rpile): def _getMoveWasteScore(self, score, color, r, t, pile, rpile):
@ -72,7 +85,8 @@ class Calculation_RowStack(BasicRowStack):
class Calculation(Game): class Calculation(Game):
Hint_Class = Calculation_Hint Hint_Class = Calculation_Hint
Foundation_Class = Calculation_Foundation Foundation_Class = Calculation_Foundation
RowStack_Class = StackWrapper(Calculation_RowStack, max_move=1, max_accept=1) RowStack_Class = StackWrapper(
Calculation_RowStack, max_move=1, max_accept=1)
# #
# game layout # game layout
@ -86,7 +100,7 @@ class Calculation(Game):
4: 8 Q 3 7 J 2 6 T A 5 9 K''')) 4: 8 Q 3 7 J 2 6 T A 5 9 K'''))
# calculate text_width # calculate text_width
lines = help.split('\n') lines = help.split('\n')
lines.sort(lambda a, b: cmp(len(a), len(b))) lines.sort(key=len)
max_line = lines[-1] max_line = lines[-1]
text_width = get_text_width(max_line, text_width = get_text_width(max_line,
font=self.app.getFont("canvas_fixed")) font=self.app.getFont("canvas_fixed"))
@ -116,8 +130,9 @@ class Calculation(Game):
stack.texts.misc = MfxCanvasText(self.canvas, tx, ty, stack.texts.misc = MfxCanvasText(self.canvas, tx, ty,
anchor=ta, font=font) anchor=ta, font=font)
x = x + l.XS x = x + l.XS
self.texts.help = MfxCanvasText(self.canvas, x + l.XM, y + l.CH / 2, text=help, self.texts.help = MfxCanvasText(
anchor="w", font=self.app.getFont("canvas_fixed")) self.canvas, x + l.XM, y + l.CH / 2, text=help,
anchor="w", font=self.app.getFont("canvas_fixed"))
x = x0 x = x0
y = l.YM + l.YS + l.TEXT_HEIGHT y = l.YM + l.YS + l.TEXT_HEIGHT
for i in range(4): for i in range(4):
@ -139,7 +154,7 @@ class Calculation(Game):
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
# prepare first cards # prepare first cards
topcards = [ None ] * 4 topcards = [None] * 4
for c in cards[:]: for c in cards[:]:
if c.rank <= 3 and topcards[c.rank] is None: if c.rank <= 3 and topcards[c.rank] is None:
topcards[c.rank] = c topcards[c.rank] = c
@ -163,7 +178,7 @@ class Calculation(Game):
class Hopscotch(Calculation): class Hopscotch(Calculation):
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
# prepare first cards # prepare first cards
topcards = [ None ] * 4 topcards = [None] * 4
for c in cards[:]: for c in cards[:]:
if c.suit == 0 and c.rank <= 3 and topcards[c.rank] is None: if c.suit == 0 and c.rank <= 3 and topcards[c.rank] is None:
topcards[c.rank] = c topcards[c.rank] = c
@ -225,14 +240,13 @@ class BetsyRoss(Calculation):
# define stack-groups # define stack-groups
l.defaultStackGroups() l.defaultStackGroups()
# #
# game overrides # game overrides
# #
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
# prepare first cards # prepare first cards
topcards = [ None ] * 8 topcards = [None] * 8
for c in cards[:]: for c in cards[:]:
if c.rank <= 3 and topcards[c.rank] is None: if c.rank <= 3 and topcards[c.rank] is None:
topcards[c.rank] = c topcards[c.rank] = c
@ -255,12 +269,13 @@ class One234_Foundation(BetsyRoss_Foundation):
if not BetsyRoss_Foundation.canMoveCards(self, cards): if not BetsyRoss_Foundation.canMoveCards(self, cards):
return False return False
return len(self.cards) > 1 return len(self.cards) > 1
def updateText(self): def updateText(self):
BetsyRoss_Foundation.updateText(self, update_empty=False) BetsyRoss_Foundation.updateText(self, update_empty=False)
class One234_RowStack(BasicRowStack): class One234_RowStack(BasicRowStack):
##clickHandler = BasicRowStack.doubleclickHandler # clickHandler = BasicRowStack.doubleclickHandler
pass pass
@ -291,8 +306,9 @@ class One234(Calculation):
stack.texts.misc = MfxCanvasText(self.canvas, tx, ty, stack.texts.misc = MfxCanvasText(self.canvas, tx, ty,
anchor=ta, font=font) anchor=ta, font=font)
x = x + l.XS x = x + l.XS
self.texts.help = MfxCanvasText(self.canvas, x + l.XM, y + l.CH / 2, text=help, self.texts.help = MfxCanvasText(
anchor="w", font=self.app.getFont("canvas_fixed")) self.canvas, x + l.XM, y + l.CH / 2, text=help,
anchor="w", font=self.app.getFont("canvas_fixed"))
x, y = l.XM, l.YM+l.YS+l.TEXT_HEIGHT x, y = l.XM, l.YM+l.YS+l.TEXT_HEIGHT
for i in range(8): for i in range(8):
s.rows.append(self.RowStack_Class(x, y, self)) s.rows.append(self.RowStack_Class(x, y, self))
@ -347,8 +363,9 @@ class SeniorWrangler_Talon(DealRowTalonStack):
self.game.stopSamples() self.game.stopSamples()
return num_cards return num_cards
class SeniorWrangler_RowStack(BasicRowStack): class SeniorWrangler_RowStack(BasicRowStack):
#clickHandler = BasicRowStack.doubleclickHandler # clickHandler = BasicRowStack.doubleclickHandler
pass pass
@ -381,7 +398,6 @@ class SeniorWrangler(Game):
# define stack-groups # define stack-groups
l.defaultStackGroups() l.defaultStackGroups()
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
top = [] top = []
ranks = [] ranks = []
@ -390,10 +406,9 @@ class SeniorWrangler(Game):
ranks.append(c.rank) ranks.append(c.rank)
cards.remove(c) cards.remove(c)
top.append(c) top.append(c)
top.sort(lambda a, b: cmp(b.rank, a.rank)) top.sort(key=lambda x: x.rank)
return cards+top return cards+top
def startGame(self): def startGame(self):
self.s.talon.dealRow(rows=self.s.foundations[:8], frames=0) self.s.talon.dealRow(rows=self.s.foundations[:8], frames=0)
for i in range(11): for i in range(11):
@ -433,7 +448,7 @@ class SPatience(Game):
max_cards=8, mod=13, max_move=0)) max_cards=8, mod=13, max_move=0))
x, y = l.XM+5.5*l.XS, l.YM+2*l.YS x, y = l.XM+5.5*l.XS, l.YM+2*l.YS
for i in (0,1): for i in (0, 1):
stack = Calculation_RowStack(x, y, self, max_move=1, max_accept=1) stack = Calculation_RowStack(x, y, self, max_move=1, max_accept=1)
stack.CARD_YOFFSET = 0 stack.CARD_YOFFSET = 0
s.rows.append(stack) s.rows.append(stack)
@ -455,7 +470,7 @@ class SPatience(Game):
ranks.append(c.rank) ranks.append(c.rank)
cards.remove(c) cards.remove(c)
top.append(c) top.append(c)
top.sort(lambda a, b: cmp(b.rank, a.rank)) top.sort(key=lambda x: x.rank)
return cards+top[7:]+top[:7] return cards+top[7:]+top[:7]
def startGame(self): def startGame(self):
@ -464,21 +479,19 @@ class SPatience(Game):
self.s.talon.dealCards() self.s.talon.dealCards()
# register the game # register the game
registerGame(GameInfo(256, Calculation, "Calculation", registerGame(GameInfo(256, Calculation, "Calculation",
GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_SKILL, GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_SKILL,
altnames=("Progression",) )) altnames=("Progression",)))
registerGame(GameInfo(94, Hopscotch, "Hopscotch", registerGame(GameInfo(94, Hopscotch, "Hopscotch",
GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_SKILL)) GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(134, BetsyRoss, "Betsy Ross", registerGame(GameInfo(134, BetsyRoss, "Betsy Ross",
GI.GT_1DECK_TYPE, 1, 2, GI.SL_MOSTLY_LUCK, GI.GT_1DECK_TYPE, 1, 2, GI.SL_MOSTLY_LUCK,
altnames=("Fairest", "Four Kings", "Musical Patience", altnames=("Fairest", "Four Kings", "Musical Patience",
"Quadruple Alliance", "Plus Belle") )) "Quadruple Alliance", "Plus Belle")))
registerGame(GameInfo(550, One234, "One234", registerGame(GameInfo(550, One234, "One234",
GI.GT_1DECK_TYPE | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL)) GI.GT_1DECK_TYPE | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(653, SeniorWrangler, "Senior Wrangler", registerGame(GameInfo(653, SeniorWrangler, "Senior Wrangler",
GI.GT_2DECK_TYPE, 2, 8, GI.SL_BALANCED)) GI.GT_2DECK_TYPE, 2, 8, GI.SL_BALANCED))
registerGame(GameInfo(704, SPatience, "S Patience", registerGame(GameInfo(704, SPatience, "S Patience",
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED)) GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))

View file

@ -26,22 +26,36 @@ __all__ = []
# imports # imports
# PySol imports # PySol imports
from pysollib.mygettext import _, n_ from pysollib.mygettext import _
from pysollib.gamedb import registerGame, GameInfo, GI from pysollib.gamedb import registerGame, GameInfo, GI
from pysollib.util import *
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, CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText from pysollib.pysoltk import MfxCanvasText
from numerica import Numerica_Hint from numerica import Numerica_Hint
from pysollib.util import ACE, ANY_RANK, ANY_SUIT, JACK, KING, NO_RANK, \
RANKS, QUEEN, \
UNLIMITED_CARDS
from pysollib.stack import \
AbstractFoundationStack, \
BasicRowStack, \
OpenStack, \
OpenTalonStack, \
ReserveStack, \
SS_FoundationStack, \
SS_RowStack, \
WasteStack, \
WasteTalonStack, \
StackWrapper
# ************************************************************************ # ************************************************************************
# * Camelot # * Camelot
# ************************************************************************ # ************************************************************************
class Camelot_Hint(AbstractHint): class Camelot_Hint(AbstractHint):
def computeHints(self): def computeHints(self):
@ -103,23 +117,24 @@ class Camelot_RowStack(ReserveStack):
return False return False
def moveMove(self, ncards, to_stack, frames=-1, shadow=-1): def moveMove(self, ncards, to_stack, frames=-1, shadow=-1):
if not to_stack is self.game.s.foundations[0]: if to_stack is not self.game.s.foundations[0]:
self._dropPairMove(ncards, to_stack, frames=-1, shadow=shadow) self._dropPairMove(ncards, to_stack, frames=-1, shadow=shadow)
else: else:
ReserveStack.moveMove(self, ncards, to_stack, frames=frames, shadow=shadow) ReserveStack.moveMove(
self, ncards, to_stack, frames=frames, shadow=shadow)
def _dropPairMove(self, n, other_stack, frames=-1, shadow=-1): def _dropPairMove(self, n, other_stack, frames=-1, shadow=-1):
game = self.game game = self.game
old_state = game.enterState(game.S_FILL) old_state = game.enterState(game.S_FILL)
f = game.s.foundations[0] f = game.s.foundations[0]
game.updateStackMove(game.s.talon, 2|16) # for undo game.updateStackMove(game.s.talon, 2 | 16) # for undo
if not game.demo: if not game.demo:
game.playSample("droppair", priority=200) game.playSample("droppair", priority=200)
game.moveMove(n, self, f, frames=frames, shadow=shadow) game.moveMove(n, self, f, frames=frames, shadow=shadow)
game.moveMove(n, other_stack, f, frames=frames, shadow=shadow) game.moveMove(n, other_stack, f, frames=frames, shadow=shadow)
self.fillStack() self.fillStack()
other_stack.fillStack() other_stack.fillStack()
game.updateStackMove(game.s.talon, 1|16) # for redo game.updateStackMove(game.s.talon, 1 | 16) # for redo
game.leaveState(old_state) game.leaveState(old_state)
@ -131,9 +146,9 @@ class Camelot_Foundation(AbstractFoundationStack):
class Camelot_Talon(OpenTalonStack): class Camelot_Talon(OpenTalonStack):
def fillStack(self): def fillStack(self):
old_state = self.game.enterState(self.game.S_FILL) old_state = self.game.enterState(self.game.S_FILL)
self.game.saveStateMove(2|16) # for undo self.game.saveStateMove(2 | 16) # for undo
self.game.is_fill = self.game.isRowsFill() self.game.is_fill = self.game.isRowsFill()
self.game.saveStateMove(1|16) # for redo self.game.saveStateMove(1 | 16) # for redo
self.game.leaveState(old_state) self.game.leaveState(old_state)
OpenTalonStack.fillStack(self) OpenTalonStack.fillStack(self)
@ -160,7 +175,6 @@ class Camelot(Game):
# create stacks # create stacks
for i in range(4): for i in range(4):
for j in range(4): for j in range(4):
k = i+j*4
x, y = l.XM + w + j*l.XS, l.YM + i*l.YS x, y = l.XM + w + j*l.XS, l.YM + i*l.YS
s.rows.append(self.RowStack_Class(x, y, self)) s.rows.append(self.RowStack_Class(x, y, self))
x, y = l.XM, l.YM x, y = l.XM, l.YM
@ -183,14 +197,12 @@ class Camelot(Game):
self.is_fill = False self.is_fill = False
self.s.talon.fillStack() self.s.talon.fillStack()
def isGameWon(self): def isGameWon(self):
for i in (5, 6, 9, 10): for i in (5, 6, 9, 10):
if len(self.s.rows[i].cards) != 0: if len(self.s.rows[i].cards) != 0:
return False return False
return len(self.s.talon.cards) == 0 return len(self.s.talon.cards) == 0
def isRowsFill(self): def isRowsFill(self):
for i in range(16): for i in range(16):
if len(self.s.rows[i].cards) == 0: if len(self.s.rows[i].cards) == 0:
@ -239,12 +251,13 @@ class SlyFox_Talon(OpenTalonStack):
def moveMove(self, ncards, to_stack, frames=-1, shadow=-1): def moveMove(self, ncards, to_stack, frames=-1, shadow=-1):
old_state = self.game.enterState(self.game.S_FILL) old_state = self.game.enterState(self.game.S_FILL)
self.game.saveStateMove(2|16) # for undo self.game.saveStateMove(2 | 16) # for undo
if old_state == self.game.S_PLAY and to_stack in self.game.s.rows: if old_state == self.game.S_PLAY and to_stack in self.game.s.rows:
n = self.game.num_dealled n = self.game.num_dealled
if n < 0: n = 0 if n < 0:
self.game.num_dealled = (n+1)%20 n = 0
self.game.saveStateMove(1|16) # for redo self.game.num_dealled = (n+1) % 20
self.game.saveStateMove(1 | 16) # for redo
self.game.leaveState(old_state) self.game.leaveState(old_state)
OpenTalonStack.moveMove(self, ncards, to_stack, frames, shadow) OpenTalonStack.moveMove(self, ncards, to_stack, frames, shadow)
@ -293,10 +306,11 @@ class SlyFox(Game):
l.defaultStackGroups() l.defaultStackGroups()
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
return self._shuffleHookMoveToTop(cards, return self._shuffleHookMoveToTop(
lambda c: (c.rank in (ACE, KING) and c.deck == 0, (c.suit, c.rank))) cards,
lambda c: (c.rank in (ACE, KING) and c.deck == 0,
(c.suit, c.rank)))
def startGame(self): def startGame(self):
self.num_dealled = -1 self.num_dealled = -1
@ -322,20 +336,19 @@ class SlyFox(Game):
# save vars (for undo/redo) # save vars (for undo/redo)
return [self.num_dealled] return [self.num_dealled]
def fillStack(self, stack): def fillStack(self, stack):
if self.num_dealled == -1 and stack in self.s.rows and not stack.cards: if self.num_dealled == -1 and stack in self.s.rows and not stack.cards:
old_state = self.enterState(self.S_FILL) old_state = self.enterState(self.S_FILL)
self.s.talon.moveMove(1, stack) self.s.talon.moveMove(1, stack)
self.leaveState(old_state) self.leaveState(old_state)
def updateText(self): def updateText(self):
if self.preview > 1: if self.preview > 1:
return return
n = self.num_dealled n = self.num_dealled
if n < 0: n = 0 if n < 0:
text=str(n)+'/20' n = 0
text = str(n)+'/20'
self.texts.misc.config(text=text) self.texts.misc.config(text=text)
@ -345,7 +358,8 @@ class OpenSlyFox(SlyFox):
playcards = 6 playcards = 6
l, s = Layout(self), self.s l, s = Layout(self), self.s
self.setSize(l.XM+10*l.XS, l.YM+3*l.YS+2*playcards*l.YOFFSET+l.TEXT_HEIGHT) self.setSize(
l.XM+10*l.XS, l.YM+3*l.YS+2*playcards*l.YOFFSET+l.TEXT_HEIGHT)
x, y = l.XM, l.YM x, y = l.XM, l.YM
s.talon = SlyFox_Talon(x, y, self) s.talon = SlyFox_Talon(x, y, self)
@ -384,16 +398,17 @@ class PrincessPatience_RowStack(SS_RowStack):
def canMoveCards(self, cards): def canMoveCards(self, cards):
if not SS_RowStack.canMoveCards(self, cards): if not SS_RowStack.canMoveCards(self, cards):
return False return False
##index = list(self.game.s.rows).index(self) # don't work in demo-mode with cloned stack # don't work in demo-mode with cloned stack
# index = list(self.game.s.rows).index(self)
index = self.id index = self.id
col = index % 4 col = index % 4
row = index / 4 row = index / 4
if index < 16: # left if index < 16: # left
for i in range(col+1, 4): for i in range(col+1, 4):
r = self.game.s.rows[row*4+i] r = self.game.s.rows[row*4+i]
if r.cards: if r.cards:
return False return False
else: # right else: # right
for i in range(0, col): for i in range(0, col):
r = self.game.s.rows[row*4+i] r = self.game.s.rows[row*4+i]
if r.cards: if r.cards:
@ -451,13 +466,11 @@ class PrincessPatience(Game):
l.defaultStackGroups() l.defaultStackGroups()
def startGame(self): def startGame(self):
self.startDealSample() self.startDealSample()
self.s.talon.dealRow() self.s.talon.dealRow()
self.s.talon.dealCards() self.s.talon.dealCards()
shallHighlightMatch = Game._shallHighlightMatch_SS shallHighlightMatch = Game._shallHighlightMatch_SS
@ -492,14 +505,16 @@ class GrandmammasPatience(Game):
x, y = self.width-4*l.XS, l.YM x, y = self.width-4*l.XS, 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(
dir=-1, mod=13, max_move=0, base_rank=ANY_RANK)) SS_FoundationStack(
x, y, self, suit=i,
dir=-1, mod=13, max_move=0, base_rank=ANY_RANK))
x += l.XS x += l.XS
stack = s.foundations[0] stack = s.foundations[0]
tx, ty, ta, tf = l.getTextAttr(stack, "sw") tx, ty, ta, tf = l.getTextAttr(stack, "sw")
font = self.app.getFont("canvas_default") font = self.app.getFont("canvas_default")
stack.texts.misc = MfxCanvasText(self.canvas, tx, ty, stack.texts.misc = MfxCanvasText(
anchor=ta, font=font) self.canvas, tx, ty, anchor=ta, font=font)
x, y = self.width-4*l.XS, self.height-l.YS x, y = self.width-4*l.XS, self.height-l.YS
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,
@ -508,8 +523,8 @@ class GrandmammasPatience(Game):
stack = s.foundations[4] stack = s.foundations[4]
tx, ty, ta, tf = l.getTextAttr(stack, "sw") tx, ty, ta, tf = l.getTextAttr(stack, "sw")
font = self.app.getFont("canvas_default") font = self.app.getFont("canvas_default")
stack.texts.misc = MfxCanvasText(self.canvas, stack.texts.misc = MfxCanvasText(
tx, ty, anchor=ta, font=font) self.canvas, tx, ty, anchor=ta, font=font)
y = l.YM+l.YS y = l.YM+l.YS
for i in range(2): for i in range(2):
@ -528,7 +543,6 @@ class GrandmammasPatience(Game):
l.defaultStackGroups() l.defaultStackGroups()
self.sg.dropstacks.append(s.talon) self.sg.dropstacks.append(s.talon)
def startGame(self): def startGame(self):
c = self.s.talon.cards[-1] c = self.s.talon.cards[-1]
self.base_rank = c.rank self.base_rank = c.rank
@ -538,12 +552,11 @@ class GrandmammasPatience(Game):
for s in self.s.foundations[:4]: for s in self.s.foundations[:4]:
s.cap.base_rank = c.rank s.cap.base_rank = c.rank
for s in self.s.foundations[4:]: for s in self.s.foundations[4:]:
s.cap.base_rank = (c.rank+1)%13 s.cap.base_rank = (c.rank+1) % 13
self.startDealSample() self.startDealSample()
self.s.talon.dealRow() self.s.talon.dealRow()
self.s.talon.fillStack() self.s.talon.fillStack()
def fillStack(self, stack): def fillStack(self, stack):
if stack in self.s.rows and not stack.cards: if stack in self.s.rows and not stack.cards:
if self.s.talon.cards: if self.s.talon.cards:
@ -559,17 +572,16 @@ class GrandmammasPatience(Game):
t1 = t2 = '' t1 = t2 = ''
else: else:
t1 = RANKS[base_rank]+_(" Descending") t1 = RANKS[base_rank]+_(" Descending")
t2 = RANKS[(base_rank+1)%13]+_(" Ascending") t2 = RANKS[(base_rank+1) % 13]+_(" Ascending")
self.s.foundations[0].texts.misc.config(text=t1) self.s.foundations[0].texts.misc.config(text=t1)
self.s.foundations[4].texts.misc.config(text=t2) self.s.foundations[4].texts.misc.config(text=t2)
def _restoreGameHook(self, game): def _restoreGameHook(self, game):
self.base_rank = game.loadinfo.base_rank self.base_rank = game.loadinfo.base_rank
for s in self.s.foundations[:4]: for s in self.s.foundations[:4]:
s.cap.base_rank = self.base_rank s.cap.base_rank = self.base_rank
for s in self.s.foundations[4:]: for s in self.s.foundations[4:]:
s.cap.base_rank = (self.base_rank+1)%13 s.cap.base_rank = (self.base_rank+1) % 13
def _loadGameHook(self, p): def _loadGameHook(self, p):
self.loadinfo.addattr(base_rank=None) # register extra load var. self.loadinfo.addattr(base_rank=None) # register extra load var.
@ -579,7 +591,6 @@ class GrandmammasPatience(Game):
p.dump(self.base_rank) p.dump(self.base_rank)
# ************************************************************************ # ************************************************************************
# * Double Line # * Double Line
# ************************************************************************ # ************************************************************************
@ -612,7 +623,7 @@ class DoubleLine(Game):
x += l.XS x += l.XS
for i in range(4): for i in range(4):
s.foundations.append(SS_FoundationStack(x, y, self, suit=i%4)) s.foundations.append(SS_FoundationStack(x, y, self, suit=i % 4))
x += l.XS x += l.XS
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,
@ -651,12 +662,11 @@ registerGame(GameInfo(280, Camelot, "Camelot",
registerGame(GameInfo(610, SlyFox, "Sly Fox", registerGame(GameInfo(610, SlyFox, "Sly Fox",
GI.GT_NUMERICA, 2, 0, GI.SL_BALANCED)) GI.GT_NUMERICA, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(614, OpenSlyFox, "Open Sly Fox", registerGame(GameInfo(614, OpenSlyFox, "Open Sly Fox",
GI.GT_NUMERICA | GI.GT_ORIGINAL, 2, 0, GI.SL_MOSTLY_SKILL)) GI.GT_NUMERICA | GI.GT_ORIGINAL, 2, 0,
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(623, PrincessPatience, "Princess Patience", registerGame(GameInfo(623, PrincessPatience, "Princess Patience",
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED)) GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(622, GrandmammasPatience, "Grandmamma's Patience", registerGame(GameInfo(622, GrandmammasPatience, "Grandmamma's Patience",
GI.GT_NUMERICA, 2, 0, GI.SL_MOSTLY_SKILL)) GI.GT_NUMERICA, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(702, DoubleLine, "Double Line", registerGame(GameInfo(702, DoubleLine, "Double Line",
GI.GT_NUMERICA, 2, 0, GI.SL_BALANCED)) GI.GT_NUMERICA, 2, 0, GI.SL_BALANCED))

View file

@ -1,21 +1,35 @@
from pysollib.gamedb import registerGame, GameInfo, GI from pysollib.gamedb import registerGame, GameInfo, GI
from pysollib.util import *
from pysollib.stack import *
from pysollib.game import Game from pysollib.game import Game
from pysollib.mygettext import _
from pysollib.layout import Layout from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import CautiousDefaultHint
from pysollib.pysoltk import MfxCanvasText from pysollib.pysoltk import MfxCanvasText
from pysollib.util import KING, RANKS, QUEEN, UNLIMITED_REDEALS
from pysollib.stack import \
AC_RowStack, \
KingAC_RowStack, \
OpenStack, \
RK_RowStack, \
ReserveStack, \
SS_FoundationStack, \
SS_RowStack, \
WasteStack, \
WasteTalonStack, \
StackWrapper
# ************************************************************************ # ************************************************************************
# * # *
# ************************************************************************ # ************************************************************************
class Canfield_Hint(CautiousDefaultHint): class Canfield_Hint(CautiousDefaultHint):
# FIXME: demo is not too clever in this game # FIXME: demo is not too clever in this game
# Score for moving a pile (usually a single card) from the WasteStack. # Score for moving a pile (usually a single card) from the WasteStack.
def _getMoveWasteScore(self, score, color, r, t, pile, rpile): def _getMoveWasteScore(self, score, color, r, t, pile, rpile):
score, color = CautiousDefaultHint._getMovePileScore(self, score, color, r, t, pile, rpile) score, color = CautiousDefaultHint._getMovePileScore(
self, score, color, r, t, pile, rpile)
# we prefer moving cards from the waste over everything else # we prefer moving cards from the waste over everything else
return score + 100000, color return score + 100000, color
@ -76,7 +90,7 @@ class Canfield(Game):
# set window # set window
if self.INITIAL_RESERVE_FACEUP == 1: if self.INITIAL_RESERVE_FACEUP == 1:
yoffset = l.YOFFSET ##min(l.YOFFSET, 14) yoffset = l.YOFFSET # min(l.YOFFSET, 14)
else: else:
yoffset = 10 yoffset = 10
if self.INITIAL_RESERVE_CARDS > 30: if self.INITIAL_RESERVE_CARDS > 30:
@ -85,7 +99,9 @@ class Canfield(Game):
h = max(3*l.YS, l.YS+self.INITIAL_RESERVE_CARDS*yoffset) h = max(3*l.YS, l.YS+self.INITIAL_RESERVE_CARDS*yoffset)
if round_text: if round_text:
h += l.TEXT_HEIGHT h += l.TEXT_HEIGHT
self.setSize(l.XM + (2+max(rows, 4*decks))*l.XS + l.XM, l.YM + l.YS + l.TEXT_HEIGHT + h) self.setSize(
l.XM + (2+max(rows, 4*decks))*l.XS + l.XM,
l.YM + l.YS + l.TEXT_HEIGHT + h)
# extra settings # extra settings
self.base_card = None self.base_card = None
@ -170,7 +186,8 @@ class Canfield(Game):
for i in range(self.INITIAL_RESERVE_CARDS): for i in range(self.INITIAL_RESERVE_CARDS):
if self.INITIAL_RESERVE_FACEUP: if self.INITIAL_RESERVE_FACEUP:
self.flipMove(self.s.talon) self.flipMove(self.s.talon)
self.moveMove(1, self.s.talon, self.s.reserves[0], frames=4, shadow=0) self.moveMove(
1, self.s.talon, self.s.reserves[0], frames=4, shadow=0)
if self.s.reserves[0].canFlipCard(): if self.s.reserves[0].canFlipCard():
self.flipMove(self.s.reserves[0]) self.flipMove(self.s.reserves[0])
self.s.talon.dealRow(reverse=1) self.s.talon.dealRow(reverse=1)
@ -233,6 +250,7 @@ class Rainbow(Canfield):
# * Storehouse (aka Straight Up) # * Storehouse (aka Straight Up)
# ************************************************************************ # ************************************************************************
class Storehouse(Canfield): class Storehouse(Canfield):
RowStack_Class = StackWrapper(Canfield_SS_RowStack, mod=13) RowStack_Class = StackWrapper(Canfield_SS_RowStack, mod=13)
@ -241,7 +259,8 @@ class Storehouse(Canfield):
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
# move Twos to top of the Talon (i.e. first cards to be dealt) # move Twos to top of the Talon (i.e. first cards to be dealt)
return self._shuffleHookMoveToTop(cards, lambda c: (c.rank == 1, c.suit)) return self._shuffleHookMoveToTop(
cards, lambda c: (c.rank == 1, c.suit))
def startGame(self): def startGame(self):
self.startDealSample() self.startDealSample()
@ -310,7 +329,8 @@ class VariegatedCanfield(Canfield):
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
# move Aces to top of the Talon (i.e. first cards to be dealt) # move Aces to top of the Talon (i.e. first cards to be dealt)
return self._shuffleHookMoveToTop(cards, lambda c: (c.rank == 0, c.suit)) return self._shuffleHookMoveToTop(
cards, lambda c: (c.rank == 0, c.suit))
def startGame(self): def startGame(self):
self.startDealSample() self.startDealSample()
@ -337,7 +357,7 @@ class EagleWing(Canfield):
ReserveStack_Class = EagleWing_ReserveStack ReserveStack_Class = EagleWing_ReserveStack
def createGame(self): def createGame(self):
##Canfield.createGame(self, rows=8, max_rounds=3, num_deal=1) # Canfield.createGame(self, rows=8, max_rounds=3, num_deal=1)
# create layout # create layout
l, s = Layout(self), self.s l, s = Layout(self), self.s
@ -357,11 +377,13 @@ class EagleWing(Canfield):
l.createText(s.waste, "s") l.createText(s.waste, "s")
for i in range(4): for i in range(4):
x = l.XM + (i+3)*l.XS x = l.XM + (i+3)*l.XS
s.foundations.append(self.Foundation_Class(x, y, self, i, mod=13, max_move=0)) s.foundations.append(
self.Foundation_Class(x, y, self, i, mod=13, max_move=0))
tx, ty, ta, tf = l.getTextAttr(None, "se") tx, ty, ta, tf = l.getTextAttr(None, "se")
tx, ty = x + tx + l.XM, y + ty tx, ty = x + tx + l.XM, y + ty
font = self.app.getFont("canvas_default") font = self.app.getFont("canvas_default")
self.texts.info = MfxCanvasText(self.canvas, tx, ty, anchor=ta, font=font) self.texts.info = MfxCanvasText(
self.canvas, tx, ty, anchor=ta, font=font)
ry = l.YM + 2*l.YS ry = l.YM + 2*l.YS
for i in range(8): for i in range(8):
x = l.XM + (i + (i >= 4))*l.XS x = l.XM + (i + (i >= 4))*l.XS
@ -369,7 +391,7 @@ class EagleWing(Canfield):
s.rows.append(self.RowStack_Class(x, y, self)) s.rows.append(self.RowStack_Class(x, y, self))
x, y = l.XM + 4*l.XS, ry x, y = l.XM + 4*l.XS, ry
s.reserves.append(self.ReserveStack_Class(x, y, self)) s.reserves.append(self.ReserveStack_Class(x, y, self))
##s.reserves[0].CARD_YOFFSET = 0 # s.reserves[0].CARD_YOFFSET = 0
l.createText(s.reserves[0], "s") l.createText(s.reserves[0], "s")
# define stack-groups # define stack-groups
@ -546,7 +568,8 @@ class Minerva(Canfield):
self.startDealSample() self.startDealSample()
self.s.talon.dealRow() self.s.talon.dealRow()
for i in range(self.INITIAL_RESERVE_CARDS): for i in range(self.INITIAL_RESERVE_CARDS):
self.moveMove(1, self.s.talon, self.s.reserves[0], frames=4, shadow=0) self.moveMove(
1, self.s.talon, self.s.reserves[0], frames=4, shadow=0)
self.flipMove(self.s.reserves[0]) self.flipMove(self.s.reserves[0])
self.s.talon.dealCards() self.s.talon.dealCards()
@ -554,14 +577,17 @@ class Minerva(Canfield):
def _restoreGameHook(self, game): def _restoreGameHook(self, game):
pass pass
def _loadGameHook(self, p): def _loadGameHook(self, p):
pass pass
def _saveGameHook(self, p): def _saveGameHook(self, p):
pass pass
class Munger(Minerva): class Munger(Minerva):
INITIAL_RESERVE_CARDS = 7 INITIAL_RESERVE_CARDS = 7
def createGame(self): def createGame(self):
Canfield.createGame(self, rows=7, max_rounds=1, num_deal=1, text=False) Canfield.createGame(self, rows=7, max_rounds=1, num_deal=1, text=False)
@ -577,6 +603,7 @@ class Mystique(Munger):
class TripleCanfield(Canfield): class TripleCanfield(Canfield):
INITIAL_RESERVE_CARDS = 26 INITIAL_RESERVE_CARDS = 26
def createGame(self): def createGame(self):
Canfield.createGame(self, rows=7) Canfield.createGame(self, rows=7)
@ -595,13 +622,15 @@ class Acme(Canfield):
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
# move Aces to top of the Talon (i.e. first cards to be dealt) # move Aces to top of the Talon (i.e. first cards to be dealt)
return self._shuffleHookMoveToTop(cards, lambda c: (c.rank == 0, c.suit)) return self._shuffleHookMoveToTop(
cards, lambda c: (c.rank == 0, c.suit))
def startGame(self): def startGame(self):
self.s.talon.dealRow(rows=self.s.foundations, frames=0) self.s.talon.dealRow(rows=self.s.foundations, frames=0)
self.startDealSample() self.startDealSample()
for i in range(13): for i in range(13):
self.moveMove(1, self.s.talon, self.s.reserves[0], frames=4, shadow=0) self.moveMove(
1, self.s.talon, self.s.reserves[0], frames=4, shadow=0)
self.flipMove(self.s.reserves[0]) self.flipMove(self.s.reserves[0])
self.s.talon.dealRow(reverse=1) self.s.talon.dealRow(reverse=1)
self.s.talon.dealCards() self.s.talon.dealCards()
@ -610,10 +639,13 @@ class Acme(Canfield):
def updateText(self): def updateText(self):
pass pass
def _restoreGameHook(self, game): def _restoreGameHook(self, game):
pass pass
def _loadGameHook(self, p): def _loadGameHook(self, p):
pass pass
def _saveGameHook(self, p): def _saveGameHook(self, p):
pass pass
@ -630,7 +662,8 @@ class Duke(Game):
def createGame(self): def createGame(self):
l, s = Layout(self), self.s l, s = Layout(self), self.s
w, h = l.XM + 6*l.XS + 4*l.XOFFSET, l.YM + l.TEXT_HEIGHT + 2*l.YS + 12*l.YOFFSET w, h = l.XM + 6*l.XS + 4*l.XOFFSET, \
l.YM + l.TEXT_HEIGHT + 2*l.YS + 12*l.YOFFSET
self.setSize(w, h) self.setSize(w, h)
x, y = l.XM, l.YM x, y = l.XM, l.YM
@ -646,7 +679,7 @@ class Duke(Game):
s.foundations.append(self.Foundation_Class(x, y, self, suit=i)) s.foundations.append(self.Foundation_Class(x, y, self, suit=i))
x += l.XS x += l.XS
x0, y0, w = l.XM, l.YM+l.YS+2*l.TEXT_HEIGHT, l.XS+2*l.XOFFSET x0, y0, w = l.XM, l.YM+l.YS+2*l.TEXT_HEIGHT, l.XS+2*l.XOFFSET
for i, j in ((0,0), (0,1), (1,0), (1,1)): for i, j in ((0, 0), (0, 1), (1, 0), (1, 1)):
x, y = x0+i*w, y0+j*l.YS x, y = x0+i*w, y0+j*l.YS
stack = self.ReserveStack_Class(x, y, self, max_accept=0) stack = self.ReserveStack_Class(x, y, self, max_accept=0)
stack.CARD_XOFFSET, stack.CARD_YOFFSET = l.XOFFSET, 0 stack.CARD_XOFFSET, stack.CARD_YOFFSET = l.XOFFSET, 0
@ -658,7 +691,6 @@ class Duke(Game):
l.defaultStackGroups() l.defaultStackGroups()
def startGame(self): def startGame(self):
for i in range(3): for i in range(3):
self.s.talon.dealRow(rows=self.s.reserves, frames=0) self.s.talon.dealRow(rows=self.s.reserves, frames=0)
@ -666,7 +698,6 @@ class Duke(Game):
self.s.talon.dealRow() self.s.talon.dealRow()
self.s.talon.dealCards() self.s.talon.dealCards()
shallHighlightMatch = Game._shallHighlightMatch_AC shallHighlightMatch = Game._shallHighlightMatch_AC
@ -677,8 +708,10 @@ class Duke(Game):
class Demon(Canfield): class Demon(Canfield):
INITIAL_RESERVE_CARDS = 40 INITIAL_RESERVE_CARDS = 40
RowStack_Class = StackWrapper(AC_RowStack, mod=13) RowStack_Class = StackWrapper(AC_RowStack, mod=13)
def createGame(self): def createGame(self):
Canfield.createGame(self, rows=8, max_rounds=UNLIMITED_REDEALS, num_deal=3) Canfield.createGame(
self, rows=8, max_rounds=UNLIMITED_REDEALS, num_deal=3)
# ************************************************************************ # ************************************************************************
@ -690,9 +723,11 @@ class CanfieldRush_Talon(WasteTalonStack):
self.num_deal = 4-self.round self.num_deal = 4-self.round
WasteTalonStack.dealCards(self, sound=sound) WasteTalonStack.dealCards(self, sound=sound)
class CanfieldRush(Canfield): class CanfieldRush(Canfield):
Talon_Class = CanfieldRush_Talon Talon_Class = CanfieldRush_Talon
#RowStack_Class = StackWrapper(AC_RowStack, mod=13) # RowStack_Class = StackWrapper(AC_RowStack, mod=13)
def createGame(self): def createGame(self):
Canfield.createGame(self, max_rounds=3, round_text=True) Canfield.createGame(self, max_rounds=3, round_text=True)
@ -728,7 +763,7 @@ class Skippy(Canfield):
x = self.width - 8*l.XS x = self.width - 8*l.XS
for i in range(8): for i in range(8):
s.foundations.append(SS_FoundationStack(x, y, self, s.foundations.append(SS_FoundationStack(x, y, self,
suit=i%4, mod=13)) suit=i % 4, mod=13))
x += l.XS x += l.XS
tx, ty, ta, tf = l.getTextAttr(None, "ss") tx, ty, ta, tf = l.getTextAttr(None, "ss")
tx, ty = x-l.XS+tx, y+ty tx, ty = x-l.XS+tx, y+ty
@ -752,7 +787,6 @@ class Skippy(Canfield):
# define stack-groups # define stack-groups
l.defaultStackGroups() l.defaultStackGroups()
def startGame(self): def startGame(self):
self.base_card = None self.base_card = None
self.updateText() self.updateText()
@ -765,7 +799,7 @@ class Skippy(Canfield):
self.moveMove(1, self.s.talon, self.s.foundations[n], frames=0) self.moveMove(1, self.s.talon, self.s.foundations[n], frames=0)
self.updateText() self.updateText()
# update rows cap.base_rank # update rows cap.base_rank
row_base_rank = (self.base_card.rank-1)%13 row_base_rank = (self.base_card.rank-1) % 13
for s in self.s.rows: for s in self.s.rows:
s.cap.base_rank = row_base_rank s.cap.base_rank = row_base_rank
# #
@ -775,7 +809,6 @@ class Skippy(Canfield):
self.s.talon.dealRow() self.s.talon.dealRow()
self.s.talon.dealCards() self.s.talon.dealCards()
shallHighlightMatch = Game._shallHighlightMatch_RKW shallHighlightMatch = Game._shallHighlightMatch_RKW
@ -812,7 +845,6 @@ class Lafayette(Game):
l.defaultStackGroups() l.defaultStackGroups()
def startGame(self): def startGame(self):
for i in range(13): for i in range(13):
self.s.talon.dealRow(rows=self.s.reserves, frames=0) self.s.talon.dealRow(rows=self.s.reserves, frames=0)
@ -820,7 +852,6 @@ class Lafayette(Game):
self.s.talon.dealRow() self.s.talon.dealRow()
self.s.talon.dealCards() self.s.talon.dealCards()
def fillStack(self, stack): def fillStack(self, stack):
if stack in self.s.rows and not stack.cards: if stack in self.s.rows and not stack.cards:
if self.s.reserves[0].cards: if self.s.reserves[0].cards:
@ -828,11 +859,9 @@ class Lafayette(Game):
self.s.reserves[0].moveMove(1, stack) self.s.reserves[0].moveMove(1, stack)
self.leaveState(old_state) self.leaveState(old_state)
shallHighlightMatch = Game._shallHighlightMatch_AC shallHighlightMatch = Game._shallHighlightMatch_AC
# register the game # register the game
registerGame(GameInfo(105, Canfield, "Canfield", # was: 262 registerGame(GameInfo(105, Canfield, "Canfield", # was: 262
GI.GT_CANFIELD | GI.GT_CONTRIB, 1, -1, GI.SL_BALANCED)) GI.GT_CANFIELD | GI.GT_CONTRIB, 1, -1, GI.SL_BALANCED))
@ -844,7 +873,7 @@ registerGame(GameInfo(108, Rainbow, "Rainbow",
GI.GT_CANFIELD, 1, 0, GI.SL_BALANCED)) GI.GT_CANFIELD, 1, 0, GI.SL_BALANCED))
registerGame(GameInfo(100, Storehouse, "Storehouse", registerGame(GameInfo(100, Storehouse, "Storehouse",
GI.GT_CANFIELD, 1, 2, GI.SL_BALANCED, GI.GT_CANFIELD, 1, 2, GI.SL_BALANCED,
altnames=("Provisions", "Straight Up", "Thirteen Up") )) altnames=("Provisions", "Straight Up", "Thirteen Up")))
registerGame(GameInfo(43, Chameleon, "Chameleon", registerGame(GameInfo(43, Chameleon, "Chameleon",
GI.GT_CANFIELD, 1, 0, GI.SL_BALANCED, GI.GT_CANFIELD, 1, 0, GI.SL_BALANCED,
altnames="Kansas")) altnames="Kansas"))
@ -878,9 +907,8 @@ registerGame(GameInfo(521, CanfieldRush, "Canfield Rush",
GI.GT_CANFIELD, 1, 2, GI.SL_BALANCED)) GI.GT_CANFIELD, 1, 2, GI.SL_BALANCED))
registerGame(GameInfo(527, Doorway, "Doorway", registerGame(GameInfo(527, Doorway, "Doorway",
GI.GT_KLONDIKE, 1, 0, GI.SL_BALANCED, GI.GT_KLONDIKE, 1, 0, GI.SL_BALANCED,
altnames=('Solstice',) )) altnames=('Solstice',)))
registerGame(GameInfo(605, Skippy, "Skippy", registerGame(GameInfo(605, Skippy, "Skippy",
GI.GT_FAN_TYPE, 2, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FAN_TYPE, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(642, Lafayette, "Lafayette", registerGame(GameInfo(642, Lafayette, "Lafayette",
GI.GT_CANFIELD, 1, -1, GI.SL_BALANCED)) GI.GT_CANFIELD, 1, -1, GI.SL_BALANCED))

View file

@ -27,15 +27,23 @@ __all__ = []
# PySol imports # PySol imports
from pysollib.gamedb import registerGame, GameInfo, GI 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.game import Game
from pysollib.layout import Layout from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint from pysollib.hint import CautiousDefaultHint
from gypsy import DieRussische_Foundation from gypsy import DieRussische_Foundation
from pysollib.util import ANY_SUIT, KING
from pysollib.stack import \
AC_RowStack, \
InitialDealTalonStack, \
RedealTalonStack, \
RK_FoundationStack, \
SS_FoundationStack, \
UD_SS_RowStack, \
StackWrapper
# ************************************************************************ # ************************************************************************
# * Capricieuse # * Capricieuse
@ -91,7 +99,8 @@ class Capricieuse(Game):
self.s.talon.dealRow(self.s.foundations) self.s.talon.dealRow(self.s.foundations)
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
return self._shuffleHookMoveToBottom(cards, return self._shuffleHookMoveToBottom(
cards,
lambda c: (c.deck == 0 and c.rank in (0, 12), (c.rank, c.suit)), 8) lambda c: (c.deck == 0 and c.rank in (0, 12), (c.rank, c.suit)), 8)
def redealCards(self): def redealCards(self):
@ -134,7 +143,7 @@ class Strata(Game):
x, y, = l.XM+l.XS, l.YM x, y, = l.XM+l.XS, l.YM
for i in range(8): for i in range(8):
s.foundations.append(DieRussische_Foundation(x, y, self, s.foundations.append(DieRussische_Foundation(x, y, self,
suit=i%4, max_cards=8)) suit=i % 4, max_cards=8))
x += l.XS x += l.XS
x, y, = l.XM+l.XS, l.YM+l.YS x, y, = l.XM+l.XS, l.YM+l.YS
for i in range(8): for i in range(8):
@ -214,7 +223,7 @@ class Choice(Game):
x, y = l.XM + (max_rows-8)*l.XS/2, l.YM x, y = l.XM + (max_rows-8)*l.XS/2, l.YM
for i in range(8): for i in range(8):
stack = Choice_Foundation(x, y, self, base_rank=(i+5), dir=0, stack = Choice_Foundation(x, y, self, base_rank=(i+5), dir=0,
suit=ANY_SUIT, max_cards=(4*decks) ) suit=ANY_SUIT, max_cards=(4*decks))
stack.CARD_YOFFSET = l.YOFFSET stack.CARD_YOFFSET = l.YOFFSET
s.foundations.append(stack) s.foundations.append(stack)
x += l.XS x += l.XS
@ -230,7 +239,6 @@ class Choice(Game):
# define stack-groups # define stack-groups
l.defaultStackGroups() l.defaultStackGroups()
def startGame(self): def startGame(self):
for i in range(11): for i in range(11):
self.s.talon.dealRowAvail(frames=0) self.s.talon.dealRowAvail(frames=0)
@ -240,20 +248,23 @@ class Choice(Game):
shallHighlightMatch = Game._shallHighlightMatch_AC shallHighlightMatch = Game._shallHighlightMatch_AC
# register the game # register the game
registerGame(GameInfo(292, Capricieuse, "Capricieuse", registerGame(GameInfo(292, Capricieuse, "Capricieuse",
GI.GT_BAKERS_DOZEN | GI.GT_OPEN, 2, 2, GI.SL_MOSTLY_SKILL)) GI.GT_BAKERS_DOZEN | GI.GT_OPEN, 2, 2,
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(293, Nationale, "Nationale", registerGame(GameInfo(293, Nationale, "Nationale",
GI.GT_BAKERS_DOZEN | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL, GI.GT_BAKERS_DOZEN | GI.GT_OPEN, 2, 0,
altnames=('Zigzag Course',) )) GI.SL_MOSTLY_SKILL,
altnames=('Zigzag Course',)))
registerGame(GameInfo(606, Strata, "Strata", registerGame(GameInfo(606, Strata, "Strata",
GI.GT_BAKERS_DOZEN | GI.GT_OPEN, 2, 2, GI.SL_MOSTLY_SKILL, GI.GT_BAKERS_DOZEN | GI.GT_OPEN, 2, 2,
GI.SL_MOSTLY_SKILL,
ranks=(0, 6, 7, 8, 9, 10, 11, 12), ranks=(0, 6, 7, 8, 9, 10, 11, 12),
altnames=('Persian Patience',) )) altnames=('Persian Patience',)))
registerGame(GameInfo(673, Fifteen, "Fifteen", registerGame(GameInfo(673, Fifteen, "Fifteen",
GI.GT_BAKERS_DOZEN | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL)) GI.GT_BAKERS_DOZEN | GI.GT_OPEN, 2, 0,
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(755, Choice, "Choice", registerGame(GameInfo(755, Choice, "Choice",
GI.GT_3DECK_TYPE | GI.GT_OPEN | GI.GT_ORIGINAL, 3, 0, GI.SL_MOSTLY_SKILL, GI.GT_3DECK_TYPE | GI.GT_OPEN | GI.GT_ORIGINAL, 3, 0,
ranks=(5, 6, 7, 8, 9, 10, 11, 12) )) GI.SL_MOSTLY_SKILL,
ranks=(5, 6, 7, 8, 9, 10, 11, 12)))

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*- # -*- mode: python; coding: utf-8; -*-
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
# #
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer # Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
# Copyright (C) 2003 Mt. Hood Playing Card Co. # Copyright (C) 2003 Mt. Hood Playing Card Co.
@ -19,23 +19,39 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
__all__ = [] __all__ = []
# imports # imports
import sys
# PySol imports # PySol imports
from pysollib.mygettext import _, n_ from pysollib.mygettext import _
from pysollib.gamedb import registerGame, GameInfo, GI from pysollib.gamedb import registerGame, GameInfo, GI
from pysollib.util import *
from pysollib.mfxutil import kwdefault from pysollib.mfxutil import kwdefault
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, CautiousDefaultHint
from pysollib.util import ACE, ANY_RANK, ANY_SUIT, KING, UNLIMITED_ACCEPTS, \
UNLIMITED_MOVES
from pysollib.stack import \
AbstractFoundationStack, \
AC_RowStack, \
BasicRowStack, \
DealRowTalonStack, \
InitialDealTalonStack, \
isRankSequence, \
isSameSuitSequence, \
OpenStack, \
OpenTalonStack, \
RK_RowStack, \
SS_FoundationStack, \
SS_RowStack, \
TalonStack, \
WasteStack, \
WasteTalonStack, \
StackWrapper
# ************************************************************************ # ************************************************************************
# * Curds and Whey # * Curds and Whey
@ -43,6 +59,7 @@ from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
# * Nordic # * Nordic
# ************************************************************************ # ************************************************************************
class CurdsAndWhey_RowStack(BasicRowStack): class CurdsAndWhey_RowStack(BasicRowStack):
def acceptsCards(self, from_stack, cards): def acceptsCards(self, from_stack, cards):
@ -67,8 +84,9 @@ class CurdsAndWhey_RowStack(BasicRowStack):
class CurdsAndWhey(Game): class CurdsAndWhey(Game):
Hint_Class = CautiousDefaultHint Hint_Class = CautiousDefaultHint
RowStack_Class = StackWrapper(CurdsAndWhey_RowStack, base_rank=KING, RowStack_Class = StackWrapper(
max_move=UNLIMITED_MOVES, max_accept=UNLIMITED_ACCEPTS) CurdsAndWhey_RowStack, base_rank=KING,
max_move=UNLIMITED_MOVES, max_accept=UNLIMITED_ACCEPTS)
# #
# game layout # game layout
@ -130,8 +148,9 @@ class MissMuffet(CurdsAndWhey):
class Nordic(MissMuffet): class Nordic(MissMuffet):
RowStack_Class = StackWrapper(CurdsAndWhey_RowStack, base_rank=ANY_RANK, RowStack_Class = StackWrapper(
max_move=UNLIMITED_MOVES, max_accept=UNLIMITED_ACCEPTS) CurdsAndWhey_RowStack, base_rank=ANY_RANK,
max_move=UNLIMITED_MOVES, max_accept=UNLIMITED_ACCEPTS)
# ************************************************************************ # ************************************************************************
@ -144,6 +163,7 @@ class Dumfries_TalonStack(OpenTalonStack):
rightclickHandler = OpenStack.rightclickHandler rightclickHandler = OpenStack.rightclickHandler
doubleclickHandler = OpenStack.doubleclickHandler doubleclickHandler = OpenStack.doubleclickHandler
class Dumfries_RowStack(BasicRowStack): class Dumfries_RowStack(BasicRowStack):
def acceptsCards(self, from_stack, cards): def acceptsCards(self, from_stack, cards):
@ -159,9 +179,10 @@ class Dumfries_RowStack(BasicRowStack):
def canMoveCards(self, cards): def canMoveCards(self, cards):
return len(cards) == 1 or len(cards) == len(self.cards) return len(cards) == 1 or len(cards) == len(self.cards)
class Dumfries(Game): class Dumfries(Game):
##Hint_Class = KlondikeType_Hint # Hint_Class = KlondikeType_Hint
def createGame(self, **layout): def createGame(self, **layout):
# create layout # create layout
@ -188,7 +209,8 @@ class Dumfries(Game):
self.s.talon.fillStack() self.s.talon.fillStack()
def shallHighlightMatch(self, stack1, card1, stack2, card2): def shallHighlightMatch(self, stack1, card1, stack2, card2):
return card1.color != card2.color and abs(card1.rank-card2.rank) in (0, 1) return card1.color != card2.color and \
abs(card1.rank-card2.rank) in (0, 1)
class Galloway(Dumfries): class Galloway(Dumfries):
@ -200,13 +222,12 @@ class Robin(Dumfries):
def createGame(self): def createGame(self):
Dumfries.createGame(self, rows=12) Dumfries.createGame(self, rows=12)
# ************************************************************************ # ************************************************************************
# * Arachnida # * Arachnida
# * Harvestman # * Harvestman
# ************************************************************************ # ************************************************************************
class Arachnida_RowStack(BasicRowStack): class Arachnida_RowStack(BasicRowStack):
def acceptsCards(self, from_stack, cards): def acceptsCards(self, from_stack, cards):
@ -245,8 +266,10 @@ class Arachnida(CurdsAndWhey):
max_accept=UNLIMITED_ACCEPTS) max_accept=UNLIMITED_ACCEPTS)
s.rows.append(stack) s.rows.append(stack)
x += l.XS x += l.XS
s.foundations.append(AbstractFoundationStack(x, y, self, suit=ANY_SUIT, s.foundations.append(
max_accept=0, max_cards=104)) AbstractFoundationStack(
x, y, self, suit=ANY_SUIT,
max_accept=0, max_cards=104))
l.createText(s.foundations[0], "s") l.createText(s.foundations[0], "s")
# define stack-groups # define stack-groups
@ -301,7 +324,9 @@ class GermanPatience(Game):
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(RK_RowStack(x, y, self, max_cards=13, mod=13, dir=1, max_move=1)) s.rows.append(
RK_RowStack(
x, y, self, max_cards=13, mod=13, dir=1, max_move=1))
x += l.XS x += l.XS
x, y = l.XM, h-l.YS x, y = l.XM, h-l.YS
s.talon = WasteTalonStack(x, y, self, max_rounds=1) s.talon = WasteTalonStack(x, y, self, max_rounds=1)
@ -312,23 +337,20 @@ class GermanPatience(Game):
l.defaultStackGroups() l.defaultStackGroups()
def startGame(self): def startGame(self):
self.startDealSample() self.startDealSample()
self.s.talon.dealRow() self.s.talon.dealRow()
self.s.talon.dealCards() self.s.talon.dealCards()
def isGameWon(self): def isGameWon(self):
if self.s.waste.cards or self.s.talon.cards: if self.s.waste.cards or self.s.talon.cards:
return False return False
for s in self.s.rows: for s in self.s.rows:
if s.cards: if s.cards:
if len(s.cards) != 13: # or not isRankSequence(s.cards): if len(s.cards) != 13: # or not isRankSequence(s.cards):
return False return False
return True return True
shallHighlightMatch = Game._shallHighlightMatch_RKW shallHighlightMatch = Game._shallHighlightMatch_RKW
@ -531,13 +553,15 @@ registerGame(GameInfo(311, Dumfries, "Dumfries",
registerGame(GameInfo(312, Galloway, "Galloway", registerGame(GameInfo(312, Galloway, "Galloway",
GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_SKILL)) GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(313, Robin, "Robin", registerGame(GameInfo(313, Robin, "Robin",
GI.GT_2DECK_TYPE | GI.GT_ORIGINAL, 2, 0, GI.SL_MOSTLY_SKILL)) GI.GT_2DECK_TYPE | GI.GT_ORIGINAL, 2, 0,
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(348, Arachnida, "Arachnida", registerGame(GameInfo(348, Arachnida, "Arachnida",
GI.GT_SPIDER, 2, 0, GI.SL_MOSTLY_SKILL)) GI.GT_SPIDER, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(349, MissMuffet, "Miss Muffet", registerGame(GameInfo(349, MissMuffet, "Miss Muffet",
GI.GT_SPIDER | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL)) GI.GT_SPIDER | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(352, Nordic, "Nordic", registerGame(GameInfo(352, Nordic, "Nordic",
GI.GT_SPIDER | GI.GT_OPEN | GI.GT_ORIGINAL, 1, 0, GI.SL_MOSTLY_SKILL)) GI.GT_SPIDER | GI.GT_OPEN | GI.GT_ORIGINAL, 1, 0,
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(414, GermanPatience, "German Patience", registerGame(GameInfo(414, GermanPatience, "German Patience",
GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_SKILL)) GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(415, BavarianPatience, "Bavarian Patience", registerGame(GameInfo(415, BavarianPatience, "Bavarian Patience",
@ -553,8 +577,7 @@ registerGame(GameInfo(534, Harvestman, "Harvestman",
registerGame(GameInfo(687, Glacier, "Glacier", registerGame(GameInfo(687, Glacier, "Glacier",
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED)) GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(724, EightPacks, "Eight Packs", registerGame(GameInfo(724, EightPacks, "Eight Packs",
GI.GT_2DECK_TYPE | GI.GT_ORIGINAL, 2, 2, GI.SL_MOSTLY_SKILL)) GI.GT_2DECK_TYPE | GI.GT_ORIGINAL, 2, 2,
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(762, FourPacks, "Four Packs", registerGame(GameInfo(762, FourPacks, "Four Packs",
GI.GT_2DECK_TYPE, 2, 1, GI.SL_MOSTLY_SKILL)) GI.GT_2DECK_TYPE, 2, 1, GI.SL_MOSTLY_SKILL))

View file

@ -10,7 +10,7 @@ use String::ShellQuote qw/ shell_quote /;
# my $cmd = shell_quote( 'flake8', '.' ); # my $cmd = shell_quote( 'flake8', '.' );
my $cmd = shell_quote( 'flake8', my $cmd = shell_quote( 'flake8',
grep { not($_ eq './pysollib/pysoltk.py' or $_ eq './pysollib/tile/ttk.py') } glob('./pysollib/*.py ./pysollib/[cmpuw]*/*.py ./pysollib/tile/*.py ./pysollib/ui/tktile/*.py ./pysollib/games/[a-by-z]*.py') ); grep { not($_ eq './pysollib/pysoltk.py' or $_ eq './pysollib/tile/ttk.py') } glob('./pysollib/*.py ./pysollib/[cmpuw]*/*.py ./pysollib/tile/*.py ./pysollib/ui/tktile/*.py ./pysollib/games/[a-cy-z]*.py') );
# TEST # TEST
eq_or_diff( scalar(`$cmd`), '', "flake8 is happy with the code." ); eq_or_diff( scalar(`$cmd`), '', "flake8 is happy with the code." );