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

Compare commits

...

10 commits

Author SHA1 Message Date
Joe R
bdd3093a2b Compress tile images 2025-03-30 15:42:45 -04:00
Joe R
c4a62baf79 Add Cribbage Patience II game 2025-03-30 14:04:18 -04:00
Joe R
b1370fce08 Add more alternate names 2025-03-25 19:09:39 -04:00
Joe R
7b85049f7c Add Flamboyant game 2025-03-25 17:42:31 -04:00
Joe R
afc74a86f5 Remove extra paragraph tags to improve documentation formatting 2025-03-23 19:41:21 -04:00
Joe R
50e003e256 Add Ace of Penguins to the compatibility list 2025-03-17 19:44:23 -04:00
Joe R
78de569074 Fix for the total text crashing Ninety-One on Android (#436) 2025-03-17 18:04:38 -04:00
Joe R
a79c81109b Fix binding error in Kivy 2025-03-15 20:11:50 -04:00
Joe R
c14be7b73e Add Wizard's Castle game 2025-03-14 22:09:56 -04:00
Joe R
69c1440b2b Improve display details of cardset info window 2025-03-14 19:21:14 -04:00
35 changed files with 474 additions and 293 deletions

BIN
data/tiles/Felt_Blue.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 351 B

After

Width:  |  Height:  |  Size: 350 B

View file

@ -38,42 +38,18 @@ back01.ext;back02.ext;back03.ext</pre>
<p><b>$B:</b> The type of the cardset (see types below)</p>
<h3>Cardsets Types:</h3>
<ul>
<li>
<p>French = 1</p>
</li>
<li>
<p>Hanafuda = 2</p>
</li>
<li>
<p>Tarock = 3</p>
</li>
<li>
<p>Mahjongg = 4</p>
</li>
<li>
<p>Hex A Deck = 5</p>
</li>
<li>
<p>Mughal Ganjifa = 6</p>
</li>
<li>
<p>Navagraha Ganjiga = 7</p>
</li>
<li>
<p>Dashavatara Ganjifa = 8</p>
</li>
<li>
<p>Trumps Only = 9</p>
</li>
<li>
<p>Matching = 10</p>
</li>
<li>
<p>Puzzle = 11</p>
</li>
<li>
<p>Ishido = 12</p>
</li>
<li>French = 1</li>
<li>Hanafuda = 2</li>
<li>Tarock = 3</li>
<li>Mahjongg = 4</li>
<li>Hex A Deck = 5</li>
<li>Mughal Ganjifa = 6</li>
<li>Navagraha Ganjiga = 7</li>
<li>Dashavatara Ganjifa = 8</li>
<li>Trumps Only = 9</li>
<li>Matching = 10</li>
<li>Puzzle = 11</li>
<li>Ishido = 12</li>
</ul>
<p><b>$C:</b> The number of cards in the cardset, generally 42,
48, 52, 68, 78, 96 or 120</p>
@ -81,190 +57,70 @@ back01.ext;back02.ext;back03.ext</pre>
or more comma separated values)</p>
<h3>Cardsets Styles:</h3>
<ul>
<li>
<p>Abstract = 35</p>
</li>
<li>
<p>Adult = 1</p>
</li>
<li>
<p>Animals = 2</p>
</li>
<li>
<p>Anime = 3</p>
</li>
<li>
<p>Art = 4</p>
</li>
<li>
<p>Cartoons = 5</p>
</li>
<li>
<p>Children = 6</p>
</li>
<li>
<p>Classic Look = 7</p>
</li>
<li>
<p>Collectors = 8</p>
</li>
<li>
<p>Computers = 9</p>
</li>
<li>
<p>Divination = 36</p>
</li>
<li>
<p>Engines = 10</p>
</li>
<li>
<p>Fantasy = 11</p>
</li>
<li>
<p>Four Color = 37</p>
</li>
<li>
<p>Ganjifa= 30</p>
</li>
<li>
<p>Hanafuda = 12</p>
</li>
<li>
<p>Hex A Deck = 29</p>
</li>
<li>
<p>Holiday = 13</p>
</li>
<li>
<p>Ishido = 34</p>
</li>
<li>
<p>Mahjongg = 28</p>
</li>
<li>
<p>Matching = 32</p>
</li>
<li>
<p>Monochrome = 38</p>
</li>
<li>
<p>Movies = 14</p>
</li>
<li>
<p>Matrix = 31</p>
</li>
<li>
<p>Music = 15</p>
</li>
<li>
<p>Nature = 16</p>
</li>
<li>
<p>Operating Systems = 17</p>
</li>
<li>
<p>People = 19</p>
</li>
<li>
<p>Places = 20</p>
</li>
<li>
<p>Plain = 21</p>
</li>
<li>
<p>Products = 22</p>
</li>
<li>
<p>Puzzle = 33</p>
</li>
<li>
<p>Round Cardsets = 18</p>
</li>
<li>
<p>Science Fiction = 23</p>
</li>
<li>
<p>Sports = 24</p>
</li>
<li>
<p>Tarock = 27</p>
</li>
<li>
<p>Vehicles = 25</p>
</li>
<li>
<p>Video Games = 26</p>
</li>
<li>Abstract = 35</li>
<li>Adult = 1</li>
<li>Animals = 2</li>
<li>Anime = 3</li>
<li>Art = 4</li>
<li>Cartoons = 5</li>
<li>Children = 6</li>
<li>Classic Look = 7</li>
<li>Collectors = 8</li>
<li>Computers = 9</li>
<li>Divination = 36</li>
<li>Engines = 10</li>
<li>Fantasy = 11</li>
<li>Four Color = 37</li>
<li>Ganjifa= 30</li>
<li>Hanafuda = 12</li>
<li>Hex A Deck = 29</li>
<li>Holiday = 13</li>
<li>Ishido = 34</li>
<li>Mahjongg = 28</li>
<li>Matching = 32</li>
<li>Monochrome = 38</li>
<li>Movies = 14</li>
<li>Matrix = 31</li>
<li>Music = 15</li>
<li>Nature = 16</li>
<li>Operating Systems = 17</li>
<li>People = 19</li>
<li>Places = 20</li>
<li>Plain = 21</li>
<li>Products = 22</li>
<li>Puzzle = 33</li>
<li>Round Cardsets = 18</li>
<li>Science Fiction = 23</li>
<li>Sports = 24</li>
<li>Tarock = 27</li>
<li>Vehicles = 25</li>
<li>Video Games = 26</li>
</ul>
<p><b>$E:</b> The origin (country) of the cardset</p>
<h3>Cardsets Origins:</h3>
<ul>
<li>
<p>Australia = 1021</p>
</li>
<li>
<p>Austria = 1001</p>
</li>
<li>
<p>Belgium = 1019</p>
</li>
<li>
<p>Canada = 1010</p>
</li>
<li>
<p>China = 1011</p>
</li>
<li>
<p>Czech Republic = 1012</p>
</li>
<li>
<p>Denmark = 1013</p>
</li>
<li>
<p>England = 1003</p>
</li>
<li>
<p>France = 1004</p>
</li>
<li>
<p>Germany = 1006</p>
</li>
<li>
<p>Great Britain = 1014</p>
</li>
<li>
<p>Hungary = 1015</p>
</li>
<li>
<p>India = 1020</p>
</li>
<li>
<p>Italy = 1005</p>
</li>
<li>
<p>Japan = 1016</p>
</li>
<li>
<p>Netherlands = 1002</p>
</li>
<li>
<p>Portugal = 1022</p>
</li>
<li>
<p>Russia = 1007</p>
</li>
<li>
<p>Spain = 1008</p>
</li>
<li>
<p>Sweden = 1017</p>
</li>
<li>
<p>Switzerland = 1009</p>
</li>
<li>
<p>USA = 1018</p>
</li>
<li>Australia = 1021</li>
<li>Austria = 1001</li>
<li>Belgium = 1019</li>
<li>Canada = 1010</li>
<li>China = 1011</li>
<li>Czech Republic = 1012</li>
<li>Denmark = 1013</li>
<li>England = 1003</li>
<li>France = 1004</li>
<li>Germany = 1006</li>
<li>Great Britain = 1014</li>
<li>Hungary = 1015</li>
<li>India = 1020</li>
<li>Italy = 1005</li>
<li>Japan = 1016</li>
<li>Netherlands = 1002</li>
<li>Portugal = 1022</li>
<li>Russia = 1007</li>
<li>Spain = 1008</li>
<li>Sweden = 1017</li>
<li>Switzerland = 1009</li>
<li>USA = 1018</li>
</ul>
<p><b>$F:</b> The Year the cardset was created (in the range 1000
to 2299)</p>
@ -284,31 +140,16 @@ back01.ext;back02.ext;back03.ext</pre>
will be truncated.</p>
<h2>Line 3</h2>
<ul>
<li>
<p><b>X:</b> The cards' width (the card image width)</p>
</li>
<li>
<p><b>Y:</b> The cards' height (the card image height)</p>
</li>
<li>
<p><b>D:</b> The color depth (mostly 8)</p>
</li>
<li><b>X:</b> The cards' width (the card image width)</li>
<li><b>Y:</b> The cards' height (the card image height)</li>
<li><b>D:</b> The color depth (mostly 8)</li>
</ul>
<h2>Line 4</h2>
<ul>
<li>
<p><b>XOFF:</b> The horizontal offset of the cards</p>
</li>
<li>
<p><b>YOFF:</b> The vertical offset of the cards</p>
</li>
<li>
<p><b>SXOFF:</b> The offset of the horizontal shadow (mostly
7)</p>
</li>
<li>
<p><b>SYOFF:</b> The offset of the vertical shadow (mostly 7)</p>
</li>
<li><b>XOFF:</b> The horizontal offset of the cards</li>
<li><b>YOFF:</b> The vertical offset of the cards</li>
<li><b>SXOFF:</b> The offset of the horizontal shadow (mostly 7)</li>
<li><b>SYOFF:</b> The offset of the vertical shadow (mostly 7)</li>
</ul>
<h2>Line 5</h2>
<p><code>back01.ext</code>: The name of the default back image (where <code>ext</code> means the file extension e.g: <code>png</code> or <code>gif</code>.)</p>
@ -330,7 +171,9 @@ back01.ext;back02.ext;back03.ext</pre>
<a href="https://github.com/shlomif/shlomif-computer-settings/blob/master/shlomif-settings/git/commit-messages/cc0-copyright-disclaimer.txt">CC0/Public Domain/MIT License/GPL terms</a></p>
<h3>Credits:</h3>
<p>Credits go to:</p>
<p><a href="mailto:andsa@web.de">Andreas Sauer</a> for clarifying certain
points<br></p>
<p><a href="https://www.shlomifish.org/">Shlomi Fish</a> for making some
improvements to this tutorial</p>
<ul>
<li><a href="mailto:andsa@web.de">Andreas Sauer</a> for clarifying certain
points</li>
<li><a href="https://www.shlomifish.org/">Shlomi Fish</a> for making some
improvements to this tutorial</li>
</ul>

