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

View file

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

View file

@ -1,21 +1,35 @@
from pysollib.gamedb import registerGame, GameInfo, GI
from pysollib.util import *
from pysollib.stack import *
from pysollib.game import Game
from pysollib.mygettext import _
from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
from pysollib.hint import CautiousDefaultHint
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):
# FIXME: demo is not too clever in this game
# Score for moving a pile (usually a single card) from the WasteStack.
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
return score + 100000, color
@ -76,7 +90,7 @@ class Canfield(Game):
# set window
if self.INITIAL_RESERVE_FACEUP == 1:
yoffset = l.YOFFSET ##min(l.YOFFSET, 14)
yoffset = l.YOFFSET # min(l.YOFFSET, 14)
else:
yoffset = 10
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)
if round_text:
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
self.base_card = None
@ -170,7 +186,8 @@ class Canfield(Game):
for i in range(self.INITIAL_RESERVE_CARDS):
if self.INITIAL_RESERVE_FACEUP:
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():
self.flipMove(self.s.reserves[0])
self.s.talon.dealRow(reverse=1)
@ -233,6 +250,7 @@ class Rainbow(Canfield):
# * Storehouse (aka Straight Up)
# ************************************************************************
class Storehouse(Canfield):
RowStack_Class = StackWrapper(Canfield_SS_RowStack, mod=13)
@ -241,7 +259,8 @@ class Storehouse(Canfield):
def _shuffleHook(self, cards):
# 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):
self.startDealSample()
@ -310,7 +329,8 @@ class VariegatedCanfield(Canfield):
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 == 0, c.suit))
return self._shuffleHookMoveToTop(
cards, lambda c: (c.rank == 0, c.suit))
def startGame(self):
self.startDealSample()
@ -337,7 +357,7 @@ class EagleWing(Canfield):
ReserveStack_Class = EagleWing_ReserveStack
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
l, s = Layout(self), self.s
@ -357,11 +377,13 @@ class EagleWing(Canfield):
l.createText(s.waste, "s")
for i in range(4):
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 = x + tx + l.XM, y + ty
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
for i in range(8):
x = l.XM + (i + (i >= 4))*l.XS
@ -369,7 +391,7 @@ class EagleWing(Canfield):
s.rows.append(self.RowStack_Class(x, y, self))
x, y = l.XM + 4*l.XS, ry
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")
# define stack-groups
@ -546,7 +568,8 @@ class Minerva(Canfield):
self.startDealSample()
self.s.talon.dealRow()
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.s.talon.dealCards()
@ -554,14 +577,17 @@ class Minerva(Canfield):
def _restoreGameHook(self, game):
pass
def _loadGameHook(self, p):
pass
def _saveGameHook(self, p):
pass
class Munger(Minerva):
INITIAL_RESERVE_CARDS = 7
def createGame(self):
Canfield.createGame(self, rows=7, max_rounds=1, num_deal=1, text=False)
@ -577,6 +603,7 @@ class Mystique(Munger):
class TripleCanfield(Canfield):
INITIAL_RESERVE_CARDS = 26
def createGame(self):
Canfield.createGame(self, rows=7)
@ -595,13 +622,15 @@ class Acme(Canfield):
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 == 0, c.suit))
return self._shuffleHookMoveToTop(
cards, lambda c: (c.rank == 0, c.suit))
def startGame(self):
self.s.talon.dealRow(rows=self.s.foundations, frames=0)
self.startDealSample()
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.s.talon.dealRow(reverse=1)
self.s.talon.dealCards()
@ -610,10 +639,13 @@ class Acme(Canfield):
def updateText(self):
pass
def _restoreGameHook(self, game):
pass
def _loadGameHook(self, p):
pass
def _saveGameHook(self, p):
pass
@ -630,7 +662,8 @@ class Duke(Game):
def createGame(self):
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)
x, y = l.XM, l.YM
@ -646,7 +679,7 @@ class Duke(Game):
s.foundations.append(self.Foundation_Class(x, y, self, suit=i))
x += l.XS
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
stack = self.ReserveStack_Class(x, y, self, max_accept=0)
stack.CARD_XOFFSET, stack.CARD_YOFFSET = l.XOFFSET, 0
@ -658,7 +691,6 @@ class Duke(Game):
l.defaultStackGroups()
def startGame(self):
for i in range(3):
self.s.talon.dealRow(rows=self.s.reserves, frames=0)
@ -666,7 +698,6 @@ class Duke(Game):
self.s.talon.dealRow()
self.s.talon.dealCards()
shallHighlightMatch = Game._shallHighlightMatch_AC
@ -677,8 +708,10 @@ class Duke(Game):
class Demon(Canfield):
INITIAL_RESERVE_CARDS = 40
RowStack_Class = StackWrapper(AC_RowStack, mod=13)
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
WasteTalonStack.dealCards(self, sound=sound)
class CanfieldRush(Canfield):
Talon_Class = CanfieldRush_Talon
#RowStack_Class = StackWrapper(AC_RowStack, mod=13)
# RowStack_Class = StackWrapper(AC_RowStack, mod=13)
def createGame(self):
Canfield.createGame(self, max_rounds=3, round_text=True)
@ -728,7 +763,7 @@ class Skippy(Canfield):
x = self.width - 8*l.XS
for i in range(8):
s.foundations.append(SS_FoundationStack(x, y, self,
suit=i%4, mod=13))
suit=i % 4, mod=13))
x += l.XS
tx, ty, ta, tf = l.getTextAttr(None, "ss")
tx, ty = x-l.XS+tx, y+ty
@ -752,7 +787,6 @@ class Skippy(Canfield):
# define stack-groups
l.defaultStackGroups()
def startGame(self):
self.base_card = None
self.updateText()
@ -765,7 +799,7 @@ class Skippy(Canfield):
self.moveMove(1, self.s.talon, self.s.foundations[n], frames=0)
self.updateText()
# 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:
s.cap.base_rank = row_base_rank
#
@ -775,7 +809,6 @@ class Skippy(Canfield):
self.s.talon.dealRow()
self.s.talon.dealCards()
shallHighlightMatch = Game._shallHighlightMatch_RKW
@ -812,7 +845,6 @@ class Lafayette(Game):
l.defaultStackGroups()
def startGame(self):
for i in range(13):
self.s.talon.dealRow(rows=self.s.reserves, frames=0)
@ -820,7 +852,6 @@ class Lafayette(Game):
self.s.talon.dealRow()
self.s.talon.dealCards()
def fillStack(self, stack):
if stack in self.s.rows and not stack.cards:
if self.s.reserves[0].cards:
@ -828,11 +859,9 @@ class Lafayette(Game):
self.s.reserves[0].moveMove(1, stack)
self.leaveState(old_state)
shallHighlightMatch = Game._shallHighlightMatch_AC
# register the game
registerGame(GameInfo(105, Canfield, "Canfield", # was: 262
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))
registerGame(GameInfo(100, Storehouse, "Storehouse",
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",
GI.GT_CANFIELD, 1, 0, GI.SL_BALANCED,
altnames="Kansas"))
@ -878,9 +907,8 @@ registerGame(GameInfo(521, CanfieldRush, "Canfield Rush",
GI.GT_CANFIELD, 1, 2, GI.SL_BALANCED))
registerGame(GameInfo(527, Doorway, "Doorway",
GI.GT_KLONDIKE, 1, 0, GI.SL_BALANCED,
altnames=('Solstice',) ))
altnames=('Solstice',)))
registerGame(GameInfo(605, Skippy, "Skippy",
GI.GT_FAN_TYPE, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(642, Lafayette, "Lafayette",
GI.GT_CANFIELD, 1, -1, GI.SL_BALANCED))

View file

@ -27,15 +27,23 @@ __all__ = []
# 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.hint import CautiousDefaultHint
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
@ -91,7 +99,8 @@ class Capricieuse(Game):
self.s.talon.dealRow(self.s.foundations)
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)
def redealCards(self):
@ -134,7 +143,7 @@ class Strata(Game):
x, y, = l.XM+l.XS, l.YM
for i in range(8):
s.foundations.append(DieRussische_Foundation(x, y, self,
suit=i%4, max_cards=8))
suit=i % 4, max_cards=8))
x += l.XS
x, y, = l.XM+l.XS, l.YM+l.YS
for i in range(8):
@ -214,7 +223,7 @@ class Choice(Game):
x, y = l.XM + (max_rows-8)*l.XS/2, l.YM
for i in range(8):
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
s.foundations.append(stack)
x += l.XS
@ -230,7 +239,6 @@ class Choice(Game):
# define stack-groups
l.defaultStackGroups()
def startGame(self):
for i in range(11):
self.s.talon.dealRowAvail(frames=0)
@ -240,20 +248,23 @@ class Choice(Game):
shallHighlightMatch = Game._shallHighlightMatch_AC
# register the game
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",
GI.GT_BAKERS_DOZEN | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL,
altnames=('Zigzag Course',) ))
GI.GT_BAKERS_DOZEN | GI.GT_OPEN, 2, 0,
GI.SL_MOSTLY_SKILL,
altnames=('Zigzag Course',)))
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),
altnames=('Persian Patience',) ))
altnames=('Persian Patience',)))
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",
GI.GT_3DECK_TYPE | GI.GT_OPEN | GI.GT_ORIGINAL, 3, 0, GI.SL_MOSTLY_SKILL,
ranks=(5, 6, 7, 8, 9, 10, 11, 12) ))
GI.GT_3DECK_TYPE | GI.GT_OPEN | GI.GT_ORIGINAL, 3, 0,
GI.SL_MOSTLY_SKILL,
ranks=(5, 6, 7, 8, 9, 10, 11, 12)))

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*-
# ---------------------------------------------------------------------------##
# ---------------------------------------------------------------------------
#
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
# Copyright (C) 2003 Mt. Hood Playing Card Co.
@ -19,23 +19,39 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# ---------------------------------------------------------------------------##
# ---------------------------------------------------------------------------
__all__ = []
# imports
import sys
# PySol imports
from pysollib.mygettext import _, n_
from pysollib.mygettext import _
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.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
@ -43,6 +59,7 @@ from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
# * Nordic
# ************************************************************************
class CurdsAndWhey_RowStack(BasicRowStack):
def acceptsCards(self, from_stack, cards):
@ -67,8 +84,9 @@ class CurdsAndWhey_RowStack(BasicRowStack):
class CurdsAndWhey(Game):
Hint_Class = CautiousDefaultHint
RowStack_Class = StackWrapper(CurdsAndWhey_RowStack, base_rank=KING,
max_move=UNLIMITED_MOVES, max_accept=UNLIMITED_ACCEPTS)
RowStack_Class = StackWrapper(
CurdsAndWhey_RowStack, base_rank=KING,
max_move=UNLIMITED_MOVES, max_accept=UNLIMITED_ACCEPTS)
#
# game layout
@ -130,8 +148,9 @@ class MissMuffet(CurdsAndWhey):
class Nordic(MissMuffet):
RowStack_Class = StackWrapper(CurdsAndWhey_RowStack, base_rank=ANY_RANK,
max_move=UNLIMITED_MOVES, max_accept=UNLIMITED_ACCEPTS)
RowStack_Class = StackWrapper(
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
doubleclickHandler = OpenStack.doubleclickHandler
class Dumfries_RowStack(BasicRowStack):
def acceptsCards(self, from_stack, cards):
@ -159,9 +179,10 @@ class Dumfries_RowStack(BasicRowStack):
def canMoveCards(self, cards):
return len(cards) == 1 or len(cards) == len(self.cards)
class Dumfries(Game):
##Hint_Class = KlondikeType_Hint
# Hint_Class = KlondikeType_Hint
def createGame(self, **layout):
# create layout
@ -188,7 +209,8 @@ class Dumfries(Game):
self.s.talon.fillStack()
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):
@ -200,13 +222,12 @@ class Robin(Dumfries):
def createGame(self):
Dumfries.createGame(self, rows=12)
# ************************************************************************
# * Arachnida
# * Harvestman
# ************************************************************************
class Arachnida_RowStack(BasicRowStack):
def acceptsCards(self, from_stack, cards):
@ -245,8 +266,10 @@ class Arachnida(CurdsAndWhey):
max_accept=UNLIMITED_ACCEPTS)
s.rows.append(stack)
x += l.XS
s.foundations.append(AbstractFoundationStack(x, y, self, suit=ANY_SUIT,
max_accept=0, max_cards=104))
s.foundations.append(
AbstractFoundationStack(
x, y, self, suit=ANY_SUIT,
max_accept=0, max_cards=104))
l.createText(s.foundations[0], "s")
# define stack-groups
@ -301,7 +324,9 @@ class GermanPatience(Game):
x, y = l.XM, l.YM
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, y = l.XM, h-l.YS
s.talon = WasteTalonStack(x, y, self, max_rounds=1)
@ -312,23 +337,20 @@ class GermanPatience(Game):
l.defaultStackGroups()
def startGame(self):
self.startDealSample()
self.s.talon.dealRow()
self.s.talon.dealCards()
def isGameWon(self):
if self.s.waste.cards or self.s.talon.cards:
return False
for s in self.s.rows:
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 True
shallHighlightMatch = Game._shallHighlightMatch_RKW
@ -531,13 +553,15 @@ registerGame(GameInfo(311, Dumfries, "Dumfries",
registerGame(GameInfo(312, Galloway, "Galloway",
GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_SKILL))
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",
GI.GT_SPIDER, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(349, MissMuffet, "Miss Muffet",
GI.GT_SPIDER | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
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",
GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(415, BavarianPatience, "Bavarian Patience",
@ -553,8 +577,7 @@ registerGame(GameInfo(534, Harvestman, "Harvestman",
registerGame(GameInfo(687, Glacier, "Glacier",
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
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",
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',
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
eq_or_diff( scalar(`$cmd`), '', "flake8 is happy with the code." );