mirror of
https://github.com/shlomif/PySolFC.git
synced 2025-04-05 00:02:29 -04:00
+ added statistics progression; statistics progression dialog + new animation speed: `medium'; renamed `timer based' to `fast' + added flip animation (animatedFlip) + added move to waste animation (animatedFlipAndMove) + added cancel-drag animation (moveCardsBackHandler) * improved demo game (snapshots based check for loop) - removed setting text color from file name - removed auto generation shadows (too slow) * optimized menu creation * changed some keybindings * updated russian translation * many bugfixes git-svn-id: file:///home/shlomif/Backup/svn-dumps/PySolFC/svnsync-repos/pysolfc/PySolFC/trunk@138 efabe8c0-fbe8-4139-b769-b5e6d273206e
609 lines
19 KiB
Python
609 lines
19 KiB
Python
## vim:ts=4:et:nowrap
|
|
##
|
|
##---------------------------------------------------------------------------##
|
|
##
|
|
## PySol -- a Python Solitaire game
|
|
##
|
|
## Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
|
|
## Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
|
|
## Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
|
|
##
|
|
## This program is free software; you can redistribute it and/or modify
|
|
## it under the terms of the GNU General Public License as published by
|
|
## the Free Software Foundation; either version 2 of the License, or
|
|
## (at your option) any later version.
|
|
##
|
|
## This program is distributed in the hope that it will be useful,
|
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
## GNU General Public License for more details.
|
|
##
|
|
## You should have received a copy of the GNU General Public License
|
|
## along with this program; see the file COPYING.
|
|
## If not, write to the Free Software Foundation, Inc.,
|
|
## 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
##
|
|
## Markus F.X.J. Oberhumer
|
|
## <markus@oberhumer.com>
|
|
## http://www.oberhumer.com/pysol
|
|
##
|
|
##---------------------------------------------------------------------------##
|
|
|
|
__all__ = []
|
|
|
|
# imports
|
|
import sys
|
|
|
|
# PySol imports
|
|
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 DefaultHint, FreeCellType_Hint, CautiousDefaultHint
|
|
from pysollib.hint import FreeCellSolverWrapper
|
|
from pysollib.pysoltk import MfxCanvasText
|
|
|
|
|
|
# /***********************************************************************
|
|
# //
|
|
# ************************************************************************/
|
|
|
|
class DerKatzenschwanz_Hint(FreeCellType_Hint):
|
|
def _getMovePileScore(self, score, color, r, t, pile, rpile):
|
|
if len(rpile) == 0:
|
|
# don't create empty row
|
|
return -1, color
|
|
return FreeCellType_Hint._getMovePileScore(self, score, color, r, t, pile, rpile)
|
|
|
|
|
|
# /***********************************************************************
|
|
# //
|
|
# ************************************************************************/
|
|
|
|
class DerKatzenschwanz(Game):
|
|
RowStack_Class = StackWrapper(AC_RowStack, base_rank=NO_RANK)
|
|
Hint_Class = DerKatzenschwanz_Hint
|
|
Solver_Class = FreeCellSolverWrapper(esf='none', sm='unlimited')
|
|
|
|
#
|
|
# game layout
|
|
#
|
|
|
|
def createGame(self, rows=9, reserves=8):
|
|
# create layout
|
|
l, s = Layout(self), self.s
|
|
|
|
# set size
|
|
maxrows = max(rows, reserves)
|
|
self.setSize(l.XM + (maxrows+2)*l.XS, l.YM + 6*l.YS)
|
|
|
|
#
|
|
playcards = 4*l.YS / l.YOFFSET
|
|
xoffset, yoffset = [], []
|
|
for i in range(playcards):
|
|
xoffset.append(0)
|
|
yoffset.append(l.YOFFSET)
|
|
for i in range(104-playcards):
|
|
xoffset.append(l.XOFFSET)
|
|
yoffset.append(0)
|
|
|
|
# create stacks
|
|
x, y = l.XM + (maxrows-reserves)*l.XS/2, l.YM
|
|
for i in range(reserves):
|
|
s.reserves.append(ReserveStack(x, y, self))
|
|
x = x + l.XS
|
|
x, y = l.XM + (maxrows-rows)*l.XS/2, l.YM + l.YS
|
|
self.setRegion(s.reserves, (-999, -999, 999999, y - l.CH / 2))
|
|
for i in range(rows):
|
|
stack = self.RowStack_Class(x, y, self)
|
|
stack.CARD_XOFFSET = xoffset
|
|
stack.CARD_YOFFSET = yoffset
|
|
s.rows.append(stack)
|
|
x = x + l.XS
|
|
x, y = l.XM + maxrows*l.XS, l.YM
|
|
for suit in range(4):
|
|
for i in range(2):
|
|
s.foundations.append(SS_FoundationStack(x+i*l.XS, y, self, suit=suit))
|
|
y = y + l.YS
|
|
self.setRegion(self.s.foundations, (x - l.CW / 2, -999, 999999, y), priority=1)
|
|
s.talon = InitialDealTalonStack(self.width-3*l.XS/2, self.height-l.YS, self)
|
|
|
|
# define stack-groups
|
|
l.defaultStackGroups()
|
|
|
|
#
|
|
# game overrides
|
|
#
|
|
|
|
def startGame(self):
|
|
self.startDealSample()
|
|
i = 0
|
|
while self.s.talon.cards:
|
|
if self.s.talon.cards[-1].rank == KING:
|
|
if self.s.rows[i].cards:
|
|
i = i + 1
|
|
self.s.talon.dealRow(rows=[self.s.rows[i]], frames=4)
|
|
|
|
shallHighlightMatch = Game._shallHighlightMatch_AC
|
|
|
|
# must look at cards
|
|
def _getClosestStack(self, cx, cy, stacks, dragstack):
|
|
closest, cdist = None, 999999999
|
|
for stack in stacks:
|
|
if stack.cards and stack is not dragstack:
|
|
dist = (stack.cards[-1].x - cx)**2 + (stack.cards[-1].y - cy)**2
|
|
else:
|
|
dist = (stack.x - cx)**2 + (stack.y - cy)**2
|
|
if dist < cdist:
|
|
closest, cdist = stack, dist
|
|
return closest
|
|
|
|
|
|
# /***********************************************************************
|
|
# //
|
|
# ************************************************************************/
|
|
|
|
class DieSchlange(DerKatzenschwanz):
|
|
|
|
RowStack_Class = StackWrapper(FreeCell_AC_RowStack, base_rank=NO_RANK)
|
|
Solver_Class = FreeCellSolverWrapper(esf='none')
|
|
|
|
def createGame(self):
|
|
DerKatzenschwanz.createGame(self, rows=9, reserves=7)
|
|
|
|
def startGame(self):
|
|
self.startDealSample()
|
|
i = 0
|
|
while self.s.talon.cards:
|
|
c = self.s.talon.cards[-1]
|
|
if c.rank == ACE:
|
|
to_stack = self.s.foundations[c.suit*2]
|
|
if to_stack.cards:
|
|
to_stack = self.s.foundations[c.suit*2+1]
|
|
else:
|
|
if c.rank == KING and self.s.rows[i].cards:
|
|
i = i + 1
|
|
to_stack = self.s.rows[i]
|
|
self.s.talon.dealRow(rows=(to_stack,), frames=4)
|
|
|
|
|
|
# /***********************************************************************
|
|
# // Kings
|
|
# ************************************************************************/
|
|
|
|
class Kings(DerKatzenschwanz):
|
|
|
|
RowStack_Class = StackWrapper(AC_RowStack, base_rank=NO_RANK)
|
|
Solver_Class = FreeCellSolverWrapper(esf='none', sm='unlimited')
|
|
|
|
def createGame(self):
|
|
return DerKatzenschwanz.createGame(self, rows=8, reserves=8)
|
|
|
|
def _shuffleHook(self, cards):
|
|
for c in cards[:]:
|
|
if c.rank == KING:
|
|
cards.remove(c)
|
|
break
|
|
cards.append(c)
|
|
return cards
|
|
|
|
|
|
# /***********************************************************************
|
|
# // Retinue
|
|
# ************************************************************************/
|
|
|
|
class Retinue(DieSchlange, Kings):
|
|
|
|
RowStack_Class = StackWrapper(FreeCell_AC_RowStack, base_rank=NO_RANK)
|
|
Solver_Class = FreeCellSolverWrapper(esf='none')
|
|
|
|
def createGame(self):
|
|
return DerKatzenschwanz.createGame(self, rows=8, reserves=8)
|
|
def _shuffleHook(self, cards):
|
|
return Kings._shuffleHook(self, cards)
|
|
def startGame(self):
|
|
return DieSchlange.startGame(self)
|
|
|
|
|
|
# /***********************************************************************
|
|
# // Salic Law
|
|
# ************************************************************************/
|
|
|
|
class SalicLaw_Hint(CautiousDefaultHint):
|
|
|
|
# Score for dropping ncards from stack r to stack t.
|
|
def _getDropCardScore(self, score, color, r, t, ncards):
|
|
return score+len(r.cards), color
|
|
|
|
|
|
class SalicLaw_Talon(OpenTalonStack):
|
|
|
|
def canDealCards(self):
|
|
return True
|
|
|
|
def canFlipCard(self):
|
|
return False
|
|
|
|
def dealCards(self, sound=0):
|
|
if len(self.cards) == 0:
|
|
return 0
|
|
base_rank=self.game.ROW_BASE_RANK
|
|
old_state = self.game.enterState(self.game.S_DEAL)
|
|
rows = self.game.s.rows
|
|
c = self.cards[-1]
|
|
ri = len([r for r in rows if r.cards])
|
|
if c.rank == base_rank:
|
|
to_stack = rows[ri]
|
|
else:
|
|
to_stack = rows[ri-1]
|
|
##frames = (3, 4)[ri > 4]
|
|
frames = 3
|
|
if not self.game.demo:
|
|
self.game.startDealSample()
|
|
self.game.flipMove(self)
|
|
self.game.moveMove(1, self, to_stack, frames=frames)
|
|
if not self.game.demo:
|
|
self.game.stopSamples()
|
|
self.game.leaveState(old_state)
|
|
return 1
|
|
|
|
|
|
class SalicLaw(DerKatzenschwanz):
|
|
|
|
Hint_Class = SalicLaw_Hint
|
|
Solver_Class = None
|
|
|
|
Foundation_Classes = [
|
|
StackWrapper(AbstractFoundationStack, max_cards=1, base_rank=QUEEN),
|
|
StackWrapper(RK_FoundationStack, base_rank=ACE, max_cards=11),
|
|
]
|
|
RowStack_Class = OpenStack
|
|
|
|
ROW_BASE_RANK = KING
|
|
|
|
#
|
|
# game layout
|
|
#
|
|
|
|
def createGame(self): #, rows=9, reserves=8):
|
|
# create layout
|
|
l, s = Layout(self), self.s
|
|
|
|
# set size
|
|
self.setSize(l.XM+10*l.XS, l.YM+(5+len(self.Foundation_Classes))*l.YS)
|
|
|
|
#
|
|
playcards = 4*l.YS / l.YOFFSET
|
|
xoffset, yoffset = [], []
|
|
for i in range(playcards):
|
|
xoffset.append(0)
|
|
yoffset.append(l.YOFFSET)
|
|
for i in range(104-playcards):
|
|
xoffset.append(l.XOFFSET)
|
|
yoffset.append(0)
|
|
|
|
# create stacks
|
|
y = l.YM
|
|
for found_class in self.Foundation_Classes:
|
|
x = l.XM
|
|
for i in range(8):
|
|
s.foundations.append(found_class(x, y, self,
|
|
suit=ANY_SUIT, max_move=0))
|
|
x += l.XS
|
|
y += l.YS
|
|
|
|
x, y = l.XM, l.YM+l.YS*len(self.Foundation_Classes)
|
|
self.setRegion(s.foundations, (-999, -999, 999999, y - l.XM / 2))
|
|
for i in range(8):
|
|
stack = self.RowStack_Class(x, y, self, max_move=1)
|
|
stack.CARD_XOFFSET = xoffset
|
|
stack.CARD_YOFFSET = yoffset
|
|
s.rows.append(stack)
|
|
x += l.XS
|
|
s.talon = SalicLaw_Talon(l.XM+9*l.XS, l.YM, self)
|
|
l.createText(s.talon, "s")
|
|
|
|
# define stack-groups
|
|
l.defaultStackGroups()
|
|
|
|
#
|
|
# game overrides
|
|
#
|
|
|
|
def _shuffleHook(self, cards):
|
|
for c in cards[:]:
|
|
if c.rank == KING:
|
|
cards.remove(c)
|
|
break
|
|
cards.append(c)
|
|
return cards
|
|
|
|
def startGame(self):
|
|
self.startDealSample()
|
|
self.s.talon.dealRow(self.s.rows[:1]) # deal King
|
|
|
|
def isGameWon(self):
|
|
for s in self.s.foundations[8:]:
|
|
if len(s.cards) != 11:
|
|
return False
|
|
return True
|
|
|
|
def getAutoStacks(self, event=None):
|
|
if event is None:
|
|
# disable auto drop
|
|
return (self.sg.dropstacks, (), self.sg.dropstacks)
|
|
else:
|
|
# rightclickHandler
|
|
return (self.sg.dropstacks, self.sg.dropstacks, self.sg.dropstacks)
|
|
|
|
|
|
# /***********************************************************************
|
|
# // Deep
|
|
# ************************************************************************/
|
|
|
|
class Deep(DerKatzenschwanz):
|
|
RowStack_Class = StackWrapper(AC_RowStack, base_rank=ANY_RANK)
|
|
Solver_Class = FreeCellSolverWrapper(sm='unlimited')
|
|
|
|
def createGame(self):
|
|
return DerKatzenschwanz.createGame(self, rows=8, reserves=8)
|
|
|
|
def startGame(self):
|
|
for i in range(12):
|
|
self.s.talon.dealRow(frames=0)
|
|
self.startDealSample()
|
|
self.s.talon.dealRow()
|
|
|
|
|
|
# /***********************************************************************
|
|
# // Faerie Queen
|
|
# ************************************************************************/
|
|
|
|
class FaerieQueen_RowStack(RK_RowStack):
|
|
def acceptsCards(self, from_stack, cards):
|
|
if self.game.s.talon.cards:
|
|
return False
|
|
if len(self.cards) == 1:
|
|
return True
|
|
return RK_RowStack.acceptsCards(self, from_stack, cards)
|
|
|
|
|
|
class FaerieQueen(SalicLaw):
|
|
|
|
Foundation_Classes = [
|
|
StackWrapper(RK_FoundationStack, max_move=0, max_cards=12)
|
|
]
|
|
RowStack_Class = StackWrapper(FaerieQueen_RowStack, min_cards=1, max_move=1)
|
|
|
|
def isGameWon(self):
|
|
if self.s.talon.cards:
|
|
return False
|
|
for s in self.s.foundations:
|
|
if len(s.cards) != 12:
|
|
return False
|
|
return True
|
|
|
|
def getQuickPlayScore(self, ncards, from_stack, to_stack):
|
|
return int(len(to_stack.cards) > 1)
|
|
|
|
shallHighlightMatch = Game._shallHighlightMatch_RK
|
|
|
|
|
|
# /***********************************************************************
|
|
# // Intrigue
|
|
# // Laggard Lady
|
|
# // 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):
|
|
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 c.suit == r.cards[0].suit
|
|
return True
|
|
|
|
class Glencoe(Intrigue):
|
|
Foundation_Classes = [
|
|
StackWrapper(Glencoe_Foundation, base_rank=5, max_cards=6),
|
|
StackWrapper(Glencoe_Foundation, base_rank=4, max_cards=6, dir=-1, mod=13),
|
|
]
|
|
|
|
|
|
# /***********************************************************************
|
|
# // Step-Up
|
|
# ************************************************************************/
|
|
|
|
class StepUp_Foundation(SS_FoundationStack):
|
|
def acceptsCards(self, from_stack, cards):
|
|
if not SS_FoundationStack.acceptsCards(self, from_stack, cards):
|
|
return False
|
|
if from_stack in self.game.s.reserves:
|
|
return True
|
|
for r in self.game.s.reserves:
|
|
if not r.cards:
|
|
return True
|
|
return False
|
|
|
|
class StepUp_Talon(WasteTalonStack):
|
|
def canDealCards(self):
|
|
if not WasteTalonStack.canDealCards(self):
|
|
return False
|
|
for r in self.game.s.reserves:
|
|
if not r.cards:
|
|
return False
|
|
return True
|
|
|
|
class StepUp_RowStack(AC_RowStack):
|
|
def acceptsCards(self, from_stack, cards):
|
|
if not AC_RowStack.acceptsCards(self, from_stack, cards):
|
|
return False
|
|
if (from_stack in self.game.s.reserves or
|
|
from_stack in self.game.s.foundations):
|
|
return False
|
|
return True
|
|
|
|
|
|
class StepUp(Game):
|
|
Hint_Class = CautiousDefaultHint
|
|
|
|
def createGame(self):
|
|
l, s = Layout(self), self.s
|
|
self.setSize(l.XM+13*l.XS, l.YM+7*l.YS)
|
|
self.base_rank = ANY_RANK
|
|
|
|
x, y = l.XM+2.5*l.XS, l.YM
|
|
for i in range(8):
|
|
s.foundations.append(StepUp_Foundation(x, y, self,
|
|
suit=i%4, mod=13, base_rank=ANY_RANK))
|
|
x += l.XS
|
|
tx, ty, ta, tf = l.getTextAttr(s.foundations[0], "sw")
|
|
font = self.app.getFont("canvas_default")
|
|
self.texts.info = MfxCanvasText(self.canvas, tx, ty,
|
|
anchor=ta, font=font)
|
|
|
|
x, y = l.XM, l.YM+l.YS
|
|
for i in range(13):
|
|
s.reserves.append(ReserveStack(x, y, self))
|
|
x += l.XS
|
|
x, y = l.XM+2*l.XS, l.YM+2*l.YS
|
|
for i in range(9):
|
|
s.rows.append(StepUp_RowStack(x, y, self, max_move=1, mod=13))
|
|
x += l.XS
|
|
|
|
x, y = l.XM, l.YM+2.5*l.YS
|
|
s.talon = StepUp_Talon(x, y, self, max_rounds=1)
|
|
l.createText(s.talon, 'se')
|
|
y += l.YS
|
|
s.waste = WasteStack(x, y, self)
|
|
l.createText(s.waste, 'se')
|
|
|
|
l.defaultStackGroups()
|
|
|
|
|
|
def startGame(self):
|
|
c = self.s.talon.cards[-1]
|
|
self.base_rank = c.rank
|
|
self.s.talon.flipMove()
|
|
self.s.talon.moveMove(1, self.s.foundations[c.suit], frames=0)
|
|
for s in self.s.foundations:
|
|
s.cap.base_rank = c.rank
|
|
self.s.talon.dealRow(rows=self.s.reserves, frames=0)
|
|
self.startDealSample()
|
|
self.s.talon.dealRow()
|
|
self.s.talon.dealCards()
|
|
|
|
def updateText(self):
|
|
if self.preview > 1:
|
|
return
|
|
base_rank = self.base_rank
|
|
if base_rank == ANY_RANK:
|
|
t = ''
|
|
else:
|
|
t = RANKS[base_rank]
|
|
self.texts.info.config(text=t)
|
|
|
|
def _restoreGameHook(self, game):
|
|
self.base_rank = game.loadinfo.base_rank
|
|
for s in self.s.foundations:
|
|
s.cap.base_rank = self.base_rank
|
|
|
|
def _loadGameHook(self, p):
|
|
self.loadinfo.addattr(base_rank=None) # register extra load var.
|
|
self.loadinfo.base_rank = p.load()
|
|
|
|
def _saveGameHook(self, p):
|
|
p.dump(self.base_rank)
|
|
|
|
shallHighlightMatch = Game._shallHighlightMatch_ACW
|
|
|
|
|
|
# register the game
|
|
registerGame(GameInfo(141, DerKatzenschwanz, "Cat's Tail",
|
|
GI.GT_FREECELL | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL,
|
|
altnames=("Der Katzenschwanz",) ))
|
|
registerGame(GameInfo(142, DieSchlange, "Snake",
|
|
GI.GT_FREECELL | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL,
|
|
altnames=("Die Schlange",) ))
|
|
registerGame(GameInfo(279, Kings, "Kings",
|
|
GI.GT_FREECELL | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL))
|
|
registerGame(GameInfo(286, Retinue, "Retinue",
|
|
GI.GT_FREECELL | GI.GT_OPEN | GI.GT_ORIGINAL, 2, 0, GI.SL_MOSTLY_SKILL))
|
|
registerGame(GameInfo(299, SalicLaw, "Salic Law",
|
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_LUCK))
|
|
registerGame(GameInfo(442, Deep, "Deep",
|
|
GI.GT_FREECELL | GI.GT_OPEN | GI.GT_ORIGINAL, 2, 0, GI.SL_MOSTLY_SKILL))
|
|
registerGame(GameInfo(523, Intrigue, "Intrigue",
|
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
|
registerGame(GameInfo(611, FaerieQueen, "Faerie Queen",
|
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
|
registerGame(GameInfo(612, Glencoe, "Glencoe",
|
|
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"))
|
|
registerGame(GameInfo(624, StepUp, "Step-Up",
|
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
|
|
|
|
|
|