View file

@ -4,7 +4,7 @@ Cribbage type. 1 deck. No redeal.
<h3>Object</h3>
<p>
Deal five cribbage hands to get a total score of 61 points or more.
Deal five cribbage hands to get a total score of 80 points or more.
<h3>Rules</h3>
<p>
@ -16,7 +16,8 @@ Points are awarded for the 2 Cribbage hands: the remaining four cards, plus
the four cards in the crib.
<p>
After each hand, repeat the process four more times to deal a total of five
hands. You win if after all five hands, your score reaches 61 points.
hands. You win if after all five hands, your score reaches 80 points.
<h3>Cribbage Scoring</h3>
<p>
Cribbage hands are scored as follows - each hand is worth the total value

View file

@ -0,0 +1,18 @@
<h1>Cribbage Patience II</h1>
<p>
Cribbage type. 1 deck. No redeal.
<h3>Object</h3>
<p>
Deal four cribbage hands to get a total score of 80 points or more.
<h3>Quick Description</h3>
<p>
Like <a href="cribbagepatience.html">Cribbage Patience</a>,
but two cards are not dealt face-down to the crib. After moving two
cards from the hand to the crib, a second six-card hand is dealt, and
you move two cards from that hand to finish the crib. Then, all
three hands are scored.
<p>
Due to the increased number of cards per hand, only four hands are dealt
per game.

