mirror of
https://github.com/shlomif/PySolFC.git
synced 2025-04-05 00:02:29 -04:00
+ 6 new games
* improved findcarddialog + new command-line options: `--game' & `--gameid' git-svn-id: https://pysolfc.svn.sourceforge.net/svnroot/pysolfc/PySolFC/trunk@37 39dd0a4e-7c14-0410-91b3-c4f2d318f732
This commit is contained in:
parent
2c578eb8cf
commit
3a7f0238dd
10 changed files with 337 additions and 120 deletions
|
@ -150,15 +150,14 @@ class Options:
|
||||||
# fonts
|
# fonts
|
||||||
self.fonts = {"default" : None,
|
self.fonts = {"default" : None,
|
||||||
#"default" : ("helvetica", 12),
|
#"default" : ("helvetica", 12),
|
||||||
"sans" : ("times", 14), # for html
|
"sans" : ("times", 12), # for html
|
||||||
"fixed" : ("courier", 14), # for html & log
|
"fixed" : ("courier", 12), # for html & log
|
||||||
"small" : ("helvetica", 12),
|
"small" : ("helvetica", 12),
|
||||||
"canvas_default" : ("helvetica", 12),
|
"canvas_default" : ("helvetica", 12),
|
||||||
#"canvas_card" : ("helvetica", 12),
|
#"canvas_card" : ("helvetica", 12),
|
||||||
"canvas_fixed" : ("courier", 12),
|
"canvas_fixed" : ("courier", 12),
|
||||||
"canvas_large" : ("helvetica", 18),
|
"canvas_large" : ("helvetica", 16),
|
||||||
"canvas_small" : ("helvetica", 12), # not used?
|
"canvas_small" : ("helvetica", 10),
|
||||||
#"tree_small" : ("helvetica", 12),
|
|
||||||
}
|
}
|
||||||
if os.name == 'posix':
|
if os.name == 'posix':
|
||||||
self.fonts["sans"] = ("helvetica", 12)
|
self.fonts["sans"] = ("helvetica", 12)
|
||||||
|
@ -579,6 +578,8 @@ class Application:
|
||||||
)
|
)
|
||||||
self.commandline = Struct(
|
self.commandline = Struct(
|
||||||
loadgame = None, # load a game ?
|
loadgame = None, # load a game ?
|
||||||
|
game = None,
|
||||||
|
gameid = None,
|
||||||
)
|
)
|
||||||
self.demo_counter = 0
|
self.demo_counter = 0
|
||||||
|
|
||||||
|
@ -619,12 +620,21 @@ class Application:
|
||||||
game.destruct()
|
game.destruct()
|
||||||
destruct(game)
|
destruct(game)
|
||||||
game = None
|
game = None
|
||||||
if self.commandline.loadgame and not self.nextgame.loadedgame:
|
if not self.nextgame.loadedgame:
|
||||||
try:
|
if self.commandline.loadgame:
|
||||||
self.nextgame.loadedgame = tmpgame._loadGame(self.commandline.loadgame, self)
|
try:
|
||||||
self.nextgame.loadedgame.gstats.holded = 0
|
self.nextgame.loadedgame = tmpgame._loadGame(self.commandline.loadgame, self)
|
||||||
except:
|
self.nextgame.loadedgame.gstats.holded = 0
|
||||||
self.nextgame.loadedgame = None
|
except:
|
||||||
|
self.nextgame.loadedgame = None
|
||||||
|
elif not self.commandline.game is None:
|
||||||
|
gameid = self.gdb.getGameByName(self.commandline.game)
|
||||||
|
if gameid is None:
|
||||||
|
print >> sys.stderr, "WARNING: can't find game:", self.commandline.game
|
||||||
|
else:
|
||||||
|
self.nextgame.id, self.nextgame.random = gameid, None
|
||||||
|
elif not self.commandline.gameid is None:
|
||||||
|
self.nextgame.id, self.nextgame.random = self.commandline.gameid, None
|
||||||
self.opt.game_holded = 0
|
self.opt.game_holded = 0
|
||||||
tmpgame.destruct()
|
tmpgame.destruct()
|
||||||
destruct(tmpgame)
|
destruct(tmpgame)
|
||||||
|
|
|
@ -572,6 +572,13 @@ class GameManager:
|
||||||
self.getGamesIdSortedByName()
|
self.getGamesIdSortedByName()
|
||||||
return self.__games_by_altname
|
return self.__games_by_altname
|
||||||
|
|
||||||
|
# find game by name
|
||||||
|
def getGameByName(self, name):
|
||||||
|
gi = self.__all_gamenames.get(name)
|
||||||
|
if gi:
|
||||||
|
return gi.id
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
# //
|
# //
|
||||||
|
|
|
@ -222,6 +222,8 @@ class SlyFox_Foundation(SS_FoundationStack):
|
||||||
if not SS_FoundationStack.acceptsCards(self, from_stack, cards):
|
if not SS_FoundationStack.acceptsCards(self, from_stack, cards):
|
||||||
return False
|
return False
|
||||||
if from_stack in self.game.s.rows:
|
if from_stack in self.game.s.rows:
|
||||||
|
if len(self.game.s.talon.cards) == 0:
|
||||||
|
return True
|
||||||
return self.game.num_dealled <= 0
|
return self.game.num_dealled <= 0
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -332,10 +334,47 @@ class SlyFox(Game):
|
||||||
self.texts.misc.config(text=text)
|
self.texts.misc.config(text=text)
|
||||||
|
|
||||||
|
|
||||||
|
class OpenSlyFox(SlyFox):
|
||||||
|
|
||||||
|
def createGame(self):
|
||||||
|
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)
|
||||||
|
|
||||||
|
x, y = l.XM, l.YM
|
||||||
|
s.talon = SlyFox_Talon(x, y, self)
|
||||||
|
s.waste = s.talon
|
||||||
|
l.createText(s.talon, 'ne')
|
||||||
|
tx, ty, ta, tf = l.getTextAttr(s.talon, "ss")
|
||||||
|
font = self.app.getFont("canvas_default")
|
||||||
|
self.texts.misc = MfxCanvasText(self.canvas, tx, ty,
|
||||||
|
anchor=ta, font=font)
|
||||||
|
|
||||||
|
x += 2*l.XS
|
||||||
|
for i in range(4):
|
||||||
|
s.foundations.append(SlyFox_Foundation(x, y, self, suit=i))
|
||||||
|
s.foundations.append(SlyFox_Foundation(x+4*l.XS, y, self, suit=i,
|
||||||
|
base_rank=KING, dir=-1))
|
||||||
|
x += l.XS
|
||||||
|
y = l.YM+l.YS+l.TEXT_HEIGHT
|
||||||
|
for i in range(2):
|
||||||
|
x = l.XM
|
||||||
|
for j in range(10):
|
||||||
|
stack = SlyFox_RowStack(x, y, self, max_cards=UNLIMITED_CARDS)
|
||||||
|
s.rows.append(stack)
|
||||||
|
stack.CARD_YOFFSET = l.YOFFSET
|
||||||
|
x += l.XS
|
||||||
|
y += l.YS+playcards*l.YOFFSET
|
||||||
|
|
||||||
|
l.defaultStackGroups()
|
||||||
|
|
||||||
|
|
||||||
# register the game
|
# register the game
|
||||||
registerGame(GameInfo(280, Camelot, "Camelot",
|
registerGame(GameInfo(280, Camelot, "Camelot",
|
||||||
GI.GT_1DECK_TYPE, 1, 0, GI.SL_BALANCED))
|
GI.GT_1DECK_TYPE, 1, 0, GI.SL_BALANCED))
|
||||||
registerGame(GameInfo(610, SlyFox, "Sly Fox",
|
registerGame(GameInfo(610, SlyFox, "Sly Fox",
|
||||||
GI.GT_NUMERICA, 2, 0, GI.SL_MOSTLY_SKILL))
|
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))
|
||||||
|
|
||||||
|
|
|
@ -78,16 +78,25 @@ class GrandDuchess(Game):
|
||||||
# game layout
|
# game layout
|
||||||
#
|
#
|
||||||
|
|
||||||
def createGame(self):
|
def createGame(self, rows=4):
|
||||||
# create layout
|
# create layout
|
||||||
|
max_rows = max(10, 4+rows)
|
||||||
l, s = Layout(self), self.s
|
l, s = Layout(self), self.s
|
||||||
|
|
||||||
# set window
|
# set window
|
||||||
w, h = l.XM+9*l.XS, l.YM+2*l.YS+18*l.YOFFSET
|
w, h = l.XM+max_rows*l.XS, l.YM+2*l.YS+18*l.YOFFSET
|
||||||
self.setSize(w, h)
|
self.setSize(w, h)
|
||||||
|
|
||||||
# create stacks
|
# create stacks
|
||||||
x, y = l.XM, l.YM
|
x, y = l.XM, l.YM
|
||||||
|
s.talon = GrandDuchess_Talon(x, y, self, max_rounds=4)
|
||||||
|
l.createText(s.talon, 'se')
|
||||||
|
tx, ty, ta, tf = l.getTextAttr(s.talon, 'ne')
|
||||||
|
font = self.app.getFont('canvas_default')
|
||||||
|
s.talon.texts.rounds = MfxCanvasText(self.canvas, tx, ty,
|
||||||
|
anchor=ta, font=font)
|
||||||
|
|
||||||
|
x += 2*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))
|
||||||
x += l.XS
|
x += l.XS
|
||||||
|
@ -95,25 +104,18 @@ class GrandDuchess(Game):
|
||||||
s.foundations.append(SS_FoundationStack(x, y, self,
|
s.foundations.append(SS_FoundationStack(x, y, self,
|
||||||
suit=i, base_rank=KING, dir=-1))
|
suit=i, base_rank=KING, dir=-1))
|
||||||
x += l.XS
|
x += l.XS
|
||||||
x, y = l.XM+2*l.XS, l.YM+l.YS
|
x, y = l.XM+(max_rows-rows)*l.XS/2, l.YM+l.YS
|
||||||
for i in range(4):
|
for i in range(rows):
|
||||||
stack = BasicRowStack(x, y, self, max_move=1, max_accept=0)
|
stack = BasicRowStack(x, y, self, max_move=1, max_accept=0)
|
||||||
stack.CARD_YOFFSET = l.YOFFSET
|
stack.CARD_YOFFSET = l.YOFFSET
|
||||||
s.rows.append(stack)
|
s.rows.append(stack)
|
||||||
x += l.XS
|
x += l.XS
|
||||||
x, y = l.XM, l.YM+l.YS
|
dx = (max_rows-rows)*l.XS/4-l.XS/2
|
||||||
|
x, y = l.XM+dx, l.YM+l.YS
|
||||||
s.reserves.append(GrandDuchess_Reserve(x, y, self))
|
s.reserves.append(GrandDuchess_Reserve(x, y, self))
|
||||||
x, y = l.XM+7*l.XS, l.YM+l.YS
|
x, y = self.width-dx-l.XS, l.YM+l.YS
|
||||||
s.reserves.append(GrandDuchess_Reserve(x, y, self))
|
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
|
# define stack-groups
|
||||||
l.defaultStackGroups()
|
l.defaultStackGroups()
|
||||||
|
|
||||||
|
@ -133,7 +135,34 @@ class GrandDuchess(Game):
|
||||||
return ((), (), self.sg.dropstacks)
|
return ((), (), self.sg.dropstacks)
|
||||||
|
|
||||||
|
|
||||||
|
# /***********************************************************************
|
||||||
|
# // Parisienne
|
||||||
|
# ************************************************************************/
|
||||||
|
|
||||||
|
class Parisienne(GrandDuchess):
|
||||||
|
def _shuffleHook(self, cards):
|
||||||
|
# move one Ace and one King of each suit to top of the Talon
|
||||||
|
# (i.e. first cards to be dealt)
|
||||||
|
return self._shuffleHookMoveToTop(cards,
|
||||||
|
lambda c: (c.rank in (ACE, KING) and c.deck == 0, (c.rank, c.suit)))
|
||||||
|
|
||||||
|
def startGame(self):
|
||||||
|
self.s.talon.dealRow(rows=self.s.foundations, frames=0)
|
||||||
|
GrandDuchess.startGame(self)
|
||||||
|
|
||||||
|
|
||||||
|
class GrandDuchessPlus(GrandDuchess):
|
||||||
|
def createGame(self):
|
||||||
|
GrandDuchess.createGame(self, rows=6)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
registerGame(GameInfo(557, GrandDuchess, "Grand Duchess",
|
registerGame(GameInfo(557, GrandDuchess, "Grand Duchess",
|
||||||
GI.GT_2DECK_TYPE, 2, 3))
|
GI.GT_2DECK_TYPE, 2, 3))
|
||||||
|
registerGame(GameInfo(617, Parisienne, "Parisienne",
|
||||||
|
GI.GT_2DECK_TYPE, 2, 3,
|
||||||
|
rules_filename='grandduchess.html',
|
||||||
|
altnames=('La Parisienne', 'Parisian') ))
|
||||||
|
registerGame(GameInfo(618, GrandDuchessPlus, "Grand Duchess +",
|
||||||
|
GI.GT_2DECK_TYPE, 2, 3))
|
||||||
|
|
||||||
|
|
|
@ -178,7 +178,7 @@ class Kings(DerKatzenschwanz):
|
||||||
|
|
||||||
def _shuffleHook(self, cards):
|
def _shuffleHook(self, cards):
|
||||||
for c in cards[:]:
|
for c in cards[:]:
|
||||||
if c.rank == 12:
|
if c.rank == KING:
|
||||||
cards.remove(c)
|
cards.remove(c)
|
||||||
break
|
break
|
||||||
cards.append(c)
|
cards.append(c)
|
||||||
|
@ -289,7 +289,7 @@ class SalicLaw(DerKatzenschwanz):
|
||||||
y += l.YS
|
y += l.YS
|
||||||
|
|
||||||
x, y = l.XM, l.YM+l.YS*len(self.Foundation_Classes)
|
x, y = l.XM, l.YM+l.YS*len(self.Foundation_Classes)
|
||||||
self.setRegion(s.foundations[-8:], (-999, -999, 999999, y - l.XM / 2))
|
self.setRegion(s.foundations, (-999, -999, 999999, y - l.XM / 2))
|
||||||
for i in range(8):
|
for i in range(8):
|
||||||
stack = self.RowStack_Class(x, y, self, max_move=1)
|
stack = self.RowStack_Class(x, y, self, max_move=1)
|
||||||
stack.CARD_XOFFSET = xoffset
|
stack.CARD_XOFFSET = xoffset
|
||||||
|
@ -350,44 +350,6 @@ class Deep(DerKatzenschwanz):
|
||||||
self.s.talon.dealRow()
|
self.s.talon.dealRow()
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
|
||||||
# // Laggard Lady
|
|
||||||
# ************************************************************************/
|
|
||||||
|
|
||||||
class LaggardLady_RowStack(OpenStack):
|
|
||||||
def acceptsCards(self, from_stack, cards):
|
|
||||||
if not OpenStack.acceptsCards(self, from_stack, cards):
|
|
||||||
return False
|
|
||||||
return len(self.game.s.talon.cards) == 0 and len(self.cards) == 1
|
|
||||||
|
|
||||||
|
|
||||||
class LaggardLady(SalicLaw):
|
|
||||||
|
|
||||||
Foundation_Classes = [
|
|
||||||
StackWrapper(RK_FoundationStack, base_rank=5, max_cards=6),
|
|
||||||
StackWrapper(RK_FoundationStack, base_rank=4, max_cards=6, dir=-1, mod=13),
|
|
||||||
]
|
|
||||||
RowStack_Class = StackWrapper(LaggardLady_RowStack, max_accept=1, min_cards=1)
|
|
||||||
|
|
||||||
ROW_BASE_RANK = QUEEN
|
|
||||||
|
|
||||||
def _shuffleHook(self, cards):
|
|
||||||
for c in cards[:]:
|
|
||||||
if c.rank == QUEEN:
|
|
||||||
cards.remove(c)
|
|
||||||
break
|
|
||||||
cards.append(c)
|
|
||||||
return cards
|
|
||||||
|
|
||||||
def isGameWon(self):
|
|
||||||
if self.s.talon.cards:
|
|
||||||
return False
|
|
||||||
for s in self.s.foundations:
|
|
||||||
if len(s.cards) != 6:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
# // Faerie Queen
|
# // Faerie Queen
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
@ -423,9 +385,64 @@ class FaerieQueen(SalicLaw):
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
|
# // Intrigue
|
||||||
|
# // Laggard Lady
|
||||||
# // Glencoe
|
# // Glencoe
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
|
||||||
|
class Intrigue_RowStack(OpenStack):
|
||||||
|
def acceptsCards(self, from_stack, cards):
|
||||||
|
if not OpenStack.acceptsCards(self, from_stack, cards):
|
||||||
|
return False
|
||||||
|
return len(self.game.s.talon.cards) == 0 and len(self.cards) == 1
|
||||||
|
|
||||||
|
|
||||||
|
class Intrigue(SalicLaw):
|
||||||
|
|
||||||
|
Foundation_Classes = [
|
||||||
|
StackWrapper(RK_FoundationStack, base_rank=5, max_cards=6),
|
||||||
|
StackWrapper(RK_FoundationStack, base_rank=4, max_cards=6, dir=-1, mod=13),
|
||||||
|
]
|
||||||
|
RowStack_Class = StackWrapper(Intrigue_RowStack, max_accept=1, min_cards=1)
|
||||||
|
|
||||||
|
ROW_BASE_RANK = QUEEN
|
||||||
|
|
||||||
|
def _shuffleHook(self, cards):
|
||||||
|
for c in cards[:]:
|
||||||
|
if c.rank == QUEEN:
|
||||||
|
cards.remove(c)
|
||||||
|
break
|
||||||
|
cards.append(c)
|
||||||
|
return cards
|
||||||
|
|
||||||
|
def isGameWon(self):
|
||||||
|
if self.s.talon.cards:
|
||||||
|
return False
|
||||||
|
for s in self.s.foundations:
|
||||||
|
if len(s.cards) != 6:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class LaggardLady_Foundation(RK_FoundationStack):
|
||||||
|
def acceptsCards(self, from_stack, cards):
|
||||||
|
if not RK_FoundationStack.acceptsCards(self, from_stack, cards):
|
||||||
|
return False
|
||||||
|
c = cards[0]
|
||||||
|
if c.rank in (4, 5):
|
||||||
|
i = list(self.game.s.foundations).index(self) % 8
|
||||||
|
r = self.game.s.rows[i]
|
||||||
|
if not r.cards:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
class LaggardLady(Intrigue):
|
||||||
|
Foundation_Classes = [
|
||||||
|
StackWrapper(LaggardLady_Foundation, base_rank=5, max_cards=6),
|
||||||
|
StackWrapper(LaggardLady_Foundation, base_rank=4, max_cards=6, dir=-1, mod=13),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class Glencoe_Foundation(RK_FoundationStack):
|
class Glencoe_Foundation(RK_FoundationStack):
|
||||||
def acceptsCards(self, from_stack, cards):
|
def acceptsCards(self, from_stack, cards):
|
||||||
if not RK_FoundationStack.acceptsCards(self, from_stack, cards):
|
if not RK_FoundationStack.acceptsCards(self, from_stack, cards):
|
||||||
|
@ -439,16 +456,13 @@ class Glencoe_Foundation(RK_FoundationStack):
|
||||||
return c.suit == r.cards[0].suit
|
return c.suit == r.cards[0].suit
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
class Glencoe(Intrigue):
|
||||||
class Glencoe(LaggardLady):
|
|
||||||
|
|
||||||
Foundation_Classes = [
|
Foundation_Classes = [
|
||||||
StackWrapper(Glencoe_Foundation, base_rank=5, max_cards=6),
|
StackWrapper(Glencoe_Foundation, base_rank=5, max_cards=6),
|
||||||
StackWrapper(Glencoe_Foundation, base_rank=4, max_cards=6, dir=-1, mod=13),
|
StackWrapper(Glencoe_Foundation, base_rank=4, max_cards=6, dir=-1, mod=13),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# register the game
|
# register the game
|
||||||
registerGame(GameInfo(141, DerKatzenschwanz, "Cat's Tail",
|
registerGame(GameInfo(141, DerKatzenschwanz, "Cat's Tail",
|
||||||
GI.GT_FREECELL | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL,
|
GI.GT_FREECELL | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL,
|
||||||
|
@ -464,11 +478,16 @@ registerGame(GameInfo(299, SalicLaw, "Salic Law",
|
||||||
GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_LUCK))
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_LUCK))
|
||||||
registerGame(GameInfo(442, Deep, "Deep",
|
registerGame(GameInfo(442, Deep, "Deep",
|
||||||
GI.GT_FREECELL | GI.GT_OPEN | GI.GT_ORIGINAL, 2, 0, GI.SL_MOSTLY_SKILL))
|
GI.GT_FREECELL | GI.GT_OPEN | GI.GT_ORIGINAL, 2, 0, GI.SL_MOSTLY_SKILL))
|
||||||
registerGame(GameInfo(523, LaggardLady, "Laggard Lady",
|
registerGame(GameInfo(523, Intrigue, "Intrigue",
|
||||||
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
||||||
registerGame(GameInfo(611, FaerieQueen, "Faerie Queen",
|
registerGame(GameInfo(611, FaerieQueen, "Faerie Queen",
|
||||||
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
||||||
registerGame(GameInfo(612, Glencoe, "Glencoe",
|
registerGame(GameInfo(612, Glencoe, "Glencoe",
|
||||||
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED,
|
||||||
|
rules_filename="intrigue.html"))
|
||||||
|
registerGame(GameInfo(616, LaggardLady, "Laggard Lady",
|
||||||
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED,
|
||||||
|
rules_filename="intrigue.html"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
# // Parallels
|
# // Parallels
|
||||||
|
# // British Blockade
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
|
||||||
class Parallels_RowStack(BasicRowStack):
|
class Parallels_RowStack(BasicRowStack):
|
||||||
|
@ -167,9 +168,22 @@ class Parallels(Game):
|
||||||
self.s.talon.dealRow(rows=self.s.rows[:10])
|
self.s.talon.dealRow(rows=self.s.rows[:10])
|
||||||
|
|
||||||
|
|
||||||
|
class BritishBlockade(Parallels):
|
||||||
|
|
||||||
|
def fillStack(self, stack):
|
||||||
|
if not stack.cards and stack in self.s.rows:
|
||||||
|
if self.s.talon.cards:
|
||||||
|
old_state = self.enterState(self.S_FILL)
|
||||||
|
self.s.talon.flipMove()
|
||||||
|
self.s.talon.moveMove(1, stack)
|
||||||
|
self.leaveState(old_state)
|
||||||
|
|
||||||
|
|
||||||
# register the game
|
# register the game
|
||||||
registerGame(GameInfo(428, Parallels, "Parallels",
|
registerGame(GameInfo(428, Parallels, "Parallels",
|
||||||
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
||||||
|
registerGame(GameInfo(615, BritishBlockade, "British Blockade",
|
||||||
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -595,6 +595,86 @@ class Fifteens(Elevens):
|
||||||
self.leaveState(old_state)
|
self.leaveState(old_state)
|
||||||
|
|
||||||
|
|
||||||
|
# /***********************************************************************
|
||||||
|
# // Triple Alliance
|
||||||
|
# ************************************************************************/
|
||||||
|
|
||||||
|
class TripleAlliance_Reserve(ReserveStack):
|
||||||
|
def acceptsCards(self, from_stack, cards):
|
||||||
|
if not ReserveStack.acceptsCards(self, from_stack, cards):
|
||||||
|
return False
|
||||||
|
r_ranks = []
|
||||||
|
for r in self.game.s.reserves:
|
||||||
|
if r.cards:
|
||||||
|
r_ranks.append(r.cards[0].rank)
|
||||||
|
if not r_ranks:
|
||||||
|
return True
|
||||||
|
r_ranks.append(cards[0].rank)
|
||||||
|
r_ranks.sort()
|
||||||
|
if len(r_ranks) == 2:
|
||||||
|
return r_ranks[1]-r_ranks[0] in (1, 12)
|
||||||
|
for i in range(3):
|
||||||
|
j, k = (i+1)%3, (i+2)%3
|
||||||
|
if ((r_ranks[i]+1) % 13 == r_ranks[j] and
|
||||||
|
(r_ranks[j]+1) % 13 == r_ranks[k]):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class TripleAlliance(Game):
|
||||||
|
|
||||||
|
def createGame(self):
|
||||||
|
|
||||||
|
l, s = Layout(self), self.s
|
||||||
|
w0 = l.XS+5*l.XOFFSET
|
||||||
|
self.setSize(l.XM+5*w0, l.YM+5*l.YS)
|
||||||
|
|
||||||
|
x, y = l.XM, l.YM
|
||||||
|
for i in range(3):
|
||||||
|
s.reserves.append(TripleAlliance_Reserve(x, y, self))
|
||||||
|
x += l.XS
|
||||||
|
x, y = self.width-l.XS, l.YM
|
||||||
|
s.foundations.append(AbstractFoundationStack(x, y, self, suit=ANY_SUIT,
|
||||||
|
max_move=0, max_accept=0, max_cards=52))
|
||||||
|
y = l.YM+l.YS
|
||||||
|
nstacks = 0
|
||||||
|
for i in range(4):
|
||||||
|
x = l.XM
|
||||||
|
for j in range(5):
|
||||||
|
stack = BasicRowStack(x, y, self, max_accept=0)
|
||||||
|
s.rows.append(stack)
|
||||||
|
stack.CARD_XOFFSET, stack.CARD_YOFFSET = l.XOFFSET, 0
|
||||||
|
x += w0
|
||||||
|
nstacks += 1
|
||||||
|
if nstacks >= 18:
|
||||||
|
break
|
||||||
|
y += l.YS
|
||||||
|
|
||||||
|
x, y = self.width-l.XS, self.height-l.YS
|
||||||
|
s.talon = InitialDealTalonStack(x, y, self)
|
||||||
|
|
||||||
|
l.defaultStackGroups()
|
||||||
|
|
||||||
|
def startGame(self):
|
||||||
|
self.s.talon.dealRow(frames=0)
|
||||||
|
self.s.talon.dealRow(frames=0)
|
||||||
|
self.startDealSample()
|
||||||
|
self.s.talon.dealRowAvail()
|
||||||
|
|
||||||
|
def fillStack(self, stack):
|
||||||
|
for r in self.s.reserves:
|
||||||
|
if not r.cards:
|
||||||
|
return
|
||||||
|
if not self.demo:
|
||||||
|
self.playSample("droppair", priority=200)
|
||||||
|
old_state = self.enterState(self.S_FILL)
|
||||||
|
for r in self.s.reserves:
|
||||||
|
r.moveMove(1, self.s.foundations[0])
|
||||||
|
self.leaveState(old_state)
|
||||||
|
|
||||||
|
def isGameWon(self):
|
||||||
|
return len(self.s.foundations[0].cards) == 51
|
||||||
|
|
||||||
|
|
||||||
# register the game
|
# register the game
|
||||||
registerGame(GameInfo(38, Pyramid, "Pyramid",
|
registerGame(GameInfo(38, Pyramid, "Pyramid",
|
||||||
|
@ -615,6 +695,7 @@ registerGame(GameInfo(596, SuitElevens, "Suit Elevens",
|
||||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_LUCK))
|
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_LUCK))
|
||||||
registerGame(GameInfo(597, Fifteens, "Fifteens",
|
registerGame(GameInfo(597, Fifteens, "Fifteens",
|
||||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
|
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
|
||||||
|
registerGame(GameInfo(619, TripleAlliance, "Triple Alliance",
|
||||||
|
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_MOSTLY_SKILL))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -417,27 +417,29 @@ class Matrimony_Talon(DealRowTalonStack):
|
||||||
rows = self.game.s.rows
|
rows = self.game.s.rows
|
||||||
r = self.game.s.rows[-self.round]
|
r = self.game.s.rows[-self.round]
|
||||||
for i in range(len(r.cards)):
|
for i in range(len(r.cards)):
|
||||||
num_cards = num_cards + 1
|
num_cards += 1
|
||||||
self.game.moveMove(1, r, self, frames=4)
|
self.game.moveMove(1, r, self, frames=4)
|
||||||
self.game.flipMove(self)
|
self.game.flipMove(self)
|
||||||
assert len(self.cards) == num_cards
|
assert len(self.cards) == num_cards
|
||||||
self.game.nextRoundMove(self)
|
self.game.nextRoundMove(self)
|
||||||
|
return num_cards
|
||||||
|
|
||||||
def dealCards(self, sound=0):
|
def dealCards(self, sound=0):
|
||||||
if sound:
|
if sound:
|
||||||
self.game.startDealSample()
|
self.game.startDealSample()
|
||||||
|
num_cards = 0
|
||||||
if len(self.cards) == 0:
|
if len(self.cards) == 0:
|
||||||
self._redeal()
|
num_cards += self._redeal()
|
||||||
if self.round == 1:
|
if self.round == 1:
|
||||||
n = self.dealRowAvail(sound=0)
|
num_cards += self.dealRowAvail(sound=0)
|
||||||
else:
|
else:
|
||||||
rows = self.game.s.rows[-self.round+1:]
|
rows = self.game.s.rows[-self.round+1:]
|
||||||
n = self.dealRowAvail(rows=rows, sound=0)
|
num_cards += self.dealRowAvail(rows=rows, sound=0)
|
||||||
while self.cards:
|
while self.cards:
|
||||||
n += self.dealRowAvail(rows=self.game.s.rows, sound=0)
|
num_cards += self.dealRowAvail(rows=self.game.s.rows, sound=0)
|
||||||
if sound:
|
if sound:
|
||||||
self.game.stopSamples()
|
self.game.stopSamples()
|
||||||
return n
|
return num_cards
|
||||||
|
|
||||||
|
|
||||||
class Matrimony(Game):
|
class Matrimony(Game):
|
||||||
|
|
|
@ -84,8 +84,9 @@ Please check your %s installation.
|
||||||
def parse_option(argv):
|
def parse_option(argv):
|
||||||
prog_name = argv[0]
|
prog_name = argv[0]
|
||||||
try:
|
try:
|
||||||
optlist, args = getopt.getopt(argv[1:], "hD:",
|
optlist, args = getopt.getopt(argv[1:], "g:i:hD:",
|
||||||
["fg=", "foreground=",
|
["game=", "gameid=",
|
||||||
|
"fg=", "foreground=",
|
||||||
"bg=", "background=",
|
"bg=", "background=",
|
||||||
"fn=", "font=",
|
"fn=", "font=",
|
||||||
"noplugins",
|
"noplugins",
|
||||||
|
@ -97,6 +98,8 @@ def parse_option(argv):
|
||||||
% (prog_name, err, prog_name)
|
% (prog_name, err, prog_name)
|
||||||
return None
|
return None
|
||||||
opts = {"help": False,
|
opts = {"help": False,
|
||||||
|
"game": None,
|
||||||
|
"gameid": None,
|
||||||
"fg": None,
|
"fg": None,
|
||||||
"bg": None,
|
"bg": None,
|
||||||
"fn": None,
|
"fn": None,
|
||||||
|
@ -107,6 +110,10 @@ def parse_option(argv):
|
||||||
for i in optlist:
|
for i in optlist:
|
||||||
if i[0] in ("-h", "--help"):
|
if i[0] in ("-h", "--help"):
|
||||||
opts["help"] = True
|
opts["help"] = True
|
||||||
|
elif i[0] in ("-g", "--game"):
|
||||||
|
opts["game"] = i[1]
|
||||||
|
elif i[0] in ("-i", "--gameid"):
|
||||||
|
opts["gameid"] = i[1]
|
||||||
elif i[0] in ("--fg", "--foreground"):
|
elif i[0] in ("--fg", "--foreground"):
|
||||||
opts["fg"] = i[1]
|
opts["fg"] = i[1]
|
||||||
elif i[0] in ("--bg", "--background"):
|
elif i[0] in ("--bg", "--background"):
|
||||||
|
@ -122,6 +129,7 @@ def parse_option(argv):
|
||||||
|
|
||||||
if opts["help"]:
|
if opts["help"]:
|
||||||
print _("""Usage: %s [OPTIONS] [FILE]
|
print _("""Usage: %s [OPTIONS] [FILE]
|
||||||
|
-g --game=GAMENAME start game GAMENAME
|
||||||
--fg --foreground=COLOR foreground color
|
--fg --foreground=COLOR foreground color
|
||||||
--bg --background=COLOR background color
|
--bg --background=COLOR background color
|
||||||
--fn --font=FONT default font
|
--fn --font=FONT default font
|
||||||
|
@ -177,6 +185,12 @@ def pysol_init(app, args):
|
||||||
wm_command = prog + " " + os.path.abspath(argv0)
|
wm_command = prog + " " + os.path.abspath(argv0)
|
||||||
if filename:
|
if filename:
|
||||||
app.commandline.loadgame = filename
|
app.commandline.loadgame = filename
|
||||||
|
app.commandline.game = opts['game']
|
||||||
|
if not opts['gameid'] is None:
|
||||||
|
try:
|
||||||
|
app.commandline.gameid = int(opts['gameid'])
|
||||||
|
except:
|
||||||
|
print >> sys.stderr, 'WARNING: invalide game id:', opts['gameid']
|
||||||
app.debug = int(opts['debug'])
|
app.debug = int(opts['debug'])
|
||||||
|
|
||||||
# init games database
|
# init games database
|
||||||
|
|
|
@ -41,17 +41,24 @@ from tkcanvas import MfxCanvas, MfxCanvasGroup, MfxCanvasImage, MfxCanvasRectang
|
||||||
# //
|
# //
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
|
||||||
class FindCardDialog(Tkinter.Toplevel):
|
LARGE_EMBLEMS_SIZE = (38, 34)
|
||||||
SUIT_IMAGES = {} # key: (suit, color)
|
SMALL_EMBLEMS_SIZE = (31, 21)
|
||||||
RANK_IMAGES = {} # key: (rank, color)
|
|
||||||
|
|
||||||
def __init__(self, parent, game, dir):
|
class FindCardDialog(Tkinter.Toplevel):
|
||||||
|
CARD_IMAGES = {} # key: (rank, suit)
|
||||||
|
|
||||||
|
def __init__(self, parent, game, dir, size='large'):
|
||||||
Tkinter.Toplevel.__init__(self)
|
Tkinter.Toplevel.__init__(self)
|
||||||
self.title(_('Find card'))
|
self.title(_('Find card'))
|
||||||
self.wm_resizable(0, 0)
|
self.wm_resizable(0, 0)
|
||||||
#
|
#
|
||||||
self.images_dir = dir
|
##self.images_dir = dir
|
||||||
self.label_width, self.label_height = 38, 34
|
if size == 'large':
|
||||||
|
self.images_dir = os.path.join(dir, 'large-emblems')
|
||||||
|
self.label_width, self.label_height = LARGE_EMBLEMS_SIZE
|
||||||
|
else:
|
||||||
|
self.images_dir = os.path.join(dir, 'small-emblems')
|
||||||
|
self.label_width, self.label_height = SMALL_EMBLEMS_SIZE
|
||||||
self.canvas = MfxCanvas(self, bg='white')
|
self.canvas = MfxCanvas(self, bg='white')
|
||||||
self.canvas.pack(expand=True, fill='both')
|
self.canvas.pack(expand=True, fill='both')
|
||||||
#
|
#
|
||||||
|
@ -72,35 +79,28 @@ class FindCardDialog(Tkinter.Toplevel):
|
||||||
dir = self.images_dir
|
dir = self.images_dir
|
||||||
canvas = self.canvas
|
canvas = self.canvas
|
||||||
group = MfxCanvasGroup(canvas)
|
group = MfxCanvasGroup(canvas)
|
||||||
s = 'cshd'[suit]
|
|
||||||
if suit >= 2: c = 'red'
|
|
||||||
else: c = 'black'
|
|
||||||
rect_width = 4
|
|
||||||
x1, y1 = x0+dx-rect_width, y0+dy-rect_width
|
|
||||||
rect = MfxCanvasRectangle(self.canvas, x0, y0, x1, y1,
|
|
||||||
width=rect_width,
|
|
||||||
fill='white', outline='white')
|
|
||||||
rect.addtag(group)
|
|
||||||
#
|
#
|
||||||
fn = os.path.join(dir, c+'-'+str(rank)+'.gif')
|
im = FindCardDialog.CARD_IMAGES.get((rank, suit))
|
||||||
rim = FindCardDialog.RANK_IMAGES.get((rank, c))
|
if im is None:
|
||||||
if not rim:
|
r = '%02d' % (rank+1)
|
||||||
rim = makeImage(file=fn)
|
s = 'csdh'[suit]
|
||||||
FindCardDialog.RANK_IMAGES[(rank, c)] = rim
|
fn = os.path.join(dir, r+s+'.gif')
|
||||||
fn = os.path.join(dir, s+'.gif')
|
im = makeImage(file=fn)
|
||||||
sim = FindCardDialog.SUIT_IMAGES.get((suit, c))
|
FindCardDialog.CARD_IMAGES[(rank, suit)] = im
|
||||||
if not sim:
|
cim = MfxCanvasImage(canvas, x0, y0, image=im, anchor='nw')
|
||||||
sim = makeImage(file=fn)
|
cim.addtag(group)
|
||||||
FindCardDialog.SUIT_IMAGES[(suit, c)] = sim
|
cim.lower()
|
||||||
|
#
|
||||||
|
## rect_width = 4
|
||||||
|
## x1, y1 = x0+dx, y0+dy
|
||||||
|
## rect = MfxCanvasRectangle(self.canvas, x0, y0, x1, y1,
|
||||||
|
## width=rect_width,
|
||||||
|
## fill=None,
|
||||||
|
## outline='red',
|
||||||
|
## state='hidden')
|
||||||
|
## rect.addtag(group)
|
||||||
|
rect = None
|
||||||
#
|
#
|
||||||
x0 = x0+(dx-rim.width()-sim.width())/2
|
|
||||||
x0, y0 = x0-1, y0-2
|
|
||||||
x, y = x0, y0+(dy-rim.height())/2
|
|
||||||
im = MfxCanvasImage(canvas, x, y, image=rim, anchor='nw')
|
|
||||||
im.addtag(group)
|
|
||||||
x, y = x0+rim.width(), y0+(dy-sim.height())/2
|
|
||||||
im = MfxCanvasImage(canvas, x, y, image=sim, anchor='nw')
|
|
||||||
im.addtag(group)
|
|
||||||
bind(group, '<Enter>',
|
bind(group, '<Enter>',
|
||||||
lambda e, suit=suit, rank=rank, rect=rect:
|
lambda e, suit=suit, rank=rank, rect=rect:
|
||||||
self.enterEvent(suit, rank, rect))
|
self.enterEvent(suit, rank, rect))
|
||||||
|
@ -126,29 +126,31 @@ class FindCardDialog(Tkinter.Toplevel):
|
||||||
self.createCardLabel(suit=suit, rank=rank, x0=x, y0=y)
|
self.createCardLabel(suit=suit, rank=rank, x0=x, y0=y)
|
||||||
j += 1
|
j += 1
|
||||||
i += 1
|
i += 1
|
||||||
w, h = dx*j, dy*i
|
w, h = dx*j+2, dy*i+2
|
||||||
self.canvas.config(width=w, height=h)
|
self.canvas.config(width=w, height=h)
|
||||||
|
|
||||||
def enterEvent(self, suit, rank, rect):
|
def enterEvent(self, suit, rank, rect):
|
||||||
#print 'enterEvent', suit, rank
|
##print 'enterEvent', suit, rank
|
||||||
self.highlight_items = self.game.highlightCard(suit, rank)
|
self.highlight_items = self.game.highlightCard(suit, rank)
|
||||||
if not self.highlight_items:
|
if not self.highlight_items:
|
||||||
self.highlight_items = []
|
self.highlight_items = []
|
||||||
rect.config(outline='red')
|
|
||||||
if self.highlight_items:
|
if self.highlight_items:
|
||||||
self.timer = after(self, self.normal_timeout, self.timeoutEvent)
|
self.timer = after(self, self.normal_timeout, self.timeoutEvent)
|
||||||
|
return
|
||||||
|
rect.config(state='normal')
|
||||||
|
|
||||||
def leaveEvent(self, suit, rank, rect):
|
def leaveEvent(self, suit, rank, rect):
|
||||||
#print 'leaveEvent', suit, rank
|
##print 'leaveEvent', suit, rank
|
||||||
if self.highlight_items:
|
if self.highlight_items:
|
||||||
for i in self.highlight_items:
|
for i in self.highlight_items:
|
||||||
i.delete()
|
i.delete()
|
||||||
rect.config(outline='white')
|
|
||||||
#self.game.canvas.update_idletasks()
|
#self.game.canvas.update_idletasks()
|
||||||
#self.canvas.update_idletasks()
|
#self.canvas.update_idletasks()
|
||||||
if self.timer:
|
if self.timer:
|
||||||
after_cancel(self.timer)
|
after_cancel(self.timer)
|
||||||
self.timer = None
|
self.timer = None
|
||||||
|
return
|
||||||
|
rect.config(state='hidden')
|
||||||
|
|
||||||
def timeoutEvent(self, *event):
|
def timeoutEvent(self, *event):
|
||||||
if self.highlight_items:
|
if self.highlight_items:
|
||||||
|
|
Loading…
Add table
Reference in a new issue