Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cardset format version 7 - cardset subtype and joker deck support #330

Merged
merged 1 commit into from
Aug 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions contrib/customize_cardset.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ config.txt template
-------------------

....
PySolFC solitaire cardset;$A;$FMT;$B;$C;$D,$E;$F
PySolFC solitaire cardset;$A;$FMT;$B;$C;$D,$E;$F;$G;$H
<internal_name>;<cardset_name>
X Y D
XOFF YOFF SXOFF SYOFF
Expand All @@ -21,7 +21,7 @@ Line 1

*$A:* The cardset version number that belongs to the number of fields divided through ";" on the first line (e.g. `.gif;1;78;8,1016` -> `$A=4`)

( *WARNING:* For Mahjongg, $A must always be 6 and the $F field must be included in the line; however, you can put `0` in `$F` if you wish, in that case. )
( *WARNING:* For Mahjongg, $A must always be 6 or 7 and the $F field must be included in the line; however, you can put `0` in `$F` if you wish, in that case. )

( *NOTE:* $D and $E are comma separated and count for one field )

Expand Down Expand Up @@ -112,6 +112,9 @@ Cardsets Origins:
*$F:* The Year the cardset was created (in the range 1000 to 2299)

*$G:* The subtype of the cardset. Usually 0 - for French type cardsets, a value of 1 is used if there are jokers.

*$H:* Whether the cardset is a 3D Mahjongg cardset - 1 if it is, 0 if it isn't. For cardsets with a version less than 7, version 6 cardsets treat this value as 1, and older version cardsets treat it as 0.