View file

@ -0,0 +1,22 @@
<h1>Flamboyant</h1>
<p>
Fan game type. 1 deck. No redeal.
<h3>Object</h3>
<p>
Move all cards to the foundations.
<h3>Rules</h3>
<p>
The tableau piles are built in seventeen sets of three cards, with
two in the back row face-down, and a third face-up card overlapping
them. The final card is dealt separately.
<p>
The tableau piles are built down by alternate color, with any face-up card
or valid sequence of cards being movable. Once the top card is moved,
the two below it can be flipped face-up and played. Empty piles cannot
be filled, except for the final single card, where a king or sequence of
cards starting with a king can be played.
<p>
Foundations are built up in suit from Ace to King. The game is won
when all cards are moved to the foundations.

View file

@ -0,0 +1,15 @@
<h1>Wizard's Castle</h1>
<p>
Hex A Deck type. 1 deck. No redeal.
<h3>Object</h3>
<p>
Move all cards to the foundations.
<h3>Rules</h3>
<p>
Rows build down in rank in alternating color. Wizards are wild,
so any card can be played on one, and a wizard can be played on
any card. Only one card can be moved at a time. Foundations build
up in rank by suit. Any card can be played on an empty row. Cards
can be played from the foundations.

View file

@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: PySol 0.0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-12-10 10:19-0500\n"
"PO-Revision-Date: 2024-12-28 19:10-0500\n"
"PO-Revision-Date: 2025-03-14 19:16-0400\n"
"Last-Translator: H. Schaekel <Holger.Schaekel@web.de>\n"
"Language-Team: German\n"
"Language: de\n"
@ -4189,6 +4189,9 @@ msgstr "Nationalität:"
msgid "Year:"
msgstr "Jahr:"
msgid "Num. cards:"
msgstr ""
msgid "Compatible with current game"
msgstr ""

View file

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: 1.02\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-12-10 10:19-0500\n"
"PO-Revision-Date: 2024-12-28 19:10-0500\n"
"PO-Revision-Date: 2025-03-14 19:16-0400\n"
"Last-Translator: Eric Rausch <neelix570@gmail.com>\n"
"Language-Team: French\n"
"Language: fr\n"
@ -4240,6 +4240,9 @@ msgstr "Origine:"
msgid "Year:"
msgstr "Année:"
msgid "Num. cards:"
msgstr ""
msgid "Compatible with current game"
msgstr ""

