1
0
Fork 0
mirror of https://github.com/shlomif/PySolFC.git synced 2025-04-05 00:02:29 -04:00

Added Knockout and Herz zu Herz games.

This commit is contained in:
Joe R 2022-01-08 12:57:28 -05:00
parent 052fd0b78d
commit be097063ef
5 changed files with 227 additions and 1 deletions

View file

@ -0,0 +1,13 @@
<h1>Herz zu Herz</h1>
<p>
One deck type. 1 stripped deck. 2 redeals.
<h3>Object</h3>
<p>
Move all the hearts to the foundation.
<h3>Quick Description</h3>
<p>
Like <a href="knockout.html">Knockout</a>,
but hearts are moved to the foundation, and cards
moved to the foundation are not filled.

View file

@ -0,0 +1,22 @@
<h1>Knockout</h1>
<p>
One deck type. 1 stripped deck. 2 redeals.
<h3>Object</h3>
<p>
Move all the clubs to the foundation.
<h3>Rules</h3>
<p>Knockout is played with a deck of only 32 cards, including the
7 through ace of each suit.
<p>
Cards are dealt three at a time from the talon to three tableau
piles. Any clubs can be moved to the foundation. When a card is
moved to the foundation, another card is dealt from the talon to
replace it.
<p>
After dealing five sets of cards from the talon, shuffle the
tableau piles with the remainder of the talon, to create a new
talon before continuing. This can be done a max of twice.
<p>
The game is won if all the clubs have been moved to the foundation.

View file

@ -528,7 +528,7 @@ class GI:
('fc-2.12', tuple(range(774, 811)) + (16681,) +
tuple(range(22217, 22219))),
('fc-2.14', tuple(range(811, 827))),
('fc-2.16', tuple(range(827, 850)) + tuple(range(22400, 22407)))
('fc-2.16', tuple(range(827, 852)) + tuple(range(22400, 22407)))
)
# deprecated - the correct way is to or a GI.GT_XXX flag

View file

@ -56,6 +56,7 @@ from . import headsandtails # noqa: F401
from . import hitormiss # noqa: F401
from . import katzenschwanz # noqa: F401
from . import klondike # noqa: F401
from . import knockout # noqa: F401
from . import labyrinth # noqa: F401
from . import larasgame # noqa: F401
from . import matriarchy # noqa: F401

190
pysollib/games/knockout.py Normal file
View file

@ -0,0 +1,190 @@
#!/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/>.
#
# ---------------------------------------------------------------------------
from pysollib.game import Game
from pysollib.gamedb import GI, GameInfo, registerGame
from pysollib.layout import Layout
from pysollib.pysoltk import MfxCanvasText
from pysollib.stack import \
AbstractFoundationStack, \
BasicRowStack, \
DealRowTalonStack
from pysollib.util import ANY_RANK, CLUB, HEART
# ************************************************************************
# * Knockout
# ************************************************************************
class Knockout_Talon(DealRowTalonStack):
def dealCards(self, sound=False):
game = self.game
if game.cards_dealt == game.DEALS_BEFORE_SHUFFLE:
if self.round < self.max_rounds:
old_state = game.enterState(game.S_FILL)
game.saveStateMove(2 | 16) # for undo
self.game.cards_dealt = 0
game.saveStateMove(1 | 16) # for redo
game.leaveState(old_state)
self.redealCards()
else:
return False
old_state = game.enterState(game.S_FILL)
game.saveStateMove(2 | 16) # for undo
self.game.cards_dealt += 1
game.saveStateMove(1 | 16) # for redo
game.leaveState(old_state)
return DealRowTalonStack.dealCards(self, sound)
def canFlipCard(self):
return False
def redealCards(self):
for r in self.game.s.rows:
if r.cards:
while r.cards:
self.game.moveMove(1, r, self, frames=4)
if self.cards[-1].face_up:
self.game.flipMove(self)
assert self.round != self.max_rounds
self.game.shuffleStackMove(self)
self.game.nextRoundMove(self)
class Knockout_Foundation(AbstractFoundationStack):
def acceptsCards(self, from_stack, cards):
return cards[0].suit == self.cap.suit
class Knockout(Game):
FOUNDATION_SUIT = CLUB
DEALS_BEFORE_SHUFFLE = 5
cards_dealt = 0
def createGame(self, rows=3):
# create layout
l, s = Layout(self), self.s
# set window
# (piles up to 4 cards are playable in default window size)
h = max((2 * l.YS) + l.TEXT_HEIGHT, (4 * l.YOFFSET))
self.setSize(l.XM + (1.5 + rows) * l.XS + l.XM, l.YM + h)
# create stacks
x0 = l.XM + (l.XS * 1.5)
x = x0
y = l.YM
font = self.app.getFont("canvas_default")
for i in range(rows):
stack = BasicRowStack(x, y, self, max_cards=5,
max_accept=0, max_move=1)
if self.preview <= 1:
tx, ty, ta, tf = l.getTextAttr(stack, anchor="n")
stack.texts.misc = MfxCanvasText(self.canvas,
tx, ty,
anchor=ta,
font=font)
s.rows.append(stack)
x = x + l.XS
self.setRegion(s.rows, (x0-l.XS//2, y-l.CH//2, 999999, 999999))
x, y = l.XM, l.YM
s.talon = Knockout_Talon(x, y, self, max_rounds=3)
l.createText(s.talon, 'ne')
l.createRoundText(s.talon, 's')
y = y + l.YS + l.TEXT_HEIGHT
s.foundations.append(Knockout_Foundation(x, y, self, max_move=0,
base_rank=ANY_RANK,
suit=self.FOUNDATION_SUIT))
l.createText(s.foundations[0], 'se')
# define stack-groups
l.defaultStackGroups()
return l
def isGameWon(self):
return len(self.s.foundations[0].cards) == self.gameinfo.ncards / 4
#
# game overrides
#
def startGame(self):
self.cards_dealt = 0
self.startDealSample()
self.s.talon.dealCards()
shallHighlightMatch = Game._shallHighlightMatch_SS
def fillStack(self, stack):
if stack in self.s.rows:
old_state = self.enterState(self.S_FILL)
if not self.s.talon.cards[-1].face_up:
self.s.talon.flipMove()
self.s.talon.moveMove(1, stack, 4)
self.leaveState(old_state)
def _restoreGameHook(self, game):
self.cards_dealt = game.loadinfo.cards_dealt
def _loadGameHook(self, p):
self.loadinfo.addattr(cards_dealt=p.load())
def _saveGameHook(self, p):
p.dump(self.cards_dealt)
def getHighlightPilesStacks(self):
return ()
def setState(self, state):
# restore saved vars (from undo/redo)
self.cards_dealt = state[0]
def getState(self):
# save vars (for undo/redo)
return [self.cards_dealt]
# ************************************************************************
# * Herz zu Herz
# ************************************************************************
class HerzZuHerz(Knockout):
FOUNDATION_SUIT = HEART
def fillStack(self, stack):
pass
# register the game
registerGame(GameInfo(850, Knockout, "Knockout",
GI.GT_1DECK_TYPE | GI.GT_STRIPPED, 1, 2, GI.SL_LUCK,
altnames=("Hope Deferred",),
ranks=(0, 6, 7, 8, 9, 10, 11, 12)))
registerGame(GameInfo(851, HerzZuHerz, "Herz zu Herz",
GI.GT_1DECK_TYPE | GI.GT_STRIPPED, 1, 2, GI.SL_LUCK,
ranks=(0, 6, 7, 8, 9, 10, 11, 12)))