Line 2
------
Expand Down
Binary file added data/images/cards/finder/french/01z.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/images/cards/finder/french/01z.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/images/cards/finder/french/02z.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/images/cards/finder/french/02z.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 7 additions & 2 deletions html-src/cardset_customization.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<h1>Cardset Customization Tutorial</h1>
<h2>config.txt template</h2>
<pre>PySolFC solitaire cardset;$A;$FMT;$B;$C;$D,$E;$F
<pre>PySolFC solitaire cardset;$A;$FMT;$B;$C;$D,$E;$F;$G;$H
&lt;internal_name&gt;;&lt;cardset_name&gt;
X Y D
XOFF YOFF SXOFF SYOFF
Expand All @@ -9,7 +9,7 @@ <h2>config.txt template</h2>
<h2>Line 1</h2>
<p><b>$A:</b> The cardset version number that belongs to the number
of fields divided through ";" on the first line (e.g. <code>.gif;1;78;8,1016</code> &#8594; <code>$A=4</code>)</p>
<p>(<b>WARNING:</b> For Mahjongg, $A must always be 6 and the $F
<p>(<b>WARNING:</b> For Mahjongg, $A must always be 6 or 7 and the $F
field must be included in the line; however, you can put <code>0</code> in <code>$F</code> if you wish, in that case.)</p>
<p>(<b>NOTE:</b> $D and $E are comma separated and count for one
field)</p>
Expand Down Expand Up @@ -220,6 +220,11 @@ <h3>Cardsets Origins:</h3>
</ul>
<p><b>$F:</b> The Year the cardset was created (in the range 1000
to 2299)</p>
<p><b>$G:</b> The subtype of the cardset. Usually 0 - for French type
cardsets, a value of 1 is used if there are jokers.</p>
<p><b>$H:</b> Whether the cardset is a 3D Mahjongg cardset - 1 if it is, 0
if it isn't. For cardsets with a version less than 7, version 6 cardsets
treat this value as 1, and older version cardsets treat it as 0.</p>
<h2>Line 2</h2>
<p><code>&lt;internal_name&gt;</code>: A name for PySolFC to identify your
cardset (without spaces)</p>
Expand Down
3 changes: 1 addition & 2 deletions html-src/glossary.html
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,7 @@ <h1>Glossary</h1>

<dd>
<p>A deck of cards consisting of a STANDARD DECK and two jokers
making a total of 54 cards. Currently, joker decks are not
used in PySol.</p>
making a total of 54 cards.</p>
</dd>

<dt><b>OPEN</b></dt>
Expand Down
14 changes: 14 additions & 0 deletions html-src/rules/thieves.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<h1>Thieves</h1>
<p>
Golf type. 1 joker deck. No redeal.

<h3>Object</h3>
<p>
Move all cards to the waste stack.

<h3>Quick Description</h3>
<p>
Like <a href="golf.html">Golf</a>,
but with two jokers. Jokers are wild, any card
can be played on a joker, and a joker can be played
on any card.
55 changes: 36 additions & 19 deletions pysollib/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -652,22 +652,25 @@ def updateCardset(self, id=0, update=7):
self.images.setNegative(self.opt.negative_bottom)
self.subsampled_images.setNegative(self.opt.negative_bottom)
if update & 1:
self.opt.cardset[0] = (cs.name, cs.backname)
self.opt.cardset[0][0] = (cs.name, cs.backname)
if update & 2:
self.opt.cardset[cs.si.type] = (cs.name, cs.backname)
self.opt.cardset[cs.si.type][cs.si.subtype] = (cs.name,
cs.backname)
gi = self.getGameInfo(id)
if gi:
if update & 256:
try:
del self.opt.cardset[(1, gi.id)]
del self.opt.cardset[(1, gi.id)][gi.subcategory]
except KeyError:
pass
t = self.checkCompatibleCardsetType(gi, cs)
if not t[1]:
if update & 4:
self.opt.cardset[gi.category] = (cs.name, cs.backname)
self.opt.cardset[gi.category][gi.subcategory] = \
(cs.name, cs.backname)
if update & 8:
self.opt.cardset[(1, gi.id)] = (cs.name, cs.backname)
self.opt.cardset[(1, gi.id)][gi.subcategory] = \
(cs.name, cs.backname)
# from pprint import pprint; pprint(self.opt.cardset)

def loadCardset(self, cs, id=0, update=7, progress=None,
Expand All @@ -685,14 +688,16 @@ def loadCardset(self, cs, id=0, update=7, progress=None,
# key: Cardset.type
# value: (Cardset.ident, Images, SubsampledImages)
c = self.cardsets_cache.get(cs.type)
if c and c[0] == cs.ident:
# print 'load from cache', c
self.images, self.subsampled_images = c[1], c[2]
if not tocache:
self.updateCardset(id, update=update)
if self.menubar is not None:
self.menubar.updateBackgroundImagesMenu()
return 1
if c:
c2 = c.get(cs.subtype)
if c2 and c2[0] == cs.ident:
# print 'load from cache', c
self.images, self.subsampled_images = c2[1], c2[2]
if not tocache:
self.updateCardset(id, update=update)
if self.menubar is not None:
self.menubar.updateBackgroundImagesMenu()
return 1
#
if progress is None and not noprogress:
self.wm_save_state()
Expand All @@ -718,9 +723,13 @@ def loadCardset(self, cs, id=0, update=7, progress=None,
# if self.opt.save_cardsets:
c = self.cardsets_cache.get(cs.type)
if c:
# c[1].destruct()
destruct(c[1])
self.cardsets_cache[cs.type] = (cs.ident, images, simages)
c2 = c.get(cs.subtype)
if c2:
# c2[1].destruct()
destruct(c2[1])
self.cardsets_cache[cs.type] = {}
self.cardsets_cache[cs.type][cs.subtype] = (cs.ident, images,
simages)
if not tocache:
# elif self.images is not None:
# # self.images.destruct()
Expand Down Expand Up @@ -757,14 +766,19 @@ def checkCompatibleCardsetType(self, gi, cs):
assert gi is not None
assert cs is not None
gc = gi.category
gs = gi.subcategory
cs_type = cs.si.type
cs_subtype = cs.si.subtype
t0, t1 = None, None
if gc == GI.GC_FRENCH:
t0 = "French"
if cs_type not in (CSI.TYPE_FRENCH,
# CSI.TYPE_TAROCK,
):
t1 = t0
if (cs_subtype == CSI.SUBTYPE_NONE
and gs == CSI.SUBTYPE_JOKER_DECK):
t1 = t0
elif gc == GI.GC_HANAFUDA:
t0 = "Hanafuda"
if cs_type not in (CSI.TYPE_HANAFUDA,):
Expand Down Expand Up @@ -823,14 +837,17 @@ def getCompatibleCardset(self, gi, cs, trychange=True):
# try by gameid / category
for key, flag in (((1, gi.id), 8), (gi.category, 4)):
c = self.opt.cardset.get(key)
if not c or len(c) != 2:
c2 = None
if c:
c2 = c.get(gi.subcategory)
if not c2 or len(c2) != 2:
continue
cs = self.cardset_manager.getByName(c[0])
cs = self.cardset_manager.getByName(c2[0])
if not cs:
continue
t = self.checkCompatibleCardsetType(gi, cs)
if not t[1]:
cs.updateCardback(backname=c[1])
cs.updateCardback(backname=c2[1])
return cs, flag, t
# ask
return None, 0, t
Expand Down
14 changes: 14 additions & 0 deletions pysollib/cardsetparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,20 @@ def parse_cardset_config(lines_list):
except ValueError:
_perr(1, 6, 'not integer')
return None
if cs.version >= 7:
if len(fields) < 9:
_perr(1, msg='not enough fields')
return None
try:
cs.subtype = int(fields[7])
except ValueError:
_perr(1, 7, 'not integer')
return None
try:
cs.mahjongg3d = bool(fields[8])
except ValueError:
_perr(1, 8, 'not boolean')
return None
if len(cs.ext) < 2 or cs.ext[0] != ".":
_perr(1, msg='specifies an invalid file extension')
return None
Expand Down
16 changes: 11 additions & 5 deletions pysollib/gamedb.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ class GI:

NUM_CATEGORIES = CSI.TYPE_MATCHING

# game subcategory
GS_NONE = CSI.SUBTYPE_NONE
GS_JOKER_DECK = CSI.SUBTYPE_JOKER_DECK

# game type
GT_1DECK_TYPE = 0
GT_2DECK_TYPE = 1
Expand Down Expand Up @@ -341,15 +345,15 @@ def _callback(gi, gt=game_type):
# Gnome AisleRiot 2.2.0 (we have 65 out of 70 games)
# Gnome AisleRiot 3.22.7
# still missing:
# Hamilton, Labyrinth, Thieves, Treize, Valentine, Wall
# Hamilton, Labyrinth, Treize, Valentine, Wall
("Gnome AisleRiot", (
1, 2, 8, 9, 11, 12, 13, 19, 24, 27, 29, 31, 33, 34, 35, 36,
38, 40, 41, 42, 43, 45, 48, 58, 65, 67, 89, 91, 92, 93, 94,
95, 96, 97, 100, 104, 105, 111, 112, 113, 130, 135, 139, 144,
146, 147, 148, 200, 201, 206, 224, 225, 229, 230, 233, 257,
258, 277, 280, 281, 282, 283, 284, 334, 384, 479, 495, 551,
552, 553, 572, 593, 674, 700, 715, 716, 737, 772, 810, 819,
824, 829, 859, 874, 22231,
824, 829, 859, 874, 906, 22231,
)),

# Hoyle Card Games
Expand Down Expand Up @@ -560,7 +564,8 @@ def _callback(gi, gt=game_type):
('fc-2.15', tuple(range(827, 855)) + tuple(range(22400, 22407))),
('fc-2.20', tuple(range(855, 897))),
('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, 907))),
)

# deprecated - the correct way is to or a GI.GT_XXX flag
Expand Down Expand Up @@ -608,7 +613,7 @@ def __init__(self, id, gameclass, name,
game_type, decks, redeals,
skill_level=None,
# keyword arguments:
si={}, category=0,
si={}, category=0, subcategory=GI.GS_NONE,
short_name=None, altnames=(),
suits=list(range(4)), ranks=list(range(13)), trumps=(),
rules_filename=None,
Expand Down Expand Up @@ -692,7 +697,8 @@ def to_unicode(s):
name=name, short_name=short_name,
altnames=tuple(altnames), en_name=en_name,
decks=decks, redeals=redeals, ncards=ncards,
category=category, skill_level=skill_level,
category=category, subcategory=subcategory,
skill_level=skill_level,
suits=tuple(suits), ranks=tuple(ranks),
trumps=tuple(trumps),
si=gi_si, rules_filename=rules_filename)
Expand Down
14 changes: 14 additions & 0 deletions pysollib/games/golf.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ def acceptsCards(self, from_stack, cards):
return True
if not WasteStack.acceptsCards(self, from_stack, cards):
return False
# if there are jokers, they're wild
if self.cards[-1].suit == 4 or cards[0].suit == 4:
return True
# check cards
r1, r2 = self.cards[-1].rank, cards[0].rank
if self.game.getStrictness() == 1:
Expand Down Expand Up @@ -217,6 +220,14 @@ def startGame(self):
Golf.startGame(self, 7)


# ************************************************************************
# * Thieves
# ************************************************************************

class Thieves(Golf):
pass


# ************************************************************************
# *
# ************************************************************************
Expand Down Expand Up @@ -1491,3 +1502,6 @@ def fillStack(self, stack):
GI.GT_GOLF | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(892, DoublePutt, "Double Putt",
GI.GT_GOLF, 2, 0, GI.SL_BALANCED))
registerGame(GameInfo(906, Thieves, "Thieves",
GI.GT_GOLF, 1, 0, GI.SL_BALANCED,
subcategory=GI.GS_JOKER_DECK, trumps=list(range(2))))
2 changes: 1 addition & 1 deletion pysollib/games/mahjongg/mahjongg.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ def createGame(self):
# dx, dy = 2, -2
# dx, dy = 3, -3
cs = self.app.images.cs
if cs.version >= 6:
if cs.version == 6 or cs.mahjongg3d:
dx = l.XOFFSET
dy = -l.YOFFSET
d_x = cs.SHADOW_XOFFSET
Expand Down
4 changes: 2 additions & 2 deletions pysollib/games/mahjongg/shisensho.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ def drawArrow(self, other_stack, sleep):
x0, y0 = (game.XMARGIN + game.center_offset[0],
game.YMARGIN + game.center_offset[1])
cardw, cardh = images.CARDW, images.CARDH
if cs.version >= 6:
if cs.version == 6 or cs.mahjongg3d:
cardw -= cs.SHADOW_XOFFSET
cardh -= cs.SHADOW_YOFFSET
coords = []
Expand Down Expand Up @@ -314,7 +314,7 @@ def createGame(self):
# dx, dy = 3, -3

cs = self.app.images.cs
if cs.version >= 6:
if cs.version == 6 or cs.mahjongg3d:
dx = l.XOFFSET
dy = -l.YOFFSET
d_x = cs.SHADOW_XOFFSET
Expand Down
2 changes: 1 addition & 1 deletion pysollib/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ def progressCallback(*args):
# init cardsets
app.initCardsets()
cardset = None
c = app.opt.cardset.get(0)
c = app.opt.cardset.get(0).get(0)
if c:
cardset = app.cardset_manager.getByName(c[0])
if cardset and c[1]:
Expand Down
Loading