mirror of
https://github.com/shlomif/PySolFC.git
synced 2025-04-05 00:02:29 -04:00
Added Ricochet game.
This commit is contained in:
parent
7dd94e551c
commit
55d5111fb4
3 changed files with 223 additions and 1 deletions
29
html-src/rules/ricochet.html
Normal file
29
html-src/rules/ricochet.html
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<h1>Ricochet</h1>
|
||||||
|
<p>
|
||||||
|
Golf type. 1 deck. No redeal.
|
||||||
|
|
||||||
|
<h3>Object</h3>
|
||||||
|
Remove all cards from the tableau.
|
||||||
|
|
||||||
|
<h3>Rules</h3>
|
||||||
|
<p>
|
||||||
|
The tableau piles are built in four pyramid-esque "walls", with each
|
||||||
|
wall having four cards in the top layer, three in the middle, and two
|
||||||
|
in the bottom. One wall is facing in each direction, and the cards
|
||||||
|
on the edge of the top layer are shared between the adjoining walls.
|
||||||
|
The tableau and foundation are placed in the center of the four
|
||||||
|
walls.
|
||||||
|
<p>
|
||||||
|
Cards can be dealt from the tableau one at a time. Exposed cards from
|
||||||
|
the walls can be moved from the tableau if they are one rank higher or
|
||||||
|
lower than the card currently on the foundation. Turning the corner is
|
||||||
|
allowed, so kings can be played on aces, and vice versa. After a card
|
||||||
|
is played, the next card cannot be played from the same wall. The cards
|
||||||
|
in the corners are treated as part of both walls they overlap.
|
||||||
|
<p>
|
||||||
|
The game is won if all cards are removed from the tableau.
|
||||||
|
|
||||||
|
<h3>Notes</h3>
|
||||||
|
<p>
|
||||||
|
Ricochet was invented by Bram Tebbutt. More details can be found on
|
||||||
|
<a href="https://www.riffleshuffleandroll.com/ricochet">his website</a>.
|
|
@ -487,6 +487,7 @@ class GI:
|
||||||
("John Stoneham", (201,)),
|
("John Stoneham", (201,)),
|
||||||
("Bryan Stout", (655,)),
|
("Bryan Stout", (655,)),
|
||||||
("Bill Taylor", (349,)),
|
("Bill Taylor", (349,)),
|
||||||
|
("Bram Tebbutt", (924,)),
|
||||||
("Peter Voke", (876,)),
|
("Peter Voke", (876,)),
|
||||||
("Thomas Warfield", (189, 264, 300, 320, 336, 337, 359,
|
("Thomas Warfield", (189, 264, 300, 320, 336, 337, 359,
|
||||||
415, 427, 458, 495, 496, 497, 508,
|
415, 427, 458, 495, 496, 497, 508,
|
||||||
|
@ -575,7 +576,7 @@ class GI:
|
||||||
('fc-2.20', tuple(range(855, 897))),
|
('fc-2.20', tuple(range(855, 897))),
|
||||||
('fc-2.21', tuple(range(897, 900)) + tuple(range(11014, 11017)) +
|
('fc-2.21', tuple(range(897, 900)) + tuple(range(11014, 11017)) +
|
||||||
tuple(range(13160, 13163)) + (16682,)),
|
tuple(range(13160, 13163)) + (16682,)),
|
||||||
('dev', tuple(range(906, 924)) + tuple(range(11017, 11020)) +
|
('dev', tuple(range(906, 925)) + tuple(range(11017, 11020)) +
|
||||||
tuple(range(22303, 22311)) + tuple(range(22353, 22361))),
|
tuple(range(22303, 22311)) + tuple(range(22353, 22361))),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -284,6 +284,196 @@ class ThreePeaksOpenScored(ThreePeaks):
|
||||||
ThreePeaks.startGame(self, flip=1)
|
ThreePeaks.startGame(self, flip=1)
|
||||||
|
|
||||||
|
|
||||||
|
# ************************************************************************
|
||||||
|
# * Ricochet
|
||||||
|
# ************************************************************************
|
||||||
|
|
||||||
|
class Ricochet_Talon(ThreePeaks_TalonStack):
|
||||||
|
def dealCards(self, sound=False):
|
||||||
|
old_state = self.game.enterState(self.game.S_FILL)
|
||||||
|
self.game.saveStateMove(2 | 16) # for undo
|
||||||
|
self.game.lastStack = -1
|
||||||
|
self.game.saveStateMove(1 | 16) # for redo
|
||||||
|
self.game.leaveState(old_state)
|
||||||
|
ThreePeaks_TalonStack.dealCards(self, sound)
|
||||||
|
|
||||||
|
|
||||||
|
class Ricochet_Waste(Golf_Waste):
|
||||||
|
def acceptsCards(self, from_stack, cards):
|
||||||
|
for wall in self.game.walls:
|
||||||
|
if self.game.lastStack in wall and from_stack.id in wall:
|
||||||
|
return False
|
||||||
|
return Golf_Waste.acceptsCards(self, from_stack, cards)
|
||||||
|
|
||||||
|
|
||||||
|
class Ricochet_RowStack(ThreePeaks_RowStack):
|
||||||
|
|
||||||
|
def basicIsBlocked(self):
|
||||||
|
r = self.game.s.rows
|
||||||
|
step = (8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12,
|
||||||
|
12, 12, 12, 12, 12, 12)
|
||||||
|
i = self.id
|
||||||
|
while i < 20:
|
||||||
|
i = i + step[i]
|
||||||
|
for j in range(2):
|
||||||
|
d = i + j
|
||||||
|
if d > 31:
|
||||||
|
d = 20
|
||||||
|
if r[d].cards:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def clickHandler(self, event):
|
||||||
|
result = OpenStack.doubleclickHandler(self, event)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def moveMove(self, ncards, to_stack, frames=-1, shadow=-1):
|
||||||
|
x = OpenStack.moveMove(self, ncards, to_stack, frames, shadow)
|
||||||
|
old_state = self.game.enterState(self.game.S_FILL)
|
||||||
|
self.game.saveStateMove(2 | 16) # for undo
|
||||||
|
self.game.lastStack = self.id
|
||||||
|
self.game.saveStateMove(1 | 16) # for redo
|
||||||
|
self.game.leaveState(old_state)
|
||||||
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
class Ricochet(Game):
|
||||||
|
|
||||||
|
Waste_Class = StackWrapper(Ricochet_Waste, mod=13)
|
||||||
|
Hint_Class = Golf_Hint
|
||||||
|
|
||||||
|
#
|
||||||
|
# Game layout
|
||||||
|
#
|
||||||
|
|
||||||
|
def createGame(self):
|
||||||
|
# create layout
|
||||||
|
l, s = Layout(self), self.s
|
||||||
|
|
||||||
|
# set window
|
||||||
|
# compute best XOFFSET
|
||||||
|
xoffset = int(l.XS * 8 / self.gameinfo.ncards)
|
||||||
|
if xoffset < l.XOFFSET:
|
||||||
|
l.XOFFSET = xoffset
|
||||||
|
|
||||||
|
# Set window size
|
||||||
|
w, h = l.XM + l.XS * 6, l.YM + l.YS * 6
|
||||||
|
self.setSize(w, h)
|
||||||
|
self.lastStack = -1
|
||||||
|
self.walls = ((0, 1, 8, 9, 10, 20, 21, 22, 23),
|
||||||
|
(2, 3, 11, 12, 13, 23, 24, 25, 26),
|
||||||
|
(4, 5, 14, 15, 16, 26, 27, 28, 29),
|
||||||
|
(6, 7, 17, 18, 19, 29, 30, 31, 20))
|
||||||
|
|
||||||
|
# Create rows
|
||||||
|
x, y = l.XM + l.XS * 2, l.YM
|
||||||
|
|
||||||
|
s.rows.append(Ricochet_RowStack(x, y, self))
|
||||||
|
x += l.XS
|
||||||
|
s.rows.append(Ricochet_RowStack(x, y, self))
|
||||||
|
x += l.XS * 2
|
||||||
|
y += l.YS * 2
|
||||||
|
s.rows.append(Ricochet_RowStack(x, y, self))
|
||||||
|
y += l.YS
|
||||||
|
s.rows.append(Ricochet_RowStack(x, y, self))
|
||||||
|
x -= l.XS * 2
|
||||||
|
y += l.YS * 2
|
||||||
|
s.rows.append(Ricochet_RowStack(x, y, self))
|
||||||
|
x -= l.XS
|
||||||
|
s.rows.append(Ricochet_RowStack(x, y, self))
|
||||||
|
x -= l.XS * 2
|
||||||
|
y -= l.YS * 2
|
||||||
|
s.rows.append(Ricochet_RowStack(x, y, self))
|
||||||
|
y -= l.YS
|
||||||
|
s.rows.append(Ricochet_RowStack(x, y, self))
|
||||||
|
|
||||||
|
x, y = l.XM + l.XS * .5, l.YM + l.YS * .5
|
||||||
|
for i in range(3):
|
||||||
|
x += l.XS
|
||||||
|
s.rows.append(Ricochet_RowStack(x, y, self))
|
||||||
|
x += l.XS
|
||||||
|
for i in range(3):
|
||||||
|
y += l.YS
|
||||||
|
s.rows.append(Ricochet_RowStack(x, y, self))
|
||||||
|
y += l.YS
|
||||||
|
for i in range(3):
|
||||||
|
x -= l.XS
|
||||||
|
s.rows.append(Ricochet_RowStack(x, y, self))
|
||||||
|
x -= l.XS
|
||||||
|
for i in range(3):
|
||||||
|
y -= l.YS
|
||||||
|
s.rows.append(Ricochet_RowStack(x, y, self))
|
||||||
|
|
||||||
|
x, y = l.XM, l.YM + l.YS
|
||||||
|
for i in range(4):
|
||||||
|
x += l.XS
|
||||||
|
s.rows.append(Ricochet_RowStack(x, y, self))
|
||||||
|
for i in range(3):
|
||||||
|
y += l.YS
|
||||||
|
s.rows.append(Ricochet_RowStack(x, y, self))
|
||||||
|
for i in range(3):
|
||||||
|
x -= l.XS
|
||||||
|
s.rows.append(Ricochet_RowStack(x, y, self))
|
||||||
|
for i in range(2):
|
||||||
|
y -= l.YS
|
||||||
|
s.rows.append(Ricochet_RowStack(x, y, self))
|
||||||
|
|
||||||
|
# Create talon
|
||||||
|
x, y = l.XM + l.XS * 2, l.YM + l.YS * 2.5
|
||||||
|
s.talon = Ricochet_Talon(x, y, self, num_deal=1, max_rounds=1)
|
||||||
|
l.createText(s.talon, "s")
|
||||||
|
x += l.XS
|
||||||
|
s.waste = self.Waste_Class(x, y, self)
|
||||||
|
s.foundations.append(s.waste)
|
||||||
|
l.createText(s.waste, "s")
|
||||||
|
|
||||||
|
# Create text for scores
|
||||||
|
if self.preview <= 1:
|
||||||
|
self.texts.info = MfxCanvasText(
|
||||||
|
self.canvas,
|
||||||
|
l.XM + l.XS * 3, h - l.YM,
|
||||||
|
anchor="sw",
|
||||||
|
font=self.app.getFont("canvas_default"))
|
||||||
|
|
||||||
|
# Define stack groups
|
||||||
|
l.defaultStackGroups()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Game over rides
|
||||||
|
#
|
||||||
|
|
||||||
|
def startGame(self, flip=0):
|
||||||
|
self.lastStack = -1
|
||||||
|
self.startDealSample()
|
||||||
|
self.s.talon.dealRow(rows=self.s.rows[:20], flip=flip, frames=4)
|
||||||
|
self.s.talon.dealRow(rows=self.s.rows[20:], flip=1, frames=4)
|
||||||
|
self.s.talon.dealCards()
|
||||||
|
|
||||||
|
def isGameWon(self):
|
||||||
|
for r in self.s.rows:
|
||||||
|
if r.cards:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _restoreGameHook(self, game):
|
||||||
|
self.lastStack = game.loadinfo.dval.get('lastStack')
|
||||||
|
|
||||||
|
def _loadGameHook(self, p):
|
||||||
|
self.loadinfo.addattr(dval=p.load())
|
||||||
|
|
||||||
|
def _saveGameHook(self, p):
|
||||||
|
dval = {'lastStack': self.lastStack}
|
||||||
|
p.dump(dval)
|
||||||
|
|
||||||
|
def setState(self, state):
|
||||||
|
# restore saved vars (from undo/redo)
|
||||||
|
self.lastStack = state[0]
|
||||||
|
|
||||||
|
def getState(self):
|
||||||
|
# save vars (for undo/redo)
|
||||||
|
return [self.lastStack]
|
||||||
|
|
||||||
|
|
||||||
registerGame(GameInfo(22216, ThreePeaks, "Three Peaks (Scored)",
|
registerGame(GameInfo(22216, ThreePeaks, "Three Peaks (Scored)",
|
||||||
GI.GT_GOLF | GI.GT_SCORE, 1, 0, GI.SL_BALANCED,
|
GI.GT_GOLF | GI.GT_SCORE, 1, 0, GI.SL_BALANCED,
|
||||||
rules_filename="threepeaks.html"))
|
rules_filename="threepeaks.html"))
|
||||||
|
@ -296,3 +486,5 @@ registerGame(GameInfo(22218, ThreePeaksOpenScored, "Three Peaks (Scored/Open)",
|
||||||
registerGame(GameInfo(22231, ThreePeaksNoScore, "Three Peaks",
|
registerGame(GameInfo(22231, ThreePeaksNoScore, "Three Peaks",
|
||||||
GI.GT_GOLF, 1, 0, GI.SL_BALANCED,
|
GI.GT_GOLF, 1, 0, GI.SL_BALANCED,
|
||||||
altnames=("Tri Peaks",)))
|
altnames=("Tri Peaks",)))
|
||||||
|
registerGame(GameInfo(924, Ricochet, "Ricochet",
|
||||||
|
GI.GT_GOLF, 1, 0, GI.SL_BALANCED))
|
||||||
|
|
Loading…
Add table
Reference in a new issue