View file

@ -12,7 +12,7 @@ msgstr ""
"Project-Id-Version: it_pysol\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-12-10 10:19-0500\n"
"PO-Revision-Date: 2024-12-28 19:11-0500\n"
"PO-Revision-Date: 2025-03-14 19:15-0400\n"
"Last-Translator: Giuliano Colla <giuliano.colla@gmail.com>\n"
"Language-Team: Italiano <it@li.org>\n"
"Language: it\n"
@ -4303,6 +4303,9 @@ msgstr "Nazionalità:"
msgid "Year:"
msgstr "Anno:"
msgid "Num. cards:"
msgstr ""
msgid "Compatible with current game"
msgstr ""

View file

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: PySolFC\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-12-10 10:19-0500\n"
"PO-Revision-Date: 2024-12-28 19:11-0500\n"
"PO-Revision-Date: 2025-03-14 19:15-0400\n"
"Last-Translator: Jerzy Trzeciak <artusek@wp.pl>\n"
"Language-Team: Polish <pl@li.org>\n"
"Language: pl\n"
@ -4257,6 +4257,9 @@ msgstr "Narodowość:"
msgid "Year:"
msgstr "Rok:"
msgid "Num. cards:"
msgstr ""
msgid "Compatible with current game"
msgstr ""

View file

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-12-10 10:19-0500\n"
"PO-Revision-Date: 2024-12-28 19:11-0500\n"
"PO-Revision-Date: 2025-03-14 19:15-0400\n"
"Last-Translator: Matheus Knack <mtknack555@gmail.com>\n"
"Language-Team: \n"
"Language: pt_BR\n"
@ -4263,6 +4263,9 @@ msgstr "Nacionalidade:"
msgid "Year:"
msgstr "Ano:"
msgid "Num. cards:"
msgstr ""
msgid "Compatible with current game"
msgstr ""

View file

@ -4045,6 +4045,9 @@ msgstr ""
msgid "Year:"
msgstr ""
msgid "Num. cards:"
msgstr ""
msgid "Compatible with current game"
msgstr ""

View file

@ -7,7 +7,7 @@ msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-12-10 10:19-0500\n"
"PO-Revision-Date: 2024-12-28 19:12-0500\n"
"PO-Revision-Date: 2025-03-14 19:14-0400\n"
"Last-Translator: Skomoroh <skomoroh@gmail.com>\n"
"Language-Team: Russian <ru@li.org>\n"
"Language: ru\n"
@ -4312,6 +4312,9 @@ msgstr "Национальность:"
msgid "Year:"
msgstr "Год:"
msgid "Num. cards:"
msgstr ""
msgid "Compatible with current game"
msgstr ""

View file

@ -589,10 +589,11 @@ class Game(object):
if not self.cards:
self.cards = self.createCards(progress=self.app.intro.progress)
self.initBindings()
# self.top.bind('<ButtonPress>', self.top._sleepEvent)
# self.top.bind('<3>', self.top._sleepEvent)
self.top.bind("<FocusOut>", self.top._focusOutEvent)
self.top.bind("<FocusIn>", self.top._focusInEvent)
if TOOLKIT == 'tk':
# self.top.bind('<ButtonPress>', self.top._sleepEvent)
# self.top.bind('<3>', self.top._sleepEvent)
self.top.bind("<FocusOut>", self.top._focusOutEvent)
self.top.bind("<FocusIn>", self.top._focusInEvent)
# update display properties
self.canvas.busy = True
# geometry

View file

@ -345,6 +345,15 @@ class GI:
# adding it should be a priority.
GAMES_BY_COMPATIBILITY = (
# Ace of Penguins (We have 6 out of 6 card games)
# Non-card games missing:
# - Mastermind
# - Minesweeper (Needs a new cardset type)
# - Pegged layouts (Not all compatible with the PySol engine)
# - Mahjongg/Taipei layouts
("Ace of Penguins", (2, 8, 11, 36, 105, 181, 210, 492,
5401, 22399)),
# Atari ST Patience game v2.13 (we have 10 out of 10 games)
("Atari ST Patience", (1, 3, 4, 7, 12, 14, 15, 16, 17, 39,)),
@ -594,9 +603,9 @@ class GI:
tuple(range(19000, 19012)) + tuple(range(22303, 22311)) +
tuple(range(22353, 22361))),
('fc-3.1', tuple(range(961, 971))),
('dev', tuple(range(971, 979)) + tuple(range(5419, 5421)) +
tuple(range(16683, 16685)) + tuple(range(18005, 18007)) +
(44, 526,)),
('dev', tuple(range(971, 981)) + tuple(range(5419, 5421)) +
tuple(range(16683, 16686)) + tuple(range(18005, 18007)) +
(44, 526, 22399,)),
)
# deprecated - the correct way is to or a GI.GT_XXX flag

View file

