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 22:30:01 +03:00
parent d71a5d0a51
commit b44d11c281
4 changed files with 245 additions and 135 deletions

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,24 +19,45 @@
# 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.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 pysollib.hint import FreeCellSolverWrapper from pysollib.hint import FreeCellSolverWrapper
from pysollib.pysoltk import MfxCanvasText from pysollib.pysoltk import MfxCanvasText
from pysollib.util import ACE, KING, NO_RANK, UNLIMITED_CARDS
from pysollib.stack import \
AC_FoundationStack, \
AC_RowStack, \
DealRowRedealTalonStack, \
DealRow_StackMethods, \
FullStackWrapper, \
InitialDealTalonStack, \
InvisibleStack, \
KingAC_RowStack, \
KingSS_RowStack, \
RK_RowStack, \
RedealTalonStack, \
ReserveStack, \
SS_FoundationStack, \
SS_RowStack, \
Stack, \
SuperMoveSS_RowStack, \
TalonStack, \
UD_RK_RowStack, \
UD_SS_RowStack, \
StackWrapper
# ************************************************************************ # ************************************************************************
# * # *
@ -62,7 +83,8 @@ class Fan(Game):
# game layout # game layout
# #
def createGame(self, rows=(5,5,5,3), playcards=9, reserves=0, texts=False): def createGame(self, rows=(5, 5, 5, 3), playcards=9, reserves=0,
texts=False):
# create layout # create layout
l, s = Layout(self), self.s l, s = Layout(self), self.s
@ -71,7 +93,7 @@ class Fan(Game):
w = max(2*l.XS, l.XS+(playcards-1)*l.XOFFSET) w = max(2*l.XS, l.XS+(playcards-1)*l.XOFFSET)
w = min(3*l.XS, w) w = min(3*l.XS, w)
w = (w + 1) & ~1 w = (w + 1) & ~1
##print 2*l.XS, w # print 2*l.XS, w
self.setSize(l.XM + max(rows)*w, l.YM + (1+len(rows))*l.YS) self.setSize(l.XM + max(rows)*w, l.YM + (1+len(rows))*l.YS)
# create stacks # create stacks
@ -81,7 +103,7 @@ class Fan(Game):
for r in range(reserves): for r in range(reserves):
s.reserves.append(self.ReserveStack_Class(x, y, self)) s.reserves.append(self.ReserveStack_Class(x, y, self))
x += l.XS x += l.XS
x = (self.width - decks*4*l.XS) # - 2*l.XS) / 2 x = (self.width - decks*4*l.XS) # - 2*l.XS) / 2
dx = l.XS dx = l.XS
else: else:
dx = (self.width - decks*4*l.XS)/(decks*4+1) dx = (self.width - decks*4*l.XS)/(decks*4+1)
@ -94,7 +116,8 @@ class Fan(Game):
for i in range(len(rows)): for i in range(len(rows)):
x, y = l.XM, y + l.YS x, y = l.XM, y + l.YS
for j in range(rows[i]): for j in range(rows[i]):
stack = self.RowStack_Class(x, y, self, max_move=1, max_accept=1) stack = self.RowStack_Class(
x, y, self, max_move=1, max_accept=1)
stack.CARD_XOFFSET, stack.CARD_YOFFSET = l.XOFFSET, 0 stack.CARD_XOFFSET, stack.CARD_YOFFSET = l.XOFFSET, 0
s.rows.append(stack) s.rows.append(stack)
x += w x += w
@ -134,6 +157,7 @@ class FanGame(Fan):
class ScotchPatience(Fan): class ScotchPatience(Fan):
Foundation_Classes = [AC_FoundationStack] Foundation_Classes = [AC_FoundationStack]
RowStack_Class = StackWrapper(RK_RowStack, base_rank=NO_RANK) RowStack_Class = StackWrapper(RK_RowStack, base_rank=NO_RANK)
def createGame(self): def createGame(self):
Fan.createGame(self, playcards=8) Fan.createGame(self, playcards=8)
shallHighlightMatch = Game._shallHighlightMatch_RK shallHighlightMatch = Game._shallHighlightMatch_RK
@ -145,11 +169,14 @@ class ScotchPatience(Fan):
# ************************************************************************ # ************************************************************************
class Shamrocks(Fan): class Shamrocks(Fan):
RowStack_Class = StackWrapper(UD_RK_RowStack, base_rank=NO_RANK, max_cards=3) RowStack_Class = StackWrapper(
UD_RK_RowStack, base_rank=NO_RANK, max_cards=3)
def createGame(self): def createGame(self):
Fan.createGame(self, playcards=4) Fan.createGame(self, playcards=4)
shallHighlightMatch = Game._shallHighlightMatch_RK shallHighlightMatch = Game._shallHighlightMatch_RK
class ShamrocksII(Shamrocks): class ShamrocksII(Shamrocks):
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
# move Kings to bottom of each stack # move Kings to bottom of each stack
@ -216,8 +243,8 @@ class LaBelleLucie_Talon(TalonStack):
to_stacks = self.game.s.rows to_stacks = self.game.s.rows
n = min(len(self.cards), 3*len(to_stacks)) n = min(len(self.cards), 3*len(to_stacks))
for i in range(3): for i in range(3):
j = (n/3, (n+1)/3, (n+2)/3) [i] j = (n/3, (n+1)/3, (n+2)/3)[i]
frames = (0, 0, 4) [i] frames = (0, 0, 4)[i]
for r in to_stacks[:j]: for r in to_stacks[:j]:
if self.cards[-1].face_up != face_up: if self.cards[-1].face_up != face_up:
self.game.flipMove(self) self.game.flipMove(self)
@ -227,6 +254,7 @@ class LaBelleLucie_Talon(TalonStack):
class LaBelleLucie(Fan): class LaBelleLucie(Fan):
Talon_Class = StackWrapper(LaBelleLucie_Talon, max_rounds=3) Talon_Class = StackWrapper(LaBelleLucie_Talon, max_rounds=3)
RowStack_Class = StackWrapper(SS_RowStack, base_rank=NO_RANK) RowStack_Class = StackWrapper(SS_RowStack, base_rank=NO_RANK)
def createGame(self): def createGame(self):
return Fan.createGame(self, texts=True) return Fan.createGame(self, texts=True)
@ -248,15 +276,16 @@ class ThreeShufflesAndADraw_RowStack(SS_RowStack):
def moveMove(self, ncards, to_stack, frames=-1, shadow=-1): def moveMove(self, ncards, to_stack, frames=-1, shadow=-1):
game, r = self.game, self.game.s.reserves[0] game, r = self.game, self.game.s.reserves[0]
if to_stack is not r: if to_stack is not r:
SS_RowStack.moveMove(self, ncards, to_stack, frames=frames, shadow=shadow) SS_RowStack.moveMove(
self, ncards, to_stack, frames=frames, shadow=shadow)
return return
f = self._canDrawCard() f = self._canDrawCard()
assert f and game.draw_done == 0 and ncards == 1 assert f and game.draw_done == 0 and ncards == 1
# 1) top card from self to reserve # 1) top card from self to reserve
game.updateStackMove(r, 2|16) # update view for undo game.updateStackMove(r, 2 | 16) # update view for undo
game.moveMove(1, self, r, frames=frames, shadow=shadow) game.moveMove(1, self, r, frames=frames, shadow=shadow)
game.updateStackMove(r, 3|64) # update model game.updateStackMove(r, 3 | 64) # update model
game.updateStackMove(r, 1|16) # update view for redo game.updateStackMove(r, 1 | 16) # update view for redo
# 2) second card from self to foundation/row # 2) second card from self to foundation/row
if 1 or not game.demo: if 1 or not game.demo:
game.playSample("drop", priority=200) game.playSample("drop", priority=200)
@ -282,7 +311,7 @@ class ThreeShufflesAndADraw_ReserveStack(ReserveStack):
def acceptsCards(self, from_stack, cards): def acceptsCards(self, from_stack, cards):
if not ReserveStack.acceptsCards(self, from_stack, cards): if not ReserveStack.acceptsCards(self, from_stack, cards):
return False return False
if not from_stack in self.game.s.rows: if from_stack not in self.game.s.rows:
return False return False
if self.game.draw_done or not from_stack._canDrawCard(): if self.game.draw_done or not from_stack._canDrawCard():
return False return False
@ -295,7 +324,7 @@ class ThreeShufflesAndADraw_ReserveStack(ReserveStack):
def updateText(self): def updateText(self):
if self.game.preview > 1 or self.texts.misc is None: if self.game.preview > 1 or self.texts.misc is None:
return return
t = (_("X"), _("Draw")) [self.game.draw_done == 0] t = (_("X"), _("Draw"))[self.game.draw_done == 0]
self.texts.misc.config(text=t) self.texts.misc.config(text=t)
def prepareView(self): def prepareView(self):
@ -304,13 +333,15 @@ class ThreeShufflesAndADraw_ReserveStack(ReserveStack):
return return
images = self.game.app.images images = self.game.app.images
x, y = self.x + images.CARDW/2, self.y + images.CARDH/2 x, y = self.x + images.CARDW/2, self.y + images.CARDH/2
self.texts.misc = MfxCanvasText(self.game.canvas, x, y, self.texts.misc = MfxCanvasText(
anchor="center", self.game.canvas, x, y,
font=self.game.app.getFont("canvas_default")) anchor="center",
font=self.game.app.getFont("canvas_default"))
class ThreeShufflesAndADraw(LaBelleLucie): class ThreeShufflesAndADraw(LaBelleLucie):
RowStack_Class = StackWrapper(ThreeShufflesAndADraw_RowStack, base_rank=NO_RANK) RowStack_Class = StackWrapper(
ThreeShufflesAndADraw_RowStack, base_rank=NO_RANK)
def createGame(self): def createGame(self):
l = LaBelleLucie.createGame(self) l = LaBelleLucie.createGame(self)
@ -347,11 +378,12 @@ class Trefoil(LaBelleLucie):
Foundation_Classes = [StackWrapper(SS_FoundationStack, min_cards=1)] Foundation_Classes = [StackWrapper(SS_FoundationStack, min_cards=1)]
def createGame(self): def createGame(self):
return Fan.createGame(self, rows=(5,5,5,1), texts=True) return Fan.createGame(self, rows=(5, 5, 5, 1), texts=True)
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
# move Aces to bottom of the Talon (i.e. last cards to be dealt) # move Aces to bottom of the Talon (i.e. last cards to be dealt)
return self._shuffleHookMoveToBottom(cards, lambda c: (c.rank == 0, c.suit)) return self._shuffleHookMoveToBottom(
cards, lambda c: (c.rank == 0, c.suit))
def startGame(self): def startGame(self):
for i in range(2): for i in range(2):
@ -392,7 +424,8 @@ class Intelligence_Talon(LaBelleLucie_Talon):
if not self.cards: if not self.cards:
return return
# move all remaining cards to the reserve # move all remaining cards to the reserve
self.game.moveMove(len(self.cards), self, self.game.s.reserves[0], frames=0) self.game.moveMove(
len(self.cards), self, self.game.s.reserves[0], frames=0)
# up or down in suit # up or down in suit
@ -401,7 +434,7 @@ class Intelligence_RowStack(UD_SS_RowStack):
if not self.cards: if not self.cards:
r = self.game.s.reserves[0] r = self.game.s.reserves[0]
if r.cards: if r.cards:
r.dealRow((self,self,self), sound=True) r.dealRow((self, self, self), sound=True)
class Intelligence_ReserveStack(ReserveStack, DealRow_StackMethods): class Intelligence_ReserveStack(ReserveStack, DealRow_StackMethods):
@ -418,12 +451,15 @@ class Intelligence(Fan):
Talon_Class = StackWrapper(Intelligence_Talon, max_rounds=3) Talon_Class = StackWrapper(Intelligence_Talon, max_rounds=3)
RowStack_Class = StackWrapper(Intelligence_RowStack, base_rank=NO_RANK) RowStack_Class = StackWrapper(Intelligence_RowStack, base_rank=NO_RANK)
def createGame(self, rows=(5,5,5,3)): def createGame(self, rows=(5, 5, 5, 3)):
l = Fan.createGame(self, rows) l = Fan.createGame(self, rows)
s = self.s s = self.s
# add a reserve stack # add a reserve stack
x, y = s.talon.x - l.XS, s.talon.y x, y = s.talon.x - l.XS, s.talon.y
s.reserves.append(Intelligence_ReserveStack(x, y, self, max_move=0, max_accept=0, max_cards=UNLIMITED_CARDS)) s.reserves.append(
Intelligence_ReserveStack(
x, y, self, max_move=0, max_accept=0,
max_cards=UNLIMITED_CARDS))
l.createText(s.reserves[0], "sw") l.createText(s.reserves[0], "sw")
l.createRoundText(s.talon, 'nn') l.createRoundText(s.talon, 'nn')
# redefine the stack-groups # redefine the stack-groups
@ -441,7 +477,7 @@ class Intelligence(Fan):
class IntelligencePlus(Intelligence): class IntelligencePlus(Intelligence):
def createGame(self): def createGame(self):
Intelligence.createGame(self, rows=(5,5,5,4)) Intelligence.createGame(self, rows=(5, 5, 5, 4))
# ************************************************************************ # ************************************************************************
@ -455,7 +491,7 @@ class HouseInTheWood(Fan):
RowStack_Class = StackWrapper(UD_SS_RowStack, base_rank=NO_RANK) RowStack_Class = StackWrapper(UD_SS_RowStack, base_rank=NO_RANK)
def createGame(self): def createGame(self):
Fan.createGame(self, rows=(6,6,6,6,6,5)) Fan.createGame(self, rows=(6, 6, 6, 6, 6, 5))
def startGame(self): def startGame(self):
self.s.talon.dealRow(rows=self.s.rows[:34], frames=0) self.s.talon.dealRow(rows=self.s.rows[:34], frames=0)
@ -466,7 +502,8 @@ class HouseInTheWood(Fan):
class HouseOnTheHill(HouseInTheWood): class HouseOnTheHill(HouseInTheWood):
Foundation_Classes = [SS_FoundationStack, Foundation_Classes = [SS_FoundationStack,
StackWrapper(SS_FoundationStack, base_rank=KING, dir=-1)] StackWrapper(
SS_FoundationStack, base_rank=KING, dir=-1)]
# ************************************************************************ # ************************************************************************
@ -480,6 +517,7 @@ class CloverLeaf_RowStack(UD_SS_RowStack):
if not self.cards: if not self.cards:
return cards[0].rank in (ACE, KING) return cards[0].rank in (ACE, KING)
return True return True
def _getBaseCard(self): def _getBaseCard(self):
return _('Base card - Ace or King.') return _('Base card - Ace or King.')
@ -539,10 +577,11 @@ class CloverLeaf(Game):
self.s.talon.dealRow(rows=self.s.foundations) self.s.talon.dealRow(rows=self.s.foundations)
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
return self._shuffleHookMoveToBottom(cards, return self._shuffleHookMoveToBottom(
lambda c: ((c.rank == ACE and c.suit in (0,1)) or cards,
(c.rank == KING and c.suit in (2,3)), lambda c: ((c.rank == ACE and c.suit in (0, 1)) or
c.suit)) (c.rank == KING and c.suit in (2, 3)),
c.suit))
shallHighlightMatch = Game._shallHighlightMatch_SS shallHighlightMatch = Game._shallHighlightMatch_SS
@ -554,6 +593,7 @@ class CloverLeaf(Game):
class FreeFan(Fan): class FreeFan(Fan):
RowStack_Class = FullStackWrapper(SuperMoveSS_RowStack, base_rank=KING) RowStack_Class = FullStackWrapper(SuperMoveSS_RowStack, base_rank=KING)
Solver_Class = FreeCellSolverWrapper(esf='kings', sbb='suit') Solver_Class = FreeCellSolverWrapper(esf='kings', sbb='suit')
def createGame(self): def createGame(self):
Fan.createGame(self, reserves=2, playcards=8) Fan.createGame(self, reserves=2, playcards=8)
@ -568,7 +608,7 @@ class BoxFan(Fan):
Solver_Class = FreeCellSolverWrapper(esf='kings') Solver_Class = FreeCellSolverWrapper(esf='kings')
def createGame(self): def createGame(self):
Fan.createGame(self, rows=(4,4,4,4)) Fan.createGame(self, rows=(4, 4, 4, 4))
def startGame(self): def startGame(self):
for i in range(2): for i in range(2):
@ -579,7 +619,8 @@ class BoxFan(Fan):
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
# move Aces to bottom of the Talon (i.e. last cards to be dealt) # move Aces to bottom of the Talon (i.e. last cards to be dealt)
return self._shuffleHookMoveToBottom(cards, lambda c: (c.rank == 0, c.suit)) return self._shuffleHookMoveToBottom(
cards, lambda c: (c.rank == 0, c.suit))
shallHighlightMatch = Game._shallHighlightMatch_AC shallHighlightMatch = Game._shallHighlightMatch_AC
@ -615,16 +656,20 @@ class Troika(Fan):
class Quads_RowStack(RK_RowStack): class Quads_RowStack(RK_RowStack):
getBottomImage = Stack._getReserveBottomImage getBottomImage = Stack._getReserveBottomImage
class Quads(Troika): class Quads(Troika):
RowStack_Class = FullStackWrapper(Quads_RowStack, dir=0, RowStack_Class = FullStackWrapper(
##base_rank=NO_RANK, Quads_RowStack, dir=0,
max_cards=4) # base_rank=NO_RANK,
max_cards=4)
def createGame(self): def createGame(self):
Fan.createGame(self, rows=(5, 5, 3), playcards=5) Fan.createGame(self, rows=(5, 5, 3), playcards=5)
def startGame(self): def startGame(self):
Troika.startGame(self, ncards=4) Troika.startGame(self, ncards=4)
class QuadsPlus(Quads): class QuadsPlus(Quads):
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
return self._shuffleHookMoveToTop(cards, return self._shuffleHookMoveToTop(cards,
@ -646,9 +691,10 @@ class FascinationFan_Talon(RedealTalonStack):
def dealCards(self, sound=False): def dealCards(self, sound=False):
RedealTalonStack.redealCards(self, shuffle=True, sound=sound) RedealTalonStack.redealCards(self, shuffle=True, sound=sound)
class FascinationFan(Fan): class FascinationFan(Fan):
Talon_Class = StackWrapper(FascinationFan_Talon, max_rounds=7) Talon_Class = StackWrapper(FascinationFan_Talon, max_rounds=7)
#Talon_Class = StackWrapper(LaBelleLucie_Talon, max_rounds=7) # Talon_Class = StackWrapper(LaBelleLucie_Talon, max_rounds=7)
RowStack_Class = StackWrapper(AC_RowStack, base_rank=NO_RANK) RowStack_Class = StackWrapper(AC_RowStack, base_rank=NO_RANK)
def createGame(self): def createGame(self):
@ -662,8 +708,9 @@ class FascinationFan(Fan):
def redealCards(self): def redealCards(self):
r0 = r1 = len(self.s.talon.cards)/3 r0 = r1 = len(self.s.talon.cards)/3
m = len(self.s.talon.cards)%3 m = len(self.s.talon.cards) % 3
if m >= 1: r1 += 1 if m >= 1:
r1 += 1
self.s.talon.dealRow(rows=self.s.rows[:r0], flip=0, frames=4) self.s.talon.dealRow(rows=self.s.rows[:r0], flip=0, frames=4)
self.s.talon.dealRow(rows=self.s.rows[:r1], flip=0, frames=4) self.s.talon.dealRow(rows=self.s.rows[:r1], flip=0, frames=4)
self.s.talon.dealRowAvail(frames=4) self.s.talon.dealRowAvail(frames=4)
@ -736,11 +783,11 @@ class Crescent(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, cards,
(c.rank, c.suit))) lambda c: (c.rank in (ACE, KING) and c.deck == 0,
(c.rank, 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)
@ -896,7 +943,6 @@ class ForestGlade(Game):
l.defaultStackGroups() l.defaultStackGroups()
def startGame(self): def startGame(self):
for i in range(2): for i in range(2):
self.s.talon.dealRow(frames=0) self.s.talon.dealRow(frames=0)
@ -906,7 +952,6 @@ class ForestGlade(Game):
shallHighlightMatch = Game._shallHighlightMatch_SS shallHighlightMatch = Game._shallHighlightMatch_SS
# register the game # register the game
registerGame(GameInfo(56, FanGame, "Fan", registerGame(GameInfo(56, FanGame, "Fan",
GI.GT_FAN_TYPE | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FAN_TYPE | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
@ -916,7 +961,7 @@ registerGame(GameInfo(57, Shamrocks, "Shamrocks",
GI.GT_FAN_TYPE | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FAN_TYPE | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(901, LaBelleLucie, "La Belle Lucie", # was: 32, 82 registerGame(GameInfo(901, LaBelleLucie, "La Belle Lucie", # was: 32, 82
GI.GT_FAN_TYPE | GI.GT_OPEN, 1, 2, GI.SL_MOSTLY_SKILL, GI.GT_FAN_TYPE | GI.GT_OPEN, 1, 2, GI.SL_MOSTLY_SKILL,
altnames=("Fair Lucy", "Midnight Oil") )) altnames=("Fair Lucy", "Midnight Oil")))
registerGame(GameInfo(132, SuperFlowerGarden, "Super Flower Garden", registerGame(GameInfo(132, SuperFlowerGarden, "Super Flower Garden",
GI.GT_FAN_TYPE | GI.GT_OPEN, 1, 2, GI.SL_MOSTLY_SKILL)) GI.GT_FAN_TYPE | GI.GT_OPEN, 1, 2, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(128, ThreeShufflesAndADraw, "Three Shuffles and a Draw", registerGame(GameInfo(128, ThreeShufflesAndADraw, "Three Shuffles and a Draw",
@ -941,10 +986,11 @@ registerGame(GameInfo(385, BoxFan, "Box Fan",
registerGame(GameInfo(516, Troika, "Troika", registerGame(GameInfo(516, Troika, "Troika",
GI.GT_FAN_TYPE | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FAN_TYPE | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(517, Quads, "Quads", registerGame(GameInfo(517, Quads, "Quads",
GI.GT_FAN_TYPE | GI.GT_OPEN | GI.GT_ORIGINAL, 1, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FAN_TYPE | GI.GT_OPEN | GI.GT_ORIGINAL, 1, 0,
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(625, FascinationFan, "Fascination Fan", registerGame(GameInfo(625, FascinationFan, "Fascination Fan",
GI.GT_FAN_TYPE, 1, 6, GI.SL_BALANCED, GI.GT_FAN_TYPE, 1, 6, GI.SL_BALANCED,
altnames=('Demon Fan',) )) altnames=('Demon Fan',)))
registerGame(GameInfo(647, Crescent, "Crescent", registerGame(GameInfo(647, Crescent, "Crescent",
GI.GT_FAN_TYPE, 2, 3, GI.SL_MOSTLY_SKILL)) GI.GT_FAN_TYPE, 2, 3, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(714, ShamrocksII, "Shamrocks II", registerGame(GameInfo(714, ShamrocksII, "Shamrocks II",
@ -954,5 +1000,5 @@ registerGame(GameInfo(719, School, "School",
registerGame(GameInfo(739, ForestGlade, "Forest Glade", registerGame(GameInfo(739, ForestGlade, "Forest Glade",
GI.GT_FAN_TYPE, 2, 2, GI.SL_MOSTLY_SKILL)) GI.GT_FAN_TYPE, 2, 2, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(767, QuadsPlus, "Quads +", registerGame(GameInfo(767, QuadsPlus, "Quads +",
GI.GT_FAN_TYPE | GI.GT_OPEN | GI.GT_ORIGINAL, 1, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FAN_TYPE | GI.GT_OPEN | GI.GT_ORIGINAL, 1, 0,
GI.SL_MOSTLY_SKILL))

View file

@ -27,14 +27,32 @@ __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.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, CautiousDefaultHint
from gypsy import DieRussische_Foundation from gypsy import DieRussische_Foundation
from pysollib.util import ACE, ANY_RANK, ANY_SUIT, KING, NO_RANK, \
UNLIMITED_MOVES, UNLIMITED_REDEALS
from pysollib.stack import \
AC_FoundationStack, \
AC_RowStack, \
BO_RowStack, \
RK_FoundationStack, \
RK_RowStack, \
ReserveStack, \
SS_FoundationStack, \
SS_RowStack, \
Spider_SS_RowStack, \
Stack, \
TalonStack, \
UD_AC_RowStack, \
WasteStack, \
WasteTalonStack, \
StackWrapper
# ************************************************************************ # ************************************************************************
# * # *
@ -64,7 +82,8 @@ class FortyThieves(Game):
# game layout # game layout
# #
def createGame(self, max_rounds=1, num_deal=1, rows=10, playcards=12, XCARDS=64, XOFFSET=None): def createGame(self, max_rounds=1, num_deal=1, rows=10,
playcards=12, XCARDS=64, XOFFSET=None):
# create layout # create layout
if XOFFSET is None: if XOFFSET is None:
l, s = Layout(self), self.s l, s = Layout(self), self.s
@ -80,7 +99,8 @@ class FortyThieves(Game):
w1, w2 = maxrows*l.XS+l.XM, 2*l.XS w1, w2 = maxrows*l.XS+l.XM, 2*l.XS
if w2 + XCARDS * l.XOFFSET > w1: if w2 + XCARDS * l.XOFFSET > w1:
l.XOFFSET = int((w1 - w2) / XCARDS) l.XOFFSET = int((w1 - w2) / XCARDS)
# (piles up to 12 cards are playable without overlap in default window size) # (piles up to 12 cards are playable without overlap
# in default window size)
h = max(2*l.YS, l.YS+(playcards-1)*l.YOFFSET) h = max(2*l.YS, l.YS+(playcards-1)*l.YOFFSET)
self.setSize(w1, l.YM + l.YS + h + l.YS + l.TEXT_HEIGHT) self.setSize(w1, l.YM + l.YS + h + l.YS + l.TEXT_HEIGHT)
@ -89,8 +109,10 @@ class FortyThieves(Game):
x = l.XM + (maxrows - 4*decks) * l.XS / 2 x = l.XM + (maxrows - 4*decks) * l.XS / 2
y = l.YM y = l.YM
for i in range(4*decks): for i in range(4*decks):
s.foundations.append(self.Foundation_Class(x, y, self, s.foundations.append(
suit=i/decks, max_move=self.FOUNDATION_MAX_MOVE)) self.Foundation_Class(
x, y, self,
suit=i/decks, max_move=self.FOUNDATION_MAX_MOVE))
x = x + l.XS x = x + l.XS
# rows # rows
x = l.XM + (maxrows - rows) * l.XS / 2 x = l.XM + (maxrows - rows) * l.XS / 2
@ -184,6 +206,7 @@ class Lucas(WaningMoon):
class NapoleonsSquare(FortyThieves): class NapoleonsSquare(FortyThieves):
ROW_MAX_MOVE = UNLIMITED_MOVES ROW_MAX_MOVE = UNLIMITED_MOVES
def createGame(self): def createGame(self):
FortyThieves.createGame(self, rows=12) FortyThieves.createGame(self, rows=12)
@ -226,6 +249,7 @@ class Josephine(FortyThieves):
class MarieRose(Josephine): class MarieRose(Josephine):
DEAL = (0, 5) DEAL = (0, 5)
def createGame(self): def createGame(self):
FortyThieves.createGame(self, rows=12, playcards=16, XCARDS=96) FortyThieves.createGame(self, rows=12, playcards=16, XCARDS=96)
@ -272,7 +296,8 @@ class Deuces(FortyThieves):
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()
@ -297,7 +322,8 @@ class Corona(FortyThieves):
class Quadrangle(Corona): class Quadrangle(Corona):
Foundation_Class = StackWrapper(SS_FoundationStack, mod=13, base_rank=NO_RANK) Foundation_Class = StackWrapper(
SS_FoundationStack, mod=13, base_rank=NO_RANK)
RowStack_Class = StackWrapper(SS_RowStack, mod=13) RowStack_Class = StackWrapper(SS_RowStack, mod=13)
def startGame(self): def startGame(self):
@ -395,6 +421,7 @@ class NumberTwelve(NumberTen):
class Roosevelt(Streets): class Roosevelt(Streets):
DEAL = (0, 4) DEAL = (0, 4)
def createGame(self): def createGame(self):
Streets.createGame(self, rows=7) Streets.createGame(self, rows=7)
@ -416,7 +443,8 @@ class RedAndBlack(Streets):
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()
@ -499,7 +527,6 @@ class FinalBattle(DoubleRail):
FortyThieves.createGame(self, rows=6) FortyThieves.createGame(self, rows=6)
# ************************************************************************ # ************************************************************************
# * Octave # * Octave
# ************************************************************************ # ************************************************************************
@ -609,7 +636,8 @@ class Octave(Game):
shallHighlightMatch = Game._shallHighlightMatch_AC shallHighlightMatch = Game._shallHighlightMatch_AC
def _autoDeal(self, sound=True): def _autoDeal(self, sound=True):
ncards = len(self.s.waste.cards) + sum([len(i.cards) for i in self.s.reserves]) ncards = len(self.s.waste.cards) + sum(
[len(i.cards) for i in self.s.reserves])
if ncards == 0: if ncards == 0:
return self.dealCards(sound=sound) return self.dealCards(sound=sound)
return 0 return 0
@ -660,20 +688,17 @@ class FortunesFavor(Game):
l.defaultStackGroups() l.defaultStackGroups()
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, return self._shuffleHookMoveToTop(cards,
lambda c: (c.rank == ACE, c.suit)) lambda c: (c.rank == ACE, 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()
self.s.talon.dealRow() self.s.talon.dealRow()
self.s.talon.dealCards() # deal first card to WasteStack self.s.talon.dealCards() # deal first card to WasteStack
def fillStack(self, stack): def fillStack(self, stack):
if len(stack.cards) == 0: if len(stack.cards) == 0:
if stack is self.s.waste and self.s.talon.cards: if stack is self.s.waste and self.s.talon.cards:
@ -681,7 +706,6 @@ class FortunesFavor(Game):
elif stack in self.s.rows and self.s.waste.cards: elif stack in self.s.rows and self.s.waste.cards:
self.s.waste.moveMove(1, stack) self.s.waste.moveMove(1, stack)
shallHighlightMatch = Game._shallHighlightMatch_SS shallHighlightMatch = Game._shallHighlightMatch_SS
@ -716,7 +740,7 @@ class Octagon(Game):
(l.XM+w1+3*l.XS+l.XS/2+l.XM, l.YM+1.5*l.YS), (l.XM+w1+3*l.XS+l.XS/2+l.XM, l.YM+1.5*l.YS),
(l.XM+w1, l.YM+3*l.YS), (l.XM+w1, l.YM+3*l.YS),
(l.XM+w1+l.XS, l.YM+3*l.YS),): (l.XM+w1+l.XS, l.YM+3*l.YS),):
s.foundations.append(SS_FoundationStack(x, y, self, suit=i%4)) s.foundations.append(SS_FoundationStack(x, y, self, suit=i % 4))
i += 1 i += 1
x, y = l.XM+w1, l.YM+1.5*l.YS x, y = l.XM+w1, l.YM+1.5*l.YS
s.talon = WasteTalonStack(x, y, self, max_rounds=4) s.talon = WasteTalonStack(x, y, self, max_rounds=4)
@ -728,11 +752,10 @@ class Octagon(Game):
l.defaultStackGroups() l.defaultStackGroups()
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, return self._shuffleHookMoveToTop(
lambda c: (c.rank == ACE, (c.deck, c.suit))) cards, lambda c: (c.rank == ACE, (c.deck, 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)
@ -783,7 +806,6 @@ class Squadron(FortyThieves):
l.defaultStackGroups() l.defaultStackGroups()
def startGame(self): def startGame(self):
self.s.talon.dealRow(rows=self.s.reserves, frames=0) self.s.talon.dealRow(rows=self.s.reserves, frames=0)
for i in range(3): for i in range(3):
@ -809,8 +831,8 @@ class Waterloo(FortyThieves):
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, return self._shuffleHookMoveToTop(
lambda c: (c.rank == ACE, (c.deck, c.suit))) cards, lambda c: (c.rank == ACE, (c.deck, c.suit)))
def startGame(self): def startGame(self):
self.startDealSample() self.startDealSample()
@ -841,7 +863,7 @@ class Junction(Game):
x = l.XM+2*l.XS x = l.XM+2*l.XS
for j in range(8): for j in range(8):
s.foundations.append(self.Foundation_Class(x, y, self, s.foundations.append(self.Foundation_Class(x, y, self,
suit=j%4)) suit=j % 4))
x += l.XS x += l.XS
y += l.YS y += l.YS
@ -859,13 +881,11 @@ class Junction(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_AC shallHighlightMatch = Game._shallHighlightMatch_AC
@ -926,7 +946,7 @@ class TheSpark(Game):
s.talon = TheSpark_Talon(x, y, self, max_rounds=1, num_deal=3) s.talon = TheSpark_Talon(x, y, self, max_rounds=1, num_deal=3)
l.createText(s.talon, 'se') l.createText(s.talon, 'se')
y += l.YS y += l.YS
for i in (0,1): for i in (0, 1):
stack = WasteStack(x, y, self) stack = WasteStack(x, y, self)
s.reserves.append(stack) s.reserves.append(stack)
l.createText(stack, 'se') l.createText(stack, 'se')
@ -943,20 +963,17 @@ class TheSpark(Game):
l.defaultStackGroups() l.defaultStackGroups()
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, return self._shuffleHookMoveToTop(cards,
lambda c: (c.rank == KING, c.suit)) lambda c: (c.rank == KING, 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()
self.s.talon.dealRow() self.s.talon.dealRow()
self.s.talon.dealCards() # deal first card to WasteStack self.s.talon.dealCards() # deal first card to WasteStack
shallHighlightMatch = Game._shallHighlightMatch_SS shallHighlightMatch = Game._shallHighlightMatch_SS
@ -967,6 +984,7 @@ class TheSpark(Game):
class DoubleGoldMine_RowStack(AC_RowStack): class DoubleGoldMine_RowStack(AC_RowStack):
getBottomImage = Stack._getReserveBottomImage getBottomImage = Stack._getReserveBottomImage
class DoubleGoldMine(Streets): class DoubleGoldMine(Streets):
RowStack_Class = DoubleGoldMine_RowStack RowStack_Class = DoubleGoldMine_RowStack
@ -1000,7 +1018,7 @@ class Interchange(FortyThieves):
FortyThieves.createGame(self, rows=7) FortyThieves.createGame(self, rows=7)
def startGame(self): def startGame(self):
for i in (0,1,2): for i in (0, 1, 2):
self.s.talon.dealRow(frames=0) self.s.talon.dealRow(frames=0)
self.s.talon.dealRow(flip=0, frames=0) self.s.talon.dealRow(flip=0, frames=0)
self.startDealSample() self.startDealSample()
@ -1054,7 +1072,7 @@ class TripleInterchange(Interchange):
max_rounds=UNLIMITED_REDEALS) max_rounds=UNLIMITED_REDEALS)
def startGame(self): def startGame(self):
for i in (0,1,2,3): for i in (0, 1, 2, 3):
self.s.talon.dealRow(frames=0) self.s.talon.dealRow(frames=0)
self.s.talon.dealRow(flip=0, frames=0) self.s.talon.dealRow(flip=0, frames=0)
self.startDealSample() self.startDealSample()
@ -1078,6 +1096,7 @@ class IndianPatience_RowStack(BO_RowStack):
return len(self.cards) != 1 return len(self.cards) != 1
return True return True
class IndianPatience(Indian): class IndianPatience(Indian):
RowStack_Class = IndianPatience_RowStack RowStack_Class = IndianPatience_RowStack
@ -1118,7 +1137,7 @@ class Floradora(Game):
l.createText(s.waste, 's') l.createText(s.waste, 's')
x += l.XS x += l.XS
for i in range(8): for i in range(8):
s.foundations.append(SS_FoundationStack(x, y, self, suit=i%4, s.foundations.append(SS_FoundationStack(x, y, self, suit=i % 4,
max_cards=12)) max_cards=12))
x += l.XS x += l.XS
x, y = l.XM, l.YM+l.YS+l.TEXT_HEIGHT x, y = l.XM, l.YM+l.YS+l.TEXT_HEIGHT
@ -1149,7 +1168,8 @@ class BlindPatience_Hint(DefaultHint):
SCORE_FLIP = 80000 SCORE_FLIP = 80000
def shallMovePile(self, from_stack, to_stack, pile, rpile): def shallMovePile(self, from_stack, to_stack, pile, rpile):
if from_stack is to_stack or not to_stack.acceptsCards(from_stack, pile): if from_stack is to_stack or \
not to_stack.acceptsCards(from_stack, pile):
return False return False
# #
if len(rpile) == 0: if len(rpile) == 0:
@ -1224,12 +1244,12 @@ class BlindPatience(FortyThieves):
class Foothold(FortyThieves): class Foothold(FortyThieves):
RowStack_Class = UD_AC_RowStack RowStack_Class = UD_AC_RowStack
DEAL = (0, 5) DEAL = (0, 5)
def createGame(self): def createGame(self):
FortyThieves.createGame(self, rows=8, playcards=16) FortyThieves.createGame(self, rows=8, playcards=16)
shallHighlightMatch = Game._shallHighlightMatch_AC shallHighlightMatch = Game._shallHighlightMatch_AC
# register the game # register the game
registerGame(GameInfo(13, FortyThieves, "Forty Thieves", registerGame(GameInfo(13, FortyThieves, "Forty Thieves",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_SKILL, GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_SKILL,
@ -1259,14 +1279,15 @@ registerGame(GameInfo(76, Streets, "Streets",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(73, Maria, "Maria", registerGame(GameInfo(73, Maria, "Maria",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED, GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED,
altnames=("Maria Luisa",) )) altnames=("Maria Luisa",)))
registerGame(GameInfo(70, NumberTen, "Number Ten", registerGame(GameInfo(70, NumberTen, "Number Ten",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED)) GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(71, RankAndFile, "Rank and File", registerGame(GameInfo(71, RankAndFile, "Rank and File",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED, GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED,
altnames=("Dress Parade") )) altnames=("Dress Parade")))
registerGame(GameInfo(197, TripleLine, "Triple Line", registerGame(GameInfo(197, TripleLine, "Triple Line",
GI.GT_FORTY_THIEVES | GI.GT_XORIGINAL, 2, 1, GI.SL_BALANCED)) GI.GT_FORTY_THIEVES | GI.GT_XORIGINAL, 2, 1,
GI.SL_BALANCED))
registerGame(GameInfo(126, RedAndBlack, "Red and Black", # was: 75 registerGame(GameInfo(126, RedAndBlack, "Red and Black", # was: 75
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED)) GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(113, Zebra, "Zebra", registerGame(GameInfo(113, Zebra, "Zebra",
@ -1276,7 +1297,8 @@ registerGame(GameInfo(69, Indian, "Indian",
registerGame(GameInfo(74, Midshipman, "Midshipman", registerGame(GameInfo(74, Midshipman, "Midshipman",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED)) GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(198, NapoleonsExile, "Napoleon's Exile", registerGame(GameInfo(198, NapoleonsExile, "Napoleon's Exile",
GI.GT_FORTY_THIEVES | GI.GT_XORIGINAL, 2, 0, GI.SL_BALANCED)) GI.GT_FORTY_THIEVES | GI.GT_XORIGINAL, 2, 0,
GI.SL_BALANCED))
registerGame(GameInfo(131, DoubleRail, "Double Rail", registerGame(GameInfo(131, DoubleRail, "Double Rail",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED)) GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(199, SingleRail, "Single Rail", registerGame(GameInfo(199, SingleRail, "Single Rail",
@ -1302,15 +1324,20 @@ registerGame(GameInfo(462, Josephine, "Josephine",
registerGame(GameInfo(493, MarieRose, "Marie Rose", registerGame(GameInfo(493, MarieRose, "Marie Rose",
GI.GT_FORTY_THIEVES, 3, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FORTY_THIEVES, 3, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(503, BigStreets, "Big Streets", registerGame(GameInfo(503, BigStreets, "Big Streets",
GI.GT_FORTY_THIEVES | GI.GT_ORIGINAL, 3, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FORTY_THIEVES | GI.GT_ORIGINAL, 3, 0,
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(504, NumberTwelve, "Number Twelve", registerGame(GameInfo(504, NumberTwelve, "Number Twelve",
GI.GT_FORTY_THIEVES | GI.GT_ORIGINAL, 3, 0, GI.SL_BALANCED)) GI.GT_FORTY_THIEVES | GI.GT_ORIGINAL, 3, 0,
GI.SL_BALANCED))
registerGame(GameInfo(505, BigCourtyard, "Big Courtyard", registerGame(GameInfo(505, BigCourtyard, "Big Courtyard",
GI.GT_FORTY_THIEVES | GI.GT_ORIGINAL, 3, 0, GI.SL_BALANCED)) GI.GT_FORTY_THIEVES | GI.GT_ORIGINAL, 3, 0,
GI.SL_BALANCED))
registerGame(GameInfo(506, Express, "Express", registerGame(GameInfo(506, Express, "Express",
GI.GT_FORTY_THIEVES | GI.GT_ORIGINAL, 3, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FORTY_THIEVES | GI.GT_ORIGINAL, 3, 0,
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(514, Carnation, "Carnation", registerGame(GameInfo(514, Carnation, "Carnation",
GI.GT_FORTY_THIEVES | GI.GT_ORIGINAL, 4, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FORTY_THIEVES | GI.GT_ORIGINAL, 4, 0,
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(528, FinalBattle, "Final Battle", registerGame(GameInfo(528, FinalBattle, "Final Battle",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED)) GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(529, SanJuanHill, "San Juan Hill", registerGame(GameInfo(529, SanJuanHill, "San Juan Hill",
@ -1319,11 +1346,12 @@ registerGame(GameInfo(540, Waterloo, "Waterloo",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED)) GI.GT_FORTY_THIEVES, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(556, Junction, "Junction", registerGame(GameInfo(556, Junction, "Junction",
GI.GT_FORTY_THIEVES, 4, 0, GI.SL_MOSTLY_SKILL, GI.GT_FORTY_THIEVES, 4, 0, GI.SL_MOSTLY_SKILL,
ranks=(0, 6, 7, 8, 9, 10, 11, 12) )) ranks=(0, 6, 7, 8, 9, 10, 11, 12)))
registerGame(GameInfo(564, TheSpark, "The Spark", registerGame(GameInfo(564, TheSpark, "The Spark",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_LUCK)) GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_LUCK))
registerGame(GameInfo(573, DoubleGoldMine, "Double Gold Mine", registerGame(GameInfo(573, DoubleGoldMine, "Double Gold Mine",
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(574, Interchange, "Interchange", registerGame(GameInfo(574, Interchange, "Interchange",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(575, Unlimited, "Unlimited", registerGame(GameInfo(575, Unlimited, "Unlimited",
@ -1349,5 +1377,5 @@ registerGame(GameInfo(683, FamousFifty, "Famous Fifty",
registerGame(GameInfo(751, BlindPatience, "Blind Patience", registerGame(GameInfo(751, BlindPatience, "Blind Patience",
GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FORTY_THIEVES, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(765, Foothold, "Foothold", registerGame(GameInfo(765, Foothold, "Foothold",
GI.GT_FORTY_THIEVES | GI.GT_ORIGINAL, 2, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FORTY_THIEVES | GI.GT_ORIGINAL, 2, 0,
GI.SL_MOSTLY_SKILL))

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,30 +19,47 @@
# 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.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 DefaultHint
from pysollib.hint import FreeCellType_Hint, FreeCellSolverWrapper from pysollib.hint import FreeCellType_Hint, FreeCellSolverWrapper
from spider import Spider_AC_Foundation from spider import Spider_AC_Foundation
from pysollib.util import ACE, ANY_SUIT, KING, NO_RANK, UNLIMITED_CARDS
from pysollib.stack import \
AC_FoundationStack, \
AC_RowStack, \
BasicRowStack, \
FreeCell_AC_RowStack, \
FreeCell_SS_RowStack, \
InitialDealTalonStack, \
KingAC_RowStack, \
OpenStack, \
RK_FoundationStack, \
ReserveStack, \
SS_FoundationStack, \
Stack, \
SuperMoveAC_RowStack, \
SuperMoveRK_RowStack, \
isAlternateColorSequence, \
StackWrapper
# ************************************************************************ # ************************************************************************
# * FreeCell # * FreeCell
# ************************************************************************ # ************************************************************************
class FreeCell(Game): class FreeCell(Game):
Layout_Method = Layout.freeCellLayout Layout_Method = Layout.freeCellLayout
Talon_Class = InitialDealTalonStack Talon_Class = InitialDealTalonStack
@ -52,7 +69,6 @@ class FreeCell(Game):
Hint_Class = FreeCellType_Hint Hint_Class = FreeCellType_Hint
Solver_Class = FreeCellSolverWrapper() Solver_Class = FreeCellSolverWrapper()
# #
# game layout # game layout
# #
@ -66,7 +82,8 @@ class FreeCell(Game):
# create stacks # create stacks
s.talon = self.Talon_Class(l.s.talon.x, l.s.talon.y, self) s.talon = self.Talon_Class(l.s.talon.x, l.s.talon.y, self)
for r in l.s.foundations: for r in l.s.foundations:
s.foundations.append(self.Foundation_Class(r.x, r.y, self, suit=r.suit)) s.foundations.append(
self.Foundation_Class(r.x, r.y, self, suit=r.suit))
for r in l.s.rows: for r in l.s.rows:
s.rows.append(self.RowStack_Class(r.x, r.y, self)) s.rows.append(self.RowStack_Class(r.x, r.y, self))
for r in l.s.reserves: for r in l.s.reserves:
@ -84,7 +101,7 @@ class FreeCell(Game):
self.startDealSample() self.startDealSample()
self.s.talon.dealRow() self.s.talon.dealRow()
r = self.s.rows r = self.s.rows
##self.s.talon.dealRow(rows=(r[0], r[2], r[4], r[6])) # self.s.talon.dealRow(rows=(r[0], r[2], r[4], r[6]))
self.s.talon.dealRow(rows=r[:4]) self.s.talon.dealRow(rows=r[:4])
shallHighlightMatch = Game._shallHighlightMatch_AC shallHighlightMatch = Game._shallHighlightMatch_AC
@ -123,8 +140,9 @@ class ForeCell(FreeCell):
class ChallengeFreeCell(FreeCell): class ChallengeFreeCell(FreeCell):
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
# move Aces and Twos to top of the Talon # move Aces and Twos to top of the Talon
return self._shuffleHookMoveToTop(cards, return self._shuffleHookMoveToTop(
lambda c: (c.rank in (ACE, 1), (-c.rank, c.suit))) cards, lambda c: (c.rank in (ACE, 1), (-c.rank, c.suit)))
class SuperChallengeFreeCell(ChallengeFreeCell): class SuperChallengeFreeCell(ChallengeFreeCell):
RowStack_Class = StackWrapper(FreeCell_AC_RowStack, base_rank=KING) RowStack_Class = StackWrapper(FreeCell_AC_RowStack, base_rank=KING)
@ -136,7 +154,8 @@ class SuperChallengeFreeCell(ChallengeFreeCell):
# ************************************************************************ # ************************************************************************
class Stalactites(FreeCell): class Stalactites(FreeCell):
Foundation_Class = StackWrapper(RK_FoundationStack, suit=ANY_SUIT, mod=13, min_cards=1) Foundation_Class = StackWrapper(
RK_FoundationStack, suit=ANY_SUIT, mod=13, min_cards=1)
RowStack_Class = StackWrapper(BasicRowStack, max_move=1, max_accept=0) RowStack_Class = StackWrapper(BasicRowStack, max_move=1, max_accept=0)
Solver_Class = None Solver_Class = None
@ -180,7 +199,9 @@ class DoubleFreecell(FreeCell):
s.talon = self.Talon_Class(l.XM, h-l.YS, self) s.talon = self.Talon_Class(l.XM, h-l.YS, self)
x, y = 3*l.XM + 6*l.XS, l.YM x, y = 3*l.XM + 6*l.XS, l.YM
for i in range(4): for i in range(4):
s.foundations.append(self.Foundation_Class(x, y, self, suit=i, mod=13, max_cards=26)) s.foundations.append(
self.Foundation_Class(
x, y, self, suit=i, mod=13, max_cards=26))
x += l.XS x += l.XS
x, y = 2*l.XM, l.YM + l.YS + l.YM x, y = 2*l.XM, l.YM + l.YS + l.YM
for i in range(10): for i in range(10):
@ -199,8 +220,8 @@ class DoubleFreecell(FreeCell):
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
# move 4 Aces to bottom of the Talon (i.e. last cards to be dealt) # move 4 Aces to bottom of the Talon (i.e. last cards to be dealt)
return self._shuffleHookMoveToBottom(cards, return self._shuffleHookMoveToBottom(
lambda c: (c.rank == ACE and c.deck == 0, c.suit)) cards, lambda c: (c.rank == ACE and c.deck == 0, c.suit))
def startGame(self): def startGame(self):
for i in range(9): for i in range(9):
@ -272,7 +293,7 @@ class Cell11(TripleFreecell):
self.s.talon.dealRow(frames=0) self.s.talon.dealRow(frames=0)
self.startDealSample() self.startDealSample()
self.s.talon.dealRow(rows=self.s.rows[1:-1]) self.s.talon.dealRow(rows=self.s.rows[1:-1])
self.s.talon.dealRow(rows=[self.s.reserves[0],self.s.reserves[-1]]) self.s.talon.dealRow(rows=[self.s.reserves[0], self.s.reserves[-1]])
class BigCell(TripleFreecell): class BigCell(TripleFreecell):
@ -297,6 +318,7 @@ class Spidercells_RowStack(SuperMoveAC_RowStack):
if len(cards) == 13 and isAlternateColorSequence(cards): if len(cards) == 13 and isAlternateColorSequence(cards):
return True return True
return SuperMoveAC_RowStack.canMoveCards(self, cards) return SuperMoveAC_RowStack.canMoveCards(self, cards)
def canDropCards(self, stacks): def canDropCards(self, stacks):
if len(self.cards) < 13: if len(self.cards) < 13:
return (None, 0) return (None, 0)
@ -322,7 +344,8 @@ class Spidercells(FreeCell):
# create stacks # create stacks
s.talon = self.Talon_Class(l.s.talon.x, l.s.talon.y, self) s.talon = self.Talon_Class(l.s.talon.x, l.s.talon.y, self)
for r in l.s.foundations: for r in l.s.foundations:
s.foundations.append(self.Foundation_Class(r.x, r.y, self, suit=ANY_SUIT)) s.foundations.append(
self.Foundation_Class(r.x, r.y, self, suit=ANY_SUIT))
for r in l.s.rows: for r in l.s.rows:
s.rows.append(self.RowStack_Class(r.x, r.y, self)) s.rows.append(self.RowStack_Class(r.x, r.y, self))
for r in l.s.reserves: for r in l.s.reserves:
@ -340,6 +363,7 @@ class Spidercells(FreeCell):
class SevenByFour(FreeCell): class SevenByFour(FreeCell):
def createGame(self): def createGame(self):
FreeCell.createGame(self, rows=7) FreeCell.createGame(self, rows=7)
def startGame(self): def startGame(self):
for i in range(6): for i in range(6):
self.s.talon.dealRow(frames=0) self.s.talon.dealRow(frames=0)
@ -347,15 +371,19 @@ class SevenByFour(FreeCell):
self.s.talon.dealRow() self.s.talon.dealRow()
self.s.talon.dealRow(rows=self.s.rows[:3]) self.s.talon.dealRow(rows=self.s.rows[:3])
class SevenByFive(SevenByFour): class SevenByFive(SevenByFour):
def createGame(self): def createGame(self):
FreeCell.createGame(self, rows=7, reserves=5) FreeCell.createGame(self, rows=7, reserves=5)
class Bath(FreeCell): class Bath(FreeCell):
Solver_Class = FreeCellSolverWrapper(esf='kings') Solver_Class = FreeCellSolverWrapper(esf='kings')
RowStack_Class = StackWrapper(SuperMoveAC_RowStack, base_rank=KING) RowStack_Class = StackWrapper(SuperMoveAC_RowStack, base_rank=KING)
def createGame(self): def createGame(self):
FreeCell.createGame(self, rows=10, reserves=2) FreeCell.createGame(self, rows=10, reserves=2)
def startGame(self): def startGame(self):
for i in range(6): for i in range(6):
self.s.talon.dealRow(rows=self.s.rows[i:], frames=0) self.s.talon.dealRow(rows=self.s.rows[i:], frames=0)
@ -405,8 +433,9 @@ class Clink(FreeCell):
def _shuffleHook(self, cards): def _shuffleHook(self, cards):
# move two Aces to bottom of the Talon (i.e. last cards to be dealt) # move two Aces to bottom of the Talon (i.e. last cards to be dealt)
return self._shuffleHookMoveToBottom(cards, return self._shuffleHookMoveToBottom(
lambda c: (c.rank == ACE and c.suit in (0, 2), (c.suit))) cards,
lambda c: (c.rank == ACE and c.suit in (0, 2), (c.suit)))
# ************************************************************************ # ************************************************************************
@ -436,6 +465,7 @@ class Repair(FreeCell):
class FourColours_RowStack(AC_RowStack): class FourColours_RowStack(AC_RowStack):
getBottomImage = Stack._getReserveBottomImage getBottomImage = Stack._getReserveBottomImage
class FourColours(FreeCell): class FourColours(FreeCell):
Solver_Class = None Solver_Class = None
RowStack_Class = AC_RowStack RowStack_Class = AC_RowStack
@ -543,7 +573,7 @@ class Headquarters(Game):
self.setSize(w, h) self.setSize(w, h)
x, y = l.XM+(rows+reserves+1-8)*l.XS/2, l.YM x, y = l.XM+(rows+reserves+1-8)*l.XS/2, l.YM
for i in range(8): for i in range(8):
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
x, y = l.XM, l.YM+l.YS x, y = l.XM, l.YM+l.YS
for i in range(reserves): for i in range(reserves):
@ -563,7 +593,6 @@ class Headquarters(Game):
l.defaultStackGroups() l.defaultStackGroups()
def startGame(self): def startGame(self):
for i in range(12): for i in range(12):
self.s.talon.dealRow(frames=0) self.s.talon.dealRow(frames=0)
@ -610,7 +639,7 @@ class Limpopo(Game):
# create stacks # create stacks
x, y = l.XM, l.YM+l.YS/2 x, y = l.XM, l.YM+l.YS/2
for i in (0,1): for i in (0, 1):
stack = ReserveStack(x, y, self, max_cards=4) stack = ReserveStack(x, y, self, max_cards=4)
s.reserves.append(stack) s.reserves.append(stack)
stack.CARD_YOFFSET = l.YOFFSET stack.CARD_YOFFSET = l.YOFFSET
@ -641,13 +670,16 @@ class Limpopo(Game):
shallHighlightMatch = Game._shallHighlightMatch_AC shallHighlightMatch = Game._shallHighlightMatch_AC
class PairFcFreeCell(FreeCell): class PairFcFreeCell(FreeCell):
def createGame(self): def createGame(self):
FreeCell.createGame(self, reserves=2) FreeCell.createGame(self, reserves=2)
# register the game # register the game
registerGame(GameInfo(5, RelaxedFreeCell, "Relaxed FreeCell", registerGame(GameInfo(5, RelaxedFreeCell, "Relaxed FreeCell",
GI.GT_FREECELL | GI.GT_RELAXED | GI.GT_OPEN, 1, 0, GI.SL_SKILL)) GI.GT_FREECELL | GI.GT_RELAXED | GI.GT_OPEN, 1, 0,
GI.SL_SKILL))
registerGame(GameInfo(8, FreeCell, "FreeCell", registerGame(GameInfo(8, FreeCell, "FreeCell",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_SKILL)) GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_SKILL))
registerGame(GameInfo(1900, PairFcFreeCell, "FreeCell with Two Reserves", registerGame(GameInfo(1900, PairFcFreeCell, "FreeCell with Two Reserves",
@ -656,7 +688,7 @@ registerGame(GameInfo(46, ForeCell, "ForeCell",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(77, Stalactites, "Stalactites", registerGame(GameInfo(77, Stalactites, "Stalactites",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL, GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL,
altnames=("Grampus", "Old Mole") )) altnames=("Grampus", "Old Mole")))
registerGame(GameInfo(264, DoubleFreecell, "Double FreeCell", registerGame(GameInfo(264, DoubleFreecell, "Double FreeCell",
GI.GT_FREECELL | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FREECELL | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(265, TripleFreecell, "Triple FreeCell", registerGame(GameInfo(265, TripleFreecell, "Triple FreeCell",
@ -675,7 +707,8 @@ registerGame(GameInfo(365, SevenByFive, "Seven by Five",
registerGame(GameInfo(383, Bath, "Bath", registerGame(GameInfo(383, Bath, "Bath",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_SKILL)) GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_SKILL))
registerGame(GameInfo(394, Clink, "Clink", registerGame(GameInfo(394, Clink, "Clink",
GI.GT_FREECELL | GI.GT_OPEN | GI.GT_ORIGINAL, 1, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FREECELL | GI.GT_OPEN | GI.GT_ORIGINAL, 1, 0,
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(448, Repair, "Repair", registerGame(GameInfo(448, Repair, "Repair",
GI.GT_FREECELL | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FREECELL | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(451, Cell11, "Cell 11", registerGame(GameInfo(451, Cell11, "Cell 11",
@ -683,17 +716,20 @@ registerGame(GameInfo(451, Cell11, "Cell 11",
registerGame(GameInfo(464, FourColours, "Four Colours", registerGame(GameInfo(464, FourColours, "Four Colours",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(509, BigCell, "Big Cell", registerGame(GameInfo(509, BigCell, "Big Cell",
GI.GT_FREECELL | GI.GT_OPEN | GI.GT_ORIGINAL, 3, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FREECELL | GI.GT_OPEN | GI.GT_ORIGINAL, 3, 0,
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(513, OceanTowers, "Ocean Towers", registerGame(GameInfo(513, OceanTowers, "Ocean Towers",
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(520, GermanFreeCell, "German FreeCell", registerGame(GameInfo(520, GermanFreeCell, "German FreeCell",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_SKILL)) GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_SKILL))
registerGame(GameInfo(542, KingCell, "KingCell", registerGame(GameInfo(542, KingCell, "KingCell",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(648, Headquarters, "Headquarters", registerGame(GameInfo(648, Headquarters, "Headquarters",
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(698, CanCan, "Can Can", registerGame(GameInfo(698, CanCan, "Can Can",
GI.GT_RAGLAN | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL)) GI.GT_RAGLAN | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(746, Limpopo, "Limpopo", registerGame(GameInfo(746, Limpopo, "Limpopo",
GI.GT_FREECELL | GI.GT_ORIGINAL, 2, 0, GI.SL_MOSTLY_SKILL)) GI.GT_FREECELL | GI.GT_ORIGINAL, 2, 0,
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-ey-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-fy-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." );