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

Added Magic Montana game.

This commit is contained in:
Joe R 2023-05-13 18:10:50 -04:00
parent de3e8cc3f8
commit d0c000f797
3 changed files with 127 additions and 2 deletions

View file

@ -0,0 +1,21 @@
<h1>Magic Montana</h1>
<p>
Hex A Deck type. 1 deck. 2 redeals.
<h3>Object</h3>
<p>
Group all the cards in sets of 17 cards in ascending sequence
by suit from 1 to 16, with a wizard at the end of each row.
<h3>Quick Description</h3>
<p>
Like <a href="montana.html">Montana</a>, but with a Hex A Deck.
The initial column is dealt empty, and the sequences are built up
from 1 to 16. Wizards are wild, and can be freely moved anywhere,
except directly after another wizard or an empty space. Ultimately,
the wizards must be in the column at the far right, adjacent to the
10s, at the end of the game.
<h3>Notes</h3>
<p>
<i>Autodrop</i> is disabled for this game.

View file

@ -559,7 +559,7 @@ class GI:
('fc-2.14', tuple(range(811, 827))),
('fc-2.15', tuple(range(827, 855)) + tuple(range(22400, 22407))),
('fc-2.20', tuple(range(855, 897))),
('dev', tuple(range(897, 899)) + tuple(range(13160, 13163)))
('dev', tuple(range(897, 899)) + tuple(range(13160, 13163)) + (16682,))
)
# deprecated - the correct way is to or a GI.GT_XXX flag

View file

@ -26,6 +26,7 @@ import math
from pysollib.game import Game
from pysollib.gamedb import GI, GameInfo, registerGame
from pysollib.games.montana import Montana, Montana_RowStack
from pysollib.hint import CautiousDefaultHint, DefaultHint
from pysollib.layout import Layout
from pysollib.mfxutil import kwdefault
@ -34,6 +35,7 @@ from pysollib.pysoltk import MfxCanvasText
from pysollib.stack import \
AC_RowStack, \
AbstractFoundationStack, \
BasicRowStack, \
InitialDealTalonStack, \
OpenStack, \
ReserveStack, \
@ -1502,6 +1504,107 @@ class HexYukon(Game):
# ************************************************************************
class MagicMontana_RowStack(Montana_RowStack):
def acceptsCards(self, from_stack, cards):
if not BasicRowStack.acceptsCards(self, from_stack, cards):
return False
if self.id % self.game.RSTEP == 0:
return cards[0].rank == self.game.RBASE
left = self.game.s.rows[self.id - 1]
if left.cards:
if left.cards[-1].suit == 4:
return False
if cards[0].suit == 4:
return True
return left.cards and left.cards[-1].suit == cards[0].suit \
and left.cards[-1].rank + 1 == cards[0].rank
class MagicMontana_Hint(DefaultHint):
def computeHints(self):
game = self.game
RSTEP, RBASE = game.RSTEP, game.RBASE
freerows = [s for s in game.s.rows if not s.cards]
# for each stack
for r in game.s.rows:
if not r.cards:
continue
assert len(r.cards) == 1 and r.cards[-1].face_up
c, pile, rpile = r.cards[0], r.cards, []
if r.id % RSTEP > 0:
left = game.s.rows[r.id - 1]
else:
left = None
if c.rank == RBASE:
# do not move the leftmost card of a row if the
# rank is correct
continue
for t in freerows:
if self.shallMovePile(r, t, pile, rpile):
# FIXME: this scoring is completely simple
if left and left.cards:
# prefer low-rank left neighbours
score = 40000 + (self.K - left.cards[-1].rank)
else:
score = 50000
# Deprioritize moving wizards, unless the next card
# is a 10. This will prevent an endless loop in the
# demo, but more advanced logic can probably use the
# wizards more strategically.
if r.cards[-1].suit == 4:
if t.id % RSTEP > 0:
leftt = game.s.rows[t.id - 1]
if leftt.cards[-1].rank < 15:
score -= 30000
else:
continue
self.addHint(score, 1, r, t)
class MagicMontana(Montana):
RowStack_Class = MagicMontana_RowStack
Hint_Class = MagicMontana_Hint
RLEN, RSTEP, RBASE = 72, 18, 0
def startGame(self):
frames = 0
for i in range(self.RLEN):
if i == self.RLEN-self.RSTEP: # last row
self.startDealSample()
frames = -1
if i % self.RSTEP == 0: # left column
continue
self.s.talon.dealRow(rows=(self.s.rows[i],), frames=frames)
def isGameWon(self):
rows = self.s.rows
for i in range(0, self.RLEN, self.RSTEP):
if not rows[i].cards:
return False
suit = rows[i].cards[-1].suit
for j in range(self.RSTEP - 2):
r = rows[i + j]
if not r.cards or r.cards[-1].rank != self.RBASE + j \
or r.cards[-1].suit != suit:
return False
w = rows[i + self.RSTEP - 2]
if not w.cards or w.cards[-1].suit != 4:
return False
return True
# ************************************************************************
# *
# ************************************************************************
def r(id, gameclass, name, game_type, decks, redeals, skill_level):
game_type = game_type | GI.GT_HEXADECK
gi = GameInfo(id, gameclass, name, game_type, decks, redeals, skill_level,
@ -1540,5 +1643,6 @@ r(16679, Labyrinth, 'Hex Labyrinth', GI.GT_HEXADECK | GI.GT_OPEN, 2, 0,
r(16680, Snakestone, 'Snakestone', GI.GT_HEXADECK | GI.GT_OPEN, 2, 0,
GI.SL_MOSTLY_SKILL)
r(16681, HexYukon, 'Hex Yukon', GI.GT_HEXADECK, 1, 0, GI.SL_BALANCED)
r(16682, MagicMontana, 'Magic Montana', GI.GT_HEXADECK | GI.GT_OPEN, 1, 2,
GI.SL_MOSTLY_SKILL)
del r