@ -957,7 +957,7 @@ registerGame(GameInfo(831, Siegecraft, "Siegecraft",
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(881, Lasker, "Lasker",
GI.GT_BELEAGUERED_CASTLE | GI.GT_OPEN, 1, 0,
GI.SL_SKILL))
GI.SL_SKILL, altnames=('Xantia',)))
registerGame(GameInfo(951, Morphy, "Morphy",
GI.GT_BELEAGUERED_CASTLE | GI.GT_OPEN, 1, 0,
GI.SL_SKILL))

View file

@ -36,7 +36,7 @@ from pysollib.stack import \
WasteTalonStack, \
Yukon_AC_RowStack, \
getNumberOfFreeStacks
from pysollib.util import ANY_RANK, KING
from pysollib.util import ANY_RANK, KING, NO_RANK
# ************************************************************************
@ -301,6 +301,96 @@ class Sarlacc(Interlock):
self.s.talon.dealRow(rows=self.s.rows[42:])
# ************************************************************************
# * Flamboyant
# ************************************************************************
class Flamboyant_RowStack(Interlock_RowStack):
STEP = ((2,), (1,), (), (2,), (1,), (), (2,), (1,), (),
(2,), (1,), (), (2,), (1,), (), (2,), (1,), (),
(2,), (1,), (), (2,), (1,), (), (2,), (1,), (),
(2,), (1,), (), (2,), (1,), (), (2,), (1,), (),
(2,), (1,), (), (2,), (1,), (), (2,), (1,), (),
(2,), (1,), (), (2,), (1,), ())
class Flamboyant(Interlock):
RowStack_Class = Flamboyant_RowStack
Talon_Class = InitialDealTalonStack
PLAYCARDS = 8
def _createTableauPiece(self, layout, x0, y0):
for i in range(2):
x = x0 + i * layout.XS // 2
y = y0 + i * layout.YS // 4
for j in range(2 - i):
stack = self.RowStack_Class(x, y, self, base_rank=NO_RANK)
self.s.rows.append(stack)
x = x + layout.XS
def createGame(self):
lay, s = Layout(self), self.s
w = (14.5 * lay.XS) + lay.XM
h = (4.2 * lay.YS) + (self.PLAYCARDS * lay.YOFFSET * 3) + lay.YM
self.setSize(w, h)
x, y = lay.XM, lay.YM
# create stacks
for i in range(2):
for i in range(6):
self._createTableauPiece(lay, x, y)
x += (2.25 * lay.XS)
y += (1.4 * lay.YS) + (self.PLAYCARDS * lay.YOFFSET)
x = lay.XM
for i in range(5):
self._createTableauPiece(lay, x, y)
x += (2.25 * lay.XS)
x += (.5 * lay.XS)
self.s.rows.append(AC_RowStack(x, y, self, base_rank=KING))
x, y = lay.XM + (13.5 * lay.XS), lay.YM
for i in range(4):
s.foundations.append(SS_FoundationStack(x, y, self, i))
y += lay.YS
s.talon = InitialDealTalonStack(x, y, self)
lay.defaultStackGroups()
def startGame(self):
self.startDealSample()
backrows = []
frontrows = []
for i, item in enumerate(self.s.rows):
if (i + 1) % 3 == 0 or i >= 51:
frontrows.append(item)
else:
backrows.append(item)
self.s.talon.dealRow(rows=backrows, flip=0, frames=0)
self.s.talon.dealRow(rows=frontrows)
def _getClosestStack(self, cx, cy, stacks, dragstack):
closest, cdist = None, 999999999
# Since we only compare distances,
# we don't bother to take the square root.
for stack in stacks:
# Flamboyant uses different logic to determine back row
# stacks.
backrows = []
frontrows = []
for i, item in enumerate(self.s.rows):
if (i + 1) % 3 == 0:
frontrows.append(item)
else:
backrows.append(item)
if len(stack.cards) == 0 and stack in frontrows:
continue
dist = (stack.x - cx)**2 + (stack.y - cy)**2
if dist < cdist:
closest, cdist = stack, dist
return closest
# register the game
registerGame(GameInfo(852, Guardian, "Guardian",
GI.GT_KLONDIKE, 1, -1, GI.SL_BALANCED))
@ -310,3 +400,5 @@ registerGame(GameInfo(939, LoveADuck, "Love a Duck",
GI.GT_YUKON | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(946, Sarlacc, "Sarlacc",
GI.GT_FREECELL | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(979, Flamboyant, "Flamboyant",
GI.GT_FAN_TYPE, 1, 0, GI.SL_BALANCED))

View file

@ -1409,7 +1409,7 @@ class NinetyOne(Game):
def updateText(self):
if self.preview > 1 or not self.texts.score:
return
self.texts.score.config(text=self.getTotal())
self.texts.score.config(text=str(self.getTotal()))
def getTotal(self):
total = 0

View file

@ -1912,7 +1912,8 @@ registerGame(GameInfo(619, TripleAlliance, "Triple Alliance",
GI.GT_PAIRING_TYPE | GI.GT_OPEN, 1, 0,
GI.SL_MOSTLY_SKILL, altnames=('Triplets',)))
registerGame(GameInfo(655, Pharaohs, "Pharaohs",
GI.GT_PAIRING_TYPE | GI.GT_OPEN, 1, 0, GI.SL_BALANCED))
GI.GT_PAIRING_TYPE | GI.GT_OPEN, 1, 0, GI.SL_BALANCED,
altnames=("Three Pharaohs",)))
registerGame(GameInfo(657, Baroness, "Baroness",
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_BALANCED,
altnames=('Five Piles',)))

