1
0
Fork 0
mirror of https://github.com/shlomif/PySolFC.git synced 2025-04-05 00:02:29 -04:00
PySolFC/pysollib/games/freecell.py
Shlomi Fish aa4f9ee5da Crude code to get some func running in py3.
Right now klondike and freecell sort of work, but this is very hacky and
there are many leftover debug traces.
2017-08-25 18:25:58 +03:00

736 lines
24 KiB
Python

#!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*-
# ---------------------------------------------------------------------------
#
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
# Copyright (C) 2003 Mt. Hood Playing Card Co.
# Copyright (C) 2005-2009 Skomoroh
#
# 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 3 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. If not, see <http://www.gnu.org/licenses/>.
#
# ---------------------------------------------------------------------------
__all__ = []
# imports
# PySol imports
from pysollib.gamedb import registerGame, GameInfo, GI
from pysollib.mfxutil import kwdefault
from pysollib.game import Game
from pysollib.layout import Layout
from pysollib.hint import DefaultHint
from pysollib.hint import FreeCellType_Hint, FreeCellSolverWrapper
from pysollib.games.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
# ************************************************************************
class FreeCell(Game):
Layout_Method = Layout.freeCellLayout
Talon_Class = InitialDealTalonStack
Foundation_Class = SS_FoundationStack
RowStack_Class = SuperMoveAC_RowStack
ReserveStack_Class = ReserveStack
Hint_Class = FreeCellType_Hint
Solver_Class = FreeCellSolverWrapper()
#
# game layout
#
def createGame(self, **layout):
# create layout
l, s = Layout(self), self.s
kwdefault(layout, rows=8, reserves=4, texts=0)
# self.Layout_Method(l, **layout)
self.__class__.__dict__['Layout_Method'](l, **layout)
self.setSize(l.size[0], l.size[1])
# create stacks
s.talon = self.Talon_Class(l.s.talon.x, l.s.talon.y, self)
for r in l.s.foundations:
s.foundations.append(
self.Foundation_Class(r.x, r.y, self, suit=r.suit))
for r in l.s.rows:
s.rows.append(self.RowStack_Class(r.x, r.y, self))
for r in l.s.reserves:
s.reserves.append(self.ReserveStack_Class(r.x, r.y, self))
# default
l.defaultAll()
#
# game overrides
#
def startGame(self):
for i in range(5):
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow()
r = self.s.rows
# self.s.talon.dealRow(rows=(r[0], r[2], r[4], r[6]))
self.s.talon.dealRow(rows=r[:4])
shallHighlightMatch = Game._shallHighlightMatch_AC
# ************************************************************************
# * Relaxed FreeCell
# ************************************************************************
class RelaxedFreeCell(FreeCell):
RowStack_Class = AC_RowStack
Solver_Class = FreeCellSolverWrapper(sm='unlimited')
# ************************************************************************
# * ForeCell
# ************************************************************************
class ForeCell(FreeCell):
RowStack_Class = StackWrapper(FreeCell_AC_RowStack, base_rank=KING)
Solver_Class = FreeCellSolverWrapper(esf='kings')
def startGame(self):
for i in range(5):
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow()
self.s.talon.dealRow(rows=self.s.reserves)
# ************************************************************************
# * Challenge FreeCell
# * Super Challenge FreeCell
# ************************************************************************
class ChallengeFreeCell(FreeCell):
def _shuffleHook(self, cards):
# move Aces and Twos to top of the Talon
return self._shuffleHookMoveToTop(
cards, lambda c: (c.rank in (ACE, 1), (-c.rank, c.suit)))
class SuperChallengeFreeCell(ChallengeFreeCell):
RowStack_Class = StackWrapper(FreeCell_AC_RowStack, base_rank=KING)
Solver_Class = FreeCellSolverWrapper(esf='kings')
# ************************************************************************
# * Stalactites
# ************************************************************************
class Stalactites(FreeCell):
Foundation_Class = StackWrapper(
RK_FoundationStack, suit=ANY_SUIT, mod=13, min_cards=1)
RowStack_Class = StackWrapper(BasicRowStack, max_move=1, max_accept=0)
Solver_Class = None
def createGame(self):
FreeCell.createGame(self, reserves=2)
def startGame(self):
for i in range(5):
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow()
self.s.talon.dealRow(rows=self.s.foundations)
self._restoreGameHook(None)
def _restoreGameHook(self, game):
for s in self.s.foundations:
s.cap.base_rank = s.cards[0].rank
# ************************************************************************
# * Double Freecell
# ************************************************************************
class DoubleFreecell(FreeCell):
Solver_Class = None
#
# game layout
#
def createGame(self):
# create layout
l, s = Layout(self), self.s
# set window
w, h = 3*l.XM+10*l.XS, 2*l.YM+2*l.YS+16*l.YOFFSET
self.setSize(w, h)
# create stacks
s.talon = self.Talon_Class(l.XM, h-l.YS, self)
x, y = 3*l.XM + 6*l.XS, l.YM
for i in range(4):
s.foundations.append(
self.Foundation_Class(
x, y, self, suit=i, mod=13, max_cards=26))
x += l.XS
x, y = 2*l.XM, l.YM + l.YS + l.YM
for i in range(10):
s.rows.append(self.RowStack_Class(x, y, self))
x += l.XS
x, y = l.XM, l.YM
for i in range(6):
s.reserves.append(ReserveStack(x, y, self))
x += l.XS
# default
l.defaultAll()
#
# game overrides
#
def _shuffleHook(self, cards):
# move 4 Aces to bottom of the Talon (i.e. last cards to be dealt)
return self._shuffleHookMoveToBottom(
cards, lambda c: (c.rank == ACE and c.deck == 0, c.suit))
def startGame(self):
for i in range(9):
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow()
self.s.talon.dealRow(rows=self.s.foundations)
# ************************************************************************
# * Triple Freecell
# ************************************************************************
class TripleFreecell(FreeCell):
Solver_Class = None
#
# game layout
#
def createGame(self, rows=13, reserves=10, playcards=20):
# create layout
l, s = Layout(self), self.s
# set window
decks = self.gameinfo.decks
max_rows = max(decks*4, rows, reserves)
w, h = l.XM+max_rows*l.XS, l.YM+3*l.YS+playcards*l.YOFFSET
self.setSize(w, h)
# create stacks
s.talon = self.Talon_Class(l.XM, h-l.YS, self)
x, y = l.XM+(max_rows-decks*4)*l.XS/2, l.YM
for j in range(4):
for i in range(decks):
s.foundations.append(self.Foundation_Class(x, y, self, suit=j))
x += l.XS
x, y = l.XM+(max_rows-reserves)*l.XS/2, l.YM+l.YS
for i in range(reserves):
s.reserves.append(ReserveStack(x, y, self))
x += l.XS
x, y = l.XM+(max_rows-rows)*l.XS/2, l.YM+2*l.YS
for i in range(rows):
s.rows.append(self.RowStack_Class(x, y, self))
x += l.XS
# default
l.defaultAll()
#
# game overrides
#
def startGame(self):
for i in range(11):
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow()
class Cell11(TripleFreecell):
def createGame(self):
TripleFreecell.createGame(self, rows=12, reserves=11)
def startGame(self):
for i in range(12):
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow(rows=self.s.rows[1:-1])
self.s.talon.dealRow(rows=[self.s.reserves[0], self.s.reserves[-1]])
class BigCell(TripleFreecell):
RowStack_Class = AC_RowStack
def createGame(self):
TripleFreecell.createGame(self, rows=13, reserves=4)
def startGame(self):
for i in range(11):
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow()
# ************************************************************************
# * Spidercells
# ************************************************************************
class Spidercells_RowStack(SuperMoveAC_RowStack):
def canMoveCards(self, cards):
if len(cards) == 13 and isAlternateColorSequence(cards):
return True
return SuperMoveAC_RowStack.canMoveCards(self, cards)
def canDropCards(self, stacks):
if len(self.cards) < 13:
return (None, 0)
cards = self.cards[-13:]
for s in stacks:
if s is not self and s.acceptsCards(self, cards):
return (s, 13)
return (None, 0)
class Spidercells(FreeCell):
Solver_Class = None
Foundation_Class = Spider_AC_Foundation
RowStack_Class = Spidercells_RowStack
def createGame(self, **layout):
# create layout
l, s = Layout(self), self.s
kwdefault(layout, rows=8, reserves=4, texts=0)
self.Layout_Method(l, **layout)
self.setSize(l.size[0], l.size[1])
# create stacks
s.talon = self.Talon_Class(l.s.talon.x, l.s.talon.y, self)
for r in l.s.foundations:
s.foundations.append(
self.Foundation_Class(r.x, r.y, self, suit=ANY_SUIT))
for r in l.s.rows:
s.rows.append(self.RowStack_Class(r.x, r.y, self))
for r in l.s.reserves:
s.reserves.append(ReserveStack(r.x, r.y, self))
# default
l.defaultAll()
# ************************************************************************
# * Seven by Four
# * Seven by Five
# * Bath
# ************************************************************************
class SevenByFour(FreeCell):
def createGame(self):
FreeCell.createGame(self, rows=7)
def startGame(self):
for i in range(6):
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow()
self.s.talon.dealRow(rows=self.s.rows[:3])
class SevenByFive(SevenByFour):
def createGame(self):
FreeCell.createGame(self, rows=7, reserves=5)
class Bath(FreeCell):
Solver_Class = FreeCellSolverWrapper(esf='kings')
RowStack_Class = StackWrapper(SuperMoveAC_RowStack, base_rank=KING)
def createGame(self):
FreeCell.createGame(self, rows=10, reserves=2)
def startGame(self):
for i in range(6):
self.s.talon.dealRow(rows=self.s.rows[i:], frames=0)
self.startDealSample()
self.s.talon.dealRow(rows=self.s.rows[6:])
self.s.talon.dealRow(rows=self.s.rows[7:])
# ************************************************************************
# * Clink
# ************************************************************************
class Clink(FreeCell):
Solver_Class = None
def createGame(self):
# create layout
l, s = Layout(self), self.s
self.setSize(l.XM+8*l.XS, l.YM+2*l.YS+12*l.YOFFSET)
# create stacks
x, y = l.XM, self.height-l.YS
s.talon = InitialDealTalonStack(x, y, self)
x, y = l.XM+l.XS, l.YM
for i in range(2):
s.reserves.append(ReserveStack(x, y, self))
x += l.XS
x += 2*l.XS
for i in range(2):
s.foundations.append(AC_FoundationStack(x, y, self, suit=ANY_SUIT,
max_cards=26, mod=13, max_move=0))
x += l.XS
x, y = l.XM, l.YM+l.YS
for i in range(8):
s.rows.append(AC_RowStack(x, y, self))
x += l.XS
# default
l.defaultAll()
def startGame(self):
for i in range(4):
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow()
self.s.talon.dealRow()
self.s.talon.dealRow(rows=self.s.reserves)
self.s.talon.dealRow(rows=self.s.foundations)
def _shuffleHook(self, cards):
# move two Aces to bottom of the Talon (i.e. last cards to be dealt)
return self._shuffleHookMoveToBottom(
cards,
lambda c: (c.rank == ACE and c.suit in (0, 2), (c.suit)))
# ************************************************************************
# * Repair
# ************************************************************************
class Repair(FreeCell):
Solver_Class = FreeCellSolverWrapper(sm='unlimited')
RowStack_Class = AC_RowStack
def createGame(self):
FreeCell.createGame(self, rows=10, reserves=4, playcards=26)
def startGame(self):
for i in range(9):
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow()
self.s.talon.dealRow(rows=self.s.reserves)
# ************************************************************************
# * Four Colours
# * German FreeCell
# ************************************************************************
class FourColours_RowStack(AC_RowStack):
getBottomImage = Stack._getReserveBottomImage
class FourColours(FreeCell):
Solver_Class = None
RowStack_Class = AC_RowStack
def createGame(self):
# create layout
l, s = Layout(self), self.s
self.setSize(l.XM+9*l.XS, l.YM+2*l.YS+12*l.YOFFSET)
# create stacks
x, y = self.width-l.XS, self.height-l.YS
s.talon = InitialDealTalonStack(x, y, self)
x, y = l.XM, l.YM
for i in range(4):
s.reserves.append(ReserveStack(x, y, self, base_suit=i))
x += l.XS
x += l.XS
for i in range(4):
s.foundations.append(SS_FoundationStack(x, y, self, suit=i))
x += l.XS
x, y = l.XM, l.YM+l.YS
for i in range(7):
s.rows.append(FourColours_RowStack(x, y, self))
x += l.XS
# default
l.defaultAll()
def dealOne(self, frames):
suit = self.s.talon.cards[-1].suit
self.s.talon.dealRow(rows=[self.s.rows[suit]], frames=frames)
def startGame(self):
for i in range(40):
self.dealOne(frames=0)
self.startDealSample()
while self.s.talon.cards:
self.dealOne(frames=-1)
class GermanFreeCell_Reserve(ReserveStack):
getBottomImage = Stack._getSuitBottomImage
class GermanFreeCell(SevenByFour):
Solver_Class = None
RowStack_Class = AC_RowStack
ReserveStack_Class = GermanFreeCell_Reserve
def createGame(self):
FreeCell.createGame(self, rows=7)
suit = 0
for r in self.s.reserves:
r.cap.base_suit = suit
suit += 1
# ************************************************************************
# * Ocean Towers
# ************************************************************************
class OceanTowers(TripleFreecell):
Solver_Class = FreeCellSolverWrapper(esf='kings', sbb='suit')
RowStack_Class = StackWrapper(FreeCell_SS_RowStack, base_rank=KING)
def createGame(self):
TripleFreecell.createGame(self, rows=14, reserves=8, playcards=20)
def startGame(self):
for i in range(6):
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow()
self.s.talon.dealRow(rows=self.s.reserves[1:-1])
shallHighlightMatch = Game._shallHighlightMatch_SS
# ************************************************************************
# * KingCell
# ************************************************************************
class KingCell(FreeCell):
Solver_Class = FreeCellSolverWrapper(sbb='rank', esf='kings')
RowStack_Class = StackWrapper(SuperMoveRK_RowStack, base_rank=KING)
shallHighlightMatch = Game._shallHighlightMatch_RK
# ************************************************************************
# * Headquarters
# ************************************************************************
class Headquarters_Reserve(ReserveStack):
def acceptsCards(self, from_stack, cards):
if not ReserveStack.acceptsCards(self, from_stack, cards):
return False
return len(self.cards) == 0
class Headquarters(Game):
def createGame(self, rows=8, reserves=6):
l, s = Layout(self), self.s
w, h = l.XM+(rows+reserves+1)*l.XS, l.YM+3*l.YS+16*l.YOFFSET
self.setSize(w, h)
x, y = l.XM+(rows+reserves+1-8)*l.XS/2, l.YM
for i in range(8):
s.foundations.append(SS_FoundationStack(x, y, self, suit=i % 4))
x += l.XS
x, y = l.XM, l.YM+l.YS
for i in range(reserves):
stack = Headquarters_Reserve(x, y, self,
max_cards=UNLIMITED_CARDS,
max_accept=UNLIMITED_CARDS,
max_move=UNLIMITED_CARDS)
s.reserves.append(stack)
stack.CARD_YOFFSET = l.YOFFSET
x += l.XS
x, y = l.XM+(reserves+1)*l.XS, l.YM+l.YS
for j in range(rows):
s.rows.append(AC_RowStack(x, y, self, base_rank=NO_RANK))
x += l.XS
x, y = w-l.XS, h-l.YS
s.talon = InitialDealTalonStack(x, y, self)
l.defaultStackGroups()
def startGame(self):
for i in range(12):
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow()
shallHighlightMatch = Game._shallHighlightMatch_AC
# ************************************************************************
# * Can Can
# ************************************************************************
class CanCan(FreeCell):
Hint_Class = DefaultHint
Solver_Class = None
RowStack_Class = KingAC_RowStack
ReserveStack_Class = StackWrapper(OpenStack, max_accept=0)
def createGame(self):
FreeCell.createGame(self, rows=13, reserves=3)
def startGame(self):
for i in range(3):
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow(rows=self.s.reserves)
self.s.talon.dealRowAvail()
# ************************************************************************
# * Limpopo
# ************************************************************************
class Limpopo(Game):
def createGame(self):
# create layout
l, s = Layout(self), self.s
# set window
self.setSize(l.XM+10.5*l.XS, l.YM+2*l.YS+20*l.YOFFSET)
# create stacks
x, y = l.XM, l.YM+l.YS/2
for i in (0, 1):
stack = ReserveStack(x, y, self, max_cards=4)
s.reserves.append(stack)
stack.CARD_YOFFSET = l.YOFFSET
l.createText(stack, 'n')
x += l.XS
x, y = l.XM+2.5*l.XS, l.YM
for i in range(8):
s.foundations.append(SS_FoundationStack(x, y, self, suit=i/2))
x += l.XS
x, y = l.XM+2.5*l.XS, l.YM+l.YS
for i in range(8):
s.rows.append(AC_RowStack(x, y, self))
x += l.XS
x, y = l.XM, self.height-l.YS
s.talon = InitialDealTalonStack(x, y, self)
# define stack-groups
l.defaultStackGroups()
def startGame(self):
for i in range(12):
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow()
shallHighlightMatch = Game._shallHighlightMatch_AC
class PairFcFreeCell(FreeCell):
def createGame(self):
FreeCell.createGame(self, reserves=2)
# register the game
registerGame(GameInfo(5, RelaxedFreeCell, "Relaxed FreeCell",
GI.GT_FREECELL | GI.GT_RELAXED | GI.GT_OPEN, 1, 0,
GI.SL_SKILL))
registerGame(GameInfo(8, FreeCell, "FreeCell",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_SKILL))
registerGame(GameInfo(1900, PairFcFreeCell, "FreeCell with Two Reserves",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_SKILL))
registerGame(GameInfo(46, ForeCell, "ForeCell",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(77, Stalactites, "Stalactites",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL,
altnames=("Grampus", "Old Mole")))
registerGame(GameInfo(264, DoubleFreecell, "Double FreeCell",
GI.GT_FREECELL | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(265, TripleFreecell, "Triple FreeCell",
GI.GT_FREECELL | GI.GT_OPEN, 3, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(336, ChallengeFreeCell, "Challenge FreeCell",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_SKILL,
rules_filename='freecell.html'))
registerGame(GameInfo(337, SuperChallengeFreeCell, "Super Challenge FreeCell",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_SKILL))
registerGame(GameInfo(363, Spidercells, "Spidercells",
GI.GT_SPIDER | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(364, SevenByFour, "Seven by Four",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_SKILL))
registerGame(GameInfo(365, SevenByFive, "Seven by Five",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_SKILL))
registerGame(GameInfo(383, Bath, "Bath",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_SKILL))
registerGame(GameInfo(394, Clink, "Clink",
GI.GT_FREECELL | GI.GT_OPEN | GI.GT_ORIGINAL, 1, 0,
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(448, Repair, "Repair",
GI.GT_FREECELL | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(451, Cell11, "Cell 11",
GI.GT_FREECELL | GI.GT_OPEN, 3, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(464, FourColours, "Four Colours",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(509, BigCell, "Big Cell",
GI.GT_FREECELL | GI.GT_OPEN | GI.GT_ORIGINAL, 3, 0,
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(513, OceanTowers, "Ocean Towers",
GI.GT_FREECELL | GI.GT_OPEN | GI.GT_ORIGINAL, 2, 0,
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(520, GermanFreeCell, "German FreeCell",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_SKILL))
registerGame(GameInfo(542, KingCell, "KingCell",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(648, Headquarters, "Headquarters",
GI.GT_FREECELL | GI.GT_OPEN | GI.GT_ORIGINAL, 2, 0,
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(698, CanCan, "Can Can",
GI.GT_RAGLAN | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(746, Limpopo, "Limpopo",
GI.GT_FREECELL | GI.GT_ORIGINAL, 2, 0,
GI.SL_MOSTLY_SKILL))