View file

@ -355,7 +355,7 @@ class CribbagePatience_HandStack(ReserveStack):
def clickHandler(self, event):
for s in self.game.s.rows[0:4]:
if len(s.cards) == 0:
if len(s.cards) == 0 and s.acceptsCards(self, self.cards):
return self.playMoveMove(1, s)
return 0
@ -367,26 +367,32 @@ class CribbagePatience_HandStack(ReserveStack):
def moveMove(self, ncards, to_stack, frames=-1, shadow=-1):
ReserveStack.moveMove(self, ncards, to_stack, frames=frames,
shadow=shadow)
self.game.dealAdditionalHand()
if self.game.isBoardFull():
self.game.finalizeHand()
class CribbagePatience_CribStack(ReserveStack):
def acceptsCards(self, from_stack, cards):
if from_stack not in self.game.s.rows[4:10]:
if from_stack not in self.game.s.rows[4:]:
return False
if self.game.HANDS > 1:
if (len(self.game.s.rows[10].cards) > 0 and
from_stack not in self.game.s.rows[10:]):
return False
return ReserveStack.acceptsCards(self, from_stack, cards)
class CribbagePatience(CribbageShuffle):
WIN_SCORE = 61
WIN_SCORE = 80
HANDS = 1
def createGame(self):
self.score = 0
self.isFinalizedHand = False
l, s = Layout(self), self.s
self.setSize((2 * l.XM) + 8 * l.XS,
l.YM + l.YS + 12 * l.YOFFSET)
l.YM + ((self.HANDS + 1) * l.YS))
x, y = self.getInvisibleCoords()
s.waste = ReserveStack(x, y, self)
x, y = l.XM, l.YM
@ -398,20 +404,33 @@ class CribbagePatience(CribbageShuffle):
x += l.XS
x, y = l.XM, l.YM + l.YS
s.reserves.append(ReserveStack(x, y, self))
x += 2 * l.XS
for i in range(6):
s.rows.append(CribbagePatience_HandStack(x, y, self, max_move=1))
x += l.XS
for i in range(self.HANDS):
x += 2 * l.XS
for i in range(6):
s.rows.append(CribbagePatience_HandStack(x, y, self,
max_move=1))
x += l.XS
x, y = l.XM, y + l.YS
# define hands for scoring
r = s.rows
self.cribbage_hands = [
r[0:4], r[4:8]
]
if self.HANDS == 1:
self.cribbage_hands = [
r[0:4], r[4:8]
]
else:
self.cribbage_hands = [
r[0:4], r[4:8], r[10:14]
]
self.cribbage_hands = list(map(tuple, self.cribbage_hands))
if self.preview <= 1:
for i in (0, 4):
if self.HANDS == 2:
scores = (0, 4, 10)
else:
scores = (0, 4)
for i in scores:
tx, ty, ta, tf = l.getTextAttr(s.rows[i], anchor="w")
t = MfxCanvasText(self.canvas, tx - 8, ty,
anchor=ta,
@ -444,11 +463,12 @@ class CribbagePatience(CribbageShuffle):
def dealHand(self):
self.startDealSample()
if self.isFinalizedHand:
for r in reversed(self.s.rows[:8]):
r.moveMove(1, self.s.waste)
self.s.reserves[0].moveMove(1, self.s.waste)
self.saveStateMove(2 | 16)
if self.isFinalizedHand:
for r in reversed(self.s.rows):
if (len(r.cards) > 0):
r.moveMove(1, self.s.waste)
self.s.reserves[0].moveMove(1, self.s.waste)
self.isFinalizedHand = False
self.saveStateMove(1 | 16)
@ -456,6 +476,9 @@ class CribbagePatience(CribbageShuffle):
self.s.talon.dealRow(rows=self.s.rows[4:10])
self.stopSamples()
def dealAdditionalHand(self):
return
def isBoardFull(self):
for i in range(8):
if len(self.s.rows[i].cards) == 0:
@ -474,7 +497,7 @@ class CribbagePatience(CribbageShuffle):
self.s.talon.flipMove()
self.s.talon.moveMove(1, self.s.reserves[0])
self.leaveState(old_state)
for i in range(2):
for i in range(len(self.cribbage_hands)):
value = self.getHandScore(self.cribbage_hands[i])
self.texts.list[i].config(text=str(value))
self.score += value
@ -485,12 +508,12 @@ class CribbagePatience(CribbageShuffle):
if self.preview > 1:
return
if self.isBoardFull():
for i in range(2):
for i in range(len(self.cribbage_hands)):
value = self.getHandScore(self.cribbage_hands[i])
self.texts.list[i].config(text=str(value))
else:
for i in range(2):
for i in range(len(self.cribbage_hands)):
self.texts.list[i].config(text="")
#
t = ""
@ -499,6 +522,10 @@ class CribbagePatience(CribbageShuffle):
t += _("Total: %d") % self.score
self.texts.score.config(text=t)
def _autoDeal(self, sound=True):
# don't deal a card to the waste if the waste is empty
return 0
def getUpcardStack(self):
return self.s.reserves[0]
@ -526,6 +553,66 @@ class CribbagePatience(CribbageShuffle):
return [self.score, self.isFinalizedHand]
class CribbagePatienceII(CribbagePatience):
WIN_SCORE = 80
HANDS = 2
def startGame(self):
self.score = 0
self.isFinalizedHand = False
self.dealHand()
def fillStack(self, stack):
if not stack.cards:
old_state = self.enterState(self.S_FILL)
hand = self.s.rows[4:10] + self.s.rows[10:16]
if stack in hand:
i = list(hand).index(stack)
if i < len(hand)-1:
from_stack = hand[i+1]
pile = from_stack.getPile()
if pile:
from_stack.moveMove(len(pile), stack)
self.leaveState(old_state)
def dealHand(self):
self.startDealSample()
if self.isFinalizedHand:
for r in reversed(self.s.rows):
if (len(r.cards) > 0):
r.moveMove(1, self.s.waste)
self.s.reserves[0].moveMove(1, self.s.waste)
self.saveStateMove(2 | 16)
self.isFinalizedHand = False
self.saveStateMove(1 | 16)
self.s.talon.dealRow(rows=self.s.rows[4:10])
self.stopSamples()
def dealAdditionalHand(self):
for i in range(2):
if len(self.s.rows[i].cards) == 0:
return
for i in range(2, 4):
if len(self.s.rows[i].cards) > 0:
return
if len(self.s.rows[10].cards) == 0:
self.startDealSample()
self.saveStateMove(2 | 16)
self.s.talon.dealRow(rows=self.s.rows[10:16])
self.saveStateMove(1 | 16)
self.stopSamples()
def isBoardFull(self):
for i in range(8):
if len(self.s.rows[i].cards) == 0:
return False
for i in range(10, 14):
if len(self.s.rows[i].cards) == 0:
return False
return True
# register the game
registerGame(GameInfo(805, CribbageSquare, "Cribbage Square",
GI.GT_CRIBBAGE_TYPE | GI.GT_SCORE, 1, 0,
@ -551,3 +638,6 @@ registerGame(GameInfo(809, CribbageShuffle, "Cribbage Shuffle",
registerGame(GameInfo(955, CribbagePatience, "Cribbage Patience",
GI.GT_CRIBBAGE_TYPE | GI.GT_SCORE, 1, 0,
GI.SL_MOSTLY_SKILL))
registerGame(GameInfo(980, CribbagePatienceII, "Cribbage Patience II",
GI.GT_CRIBBAGE_TYPE | GI.GT_SCORE, 1, 0,
GI.SL_MOSTLY_SKILL))

View file

@ -1500,7 +1500,6 @@ class HexYukon(Game):
shallHighlightMatch = Game._shallHighlightMatch_AC
# ************************************************************************
# *
# ************************************************************************
@ -1685,6 +1684,68 @@ class WizardsStoreroom(AbstractHexADeckGame):
card1.rank - 1 == card2.rank) and
card1.color != card2.color)
# ************************************************************************
# * Wizard's Castle
# ************************************************************************
class WizardsCastle(AbstractHexADeckGame):
Hint_Class = CautiousDefaultHint
#
# Game layout
#
def createGame(self):
l, s = Layout(self), self.s
# Set window size
h = max(5 * l.YS, 20 * l.YOFFSET)
self.setSize(l.XM + 9 * l.XS, l.YM + l.YS + h)
# Create foundations
x = self.width - l.XS
y = l.YM
s.foundations.append(SS_FoundationStack(x, y, self, 4, max_cards=22))
y = y + l.YS
for i in range(4):
s.foundations.append(
SS_FoundationStack(x, y, self, i, max_cards=14))
y = y + l.YS
# Create rows
x = l.XM
y = l.YM
for j in range(2):
for i in range(8):
s.rows.append(
HexAKlon_RowStack(x, y, self, max_move=1, max_accept=1))
x = x + l.XS
x = l.XM
y = y + l.YS * 3
self.setRegion(s.rows, (-999, -999, l.XM + l.XS * 8, 999999))
# Create talon
s.talon = InitialDealTalonStack(l.XM, self.height-l.YS, self)
# Define stack groups
l.defaultStackGroups()
#
# Game over rides
#
def startGame(self):
for i in range(2):
self.s.talon.dealRow(flip=0, frames=0)
self.s.talon.dealRow(flip=0, frames=0)
self.s.talon.dealRow(rows=self.s.rows[:4], flip=0, frames=0)
self._startAndDealRow()
def shallHighlightMatch(self, stack1, card1, stack2, card2):
return (card1.suit == card2.suit and
(card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank))
# ************************************************************************
# *
# ************************************************************************
@ -1735,4 +1796,6 @@ r(16683, WizardsStoreroom, "Wizard's Storeroom", GI.GT_HEXADECK, 1, 1,
GI.SL_MOSTLY_SKILL)
r(16684, WizardsStoreroom, "Big Storeroom", GI.GT_HEXADECK, 2, 1,
GI.SL_MOSTLY_SKILL)
r(16685, WizardsCastle, "Wizard's Castle", GI.GT_HEXADECK, 1, 0,
GI.SL_BALANCED)
del r

View file

@ -222,6 +222,7 @@ def r(id, short_name, width):
return gi
r(22399, "Lights Out 3x3", 3)
r(22400, "Lights Out 4x4", 4)
r(22401, "Lights Out 5x5", 5)
r(22402, "Lights Out 6x6", 6)

View file

@ -914,7 +914,8 @@ registerGame(GameInfo(466, DoubleRussianSolitaire, "Double Russian Solitaire",
registerGame(GameInfo(488, TripleRussianSolitaire, "Triple Russian Solitaire",
GI.GT_YUKON, 3, 0, GI.SL_BALANCED))
registerGame(GameInfo(492, Geoffrey, "Geoffrey",
GI.GT_YUKON, 1, 0, GI.SL_MOSTLY_SKILL))
GI.GT_YUKON, 1, 0, GI.SL_MOSTLY_SKILL,
altnames=('Thornq',)))
registerGame(GameInfo(525, Queensland, "Queensland",
GI.GT_YUKON, 1, 0, GI.SL_BALANCED))
registerGame(GameInfo(526, OutbackPatience, "Outback Patience",
@ -951,4 +952,5 @@ registerGame(GameInfo(942, QuadrupleYukon, "Quadruple Yukon",
registerGame(GameInfo(963, Sevastopol, "Sevastopol",
GI.GT_SPIDER, 1, 0, GI.SL_BALANCED))
registerGame(GameInfo(964, RussianCell, "Russian Cell",
GI.GT_YUKON, 1, 0, GI.SL_BALANCED))
GI.GT_YUKON, 1, 0, GI.SL_BALANCED,
altnames=('Finnish Solitaire',)))

View file

@ -662,20 +662,21 @@ class CardsetInfoDialog(MfxDialog):
row += 1
styles = nationalities = year = None
if cardset.si.styles:
styles = '\n'.join([CSI.STYLE[i] for i in cardset.si.styles])
styles = '\n'.join(sorted([CSI.STYLE[i]
for i in cardset.si.styles]))
if cardset.si.nationalities:
nationalities = '\n'.join([CSI.NATIONALITY[i]
for i in cardset.si.nationalities])
nationalities = '\n'.join(sorted([CSI.NATIONALITY[i]
for i in
cardset.si.nationalities]))
if cardset.year:
year = str(cardset.year)
frow = 0
for n, t in (
# ('Version:', str(cardset.version)),
(_('Type:'), CSI.TYPE[cardset.type]),
(_('Styles:'), styles),
(_('Nationality:'), nationalities),
(_('Year:'), year),
# (_('Number of cards:'), str(cardset.ncards)),
(_('Num. cards:'), str(cardset.ncards)),
(_('Size:'), '%d x %d' % (cardset.CARDW, cardset.CARDH)),
):
if t is not None:

View file

@ -436,20 +436,21 @@ class CardsetInfoDialog(MfxDialog):
padx=0, pady=5, ipadx=5, ipady=5)
styles = nationalities = year = None
if cardset.si.styles:
styles = '\n'.join([CSI.STYLE[i] for i in cardset.si.styles])
styles = '\n'.join(sorted([CSI.STYLE[i]
for i in cardset.si.styles]))
if cardset.si.nationalities:
nationalities = '\n'.join([CSI.NATIONALITY[i]
for i in cardset.si.nationalities])
nationalities = '\n'.join(sorted([CSI.NATIONALITY[i]
for i in
cardset.si.nationalities]))
if cardset.year:
year = str(cardset.year)
row = 0
for n, t in (
# ('Version:', str(cardset.version)),
(_('Type:'), CSI.TYPE[cardset.type]),
(_('Styles:'), styles),
(_('Nationality:'), nationalities),
(_('Year:'), year),
# (_('Number of cards:'), str(cardset.ncards)),
(_('Num. cards:'), str(cardset.ncards)),
(_('Size:'), '%d x %d' % (cardset.CARDW, cardset.CARDH)),
):
if t is not None: