Compare commits
42 commits
android-3.
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
bdd3093a2b | ||
|
c4a62baf79 | ||
|
b1370fce08 | ||
|
7b85049f7c | ||
|
afc74a86f5 | ||
|
50e003e256 | ||
|
78de569074 | ||
|
a79c81109b | ||
|
c14be7b73e | ||
|
69c1440b2b | ||
|
72386af5e6 | ||
|
a57f1eae38 | ||
|
6f0c6e00e1 | ||
|
512d3ea466 | ||
|
e7e9f0ff87 | ||
|
9773eee2d6 | ||
|
015e860557 | ||
|
04b7eacfcb | ||
|
52e2ffc58f | ||
|
81150b4681 | ||
|
f799093e35 | ||
|
12118d12ed | ||
|
fd4a4e1378 | ||
|
63a63fdfd3 | ||
|
ff9cc5e98c | ||
|
cadf8b2084 | ||
|
f4dec3ed16 | ||
|
5c8d5c26b4 | ||
|
cb0dd1ec2f | ||
|
dc5ab96c80 | ||
|
54a978b4e2 | ||
|
5b9f64a7eb | ||
|
21c2780e8e | ||
|
ed2da8cd46 | ||
|
054c0f0368 | ||
|
487d1c52f3 | ||
|
6852bb40ff | ||
|
6006e0f4c0 | ||
|
68138c7284 | ||
|
96a06108af | ||
|
ac03fa741d | ||
|
7cac54b714 |
|
@ -2,7 +2,7 @@
|
|||
image: Visual Studio 2022
|
||||
environment:
|
||||
matrix:
|
||||
- PYTHON: "C:\\Python312"
|
||||
- PYTHON: "C:\\Python313"
|
||||
# Shamelessly taken from https://github.com/plicease/Dist-Zilla-PluginBundle-Author-Plicease/blob/master/.appveyor.yml
|
||||
# Thanks!
|
||||
install:
|
||||
|
|
BIN
data/tiles/Felt_Blue.png
Normal file
After Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 351 B After Width: | Height: | Size: 350 B |
|
@ -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>
|
||||
|
|
64
html-src/faq.html
Normal file
|
@ -0,0 +1,64 @@
|
|||
<h1>FAQ</h1>
|
||||
<h2>The animation is too slow...</h2>
|
||||
<p>
|
||||
Unfortunately the Tcl/Tk toolkit lacks a sprite concept, so
|
||||
there is a lot of (invisible double-buffered) redraw going on
|
||||
when dragging cards around.
|
||||
<p>
|
||||
Disabling <i>Card shadow</i>, <i>Shade legal moves</i>,
|
||||
background table tiles and sound will somewhat improve the display speed.
|
||||
|
||||
<h2>The table tiles look strange</h2>
|
||||
<p>
|
||||
Background table tiles should only be enabled when using
|
||||
a true-color video mode - otherwise they may look bad
|
||||
because of dithering.
|
||||
<p>
|
||||
BTW, you can add your own background tiles by copying the images
|
||||
to the main <i>data/tiles</i> or your home <i>~/.PySolFC/tiles</i> directory.
|
||||
<!-- They must be in GIF or PPM format. -->
|
||||
|
||||
<h2>My antivirus app says the Windows installer contains a virus.</h2>
|
||||
<p>
|
||||
We have been asked about the fact that some anti viruses, including those
|
||||
on <a href="https://www.virustotal.com/">VirusTotal</a>, have identified the Microsoft
|
||||
Windows downloads as containing malware. What we know is that they are generated from
|
||||
the <a href="https://en.wikipedia.org/wiki/Free_and_open-source_software">open source</a>
|
||||
source code by <a href="https://www.appveyor.com/">AppVeyor</a>, are checked using
|
||||
VirusTotal before they are uploaded, and at that point were considered to be malware clean.
|
||||
<p>
|
||||
However, as time passes, they seem to accumulate classifyings as containing malware
|
||||
in what appears to be <a href="https://en.wikipedia.org/wiki/False_positives_and_false_negatives">false positives</a>. So we believe the downloads are nonetheless safe and free of
|
||||
malware.
|
||||
<p>
|
||||
Furthermore, note that we believe that many anti-malware applications are harmful
|
||||
by themselves, and that they are all an incomplete (non-)solution to an
|
||||
issue that does not exist in <a href="https://en.wikipedia.org/wiki/Linux#Desktop">Linux</a> and the <a href="https://en.wikipedia.org/wiki/List_of_BSD_operating_systems">BSDs operating systems</a>.
|
||||
<p>
|
||||
For more information, see:
|
||||
<ol>
|
||||
<li><a href="https://sourceforge.net/p/pysolfc/discussion/503709/thread/d841b6a1/">Forum discussion</a></li>
|
||||
<li><a href="http://linuxmafia.com/~rick/faq/">Viruses on Linux</a></li>
|
||||
<li><a href="https://www.mail-archive.com/wikimedia-l@lists.wikimedia.org/msg30001.html">Discussion about anti-viruses.</a></li>
|
||||
</ol>
|
||||
|
||||
<h2>I received an error that there is no module named "formatter".</h2>
|
||||
<p>
|
||||
This error occurs if you're trying to run an older version of PySolFC
|
||||
with Python 3.10. If you are using Python 3.10 or later, please upgrade your
|
||||
version of PySolFC to 2.14.0 or later - older versions are not compatible with
|
||||
Python 3.10.
|
||||
<p>
|
||||
If you are getting your copy from your Linux distribution's package manager,
|
||||
please contact the people who maintain the packages for your distribution.
|
||||
You can always get the latest version from the PySolFC website or from
|
||||
Flathub.
|
||||
|
||||
<h2>It won't let me deal more cards in Spider.</h2>
|
||||
<p>
|
||||
When playing Spider, you are not allowed to deal more cards if there are any
|
||||
empty piles. If there aren't enough cards left to put one in each pile, the
|
||||
game is lost. Part of the game is planning ahead when to deal more cards to
|
||||
avoid this situation.
|
||||
<p>
|
||||
If you want a variation without this rule, you can play Relaxed Spider instead.
|
|
@ -46,6 +46,7 @@ fix_gettext()
|
|||
files = [
|
||||
('credits.html', 'PySol Credits'),
|
||||
('credits_old.html', 'PySol Credits'),
|
||||
('faq.html', 'PySol - FAQ'),
|
||||
('ganjifa.html', 'PySol - General Ganjifa Card Rules'),
|
||||
('general_rules.html', 'PySol - General Rules'),
|
||||
('glossary.html', 'PySol - Glossary'),
|
||||
|
|
|
@ -323,6 +323,15 @@ the deck.</p>
|
|||
Hearts, and Diamonds.</p>
|
||||
</dd>
|
||||
|
||||
<dt><b>SUPER MOVE</b></dt>
|
||||
|
||||
<dd>
|
||||
<p>A special move where you move a sequence of cards at once, in a game
|
||||
that does not normally allow it. However, if there are enough open
|
||||
reserves and empty stacks to perform the move by moving cards between
|
||||
them one at a time, you can make it as a single move as a shortcut.</p>
|
||||
</dd>
|
||||
|
||||
<dt><b>TABLEAU</b></dt>
|
||||
|
||||
<dd>
|
||||
|
|
|
@ -55,27 +55,6 @@ disable certain features as they would be trivial otherwise.
|
|||
The logic involved is not too clever on purpose (i.e. it does not consult the hint system).
|
||||
</ul>
|
||||
|
||||
<h2>The animation is too slow...</h2>
|
||||
<p>
|
||||
Unfortunately the Tcl/Tk toolkit lacks a sprite concept, so
|
||||
there is a lot of (invisible double-buffered) redraw going on
|
||||
when dragging cards around.
|
||||
<p>
|
||||
Disabling <i>Card shadow</i>, <i>Shade legal moves</i>,
|
||||
background table tiles and sound will somewhat improve the display speed.
|
||||
|
||||
|
||||
<h2>The table tiles look strange</h2>
|
||||
<p>
|
||||
Background table tiles should only be enabled when using
|
||||
a true-color video mode - otherwise they may look bad
|
||||
because of dithering.
|
||||
<p>
|
||||
BTW, you can add your own background tiles by copying the images
|
||||
to the main <i>data/tiles</i> or your home <i>~/.PySolFC/tiles</i> directory.
|
||||
<!-- They must be in GIF or PPM format. -->
|
||||
|
||||
|
||||
<h2>Some notes about scoring</h2>
|
||||
<p>
|
||||
<ul type="disc">
|
||||
|
|
|
@ -19,9 +19,10 @@
|
|||
<li> <a href="cardset_customization.html">Cardset Customization</a>
|
||||
<li> <a href="plugins.html">Plugins</a>
|
||||
</ul>
|
||||
<h2>Misc</h2>
|
||||
<h2>About</h2>
|
||||
<ul>
|
||||
<li> <a href="news.html">What's new?</a>
|
||||
<li> <a href="faq.html">FAQ</a>
|
||||
<li> <a href="report_bug.html">Report a Bug</a>
|
||||
<li> <a href="license.html">PySol license terms</a>
|
||||
<li> <a href="credits.html">PySol credits</a>
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
<h1>Report a Bug</h1>
|
||||
<p>
|
||||
Before you report a bug, please verify that you are running
|
||||
the latest version of PySolFC, and also check the PySolFC site's
|
||||
<a href="https://pysolfc.sourceforge.io/faq.html">FAQ page</a>,
|
||||
and issues previously reported on GitHub, to ensure that the bug
|
||||
was not previously reported.
|
||||
the latest version of PySolFC. Also, check the
|
||||
<a href="faq.html">FAQ</a>, and issues previously reported
|
||||
on GitHub, to ensure that the bug was not previously reported.
|
||||
<p>
|
||||
If you found a bug in PySolFC, the best place to report it
|
||||
is on GitHub. To do so, create an issue at
|
||||
|
|
|
@ -15,7 +15,7 @@ This card must be the last remaining card in order to win the game.
|
|||
<h3>Notes</h3>
|
||||
<p>
|
||||
Accordion's Revenge is unwinnable if the first or second card is
|
||||
declared. As such, PySol will reselect the declared card if it
|
||||
is chosen.
|
||||
declared. As such, PySol will never select either of those cards as
|
||||
the target.
|
||||
<p>
|
||||
The concept of Accordion's Revenge was invented by Mark Masten.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<h1>Big Braid</h1>
|
||||
<h1>Big Braid (Der große Zopf)</h1>
|
||||
<p>
|
||||
Napoleon type. 3 decks. 2 redeals.
|
||||
|
||||
|
|
13
html-src/rules/bigstoreroom.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<h1>Big Storeroom</h1>
|
||||
<p>
|
||||
Hex A Deck type. 2 decks. 1 redeal.
|
||||
|
||||
<h3>Object</h3>
|
||||
<p>
|
||||
Move all cards to the foundations.
|
||||
|
||||
<h3>Rules</h3>
|
||||
<p>
|
||||
Like <a href="wizardsstoreroom.html">Wizard's Storeroom</a>
|
||||
but with two decks and nine piles.
|
||||
|
15
html-src/rules/colours.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
<h1>Colours</h1>
|
||||
<p>
|
||||
Numerica type. 1 deck. No redeal.
|
||||
|
||||
<h3>Object</h3>
|
||||
<p>
|
||||
Move all cards to the foundations.
|
||||
|
||||
<h3>Quick Description</h3>
|
||||
<p>
|
||||
Like <a href="ladybetty.html">Lady Betty</a>,
|
||||
but the foundations are built up by same color, and
|
||||
wrap from king to ace. At the start of the game, a
|
||||
two through five are dealt to the foundations, in
|
||||
alternating colors.
|
|
@ -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
|
||||
|
|
18
html-src/rules/cribbagepatienceii.html
Normal 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.
|
27
html-src/rules/families.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
<h1>Families</h1>
|
||||
<p>
|
||||
Memory game type. 32 cards. No redeal.
|
||||
|
||||
<h3>Object</h3>
|
||||
<p>
|
||||
Remove all groups of jack-queen-king of the same suit.
|
||||
|
||||
<h3>Rules</h3>
|
||||
<p>
|
||||
Families is played with eight sets of Jack, Queen, and King - two of
|
||||
each suit, along with six black jokers and two red jokers.
|
||||
<p>
|
||||
Flip three cards. If you flip a sequence of Jack, Queen, and King of
|
||||
the same suit, the cards are removed. If not, they are flipped face-down.
|
||||
<p>
|
||||
If a red joker is flipped, all of the remaining unmatched cards that were
|
||||
not flipped are reshuffled and redealt (after you've flipped all three
|
||||
cards).
|
||||
<p>
|
||||
If a pair of black jokers is flipped, the game is lost. If all eight
|
||||
sequences are removed before this happens, the game is won.
|
||||
|
||||
<h3>Notes</h3>
|
||||
<p>
|
||||
<i>Undo</i>, <i>Bookmarks</i>, <i>Autodrop</i> and <i>Quickplay</i>
|
||||
are disabled for this game.
|
22
html-src/rules/flamboyant.html
Normal 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.
|
|
@ -1,6 +1,6 @@
|
|||
<h1>Hurricane</h1>
|
||||
<p>
|
||||
Pairing game type. 1 deck. No redeal.
|
||||
Pairing type. 1 deck. No redeal.
|
||||
|
||||
<h3>Object</h3>
|
||||
<p>
|
||||
|
|
12
html-src/rules/idesofmarch.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<h1>Ides of March</h1>
|
||||
<p>
|
||||
Pairing type. 1 deck. No redeal.
|
||||
|
||||
<h3>Object</h3>
|
||||
<p>
|
||||
Move all cards to the single foundation.
|
||||
|
||||
<h3>Quick Description</h3>
|
||||
<p>
|
||||
Like <a href="hurricane.html">Hurricane</a>,
|
||||
but remove pairs whose ranks total 15, or pairs of aces.
|
12
html-src/rules/littleishido.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<h1>Little Ishido</h1>
|
||||
<p>
|
||||
Ishido game type. 2 decks. No redeal.
|
||||
|
||||
<h3>Object</h3>
|
||||
<p>
|
||||
Move all tiles to the playing area.
|
||||
|
||||
<h3>Quick Description</h3>
|
||||
<p>
|
||||
Like <a href='ishido.html'>Ishido</a>, but with four colors and symbols,
|
||||
and a 6X8 grid. The initial tiles are placed in the four corners only.
|
14
html-src/rules/littleishidorelaxed.html
Normal file
|
@ -0,0 +1,14 @@
|
|||
<h1>Little Ishido Relaxed</h1>
|
||||
<p>
|
||||
Ishido game type. 2 decks. No redeal.
|
||||
|
||||
<h3>Object</h3>
|
||||
<p>
|
||||
Move all tiles to the playing area.
|
||||
|
||||
<h3>Quick Description</h3>
|
||||
<p>
|
||||
Like <a href='ishido.html'>Ishido</a>, but with four colors and symbols,
|
||||
and a 6X8 grid. The initial tiles are placed in the four corners only.
|
||||
Also, there are no restrictions when placing a tile next to two or more
|
||||
other tiles - they just have to match the color or symbol of each.
|
19
html-src/rules/louis.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<h1>Louis</h1>
|
||||
<p>
|
||||
Two-Deck game type. 2 decks. 2 redeals.
|
||||
|
||||
<h3>Object</h3>
|
||||
<p>
|
||||
Move all the cards to the foundations.
|
||||
|
||||
<h3>Quick Description</h3>
|
||||
<p>
|
||||
Like <a href="sthelena.html">St. Helena</a>,
|
||||
but at the start of the game, a card is dealt to each of the
|
||||
twelve tableau piles. During this round, an empty tableau pile
|
||||
will be immediately filled from the talon. When no moves are left,
|
||||
the rest of the deck can be dealt.
|
||||
<p>
|
||||
Also, there are no restrictions as to which tableau piles
|
||||
cards can be moved to foundations from, and tableau piles are
|
||||
built up or down by same suit.
|
27
html-src/rules/microbe.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
<h1>Microbe</h1>
|
||||
<p>
|
||||
Spider type. 2 decks. No redeal.
|
||||
|
||||
<h3>Object</h3>
|
||||
<p>
|
||||
Group all the cards in sets of 13 cards in descending sequence
|
||||
by alternate color from King to Ace and move such sets to the foundations.
|
||||
|
||||
<h3>Rules</h3>
|
||||
<p>
|
||||
The decks are separated. From one deck, four cards are dealt to each of
|
||||
eleven tableau piles, with alternating cards face-up and face-down (the
|
||||
bottom and third from the bottom cards are face-down). The remaining
|
||||
eight cards from that deck are combined with the other deck to form the
|
||||
talon.
|
||||
<p>
|
||||
Tableau piles are built down by alternate color, and any card or valid
|
||||
sequence of cards can be moved between tableau piles. Any valid card or
|
||||
sequence can fill empty piles.
|
||||
<p>
|
||||
The object is to group the cards in sets of 13 cards, from King to Ace
|
||||
in an alternating color sequence. Such groups can be moved to the foundations.
|
||||
<p>
|
||||
When there are no moves left, you can deal one card from the talon to
|
||||
each tableau pile. The game is won if all cards are grouped into sequences
|
||||
and moved to the foundations.
|
27
html-src/rules/noumea.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
<h1>Noumea</h1>
|
||||
<p>
|
||||
One-Deck game type. 1 decks. 2 redeals.
|
||||
|
||||
<h3>Object</h3>
|
||||
<p>
|
||||
Move all cards to the foundations.
|
||||
|
||||
<h3>Rules</h3>
|
||||
<p>
|
||||
The four aces are dealt to the foundations, and 20 cards
|
||||
are dealt to reserve piles. The reserve piles can hold a
|
||||
single card and are automatically filled from the waste or
|
||||
talon when empty.
|
||||
<p>
|
||||
There is no building on the tableau piles, so you can
|
||||
only move cards to the foundations.
|
||||
<p>
|
||||
When there are no moves left, you can deal cards three at
|
||||
a time from the talon, and move them to an appropriate
|
||||
foundation. Two redeals are allowed, so you can go through
|
||||
the deck three times. The game is won if all cards are
|
||||
moved to the foundations.
|
||||
|
||||
<h3>Notes</h3>
|
||||
<p>
|
||||
<i>Autodrop</i> is disabled for this game.
|
12
html-src/rules/outbackpatience.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<h1>Outback Patience</h1>
|
||||
<p>
|
||||
Yukon type. 2 decks. No redeal.
|
||||
|
||||
<h3>Object</h3>
|
||||
<p>
|
||||
Move all cards to the foundations.
|
||||
|
||||
<h3>Quick Description</h3>
|
||||
<p>
|
||||
Like <a href="austalianpatience.html">Australian Patience</a>,
|
||||
but with two decks, and eight piles of seven cards each.
|
22
html-src/rules/pyramidthirteen.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
<h1>Pyramid Thirteen</h1>
|
||||
<p>
|
||||
Pairing game type. 1 deck. No redeal.
|
||||
|
||||
<h3>Object</h3>
|
||||
<p>
|
||||
Move all cards to the single foundation.
|
||||
|
||||
<h3>Quick Description</h3>
|
||||
<p>
|
||||
Like <a href="pyramid.html">Pyramid</a>, but all but the
|
||||
front row of the pyramid are dealt face-down, and no redeals
|
||||
are allowed.
|
||||
|
||||
<h3>Notes</h3>
|
||||
<p>
|
||||
This difficult variant of Pyramid is based on the Gnome AisleRiot
|
||||
rules. It is called "Thirteen" there, but renamed Pyramid Thirteen
|
||||
here to avoid confusion with the game
|
||||
<a href="thirteens.html">Thirteens</a>.
|
||||
<p>
|
||||
<i>Quickplay</i> is disabled for this game.
|
12
html-src/rules/relaxedcruel.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<h1>Relaxed Cruel</h1>
|
||||
<p>
|
||||
Baker's Dozen type. 1 deck. Unlimited redeals.
|
||||
|
||||
<h3>Object</h3>
|
||||
<p>
|
||||
Move all cards to the foundations.
|
||||
|
||||
<h3>Quick Description</h3>
|
||||
<p>
|
||||
Just like <a href="cruel.html">Cruel</a>,
|
||||
but the number of cards you can move as a sequence is not restricted.
|
13
html-src/rules/waspii.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<h1>Wasp II</h1>
|
||||
<p>
|
||||
Spider type. 1 deck. No redeal.
|
||||
|
||||
<h3>Object</h3>
|
||||
<p>
|
||||
Move all cards to the foundations.
|
||||
|
||||
<h3>Quick Description</h3>
|
||||
<p>
|
||||
Like <a href="wasp.html">Wasp</a>,
|
||||
but only three of the tableau piles contain
|
||||
face-down cards (similar to <a href="scorpionii.html">Scorpion II</a>).
|
15
html-src/rules/wizardscastle.html
Normal 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.
|
23
html-src/rules/wizardsstoreroom.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
<h1>Wizard's Storeroom</h1>
|
||||
<p>
|
||||
Hex A Deck type. 1 deck. 1 redeal.
|
||||
|
||||
<h3>Object</h3>
|
||||
<p>
|
||||
Move all cards to the foundations.
|
||||
|
||||
<h3>Rules</h3>
|
||||
<p>
|
||||
The tableau consists of one reserve stack and five row stacks.
|
||||
Fourteen cards are dealt to the reserve stack and one card each to the
|
||||
row stacks. When a row stack is emptied it must be filled from the reserve
|
||||
stack first. When the reserve stack is empty any card can be played on an
|
||||
empty row stack. Wizards are wild - any card can be played on them, and they
|
||||
can be played on any card. The Wizards have ranks like the suit cards
|
||||
corresponding to Ace through Four. If a Wizard is played in it's proper rank
|
||||
position the row can still be moved, otherwise, the full sequence can't be moved.
|
||||
The row stacks build down in rank by alternate colors.
|
||||
<p>
|
||||
The foundations build up in rank by suit. The Wizards will not move off of the
|
||||
tableau until all the other cards have been moved to the foundations.
|
||||
The game is won when all cards are moved to the foundations.
|
|
@ -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"
|
||||
|
@ -2653,7 +2653,7 @@ msgid "Automatic play"
|
|||
msgstr "Automatisierung"
|
||||
|
||||
#: pysollib/kivy/menubar.py:513
|
||||
msgid "Auto face up"
|
||||
msgid "Auto face-up"
|
||||
msgstr "Automatisch aufdecken"
|
||||
|
||||
#: pysollib/kivy/menubar.py:523
|
||||
|
@ -4189,6 +4189,9 @@ msgstr "Nationalität:"
|
|||
msgid "Year:"
|
||||
msgstr "Jahr:"
|
||||
|
||||
msgid "Num. cards:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compatible with current game"
|
||||
msgstr ""
|
||||
|
||||
|
@ -4370,6 +4373,9 @@ msgstr "Aktuelle Sitzung"
|
|||
msgid "Log"
|
||||
msgstr "Protokoll"
|
||||
|
||||
msgid "Demo Log"
|
||||
msgstr ""
|
||||
|
||||
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
||||
msgid "Full log"
|
||||
msgstr "Volles Protokoll"
|
||||
|
@ -5171,6 +5177,9 @@ msgstr "Kommentare..."
|
|||
msgid "Log..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Demo log..."
|
||||
msgstr ""
|
||||
|
||||
#: pysollib/ui/tktile/menubar.py:427
|
||||
msgid "D&emo statistics..."
|
||||
msgstr "D&emo Statistiken..."
|
||||
|
|
|
@ -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"
|
||||
|
@ -2694,7 +2694,7 @@ msgid "Automatic play"
|
|||
msgstr "Jouer auto"
|
||||
|
||||
#: pysollib/kivy/menubar.py:513
|
||||
msgid "Auto face up"
|
||||
msgid "Auto face-up"
|
||||
msgstr "Retourner auto"
|
||||
|
||||
#: pysollib/kivy/menubar.py:523
|
||||
|
@ -4240,6 +4240,9 @@ msgstr "Origine:"
|
|||
msgid "Year:"
|
||||
msgstr "Année:"
|
||||
|
||||
msgid "Num. cards:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compatible with current game"
|
||||
msgstr ""
|
||||
|
||||
|
@ -4421,6 +4424,9 @@ msgstr "Session en cours"
|
|||
msgid "Log"
|
||||
msgstr "Journal"
|
||||
|
||||
msgid "Demo Log"
|
||||
msgstr ""
|
||||
|
||||
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
||||
msgid "Full log"
|
||||
msgstr "Journal complet"
|
||||
|
@ -5222,6 +5228,9 @@ msgstr "&Commentaires..."
|
|||
msgid "Log..."
|
||||
msgstr "Journal..."
|
||||
|
||||
msgid "Demo log..."
|
||||
msgstr ""
|
||||
|
||||
#: pysollib/ui/tktile/menubar.py:427
|
||||
msgid "D&emo statistics..."
|
||||
msgstr "Statistiques d&émo..."
|
||||
|
|
|
@ -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"
|
||||
|
@ -2707,7 +2707,7 @@ msgstr "Gioco automatico"
|
|||
|
||||
#: pysollib/kivy/menubar.py:513
|
||||
#, fuzzy
|
||||
msgid "Auto face up"
|
||||
msgid "Auto face-up"
|
||||
msgstr "Auto &scopri"
|
||||
|
||||
#: pysollib/kivy/menubar.py:523
|
||||
|
@ -4303,6 +4303,9 @@ msgstr "Nazionalità:"
|
|||
msgid "Year:"
|
||||
msgstr "Anno:"
|
||||
|
||||
msgid "Num. cards:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compatible with current game"
|
||||
msgstr ""
|
||||
|
||||
|
@ -4485,6 +4488,9 @@ msgstr "Questa sessione"
|
|||
msgid "Log"
|
||||
msgstr "Log"
|
||||
|
||||
msgid "Demo Log"
|
||||
msgstr ""
|
||||
|
||||
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
||||
msgid "Full log"
|
||||
msgstr "Log completo"
|
||||
|
@ -5288,6 +5294,9 @@ msgstr "&Commenti..."
|
|||
msgid "Log..."
|
||||
msgstr "Log..."
|
||||
|
||||
msgid "Demo log..."
|
||||
msgstr ""
|
||||
|
||||
#: pysollib/ui/tktile/menubar.py:427
|
||||
msgid "D&emo statistics..."
|
||||
msgstr "Statistiche d&emo..."
|
||||
|
|
|
@ -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"
|
||||
|
@ -2707,7 +2707,7 @@ msgid "Automatic play"
|
|||
msgstr "Gra &automatyczna"
|
||||
|
||||
#: pysollib/kivy/menubar.py:513
|
||||
msgid "Auto face up"
|
||||
msgid "Auto face-up"
|
||||
msgstr "Odkrywaj automatycznie"
|
||||
|
||||
#: pysollib/kivy/menubar.py:523
|
||||
|
@ -4257,6 +4257,9 @@ msgstr "Narodowość:"
|
|||
msgid "Year:"
|
||||
msgstr "Rok:"
|
||||
|
||||
msgid "Num. cards:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compatible with current game"
|
||||
msgstr ""
|
||||
|
||||
|
@ -4438,6 +4441,9 @@ msgstr "Bieżąca sesja"
|
|||
msgid "Log"
|
||||
msgstr "Log"
|
||||
|
||||
msgid "Demo Log"
|
||||
msgstr ""
|
||||
|
||||
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
||||
msgid "Full log"
|
||||
msgstr "Kompletny log"
|
||||
|
@ -5242,6 +5248,9 @@ msgstr "Komentarze..."
|
|||
msgid "Log..."
|
||||
msgstr "Log..."
|
||||
|
||||
msgid "Demo log..."
|
||||
msgstr ""
|
||||
|
||||
#: pysollib/ui/tktile/menubar.py:427
|
||||
msgid "D&emo statistics..."
|
||||
msgstr "D&emo statystyk..."
|
||||
|
|
|
@ -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"
|
||||
|
@ -2715,7 +2715,7 @@ msgid "Automatic play"
|
|||
msgstr "Jogar automaticamente"
|
||||
|
||||
#: pysollib/kivy/menubar.py:513
|
||||
msgid "Auto face up"
|
||||
msgid "Auto face-up"
|
||||
msgstr "Virar pra cima automaticamente"
|
||||
|
||||
#: pysollib/kivy/menubar.py:523
|
||||
|
@ -4263,6 +4263,9 @@ msgstr "Nacionalidade:"
|
|||
msgid "Year:"
|
||||
msgstr "Ano:"
|
||||
|
||||
msgid "Num. cards:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compatible with current game"
|
||||
msgstr ""
|
||||
|
||||
|
@ -4444,6 +4447,9 @@ msgstr "Sessão atual"
|
|||
msgid "Log"
|
||||
msgstr "registro"
|
||||
|
||||
msgid "Demo Log"
|
||||
msgstr ""
|
||||
|
||||
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
||||
msgid "Full log"
|
||||
msgstr "Registro completo"
|
||||
|
@ -5244,6 +5250,9 @@ msgstr "&Comentários..."
|
|||
msgid "Log..."
|
||||
msgstr "Registro"
|
||||
|
||||
msgid "Demo log..."
|
||||
msgstr ""
|
||||
|
||||
#: pysollib/ui/tktile/menubar.py:427
|
||||
msgid "D&emo statistics..."
|
||||
msgstr "Estatísticas de D&emo..."
|
||||
|
|
11
po/pysol.pot
|
@ -2524,7 +2524,7 @@ msgid "Automatic play"
|
|||
msgstr ""
|
||||
|
||||
#: pysollib/kivy/menubar.py:513
|
||||
msgid "Auto face up"
|
||||
msgid "Auto face-up"
|
||||
msgstr ""
|
||||
|
||||
#: pysollib/kivy/menubar.py:523
|
||||
|
@ -4045,6 +4045,9 @@ msgstr ""
|
|||
msgid "Year:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Num. cards:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compatible with current game"
|
||||
msgstr ""
|
||||
|
||||
|
@ -4224,6 +4227,9 @@ msgstr ""
|
|||
msgid "Log"
|
||||
msgstr ""
|
||||
|
||||
msgid "Demo Log"
|
||||
msgstr ""
|
||||
|
||||
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
||||
msgid "Full log"
|
||||
msgstr ""
|
||||
|
@ -4974,6 +4980,9 @@ msgstr ""
|
|||
msgid "Log..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Demo log..."
|
||||
msgstr ""
|
||||
|
||||
#: pysollib/ui/tktile/menubar.py:427
|
||||
msgid "D&emo statistics..."
|
||||
msgstr ""
|
||||
|
|
|
@ -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"
|
||||
|
@ -2713,7 +2713,7 @@ msgstr "Настройки &автоматической игры"
|
|||
|
||||
#: pysollib/kivy/menubar.py:513
|
||||
#, fuzzy
|
||||
msgid "Auto face up"
|
||||
msgid "Auto face-up"
|
||||
msgstr "Автоматически &переворачивать"
|
||||
|
||||
#: pysollib/kivy/menubar.py:523
|
||||
|
@ -4312,6 +4312,9 @@ msgstr "Национальность:"
|
|||
msgid "Year:"
|
||||
msgstr "Год:"
|
||||
|
||||
msgid "Num. cards:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compatible with current game"
|
||||
msgstr ""
|
||||
|
||||
|
@ -4494,6 +4497,9 @@ msgstr "Текущая сессия"
|
|||
msgid "Log"
|
||||
msgstr "Лог"
|
||||
|
||||
msgid "Demo Log"
|
||||
msgstr ""
|
||||
|
||||
#: pysollib/tile/tkstats.py:523 data/pysolfc.glade:1404
|
||||
msgid "Full log"
|
||||
msgstr "Полный лог"
|
||||
|
@ -5311,6 +5317,9 @@ msgstr "&Комментарии..."
|
|||
msgid "Log..."
|
||||
msgstr "Лог..."
|
||||
|
||||
msgid "Demo log..."
|
||||
msgstr ""
|
||||
|
||||
#: pysollib/ui/tktile/menubar.py:427
|
||||
msgid "D&emo statistics..."
|
||||
msgstr "Статистика демо..."
|
||||
|
|
|
@ -35,7 +35,8 @@ from pysollib.app_stat_result import GameStatResult
|
|||
from pysollib.app_statistics import Statistics
|
||||
from pysollib.cardsetparser import read_cardset_config
|
||||
from pysollib.gamedb import GAME_DB, GI, loadGame
|
||||
from pysollib.help import destroy_help_html, help_about, raise_help_html
|
||||
from pysollib.help import (destroy_help_html, help_about, raise_help_html,
|
||||
unraise_help_html)
|
||||
from pysollib.images import Images, SubsampledImages
|
||||
from pysollib.mfxutil import Struct, destruct
|
||||
from pysollib.mfxutil import USE_PIL
|
||||
|
@ -58,6 +59,9 @@ from pysollib.pysoltk import loadImage, wm_withdraw
|
|||
from pysollib.pysoltk import raise_find_card_dialog
|
||||
from pysollib.pysoltk import raise_full_picture_dialog
|
||||
from pysollib.pysoltk import raise_solver_dialog
|
||||
from pysollib.pysoltk import unraise_find_card_dialog
|
||||
from pysollib.pysoltk import unraise_full_picture_dialog
|
||||
from pysollib.pysoltk import unraise_solver_dialog
|
||||
from pysollib.resource import CSI, CardsetManager
|
||||
from pysollib.resource import Music, MusicManager
|
||||
from pysollib.resource import Sample, SampleManager
|
||||
|
@ -525,6 +529,12 @@ class Application:
|
|||
raise_solver_dialog(self.game)
|
||||
raise_help_html(self.game)
|
||||
|
||||
def unraiseAll(self):
|
||||
unraise_find_card_dialog()
|
||||
unraise_full_picture_dialog()
|
||||
unraise_solver_dialog()
|
||||
unraise_help_html()
|
||||
|
||||
def loadImages1(self):
|
||||
# load dialog images
|
||||
dirname = os.path.join("images", "logos")
|
||||
|
|
|
@ -115,18 +115,13 @@ class Statistics:
|
|||
game.GAME_VERSION)
|
||||
# full log
|
||||
if status >= 0:
|
||||
if player is None:
|
||||
# demo
|
||||
ret = self.updateGameStat(player, game, status)
|
||||
else:
|
||||
# player
|
||||
if player not in self.prev_games:
|
||||
self.prev_games[player] = []
|
||||
self.prev_games[player].append(log)
|
||||
if player not in self.all_prev_games:
|
||||
self.all_prev_games[player] = []
|
||||
self.all_prev_games[player].append(log)
|
||||
ret = self.updateGameStat(player, game, status)
|
||||
if player not in self.prev_games:
|
||||
self.prev_games[player] = []
|
||||
self.prev_games[player].append(log)
|
||||
if player not in self.all_prev_games:
|
||||
self.all_prev_games[player] = []
|
||||
self.all_prev_games[player].append(log)
|
||||
ret = self.updateGameStat(player, game, status)
|
||||
# session log
|
||||
if player not in self.session_games:
|
||||
self.session_games[player] = []
|
||||
|
|
|
@ -589,8 +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)
|
||||
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
|
||||
|
|
|
@ -112,7 +112,7 @@ class GI:
|
|||
|
||||
# extra flags
|
||||
GT_BETA = 1 << 12 # beta version of game driver
|
||||
GT_CHILDREN = 1 << 13 # *not used*
|
||||
GT_CHILDREN = 1 << 13
|
||||
GT_CONTRIB = 1 << 14 # contributed games under the GNU GPL
|
||||
GT_HIDDEN = 1 << 15 # not visible in menus, but games can be loaded
|
||||
GT_OPEN = 1 << 16
|
||||
|
@ -320,7 +320,6 @@ class GI:
|
|||
904: 68, # Lexington Harp
|
||||
237: 22231, # Three Peaks
|
||||
297: 631, # Alternation/Alternations
|
||||
526: 447, # Australian/Outback Patience
|
||||
640: 566, # Hypotenuse/Brazilian Patience
|
||||
|
||||
# Lost Mahjongg Layouts
|
||||
|
@ -346,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,)),
|
||||
|
||||
|
@ -368,12 +376,12 @@ class GI:
|
|||
# Hamilton, Labyrinth, Treize, 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, 906, 934, 22231,
|
||||
38, 40, 41, 42, 43, 44, 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, 906, 934, 22231,
|
||||
)),
|
||||
|
||||
# Hoyle Card Games
|
||||
|
@ -575,7 +583,7 @@ class GI:
|
|||
('fc-0.9.0', tuple(range(323, 421))),
|
||||
('fc-0.9.1', tuple(range(421, 441))),
|
||||
('fc-0.9.2', tuple(range(441, 466))),
|
||||
('fc-0.9.3', tuple(range(466, 661))),
|
||||
('fc-0.9.3', tuple(range(466, 526)) + tuple(range(527, 661))),
|
||||
('fc-0.9.4', tuple(range(661, 671))),
|
||||
('fc-1.0', tuple(range(671, 711))),
|
||||
('fc-1.1', tuple(range(711, 759))),
|
||||
|
@ -595,12 +603,14 @@ 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, 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
|
||||
# in the registerGame() call
|
||||
_CHILDREN_GAMES = [16, 33, 55, 90, 91, 96, 97, 176, 328, 329, 862, 865,
|
||||
886, 903, ]
|
||||
_CHILDREN_GAMES = []
|
||||
|
||||
_OPEN_GAMES = []
|
||||
|
||||
|
|
|
@ -504,8 +504,8 @@ class MaineCoon(TabbyCat):
|
|||
|
||||
# register the game
|
||||
registerGame(GameInfo(903, AcesUp, "Aces Up", # was: 52
|
||||
GI.GT_1DECK_TYPE, 1, 0, GI.SL_LUCK,
|
||||
altnames=("Aces High", "Drivel")))
|
||||
GI.GT_1DECK_TYPE | GI.GT_CHILDREN, 1, 0, GI.SL_LUCK,
|
||||
altnames=("Aces High", "Drivel", "Discard")))
|
||||
registerGame(GameInfo(206, Fortunes, "Fortunes",
|
||||
GI.GT_1DECK_TYPE, 1, 0, GI.SL_LUCK))
|
||||
registerGame(GameInfo(213, RussianAces, "Russian Aces",
|
||||
|
@ -514,7 +514,7 @@ registerGame(GameInfo(130, PerpetualMotion, "Perpetual Motion",
|
|||
GI.GT_1DECK_TYPE, 1, -1, GI.SL_MOSTLY_LUCK,
|
||||
altnames=("First Law", "Narcotic")))
|
||||
registerGame(GameInfo(353, AcesUp5, "Aces Up 5",
|
||||
GI.GT_1DECK_TYPE, 1, 0, GI.SL_LUCK))
|
||||
GI.GT_1DECK_TYPE | GI.GT_CHILDREN, 1, 0, GI.SL_LUCK))
|
||||
registerGame(GameInfo(552, Cover, "Cover",
|
||||
GI.GT_1DECK_TYPE, 1, 0, GI.SL_LUCK))
|
||||
registerGame(GameInfo(583, FiringSquad, "Firing Squad",
|
||||
|
|
|
@ -225,6 +225,7 @@ class Vineyard(CastlesInSpain):
|
|||
|
||||
# ************************************************************************
|
||||
# * Cruel
|
||||
# * Relaxed Cruel
|
||||
# * Unusual
|
||||
# ************************************************************************
|
||||
|
||||
|
@ -310,6 +311,10 @@ class Cruel(CastlesInSpain):
|
|||
shallHighlightMatch = Game._shallHighlightMatch_SS
|
||||
|
||||
|
||||
class RelaxedCruel(Cruel):
|
||||
RowStack_Class = StackWrapper(SS_RowStack, base_rank=NO_RANK)
|
||||
|
||||
|
||||
class Unusual(Cruel):
|
||||
|
||||
def createGame(self):
|
||||
|
@ -453,3 +458,6 @@ registerGame(GameInfo(876, Vineyard, "Vineyard",
|
|||
GI.SL_MOSTLY_SKILL))
|
||||
registerGame(GameInfo(907, Martha, "Stewart",
|
||||
GI.GT_BAKERS_DOZEN, 1, 0, GI.SL_BALANCED))
|
||||
registerGame(GameInfo(977, RelaxedCruel, "Relaxed Cruel",
|
||||
GI.GT_BAKERS_DOZEN | GI.GT_OPEN | GI.GT_RELAXED, 1, -1,
|
||||
GI.SL_BALANCED))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -646,7 +646,8 @@ registerGame(GameInfo(376, Backbone, "Backbone",
|
|||
registerGame(GameInfo(377, BackbonePlus, "Backbone +",
|
||||
GI.GT_NAPOLEON, 2, 0, GI.SL_BALANCED))
|
||||
registerGame(GameInfo(510, BigBraid, "Big Braid",
|
||||
GI.GT_NAPOLEON | GI.GT_ORIGINAL, 3, 2, GI.SL_BALANCED))
|
||||
GI.GT_NAPOLEON | GI.GT_ORIGINAL, 3, 2, GI.SL_BALANCED,
|
||||
altnames=("Der grose Zopf",)))
|
||||
registerGame(GameInfo(694, Casket, "Casket",
|
||||
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
||||
registerGame(GameInfo(717, Well, "Well",
|
||||
|
|
|
@ -46,6 +46,11 @@ class Crossword_Hint(AbstractHint):
|
|||
r = rows[i]
|
||||
if r.cards:
|
||||
continue
|
||||
if len(game.s.talon.cards) == 0:
|
||||
for s in game.s.reserves:
|
||||
if game.isValidPlay(r.id, s.getCard().rank + 1):
|
||||
self.addHint(5000, 1, s, r)
|
||||
continue
|
||||
if game.isValidPlay(r.id, game.s.talon.getCard().rank + 1):
|
||||
# TODO: Check a few moves ahead to get better hints.
|
||||
self.addHint(5000, 1, game.s.talon, r)
|
||||
|
|
|
@ -105,6 +105,7 @@ class StrictEiffelTower(EiffelTower):
|
|||
|
||||
# register the game
|
||||
registerGame(GameInfo(16, EiffelTower, "Eiffel Tower",
|
||||
GI.GT_PAIRING_TYPE, 2, 0, GI.SL_MOSTLY_LUCK))
|
||||
GI.GT_PAIRING_TYPE | GI.GT_CHILDREN, 2, 0,
|
||||
GI.SL_MOSTLY_LUCK))
|
||||
# registerGame(GameInfo(801, StrictEiffelTower, "Strict Eiffel Tower",
|
||||
# GI.GT_PAIRING_TYPE, 2, 0))
|
||||
|
|
|
@ -776,11 +776,11 @@ registerGame(GameInfo(697, BigBen, "Big Ben",
|
|||
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED,
|
||||
altnames=("Father Time")))
|
||||
registerGame(GameInfo(737, Clock, "Clock",
|
||||
GI.GT_1DECK_TYPE, 1, 0, GI.SL_LUCK,
|
||||
GI.GT_1DECK_TYPE | GI.GT_CHILDREN, 1, 0, GI.SL_LUCK,
|
||||
altnames=("Travellers", "Sundial")))
|
||||
registerGame(GameInfo(827, GermanClock, "German Clock",
|
||||
GI.GT_1DECK_TYPE, 1, 1, GI.SL_MOSTLY_LUCK,
|
||||
altnames=("Die Uhr",)))
|
||||
registerGame(GameInfo(915, RelaxedClock, "Relaxed Clock",
|
||||
GI.GT_1DECK_TYPE | GI.GT_RELAXED, 1, 0, GI.SL_LUCK,
|
||||
altnames=("Watch")))
|
||||
GI.GT_1DECK_TYPE | GI.GT_RELAXED | GI.GT_CHILDREN, 1, 0,
|
||||
GI.SL_LUCK, altnames=("Watch")))
|
||||
|
|
|
@ -1125,7 +1125,8 @@ registerGame(GameInfo(666, TrapdoorSpider, "Trapdoor Spider",
|
|||
registerGame(GameInfo(712, Leprechaun, "Leprechaun",
|
||||
GI.GT_GYPSY | GI.GT_ORIGINAL, 2, 0, GI.SL_MOSTLY_SKILL))
|
||||
registerGame(GameInfo(718, LockedCards, "Locked Cards",
|
||||
GI.GT_2DECK_TYPE, 2, 2, GI.SL_BALANCED))
|
||||
GI.GT_2DECK_TYPE, 2, 2, GI.SL_BALANCED,
|
||||
altnames=("Prisoners",)))
|
||||
registerGame(GameInfo(721, Thirty, "Thirty",
|
||||
GI.GT_1DECK_TYPE | GI.GT_OPEN | GI.GT_STRIPPED, 1, 0,
|
||||
GI.SL_MOSTLY_SKILL, ranks=(0, 6, 7, 8, 9, 10, 11, 12)))
|
||||
|
@ -1133,7 +1134,7 @@ registerGame(GameInfo(725, TopsyTurvyQueens, "Topsy-Turvy Queens",
|
|||
GI.GT_2DECK_TYPE, 2, 2, GI.SL_BALANCED))
|
||||
registerGame(GameInfo(792, KingsSecrets, "King's Secrets",
|
||||
GI.GT_2DECK_TYPE, 2, 2, GI.SL_BALANCED,
|
||||
altnames=('Royal Secrets',)))
|
||||
altnames=('Royal Secrets', "King's Captives")))
|
||||
registerGame(GameInfo(842, SwissPatience, "Swiss Patience",
|
||||
GI.GT_GYPSY, 1, 0, GI.SL_BALANCED))
|
||||
registerGame(GameInfo(890, YeastDough, "Yeast Dough",
|
||||
|
|
|
@ -170,5 +170,5 @@ registerGame(GameInfo(774, HitOrMiss, "Hit or Miss",
|
|||
GI.GT_1DECK_TYPE, 1, VARIABLE_REDEALS,
|
||||
GI.SL_LUCK, altnames=("Roll Call",)))
|
||||
registerGame(GameInfo(865, HitOrMissUnlimited, "Hit or Miss Unlimited",
|
||||
GI.GT_1DECK_TYPE, 1, UNLIMITED_REDEALS,
|
||||
GI.GT_1DECK_TYPE | GI.GT_CHILDREN, 1, UNLIMITED_REDEALS,
|
||||
GI.SL_LUCK))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -1640,7 +1640,8 @@ registerGame(GameInfo(66, Eastcliff, "Eastcliff",
|
|||
registerGame(GameInfo(224, Easthaven, "Easthaven",
|
||||
GI.GT_GYPSY, 1, 0, GI.SL_MOSTLY_LUCK))
|
||||
registerGame(GameInfo(33, Westcliff, "Westcliff",
|
||||
GI.GT_KLONDIKE, 1, 0, GI.SL_MOSTLY_LUCK))
|
||||
GI.GT_KLONDIKE | GI.GT_CHILDREN, 1, 0,
|
||||
GI.SL_MOSTLY_LUCK))
|
||||
registerGame(GameInfo(225, Westhaven, "Westhaven",
|
||||
GI.GT_GYPSY, 1, 0, GI.SL_BALANCED))
|
||||
registerGame(GameInfo(107, PasSeul, "Pas Seul",
|
||||
|
|
|
@ -407,7 +407,7 @@ class AbstractMahjonggGame(Game):
|
|||
|
||||
# width of self.texts.info
|
||||
# ti_width = Font(self.canvas, font).measure(_('Remaining'))
|
||||
ti_width = 80
|
||||
ti_width = max(80, l.CW)
|
||||
|
||||
# set window size
|
||||
dxx, dyy = abs(dx) * (max_tl+1), abs(dy) * (max_tl+1)
|
||||
|
|
|
@ -356,6 +356,48 @@ r(5418, "Zigzag", layout="0aabaajaaracahcb" +
|
|||
"ynvyniyoaypaAehA" +
|
||||
"faAgaAmhAnaAoaCa" +
|
||||
"aCfaCnaCs")
|
||||
r(5419, "Lizard", layout="0aadaafaahaajhbe" +
|
||||
"hbghbibccaceacga" +
|
||||
"ciackidjbebaejae" +
|
||||
"laeqheraesifkbga" +
|
||||
"agehgfaggagkagmb" +
|
||||
"grihlaiabifailai" +
|
||||
"nbirijmojqakaakg" +
|
||||
"hkhakiokihkjakko" +
|
||||
"kkvklakmvknakook" +
|
||||
"ohkpakqhllolmhln" +
|
||||
"ambamkammamohnlo" +
|
||||
"nmhnnaokaomaoohp" +
|
||||
"lopmhpnaqjaqlaqn" +
|
||||
"hrkorlhrmasjasla" +
|
||||
"snhtkotlhtmaujau" +
|
||||
"launhvkovlhvmawi" +
|
||||
"awkawmhxjpxkhxla" +
|
||||
"yiaykaymazehzfaz" +
|
||||
"gozghzhozihzjvzj" +
|
||||
"ozkhzlvzlozmhzna" +
|
||||
"zoozohzpazqaAiaA" +
|
||||
"kaAmbBdiBkbBraCj" +
|
||||
"aClaDchDdaDehDka" +
|
||||
"DqhDraDsaEjaElaF" +
|
||||
"daFraGk")
|
||||
r(5420, "Candy", layout="0daadaccaebagbai" +
|
||||
"aakdcbccdbcfbcha" +
|
||||
"cjcecbeebegaeibg" +
|
||||
"dbgfaghbieaigakc" +
|
||||
"akeakgakiamaamcb" +
|
||||
"mebmgamiamkaoabo" +
|
||||
"cboebogboiaokopf" +
|
||||
"aqabqcbqebqgbqia" +
|
||||
"qkorfasabscbsebs" +
|
||||
"gbsiaskauaaucbue" +
|
||||
"bugauiaukawcawea" +
|
||||
"wgawiayebygaAdbA" +
|
||||
"fbAhaCcbCebCgcCi" +
|
||||
"aEbbEdbEfcEhdEja" +
|
||||
"GabGcbGecGgdGidG" +
|
||||
"k")
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -299,6 +299,9 @@ class Quatorze(MonteCarlo):
|
|||
return (stack1.id // 5 == stack2.id // 5 or
|
||||
stack1.id % 5 == stack2.id % 5)
|
||||
|
||||
def shallHighlightMatch(self, stack1, card1, stack2, card2):
|
||||
return card1.rank + card2.rank == 12
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Simple Pairs
|
||||
|
@ -364,6 +367,10 @@ class BlockTen(SimplePairs):
|
|||
def isGameWon(self):
|
||||
return len(self.s.foundations[0].cards) == 48
|
||||
|
||||
def shallHighlightMatch(self, stack1, card1, stack2, card2):
|
||||
return (card1.rank + card2.rank == 8 or
|
||||
(9 < card1.rank == card2.rank > 9))
|
||||
|
||||
|
||||
class SimpleTens(BlockTen):
|
||||
def isGameWon(self):
|
||||
|
@ -1108,6 +1115,10 @@ class AcesSquare(MonteCarlo):
|
|||
return (stack1.id // 4 == stack2.id // 4 or
|
||||
stack1.id % 4 == stack2.id % 4)
|
||||
|
||||
def shallHighlightMatch(self, stack1, card1, stack2, card2):
|
||||
return (card1.suit == card2.suit and
|
||||
card1.rank != card2.rank != 0)
|
||||
|
||||
|
||||
# register the game
|
||||
registerGame(GameInfo(89, MonteCarlo, "Monte Carlo",
|
||||
|
@ -1118,15 +1129,16 @@ registerGame(GameInfo(216, MonteCarlo2Decks, "Monte Carlo (2 Decks)",
|
|||
registerGame(GameInfo(212, Weddings, "Weddings",
|
||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
|
||||
registerGame(GameInfo(90, SimpleCarlo, "Simple Carlo",
|
||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
|
||||
GI.GT_PAIRING_TYPE | GI.GT_CHILDREN, 1, 0,
|
||||
GI.SL_MOSTLY_LUCK))
|
||||
registerGame(GameInfo(91, SimplePairs, "Simple Pairs",
|
||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_LUCK,
|
||||
altnames=("Jamestown", "Pirate Gold", "Treasure Hunt",
|
||||
"Hunter")))
|
||||
GI.GT_PAIRING_TYPE | GI.GT_CHILDREN, 1, 0,
|
||||
GI.SL_LUCK, altnames=("Jamestown", "Pirate Gold",
|
||||
"Treasure Hunt", "Hunter")))
|
||||
registerGame(GameInfo(92, Neighbour, "Neighbour",
|
||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
|
||||
registerGame(GameInfo(96, Fourteen, "Fourteen",
|
||||
GI.GT_PAIRING_TYPE | GI.GT_OPEN, 1, 0,
|
||||
GI.GT_PAIRING_TYPE | GI.GT_OPEN | GI.GT_CHILDREN, 1, 0,
|
||||
GI.SL_MOSTLY_LUCK, altnames=("Fourteen Out",
|
||||
"Fourteen Puzzle",
|
||||
"Take Fourteen")))
|
||||
|
@ -1137,12 +1149,13 @@ registerGame(GameInfo(152, DerLetzteMonarch, "The Last Monarch",
|
|||
GI.GT_1DECK_TYPE | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL,
|
||||
altnames=("Der letzte Monarch",)))
|
||||
registerGame(GameInfo(328, TheWish, "The Wish",
|
||||
GI.GT_PAIRING_TYPE | GI.GT_STRIPPED, 1, 0,
|
||||
GI.SL_MOSTLY_LUCK, ranks=(0, 6, 7, 8, 9, 10, 11, 12)))
|
||||
GI.GT_PAIRING_TYPE | GI.GT_STRIPPED | GI.GT_CHILDREN,
|
||||
1, 0, GI.SL_MOSTLY_LUCK,
|
||||
ranks=(0, 6, 7, 8, 9, 10, 11, 12)))
|
||||
registerGame(GameInfo(329, TheWishOpen, "The Wish (Open)",
|
||||
GI.GT_PAIRING_TYPE | GI.GT_OPEN | GI.GT_ORIGINAL |
|
||||
GI.GT_STRIPPED, 1, 0, GI.SL_MOSTLY_SKILL,
|
||||
ranks=(0, 6, 7, 8, 9, 10, 11, 12),
|
||||
GI.GT_STRIPPED | GI.GT_CHILDREN, 1, 0,
|
||||
GI.SL_MOSTLY_SKILL, ranks=(0, 6, 7, 8, 9, 10, 11, 12),
|
||||
rules_filename="thewish.html"))
|
||||
registerGame(GameInfo(368, Vertical, "Vertical",
|
||||
GI.GT_PAIRING_TYPE | GI.GT_OPEN, 1, 0,
|
||||
|
@ -1162,8 +1175,8 @@ registerGame(GameInfo(810, Quatorze, "Quatorze",
|
|||
registerGame(GameInfo(829, BlockTen, "Block Ten",
|
||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_LUCK))
|
||||
registerGame(GameInfo(862, SimpleTens, "Simple Tens",
|
||||
GI.GT_PAIRING_TYPE | GI.GT_STRIPPED, 1, 0, GI.SL_LUCK,
|
||||
ranks=(0, 1, 2, 3, 4, 5, 6, 7, 8),
|
||||
GI.GT_PAIRING_TYPE | GI.GT_STRIPPED | GI.GT_CHILDREN,
|
||||
1, 0, GI.SL_LUCK, ranks=(0, 1, 2, 3, 4, 5, 6, 7, 8),
|
||||
altnames=("Add Up Tens",)))
|
||||
registerGame(GameInfo(867, DoubleFourteen, "Double Fourteen",
|
||||
GI.GT_PAIRING_TYPE | GI.GT_OPEN, 2, 0,
|
||||
|
|
|
@ -41,6 +41,7 @@ from pysollib.stack import \
|
|||
RK_FoundationStack, \
|
||||
RK_RowStack, \
|
||||
ReserveStack, \
|
||||
SC_FoundationStack, \
|
||||
SS_FoundationStack, \
|
||||
Stack, \
|
||||
StackWrapper, \
|
||||
|
@ -176,6 +177,7 @@ class Numerica2Decks(Numerica):
|
|||
# ************************************************************************
|
||||
# * Lady Betty
|
||||
# * Last Chance
|
||||
# * Colours
|
||||
# ************************************************************************
|
||||
|
||||
class LadyBetty(Numerica):
|
||||
|
@ -215,6 +217,40 @@ class LastChance(LadyBetty):
|
|||
self.s.talon.dealCards()
|
||||
|
||||
|
||||
class Colours(LadyBetty):
|
||||
Foundation_Class = StackWrapper(SC_FoundationStack, mod=13, suit=ANY_SUIT)
|
||||
|
||||
def startGame(self):
|
||||
self.startDealSample()
|
||||
self.s.talon.dealRow(rows=self.s.foundations)
|
||||
self.s.talon.dealCards() # deal first card to WasteStack
|
||||
|
||||
def _shuffleHook(self, cards):
|
||||
# prepare first cards
|
||||
topcards = [None] * 4
|
||||
evencolor = -1
|
||||
oddcolor = -1
|
||||
for c in cards[:]:
|
||||
if 0 < c.rank <= 4 and topcards[c.rank - 1] is None:
|
||||
if c.rank % 2 == 0:
|
||||
if evencolor != -1 and c.color != evencolor:
|
||||
continue
|
||||
if oddcolor != -1 and c.color == oddcolor:
|
||||
continue
|
||||
evencolor = c.color
|
||||
elif c.rank % 2 == 1:
|
||||
if oddcolor != -1 and c.color != oddcolor:
|
||||
continue
|
||||
if evencolor != -1 and c.color == evencolor:
|
||||
continue
|
||||
oddcolor = c.color
|
||||
|
||||
topcards[c.rank - 1] = c
|
||||
cards.remove(c)
|
||||
topcards.reverse()
|
||||
return cards + topcards
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Puss in the Corner
|
||||
# ************************************************************************
|
||||
|
@ -1373,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
|
||||
|
@ -1460,3 +1496,5 @@ registerGame(GameInfo(931, TheBogey, "The Bogey",
|
|||
GI.GT_1DECK_TYPE, 1, -1, GI.SL_BALANCED))
|
||||
registerGame(GameInfo(958, NinetyOne, "Ninety-One",
|
||||
GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_SKILL))
|
||||
registerGame(GameInfo(972, Colours, "Colours",
|
||||
GI.GT_NUMERICA, 1, 0, GI.SL_BALANCED))
|
||||
|
|
|
@ -383,51 +383,18 @@ class PyramidDozen(Giza):
|
|||
|
||||
|
||||
# ************************************************************************
|
||||
# * Thirteen
|
||||
# * FIXME: UNFINISHED
|
||||
# * (this doesn't work yet as 2 cards of the Waste should be playable)
|
||||
# * Pyramid Thirteen
|
||||
# ************************************************************************
|
||||
|
||||
# Previous comments suggest there would need to be two waste piles. This
|
||||
# is not true. Based on AisleRiot's rules, the two waste cards can only
|
||||
# be played with each other, which is the same as how PySol's traditional
|
||||
# version works. So the remaining AisleRiot differences are captured
|
||||
# in "Pyramid Thirteen", renamed from "Thirteen" to avoid confusion with
|
||||
# "Thirteens"
|
||||
|
||||
class Thirteen(Pyramid):
|
||||
|
||||
#
|
||||
# game layout
|
||||
#
|
||||
|
||||
def createGame(self):
|
||||
# create layout
|
||||
layout, s = Layout(self), self.s
|
||||
|
||||
# set window
|
||||
self.setSize(7*layout.XS+layout.XM, 5*layout.YS+layout.YM)
|
||||
|
||||
# create stacks
|
||||
for i in range(7):
|
||||
x = layout.XM + (6-i) * layout.XS // 2
|
||||
y = layout.YM + layout.YS + i * layout.YS // 2
|
||||
for j in range(i+1):
|
||||
s.rows.append(Pyramid_RowStack(x, y, self))
|
||||
x = x + layout.XS
|
||||
x, y = layout.XM, layout.YM
|
||||
s.talon = WasteTalonStack(x, y, self, max_rounds=1)
|
||||
layout.createText(s.talon, "s")
|
||||
x = x + layout.XS
|
||||
s.waste = Pyramid_Waste(x, y, self, max_accept=1)
|
||||
layout.createText(s.waste, "s")
|
||||
s.waste.CARD_XOFFSET = 14
|
||||
x, y = self.width - layout.XS, layout.YM
|
||||
s.foundations.append(Pyramid_Foundation(x, y, self,
|
||||
suit=ANY_SUIT, dir=0, base_rank=ANY_RANK,
|
||||
max_move=0, max_cards=52))
|
||||
|
||||
# define stack-groups
|
||||
self.sg.talonstacks = [s.talon] + [s.waste]
|
||||
self.sg.openstacks = s.rows + self.sg.talonstacks
|
||||
self.sg.dropstacks = s.rows + self.sg.talonstacks
|
||||
|
||||
#
|
||||
# game overrides
|
||||
#
|
||||
Talon_Class = StackWrapper(Pyramid_Talon, max_rounds=1, max_accept=1)
|
||||
|
||||
def startGame(self):
|
||||
self.startDealSample()
|
||||
|
@ -616,8 +583,8 @@ class Elevens(Pyramid):
|
|||
self.leaveState(old_state)
|
||||
|
||||
def shallHighlightMatch(self, stack1, card1, stack2, card2):
|
||||
# FIXME
|
||||
return False
|
||||
return (card1.rank + card2.rank == 9 or
|
||||
(9 < card1.rank != card2.rank > 9))
|
||||
|
||||
|
||||
class ElevensToo(Elevens):
|
||||
|
@ -666,6 +633,11 @@ class SuitElevens(Elevens):
|
|||
def createGame(self):
|
||||
Elevens.createGame(self, rows=3, cols=5)
|
||||
|
||||
def shallHighlightMatch(self, stack1, card1, stack2, card2):
|
||||
return (Elevens.shallHighlightMatch(self, stack1, card1,
|
||||
stack2, card2)
|
||||
and card1.suit == card2.suit)
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Tens
|
||||
|
@ -698,6 +670,10 @@ class Tens(ElevensToo):
|
|||
def createGame(self):
|
||||
Elevens.createGame(self, rows=2, cols=7, maxpiles=13, reserves=4)
|
||||
|
||||
def shallHighlightMatch(self, stack1, card1, stack2, card2):
|
||||
return (card1.rank + card2.rank == 8 or
|
||||
(8 < card1.rank == card2.rank > 8))
|
||||
|
||||
|
||||
class Nines_RowStack(Elevens_RowStack):
|
||||
ACCEPTED_SUM = 7
|
||||
|
@ -742,6 +718,10 @@ class Nines(Tens):
|
|||
def createGame(self):
|
||||
Elevens.createGame(self, rows=3, cols=3, reserves=4)
|
||||
|
||||
def shallHighlightMatch(self, stack1, card1, stack2, card2):
|
||||
return (card1.rank + card2.rank == 7 or
|
||||
(8 < card1.rank != card2.rank > 8))
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * The Lucky Number
|
||||
|
@ -881,6 +861,9 @@ class Fifteens(Elevens):
|
|||
self._dropReserve()
|
||||
self.leaveState(old_state)
|
||||
|
||||
def shallHighlightMatch(self, stack1, card1, stack2, card2):
|
||||
return card1.rank + card2.rank == 13
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Eighteens
|
||||
|
@ -973,6 +956,9 @@ class Eighteens(Fifteens):
|
|||
self._dropReserve()
|
||||
self.leaveState(old_state)
|
||||
|
||||
def shallHighlightMatch(self, stack1, card1, stack2, card2):
|
||||
return False # How?
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Neptune
|
||||
|
@ -1002,6 +988,10 @@ class Neptune(Thirteens):
|
|||
def isGameWon(self):
|
||||
return len(self.s.talon.cards) == 0
|
||||
|
||||
def shallHighlightMatch(self, stack1, card1, stack2, card2):
|
||||
return (card1.rank == card2.rank - 1 or
|
||||
card1.rank == card2.rank + 1)
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Eight Cards
|
||||
|
@ -1094,6 +1084,9 @@ class EightCards(Thirteens):
|
|||
# save vars (for undo/redo)
|
||||
return [self.draws]
|
||||
|
||||
def shallHighlightMatch(self, stack1, card1, stack2, card2):
|
||||
return card1.rank + card2.rank == 9
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Triple Alliance
|
||||
|
@ -1422,6 +1415,10 @@ class ElevenTriangle(Apophis):
|
|||
INVERT = True
|
||||
MAX_ROUNDS = 1
|
||||
|
||||
def shallHighlightMatch(self, stack1, card1, stack2, card2):
|
||||
return (card1.rank + card2.rank == 9 or
|
||||
(9 < card1.rank == card2.rank > 9))
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Cheops
|
||||
|
@ -1791,6 +1788,8 @@ class Hurricane_Reserve(Hurricane_StackMethods, OpenStack):
|
|||
|
||||
class Hurricane(Pyramid):
|
||||
Hint_Class = Hurricane_Hint
|
||||
RowStack_Class = Hurricane_RowStack
|
||||
Reserve_Class = Hurricane_Reserve
|
||||
|
||||
def createGame(self):
|
||||
# create layout
|
||||
|
@ -1808,7 +1807,7 @@ class Hurricane(Pyramid):
|
|||
(0, 2), (1, 2), (2, 2), (3, 2),
|
||||
):
|
||||
x, y = layout.XM + 1.5*layout.XS + ww*xx, layout.YM + layout.YS*yy
|
||||
stack = Hurricane_Reserve(x, y, self, max_accept=1)
|
||||
stack = self.Reserve_Class(x, y, self, max_accept=1)
|
||||
stack.CARD_XOFFSET, stack.CARD_YOFFSET = layout.XOFFSET, 0
|
||||
s.reserves.append(stack)
|
||||
|
||||
|
@ -1816,7 +1815,7 @@ class Hurricane(Pyramid):
|
|||
x = layout.XM + 1.5*layout.XS + layout.XS+2*layout.XOFFSET + d//2
|
||||
y = layout.YM+layout.YS
|
||||
for i in range(3):
|
||||
stack = Hurricane_RowStack(x, y, self, max_accept=1)
|
||||
stack = self.RowStack_Class(x, y, self, max_accept=1)
|
||||
s.rows.append(stack)
|
||||
x += layout.XS
|
||||
|
||||
|
@ -1846,6 +1845,45 @@ class Hurricane(Pyramid):
|
|||
self.s.talon.moveMove(1, stack)
|
||||
self.leaveState(old_state)
|
||||
|
||||
def shallHighlightMatch(self, stack1, card1, stack2, card2):
|
||||
return card1.rank + card2.rank == 12
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Ides of March
|
||||
# ************************************************************************
|
||||
|
||||
class IdesOfMarch_StackMethods(Pyramid_StackMethods):
|
||||
|
||||
def acceptsCards(self, from_stack, cards):
|
||||
if from_stack is self:
|
||||
return False
|
||||
if len(cards) != 1:
|
||||
return False
|
||||
if not self.cards:
|
||||
return False
|
||||
c1 = self.cards[-1]
|
||||
c2 = cards[0]
|
||||
return (c1.face_up and c2.face_up and
|
||||
(c1.rank + c2.rank == 13 or c1.rank + c2.rank == 0))
|
||||
|
||||
|
||||
class IdesOfMarch_RowStack(IdesOfMarch_StackMethods, BasicRowStack):
|
||||
pass
|
||||
|
||||
|
||||
class IdesOfMarch_Reserve(IdesOfMarch_StackMethods, OpenStack):
|
||||
pass
|
||||
|
||||
|
||||
class IdesOfMarch(Hurricane):
|
||||
RowStack_Class = IdesOfMarch_RowStack
|
||||
Reserve_Class = IdesOfMarch_Reserve
|
||||
|
||||
def shallHighlightMatch(self, stack1, card1, stack2, card2):
|
||||
return (card1.rank + card2.rank == 13 or
|
||||
card1.rank + card2.rank == 0)
|
||||
|
||||
|
||||
# register the game
|
||||
registerGame(GameInfo(38, Pyramid, "Pyramid",
|
||||
|
@ -1854,8 +1892,8 @@ registerGame(GameInfo(193, RelaxedPyramid, "Relaxed Pyramid",
|
|||
GI.GT_PAIRING_TYPE | GI.GT_RELAXED, 1, 2,
|
||||
GI.SL_MOSTLY_LUCK,
|
||||
altnames=("Pyramid's Stones", "Pyramid Clear")))
|
||||
# registerGame(GameInfo(44, Thirteen, "Thirteen",
|
||||
# GI.GT_PAIRING_TYPE, 1, 0))
|
||||
registerGame(GameInfo(44, Thirteen, "Pyramid Thirteen",
|
||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
|
||||
registerGame(GameInfo(592, Giza, "Giza",
|
||||
GI.GT_PAIRING_TYPE | GI.GT_OPEN, 1, 0, GI.SL_BALANCED))
|
||||
registerGame(GameInfo(593, Thirteens, "Thirteens",
|
||||
|
@ -1874,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',)))
|
||||
|
@ -1895,7 +1934,7 @@ registerGame(GameInfo(699, DoublePyramid, "Double Pyramid",
|
|||
GI.GT_PAIRING_TYPE, 2, 2, GI.SL_MOSTLY_LUCK))
|
||||
registerGame(GameInfo(700, Triangle, "Triangle",
|
||||
GI.GT_PAIRING_TYPE, 1, 2, GI.SL_MOSTLY_LUCK,
|
||||
altnames=('Yield',)))
|
||||
altnames=('Yield', 'Funnel')))
|
||||
registerGame(GameInfo(701, UpAndDown, "Up and Down",
|
||||
GI.GT_PAIRING_TYPE | GI.GT_ORIGINAL, 2, 2,
|
||||
GI.SL_MOSTLY_LUCK))
|
||||
|
@ -1927,3 +1966,6 @@ registerGame(GameInfo(961, Nines, "Nines",
|
|||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_LUCK))
|
||||
registerGame(GameInfo(969, ElevenTriangle, "Eleven Triangle",
|
||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
|
||||
registerGame(GameInfo(974, IdesOfMarch, "Ides of March",
|
||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_MOSTLY_LUCK,
|
||||
altnames=("XV",)))
|
||||
|
|
|
@ -231,6 +231,58 @@ class Kingdom(RoyalCotillion):
|
|||
self.s.talon.dealCards() # deal first card to WasteStack
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Noumea
|
||||
# ************************************************************************
|
||||
|
||||
class Noumea(RoyalCotillion):
|
||||
Foundation_Class = SS_FoundationStack
|
||||
|
||||
def createGame(self):
|
||||
# create layout
|
||||
l, s = Layout(self), self.s
|
||||
|
||||
# set window
|
||||
self.setSize(l.XM + 5*l.XS, l.YM + 6*l.YS)
|
||||
|
||||
# create stacks
|
||||
x, y, = l.XM + .5 * l.XS, l.YM
|
||||
for i in range(4):
|
||||
s.foundations.append(self.Foundation_Class(x, y, self, i))
|
||||
x += l.XS
|
||||
x, y, = l.XM, y + l.YS
|
||||
for j in range(4):
|
||||
for i in range(5):
|
||||
s.reserves.append(ReserveStack(x, y, self, max_accept=0))
|
||||
x += l.XS
|
||||
x = l.XM
|
||||
y += l.YS
|
||||
x, y = l.XM + 1.5 * l.XS, l.YM + 5 * l.YS
|
||||
s.talon = WasteTalonStack(x, y, self, max_rounds=3, num_deal=3)
|
||||
l.createText(s.talon, "sw")
|
||||
x += l.XS
|
||||
s.waste = WasteStack(x, y, self)
|
||||
l.createText(s.waste, "se")
|
||||
|
||||
# define stack-groups
|
||||
l.defaultStackGroups()
|
||||
|
||||
#
|
||||
# game overrides
|
||||
#
|
||||
|
||||
def _shuffleHook(self, cards):
|
||||
# move Aces to top of the Talon (i.e. first cards to be dealt)
|
||||
return self._shuffleHookMoveToTop(
|
||||
cards, lambda c: (c.rank == ACE, c.suit))
|
||||
|
||||
def startGame(self):
|
||||
self.s.talon.dealRow(rows=self.s.foundations, frames=0)
|
||||
self.startDealSample()
|
||||
self.s.talon.dealRow(rows=self.s.reserves)
|
||||
self.s.talon.dealCards() # deal first card to WasteStack
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Alhambra
|
||||
# * Granada
|
||||
|
@ -1573,13 +1625,14 @@ registerGame(GameInfo(54, RoyalCotillion, "Royal Cotillion",
|
|||
GI.GT_2DECK_TYPE, 2, 0, GI.SL_LUCK,
|
||||
altnames=("Lords and Ladies",)))
|
||||
registerGame(GameInfo(55, OddAndEven, "Odd and Even",
|
||||
GI.GT_2DECK_TYPE, 2, 1, GI.SL_LUCK))
|
||||
GI.GT_2DECK_TYPE | GI.GT_CHILDREN, 2, 1, GI.SL_LUCK))
|
||||
registerGame(GameInfo(143, Kingdom, "Kingdom",
|
||||
GI.GT_2DECK_TYPE, 2, 0, GI.SL_MOSTLY_LUCK))
|
||||
registerGame(GameInfo(234, Alhambra, "Alhambra",
|
||||
GI.GT_2DECK_TYPE, 2, 2, GI.SL_BALANCED))
|
||||
registerGame(GameInfo(97, Carpet, "Carpet",
|
||||
GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
|
||||
GI.GT_1DECK_TYPE | GI.GT_CHILDREN, 1, 0,
|
||||
GI.SL_MOSTLY_LUCK))
|
||||
registerGame(GameInfo(391, BritishConstitution, "British Constitution",
|
||||
GI.GT_2DECK_TYPE | GI.GT_STRIPPED, 2, 0, GI.SL_BALANCED,
|
||||
ranks=list(range(11)), # without Queens and Kings
|
||||
|
@ -1623,3 +1676,5 @@ registerGame(GameInfo(943, RosamundsBower, "Rosamund's Bower",
|
|||
altnames=("Rosamund",)))
|
||||
registerGame(GameInfo(952, BigAlhambra, "Big Alhambra",
|
||||
GI.GT_3DECK_TYPE, 3, 2, GI.SL_BALANCED))
|
||||
registerGame(GameInfo(978, Noumea, "Noumea",
|
||||
GI.GT_1DECK_TYPE, 1, 2, GI.SL_MOSTLY_LUCK))
|
||||
|
|
|
@ -291,7 +291,8 @@ class Maze(Game):
|
|||
# register the game
|
||||
registerGame(GameInfo(118, SiebenBisAs, "Sieben bis As",
|
||||
GI.GT_MONTANA | GI.GT_OPEN | GI.GT_STRIPPED, 1, 0,
|
||||
GI.SL_MOSTLY_SKILL, ranks=(0, 6, 7, 8, 9, 10, 11, 12)))
|
||||
GI.SL_MOSTLY_SKILL, ranks=(0, 6, 7, 8, 9, 10, 11, 12),
|
||||
altnames=("Seven to Ace",)))
|
||||
registerGame(GameInfo(144, Maze, "Maze",
|
||||
GI.GT_MONTANA | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL,
|
||||
si={"ncards": 48}))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -1266,10 +1266,12 @@ class Dashavatara(Game):
|
|||
# *
|
||||
# ***********************************************************************/
|
||||
|
||||
def r(id, gameclass, name, game_type, decks, redeals, skill_level):
|
||||
def r(id, gameclass, name, game_type, decks, redeals, skill_level,
|
||||
altnames=()):
|
||||
game_type = game_type | GI.GT_DASHAVATARA_GANJIFA
|
||||
gi = GameInfo(id, gameclass, name, game_type, decks, redeals, skill_level,
|
||||
suits=list(range(10)), ranks=list(range(12)))
|
||||
suits=list(range(10)), ranks=list(range(12)),
|
||||
altnames=altnames)
|
||||
registerGame(gi)
|
||||
return gi
|
||||
|
||||
|
|
|
@ -62,7 +62,8 @@ class HexATrump_Foundation(HexADeck_FoundationStack):
|
|||
def acceptsCards(self, from_stack, cards):
|
||||
if not self.basicAcceptsCards(from_stack, cards):
|
||||
return 0
|
||||
for s in self.game.s.foundations[:3]:
|
||||
for s in self.game.s.foundations[:((self.game.gameinfo.decks
|
||||
* 4) - 1)]:
|
||||
if len(s.cards) != 16:
|
||||
return 0
|
||||
return 1
|
||||
|
@ -93,11 +94,12 @@ class Merlins_Foundation(AbstractFoundationStack):
|
|||
|
||||
class HexADeck_OpenStack(OpenStack):
|
||||
|
||||
def __init__(self, x, y, game, yoffset, **cap):
|
||||
def __init__(self, x, y, game, yoffset=None, **cap):
|
||||
kwdefault(cap, max_move=UNLIMITED_MOVES, max_accept=UNLIMITED_ACCEPTS,
|
||||
dir=-1)
|
||||
OpenStack.__init__(self, x, y, game, **cap)
|
||||
self.CARD_YOFFSET = yoffset
|
||||
if yoffset is not None:
|
||||
self.CARD_YOFFSET = yoffset
|
||||
|
||||
def isRankSequence(self, cards, dir=None):
|
||||
if not dir:
|
||||
|
@ -1498,7 +1500,6 @@ class HexYukon(Game):
|
|||
|
||||
shallHighlightMatch = Game._shallHighlightMatch_AC
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# *
|
||||
# ************************************************************************
|
||||
|
@ -1600,16 +1601,162 @@ class MagicMontana(Montana):
|
|||
return True
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Wizard's Storeroom
|
||||
# ************************************************************************
|
||||
|
||||
class WizardsStoreroom(AbstractHexADeckGame):
|
||||
MAX_ROUNDS = 2
|
||||
|
||||
#
|
||||
# Game layout
|
||||
#
|
||||
|
||||
def createGame(self):
|
||||
l, s = Layout(self), self.s
|
||||
|
||||
# Set window size
|
||||
decks = self.gameinfo.decks
|
||||
self.setSize(2*l.XM + (2 + 5*decks)*l.XS, 3*l.YM + 5*l.YS)
|
||||
yoffset = min(l.YOFFSET, max(10, l.YOFFSET // 2))
|
||||
|
||||
# Create talon
|
||||
x = l.XM
|
||||
y = l.YM
|
||||
s.talon = WasteTalonStack(
|
||||
x, y, self, num_deal=1, max_rounds=self.MAX_ROUNDS)
|
||||
l.createText(s.talon, "s")
|
||||
x = x + l.XS
|
||||
s.waste = WasteStack(x, y, self)
|
||||
l.createText(s.waste, "s")
|
||||
|
||||
# Create foundations
|
||||
x = x + l.XM + l.XS
|
||||
for j in range(4):
|
||||
for i in range(decks):
|
||||
s.foundations.append(
|
||||
SS_FoundationStack(x, y, self, j, max_cards=16))
|
||||
x = x + l.XS
|
||||
for i in range(decks):
|
||||
s.foundations.append(
|
||||
HexATrump_Foundation(x, y, self, 4, max_cards=4))
|
||||
x = x + l.XS
|
||||
|
||||
# Create reserve
|
||||
x = l.XM
|
||||
y = l.YM + l.YS + l.TEXT_HEIGHT
|
||||
s.reserves.append(OpenStack(x, y, self))
|
||||
s.reserves[0].CARD_YOFFSET = (l.YOFFSET, yoffset)[decks == 2]
|
||||
|
||||
# Create rows
|
||||
x = x + l.XM + l.XS
|
||||
for i in range(4*decks+1):
|
||||
s.rows.append(HexAKlon_RowStack(x, y, self))
|
||||
x = x + l.XS
|
||||
self.setRegion(s.rows, (-999, y - l.YS, 999999, 999999))
|
||||
|
||||
# Define stack groups
|
||||
l.defaultStackGroups()
|
||||
|
||||
#
|
||||
# Game over rides
|
||||
#
|
||||
|
||||
def startGame(self):
|
||||
decks = self.gameinfo.decks
|
||||
self.startDealSample()
|
||||
for i in range(14 * decks):
|
||||
self.s.talon.dealRow(rows=self.s.reserves, flip=0, frames=4)
|
||||
self.s.reserves[0].flipMove()
|
||||
self.s.talon.dealRow(rows=self.s.rows)
|
||||
self.s.talon.dealCards() # deal first card to WasteStack
|
||||
|
||||
def fillStack(self, stack):
|
||||
r = self.s.reserves[0]
|
||||
if not stack.cards and stack in self.s.rows:
|
||||
if r.cards and stack.acceptsCards(r, r.cards[-1:]):
|
||||
r.moveMove(1, stack)
|
||||
if r.canFlipCard():
|
||||
r.flipMove()
|
||||
|
||||
def shallHighlightMatch(self, stack1, card1, stack2, card2):
|
||||
return ((card1.rank + 1 == card2.rank or
|
||||
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))
|
||||
|
||||
# ************************************************************************
|
||||
# *
|
||||
# ************************************************************************
|
||||
|
||||
|
||||
def r(id, gameclass, name, game_type, decks, redeals, skill_level):
|
||||
def r(id, gameclass, name, game_type, decks, redeals, skill_level,
|
||||
altnames=()):
|
||||
game_type = game_type | GI.GT_HEXADECK
|
||||
gi = GameInfo(id, gameclass, name, game_type, decks, redeals, skill_level,
|
||||
suits=list(range(4)), ranks=list(range(16)),
|
||||
trumps=list(range(4)))
|
||||
trumps=list(range(4)), altnames=altnames)
|
||||
registerGame(gi)
|
||||
return gi
|
||||
|
||||
|
@ -1633,7 +1780,7 @@ r(16674, HiddenPassages, 'Hidden Passages', GI.GT_HEXADECK, 1, 1,
|
|||
r(16675, CluitjarsLair, 'Cluitjar\'s Lair', GI.GT_HEXADECK, 1, 0,
|
||||
GI.SL_BALANCED)
|
||||
r(16676, MerlinsMeander, 'Merlin\'s Meander', GI.GT_HEXADECK, 2, 2,
|
||||
GI.SL_BALANCED)
|
||||
GI.SL_BALANCED, altnames=('Merlin\'s Coil'))
|
||||
r(16677, MagesGame, 'Mage\'s Game', GI.GT_HEXADECK | GI.GT_OPEN, 1, 0,
|
||||
GI.SL_BALANCED)
|
||||
r(16678, Convolution, 'Convolution', GI.GT_HEXADECK | GI.GT_OPEN, 2, 0,
|
||||
|
@ -1645,4 +1792,10 @@ r(16680, Snakestone, 'Snakestone', GI.GT_HEXADECK | GI.GT_OPEN, 2, 0,
|
|||
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)
|
||||
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
|
||||
|
|
|
@ -99,6 +99,9 @@ class Ishido(Game):
|
|||
STRICT_FOUR_WAYS = True
|
||||
SCORING = False
|
||||
|
||||
COLS = 12
|
||||
ROWS = 8
|
||||
|
||||
#
|
||||
# game layout
|
||||
#
|
||||
|
@ -115,13 +118,13 @@ class Ishido(Game):
|
|||
|
||||
w2 = max(2 * l.XS, x)
|
||||
# set window
|
||||
w, h = w2 + l.XM * 2 + l.CW * 12, l.YM * 2 + l.CH * 8
|
||||
w, h = w2 + l.XM * 2 + l.CW * self.COLS, l.YM * 2 + l.CH * self.ROWS
|
||||
self.setSize(w, h)
|
||||
|
||||
# Create rows
|
||||
for j in range(8):
|
||||
for j in range(self.ROWS):
|
||||
x, y = w2 + l.XM, l.YM + l.CH * j
|
||||
for i in range(12):
|
||||
for i in range(self.COLS):
|
||||
s.rows.append(self.RowStack_Class(x, y, self))
|
||||
x = x + l.CW
|
||||
|
||||
|
@ -269,17 +272,17 @@ class Ishido(Game):
|
|||
|
||||
def getAdjacent(self, playSpace):
|
||||
adjacentRows = []
|
||||
if playSpace % 12 != 11:
|
||||
if playSpace % self.COLS != self.COLS - 1:
|
||||
adjacentRows.append(self.s.rows[playSpace + 1])
|
||||
|
||||
if playSpace % 12 != 0:
|
||||
if playSpace % self.COLS != 0:
|
||||
adjacentRows.append(self.s.rows[playSpace - 1])
|
||||
|
||||
if playSpace + 12 < 96:
|
||||
adjacentRows.append(self.s.rows[playSpace + 12])
|
||||
if playSpace + self.COLS < (self.COLS * self.ROWS):
|
||||
adjacentRows.append(self.s.rows[playSpace + self.COLS])
|
||||
|
||||
if playSpace - 12 > -1:
|
||||
adjacentRows.append(self.s.rows[playSpace - 12])
|
||||
if playSpace - self.COLS > -1:
|
||||
adjacentRows.append(self.s.rows[playSpace - self.COLS])
|
||||
|
||||
return adjacentRows
|
||||
|
||||
|
@ -301,10 +304,46 @@ class IshidoScored(Ishido):
|
|||
SCORING = True
|
||||
|
||||
|
||||
class LittleIshido(Ishido):
|
||||
ROWS = 6
|
||||
COLS = 8
|
||||
|
||||
def startGame(self):
|
||||
self.score = 0
|
||||
self.fourways = 0
|
||||
self.moveMove(1, self.s.talon, self.s.rows[0], frames=0)
|
||||
self.s.rows[0].flipMove()
|
||||
self.moveMove(1, self.s.talon, self.s.rows[7], frames=0)
|
||||
self.s.rows[7].flipMove()
|
||||
self.moveMove(1, self.s.talon, self.s.rows[40], frames=0)
|
||||
self.s.rows[40].flipMove()
|
||||
self.moveMove(1, self.s.talon, self.s.rows[47], frames=0)
|
||||
self.s.rows[47].flipMove()
|
||||
self.s.talon.fillStack()
|
||||
|
||||
def _shuffleHook(self, cards):
|
||||
# prepare first cards
|
||||
symbols = []
|
||||
colors = []
|
||||
topcards = []
|
||||
for c in cards[:]:
|
||||
if c.suit not in colors and c.rank not in symbols:
|
||||
topcards.append(c)
|
||||
cards.remove(c)
|
||||
symbols.append(c.rank)
|
||||
colors.append(c.suit)
|
||||
if len(colors) >= 4 or len(symbols) >= 4:
|
||||
break
|
||||
return cards + topcards
|
||||
|
||||
class LittleIshidoRelaxed(LittleIshido):
|
||||
STRICT_FOUR_WAYS = False
|
||||
|
||||
|
||||
def r(id, gameclass, name, decks, redeals, skill_level,
|
||||
game_type=GI.GT_ISHIDO):
|
||||
game_type=GI.GT_ISHIDO, colors=6):
|
||||
gi = GameInfo(id, gameclass, name, game_type, decks, redeals, skill_level,
|
||||
ranks=list(range(6)), suits=list(range(6)),
|
||||
ranks=list(range(colors)), suits=list(range(colors)),
|
||||
category=GI.GC_ISHIDO)
|
||||
registerGame(gi)
|
||||
return gi
|
||||
|
@ -316,3 +355,6 @@ r(18002, FreeIshido, 'Free Ishido', 2, 0, GI.SL_MOSTLY_SKILL)
|
|||
r(18003, FreeIshidoRelaxed, 'Free Ishido Relaxed', 2, 0, GI.SL_MOSTLY_SKILL)
|
||||
r(18004, IshidoScored, 'Ishido Scored', 2, 0, GI.SL_MOSTLY_SKILL,
|
||||
game_type=GI.GT_ISHIDO | GI.GT_SCORE)
|
||||
r(18005, LittleIshido, 'Little Ishido', 2, 0, GI.SL_MOSTLY_SKILL, colors=4)
|
||||
r(18006, LittleIshidoRelaxed, 'Little Ishido Relaxed', 2, 0,
|
||||
GI.SL_MOSTLY_SKILL, colors=4)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -71,7 +71,7 @@ class Memory_RowStack(OpenStack):
|
|||
def _dropPairMove(self, n, other_stack, frames=-1, shadow=-1):
|
||||
game = self.game
|
||||
game.playSample("droppair", priority=200)
|
||||
game.closed_cards = game.closed_cards - 2
|
||||
game.closed_cards -= 2
|
||||
game.score = game.score + 5
|
||||
|
||||
rightclickHandler = clickHandler
|
||||
|
@ -108,6 +108,7 @@ class Memory24(Game):
|
|||
|
||||
# game extras
|
||||
self.other_stack = None
|
||||
self.other_stack2 = None
|
||||
self.closed_cards = -1
|
||||
self.score = 0
|
||||
|
||||
|
@ -255,7 +256,7 @@ class Concentration_RowStack(Memory_RowStack):
|
|||
def _dropPairMove(self, n, other_stack, frames=-1, shadow=-1):
|
||||
game = self.game
|
||||
game.playSample("droppair", priority=200)
|
||||
game.closed_cards = game.closed_cards - 2
|
||||
game.closed_cards -= 2
|
||||
game.score = game.score + 5
|
||||
#
|
||||
old_state = game.enterState(game.S_FILL)
|
||||
|
@ -271,6 +272,8 @@ class Concentration(Memory24):
|
|||
WIN_SCORE = 50
|
||||
PERFECT_SCORE = 130 # 5 * (13*4)/2
|
||||
|
||||
RowStack_Class = Concentration_RowStack
|
||||
|
||||
#
|
||||
# game layout
|
||||
#
|
||||
|
@ -281,6 +284,7 @@ class Concentration(Memory24):
|
|||
|
||||
# game extras
|
||||
self.other_stack = None
|
||||
self.other_stack2 = None
|
||||
self.closed_cards = -1
|
||||
self.score = 0
|
||||
|
||||
|
@ -291,11 +295,12 @@ class Concentration(Memory24):
|
|||
for i in range(self.ROWS):
|
||||
for j in range(self.COLUMNS):
|
||||
x, y = l.XM + j*l.XS, l.YM + i*l.YS
|
||||
s.rows.append(Concentration_RowStack(x, y, self,
|
||||
s.rows.append(self.RowStack_Class(x, y, self,
|
||||
max_move=0, max_accept=0, max_cards=1))
|
||||
x, y = l.XM + self.COLUMNS*l.XS//2, self.height - l.YS
|
||||
s.talon = InitialDealTalonStack(x, y, self)
|
||||
l.createText(s.talon, dx=-10, anchor="sw", text_format="%D")
|
||||
s.internals.append(InvisibleStack(self))
|
||||
|
||||
# create text
|
||||
x, y = l.XM, self.height - l.YM
|
||||
|
@ -390,14 +395,159 @@ class MemorySequence(Memory24):
|
|||
return card1.suit == card2.suit and card1.rank == card2.rank + 1
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Families
|
||||
# ************************************************************************
|
||||
|
||||
class Families_RowStack(Memory_RowStack):
|
||||
def clickHandler(self, event):
|
||||
game = self.game
|
||||
if (game.score == -1):
|
||||
return 1
|
||||
if len(self.cards) != 1 or self.cards[-1].face_up:
|
||||
return 1
|
||||
if game.other_stack is None:
|
||||
game.playSample("flip", priority=5)
|
||||
self.flipMove()
|
||||
game.other_stack = self
|
||||
elif game.other_stack2 is None:
|
||||
game.playSample("flip", priority=5)
|
||||
self.flipMove()
|
||||
game.other_stack2 = self
|
||||
else:
|
||||
assert len(game.other_stack.cards) == 1 and \
|
||||
game.other_stack.cards[-1].face_up
|
||||
c1, c2, c3 = self, game.other_stack, game.other_stack2
|
||||
self.flipMove()
|
||||
if not self.game.handleMatch(c1, c2, c3):
|
||||
game.playSample("flip", priority=5)
|
||||
game.updateStatus(moves=game.moves.index+1) # update moves now
|
||||
game.updateText()
|
||||
game.canvas.update_idletasks()
|
||||
game.sleep(0.5)
|
||||
game.other_stack.flipMove()
|
||||
game.canvas.update_idletasks()
|
||||
game.sleep(0.2)
|
||||
game.other_stack2.flipMove()
|
||||
game.canvas.update_idletasks()
|
||||
game.sleep(0.2)
|
||||
self.flipMove()
|
||||
game.other_stack = None
|
||||
game.other_stack2 = None
|
||||
self.game.finishMove()
|
||||
self.game.checkForWin()
|
||||
return 1
|
||||
|
||||
|
||||
class Families(Concentration):
|
||||
Hint_Class = None
|
||||
|
||||
COLUMNS = 8
|
||||
ROWS = 4
|
||||
|
||||
RowStack_Class = Families_RowStack
|
||||
|
||||
def updateText(self):
|
||||
pass
|
||||
|
||||
def _restoreGameHook(self, game):
|
||||
if game.loadinfo.other_stack_id >= 0:
|
||||
self.other_stack = self.allstacks[game.loadinfo.other_stack_id]
|
||||
else:
|
||||
self.other_stack = None
|
||||
if game.loadinfo.other_stack2_id >= 0:
|
||||
self.other_stack2 = self.allstacks[game.loadinfo.other_stack2_id]
|
||||
else:
|
||||
self.other_stack2 = None
|
||||
self.closed_cards = game.loadinfo.closed_cards
|
||||
self.score = game.loadinfo.score
|
||||
|
||||
def handleMatch(self, stack1, stack2, stack3):
|
||||
card1 = stack1.cards[-1]
|
||||
card2 = stack2.cards[-1]
|
||||
card3 = stack3.cards[-1]
|
||||
if (card1.suit == card2.suit and card2.suit == card3.suit and
|
||||
card1.rank != card2.rank and card2.rank != card3.rank and
|
||||
card1.rank != card3.rank):
|
||||
self.playSample("droppair", priority=200)
|
||||
self.closed_cards -= 3
|
||||
#
|
||||
old_state = self.enterState(self.S_FILL)
|
||||
f = self.s.talon
|
||||
self.moveMove(1, stack1, f)
|
||||
self.moveMove(1, stack2, f)
|
||||
self.moveMove(1, stack3, f)
|
||||
self.leaveState(old_state)
|
||||
return True
|
||||
else:
|
||||
redjokers = 0
|
||||
blackjokers = 0
|
||||
if card1.suit == 4 and card1.rank == 0:
|
||||
blackjokers += 1
|
||||
if card2.suit == 4 and card2.rank == 0:
|
||||
blackjokers += 1
|
||||
if card3.suit == 4 and card3.rank == 0:
|
||||
blackjokers += 1
|
||||
if card1.suit == 4 and card1.rank == 1:
|
||||
redjokers += 1
|
||||
if card2.suit == 4 and card2.rank == 1:
|
||||
redjokers += 1
|
||||
if card3.suit == 4 and card3.rank == 1:
|
||||
redjokers += 1
|
||||
if blackjokers > 1:
|
||||
self.score = -1
|
||||
return True
|
||||
if redjokers > 0:
|
||||
self.reshuffle()
|
||||
|
||||
def reshuffle(self):
|
||||
old_state = self.enterState(self.S_FILL)
|
||||
stacks = ()
|
||||
for r in self.s.rows:
|
||||
if r.cards and not r.cards[-1].face_up:
|
||||
stacks += (r,)
|
||||
self.moveMove(len(r.cards), r, self.s.internals[0],
|
||||
frames=0)
|
||||
self.shuffleStackMove(self.s.internals[0])
|
||||
self.startDealSample()
|
||||
for r in stacks:
|
||||
self.moveMove(1, self.s.internals[0], r)
|
||||
self.stopSamples()
|
||||
self.leaveState(old_state)
|
||||
|
||||
def isGameWon(self):
|
||||
return self.closed_cards == 8 and self.score > -1
|
||||
|
||||
def getStuck(self):
|
||||
return self.score == -1
|
||||
|
||||
def _loadGameHook(self, p):
|
||||
self.loadinfo.addattr(other_stack_id=p.load())
|
||||
self.loadinfo.addattr(other_stack2_id=p.load())
|
||||
self.loadinfo.addattr(closed_cards=p.load())
|
||||
self.loadinfo.addattr(score=p.load())
|
||||
|
||||
def _saveGameHook(self, p):
|
||||
if self.other_stack:
|
||||
p.dump(self.other_stack.id)
|
||||
else:
|
||||
p.dump(-1)
|
||||
if self.other_stack2:
|
||||
p.dump(self.other_stack2.id)
|
||||
else:
|
||||
p.dump(-1)
|
||||
p.dump(self.closed_cards)
|
||||
p.dump(self.score)
|
||||
|
||||
|
||||
# register the game
|
||||
registerGame(GameInfo(886, Memory16, "Memory 16",
|
||||
GI.GT_MEMORY | GI.GT_SCORE, 2, 0, GI.SL_SKILL,
|
||||
category=GI.GC_MATCHING,
|
||||
GI.GT_MEMORY | GI.GT_SCORE | GI.GT_CHILDREN, 2, 0,
|
||||
GI.SL_SKILL, category=GI.GC_MATCHING,
|
||||
suits=(), ranks=(), trumps=list(range(8))))
|
||||
registerGame(GameInfo(176, Memory24, "Memory 24",
|
||||
GI.GT_MEMORY | GI.GT_SCORE, 2, 0, GI.SL_SKILL,
|
||||
category=GI.GC_MATCHING,
|
||||
GI.GT_MEMORY | GI.GT_SCORE | GI.GT_CHILDREN, 2, 0,
|
||||
GI.SL_SKILL, category=GI.GC_MATCHING,
|
||||
suits=(), ranks=(), trumps=list(range(12))))
|
||||
registerGame(GameInfo(219, Memory30, "Memory 30",
|
||||
GI.GT_MEMORY | GI.GT_SCORE, 2, 0, GI.SL_SKILL,
|
||||
|
@ -417,3 +567,7 @@ registerGame(GameInfo(178, Concentration, "Concentration",
|
|||
registerGame(GameInfo(843, MemorySequence, "Memory Sequence",
|
||||
GI.GT_MEMORY | GI.GT_SCORE, 1, 0, GI.SL_SKILL,
|
||||
suits=(1,), altnames=('Ace Through King',)))
|
||||
registerGame(GameInfo(973, Families, "Families",
|
||||
GI.GT_MEMORY, 2, 0, GI.SL_MOSTLY_SKILL,
|
||||
ranks=(10, 11, 12), subcategory=GI.GS_JOKER_DECK,
|
||||
trumps=(0, 0, 0, 1)))
|
||||
|
|
|
@ -1157,10 +1157,12 @@ class AshtaDikapala(Game):
|
|||
# *
|
||||
# ************************************************************************
|
||||
|
||||
def r(id, gameclass, name, game_type, decks, redeals, skill_level):
|
||||
def r(id, gameclass, name, game_type, decks, redeals, skill_level,
|
||||
altnames=()):
|
||||
game_type = game_type | GI.GT_MUGHAL_GANJIFA
|
||||
gi = GameInfo(id, gameclass, name, game_type, decks, redeals, skill_level,
|
||||
suits=list(range(8)), ranks=list(range(12)))
|
||||
suits=list(range(8)), ranks=list(range(12)),
|
||||
altnames=altnames)
|
||||
registerGame(gi)
|
||||
return gi
|
||||
|
||||
|
@ -1187,6 +1189,6 @@ r(16001, Danda, 'Danda', GI.GT_MUGHAL_GANJIFA, 1, 0, GI.SL_MOSTLY_SKILL)
|
|||
r(16002, Khadga, 'Khadga', GI.GT_MUGHAL_GANJIFA, 1, 0, GI.SL_MOSTLY_SKILL)
|
||||
r(16003, Makara, 'Makara', GI.GT_MUGHAL_GANJIFA, 1, 0, GI.SL_MOSTLY_SKILL)
|
||||
r(16004, AshtaDikapala, 'Ashta Dikapala', GI.GT_MUGHAL_GANJIFA, 1, 0,
|
||||
GI.SL_BALANCED)
|
||||
GI.SL_BALANCED, altnames=('Eight Guardians'))
|
||||
|
||||
del r
|
||||
|
|
|
@ -501,11 +501,11 @@ class TrumpsRow(Montana):
|
|||
# ************************************************************************
|
||||
|
||||
def r(id, gameclass, name, game_type, decks, redeals, skill_level,
|
||||
numcards=78):
|
||||
numcards=78, altnames=()):
|
||||
game_type = game_type | GI.GT_TAROCK | GI.GT_CONTRIB | GI.GT_ORIGINAL
|
||||
gi = GameInfo(id, gameclass, name, game_type, decks, redeals, skill_level,
|
||||
ranks=list(range(14)), trumps=list(range(22)),
|
||||
si={"ncards": numcards})
|
||||
altnames=altnames, si={"ncards": numcards})
|
||||
registerGame(gi)
|
||||
return gi
|
||||
|
||||
|
@ -519,7 +519,8 @@ r(13166, Serpent, 'Serpent', GI.GT_TAROCK | GI.GT_OPEN, 2, 0,
|
|||
GI.SL_MOSTLY_SKILL)
|
||||
r(13167, Rambling, 'Rambling', GI.GT_TAROCK | GI.GT_OPEN, 2, 0,
|
||||
GI.SL_MOSTLY_SKILL)
|
||||
r(13168, FoolsUp, "Fool's Up", GI.GT_TAROCK, 1, 0, GI.SL_LUCK)
|
||||
r(13168, FoolsUp, "Fool's Up", GI.GT_TAROCK, 1, 0, GI.SL_LUCK,
|
||||
altnames=('Solitairot'))
|
||||
r(13169, TrumpsRow, "Trumps Row", GI.GT_TAROCK, 1, 4, GI.SL_MOSTLY_SKILL,
|
||||
numcards=73)
|
||||
r(22232, LeGrandeTeton, 'Le Grande Teton', GI.GT_TAROCK, 1, 0, GI.SL_BALANCED)
|
||||
|
|
|
@ -348,15 +348,16 @@ class Scorpion_RowStack(Yukon_SS_RowStack, Spider_RowStack):
|
|||
|
||||
|
||||
class Scorpion(RelaxedSpider):
|
||||
|
||||
Hint_Class = YukonType_Hint
|
||||
RowStack_Class = StackWrapper(Scorpion_RowStack, base_rank=KING)
|
||||
|
||||
FACEDOWNS = (4, 4, 4, 0, 0, 0)
|
||||
|
||||
def createGame(self):
|
||||
RelaxedSpider.createGame(self, rows=7, playcards=20)
|
||||
|
||||
def startGame(self):
|
||||
for i in (4, 4, 4, 0, 0, 0):
|
||||
for i in self.FACEDOWNS:
|
||||
self.s.talon.dealRow(rows=self.s.rows[:i], flip=0, frames=0)
|
||||
self.s.talon.dealRow(rows=self.s.rows[i:], flip=1, frames=0)
|
||||
self._startAndDealRow()
|
||||
|
@ -379,46 +380,46 @@ class ScorpionTail(Scorpion):
|
|||
shallHighlightMatch = Game._shallHighlightMatch_AC
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Double Scorpion
|
||||
# * Triple Scorpion
|
||||
# ************************************************************************
|
||||
|
||||
class DoubleScorpion(Scorpion):
|
||||
Talon_Class = InitialDealTalonStack
|
||||
FACEDOWNS = (5, 5, 5, 5, 0, 0, 0, 0, 0)
|
||||
|
||||
def createGame(self):
|
||||
RelaxedSpider.createGame(self, rows=10, playcards=26, texts=0)
|
||||
|
||||
def startGame(self):
|
||||
for i in (5, 5, 5, 5, 0, 0, 0, 0, 0):
|
||||
self.s.talon.dealRow(rows=self.s.rows[:i], flip=0, frames=0)
|
||||
self.s.talon.dealRow(rows=self.s.rows[i:], flip=1, frames=0)
|
||||
self.startDealSample()
|
||||
self.s.talon.dealRow()
|
||||
self.s.talon.dealRowAvail()
|
||||
|
||||
|
||||
class TripleScorpion(Scorpion):
|
||||
Talon_Class = InitialDealTalonStack
|
||||
|
||||
FACEDOWNS = (5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0)
|
||||
|
||||
def createGame(self):
|
||||
RelaxedSpider.createGame(self, rows=13, playcards=30, texts=0)
|
||||
|
||||
def startGame(self):
|
||||
for i in (5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0):
|
||||
self.s.talon.dealRow(rows=self.s.rows[:i], flip=0, frames=0)
|
||||
self.s.talon.dealRow(rows=self.s.rows[i:], flip=1, frames=0)
|
||||
self._startAndDealRow()
|
||||
|
||||
# ************************************************************************
|
||||
# * Scorpion II
|
||||
# ************************************************************************
|
||||
|
||||
class ScorpionII(Scorpion):
|
||||
FACEDOWNS = (3, 3, 3, 0, 0, 0)
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Wasp
|
||||
# * Wasp II
|
||||
# ************************************************************************
|
||||
|
||||
class Wasp(Scorpion):
|
||||
RowStack_Class = Scorpion_RowStack # anything on an empty space
|
||||
|
||||
def startGame(self):
|
||||
for i in (3, 3, 3, 0, 0, 0):
|
||||
self.s.talon.dealRow(rows=self.s.rows[:i], flip=0, frames=0)
|
||||
self.s.talon.dealRow(rows=self.s.rows[i:], flip=1, frames=0)
|
||||
self._startAndDealRow()
|
||||
|
||||
class WaspII(ScorpionII):
|
||||
RowStack_Class = Scorpion_RowStack
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
|
@ -1124,19 +1125,6 @@ class Incompatibility(Spidike):
|
|||
self._startDealNumRowsAndDealSingleRow(4)
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Scorpion II
|
||||
# ************************************************************************
|
||||
|
||||
class ScorpionII(Scorpion):
|
||||
|
||||
def startGame(self):
|
||||
for i in (3, 3, 3, 0, 0, 0):
|
||||
self.s.talon.dealRow(rows=self.s.rows[:i], flip=0, frames=0)
|
||||
self.s.talon.dealRow(rows=self.s.rows[i:], flip=1, frames=0)
|
||||
self._startAndDealRow()
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Tarantula
|
||||
# ************************************************************************
|
||||
|
@ -1158,6 +1146,7 @@ class Tarantula(Spider):
|
|||
|
||||
# ************************************************************************
|
||||
# * Fechter's Game
|
||||
# * Microbe
|
||||
# ************************************************************************
|
||||
|
||||
class FechtersGame_Talon(TalonStack):
|
||||
|
@ -1180,14 +1169,7 @@ class FechtersGame_Talon(TalonStack):
|
|||
|
||||
|
||||
class FechtersGame_RowStack(AC_RowStack):
|
||||
def canDropCards(self, stacks):
|
||||
if len(self.cards) < 13:
|
||||
return (None, 0)
|
||||
cards = self.cards[-13:]
|
||||
for s in stacks:
|
||||
if s is not self and s.acceptsCards(self, cards):
|
||||
return (s, 13)
|
||||
return (None, 0)
|
||||
canDropCards = BasicRowStack.spiderCanDropCards
|
||||
|
||||
|
||||
class FechtersGame(RelaxedSpider):
|
||||
|
@ -1208,6 +1190,17 @@ class FechtersGame(RelaxedSpider):
|
|||
shallHighlightMatch = Game._shallHighlightMatch_AC
|
||||
|
||||
|
||||
class Microbe(FechtersGame):
|
||||
Talon_Class = DealRowTalonStack
|
||||
RowStack_Class = StackWrapper(FechtersGame_RowStack, base_rank=ANY_RANK)
|
||||
|
||||
def createGame(self):
|
||||
RelaxedSpider.createGame(self, rows=11)
|
||||
|
||||
def shuffle(self):
|
||||
self.shuffleSeparateDecks()
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Bebop
|
||||
# ************************************************************************
|
||||
|
@ -1663,3 +1656,8 @@ registerGame(GameInfo(870, FairMaids, "Fair Maids",
|
|||
GI.GT_SPIDER, 1, 0, GI.SL_BALANCED))
|
||||
registerGame(GameInfo(917, Astrocyte, "Astrocyte",
|
||||
GI.GT_SPIDER, 2, 0, GI.SL_MOSTLY_SKILL))
|
||||
registerGame(GameInfo(971, Microbe, "Microbe",
|
||||
GI.GT_SPIDER | GI.GT_SEPARATE_DECKS, 2, 0,
|
||||
GI.SL_MOSTLY_SKILL))
|
||||
registerGame(GameInfo(976, WaspII, "Wasp II",
|
||||
GI.GT_SPIDER, 1, 0, GI.SL_MOSTLY_SKILL))
|
||||
|
|
|
@ -51,10 +51,18 @@ class StHelena_Talon(TalonStack):
|
|||
# move all cards to the Talon and redeal
|
||||
lr = len(self.game.s.rows)
|
||||
num_cards = 0
|
||||
assert len(self.cards) == 0
|
||||
if len(self.cards) > 0:
|
||||
num_cards = len(self.cards)
|
||||
self.game.startDealSample()
|
||||
for i in range(lr):
|
||||
k = min(lr, len(self.cards))
|
||||
for j in range(k):
|
||||
self.game.flipAndMoveMove(self, self.game.s.rows[j], 4)
|
||||
self.game.stopSamples()
|
||||
return num_cards
|
||||
for r in self.game.s.rows[::-1]:
|
||||
for i in range(len(r.cards)):
|
||||
num_cards = num_cards + 1
|
||||
num_cards += 1
|
||||
self.game.moveMove(1, r, self, frames=0)
|
||||
assert len(self.cards) == num_cards
|
||||
if num_cards == 0: # game already finished
|
||||
|
@ -169,6 +177,32 @@ class BoxKite(StHelena):
|
|||
|
||||
shallHighlightMatch = Game._shallHighlightMatch_RKW
|
||||
|
||||
# ************************************************************************
|
||||
# * Louis
|
||||
# ************************************************************************
|
||||
|
||||
|
||||
class Louis(StHelena):
|
||||
Foundation_Class = SS_FoundationStack
|
||||
RowStack_Class = StackWrapper(UD_SS_RowStack, base_rank=NO_RANK, mod=13)
|
||||
|
||||
shallHighlightMatch = Game._shallHighlightMatch_RKW
|
||||
|
||||
def startGame(self):
|
||||
self.startDealSample()
|
||||
self.s.talon.dealRow(self.s.foundations)
|
||||
self.s.talon.dealRow()
|
||||
|
||||
def _shuffleHook(self, cards):
|
||||
return self._shuffleHookMoveToTop(
|
||||
cards, lambda c: (c.deck == 0 and c.rank in (0, 12),
|
||||
(-c.rank, c.suit)), 8)
|
||||
|
||||
def fillStack(self, stack):
|
||||
if (self.s.talon.cards and stack in self.s.rows
|
||||
and len(stack.cards) == 0):
|
||||
self.s.talon.dealRow(rows=[stack])
|
||||
|
||||
|
||||
# ************************************************************************
|
||||
# * Les Quatre Coins
|
||||
|
@ -452,3 +486,5 @@ registerGame(GameInfo(621, RegalFamily, "Regal Family",
|
|||
registerGame(GameInfo(859, KingsAudience, "King's Audience",
|
||||
GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_LUCK,
|
||||
altnames=("Queen's Audience")))
|
||||
registerGame(GameInfo(975, Louis, "Louis",
|
||||
GI.GT_2DECK_TYPE, 2, 2, GI.SL_BALANCED))
|
||||
|
|
|
@ -472,6 +472,7 @@ class Panopticon(TenAcross):
|
|||
|
||||
# ************************************************************************
|
||||
# * Australian Patience
|
||||
# * Outback Patience
|
||||
# * Tasmanian Patience
|
||||
# * Canberra
|
||||
# * Raw Prawn
|
||||
|
@ -482,9 +483,9 @@ class AustralianPatience(RussianSolitaire):
|
|||
|
||||
RowStack_Class = StackWrapper(Yukon_SS_RowStack, base_rank=KING)
|
||||
|
||||
def createGame(self, rows=7, max_rounds=1, num_deal=1):
|
||||
def createGame(self, rows=7, max_rounds=1, num_deal=1, playcards=16):
|
||||
l, s = Layout(self), self.s
|
||||
Layout.klondikeLayout(l, rows=rows, waste=1)
|
||||
Layout.klondikeLayout(l, rows=rows, waste=1, playcards=playcards)
|
||||
self.setSize(l.size[0], l.size[1])
|
||||
s.talon = WasteTalonStack(l.s.talon.x, l.s.talon.y, self,
|
||||
max_rounds=max_rounds, num_deal=num_deal)
|
||||
|
@ -500,6 +501,14 @@ class AustralianPatience(RussianSolitaire):
|
|||
self._startDealNumRowsAndDealRowAndCards(3)
|
||||
|
||||
|
||||
class OutbackPatience(AustralianPatience):
|
||||
def createGame(self):
|
||||
AustralianPatience.createGame(self, rows=8, playcards=25)
|
||||
|
||||
def startGame(self):
|
||||
self._startDealNumRowsAndDealRowAndCards(6)
|
||||
|
||||
|
||||
class TasmanianPatience(AustralianPatience):
|
||||
def createGame(self):
|
||||
AustralianPatience.createGame(self, max_rounds=-1, num_deal=3)
|
||||
|
@ -895,8 +904,7 @@ registerGame(GameInfo(387, Roslin, "Roslin",
|
|||
GI.GT_YUKON, 1, 0, GI.SL_MOSTLY_SKILL,
|
||||
altnames=("Roslyn",)))
|
||||
registerGame(GameInfo(447, AustralianPatience, "Australian Patience",
|
||||
GI.GT_YUKON, 1, 0, GI.SL_BALANCED,
|
||||
altnames=('Outback Patience',)))
|
||||
GI.GT_YUKON, 1, 0, GI.SL_BALANCED))
|
||||
registerGame(GameInfo(450, RawPrawn, "Raw Prawn",
|
||||
GI.GT_YUKON, 1, 0, GI.SL_BALANCED))
|
||||
registerGame(GameInfo(456, BimBom, "Bim Bom",
|
||||
|
@ -906,9 +914,12 @@ 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",
|
||||
GI.GT_YUKON, 2, 0, GI.SL_BALANCED))
|
||||
registerGame(GameInfo(530, RussianSpider, "Russian Spider",
|
||||
GI.GT_SPIDER, 1, 0, GI.SL_BALANCED,
|
||||
altnames=('Ukrainian Solitaire',)))
|
||||
|
@ -941,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',)))
|
||||
|
|
|
@ -175,6 +175,13 @@ def raise_help_html(game):
|
|||
pass
|
||||
|
||||
|
||||
def unraise_help_html():
|
||||
try:
|
||||
help_html_viewer.parent.attributes("-topmost", False)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def destroy_help_html():
|
||||
try:
|
||||
help_html_viewer.destroy()
|
||||
|
|
|
@ -73,6 +73,10 @@ def raise_find_card_dialog(game):
|
|||
pass
|
||||
|
||||
|
||||
def unraise_find_card_dialog():
|
||||
pass
|
||||
|
||||
|
||||
def destroy_find_card_dialog():
|
||||
pass
|
||||
'''
|
||||
|
|
|
@ -112,6 +112,10 @@ def raise_full_picture_dialog(game):
|
|||
pass
|
||||
|
||||
|
||||
def unraise_full_picture_dialog():
|
||||
pass
|
||||
|
||||
|
||||
def destroy_full_picture_dialog():
|
||||
pass
|
||||
'''
|
||||
|
|
|
@ -571,7 +571,7 @@ class LOptionsMenuGenerator(LTreeGenerator):
|
|||
LTreeNode(text=_('Automatic play')))
|
||||
if rg:
|
||||
self.addCheckNode(tv, rg,
|
||||
_('Auto face up'),
|
||||
_('Auto face-up'),
|
||||
self.menubar.tkopt.autofaceup,
|
||||
self.menubar.mOptAutoFaceUp)
|
||||
|
||||
|
|
|
@ -50,6 +50,10 @@ def raise_solver_dialog(game):
|
|||
pass
|
||||
|
||||
|
||||
def unraise_solver_dialog():
|
||||
pass
|
||||
|
||||
|
||||
def destroy_solver_dialog():
|
||||
global solver_dialog
|
||||
solver_dialog = None
|
||||
|
|
|
@ -456,7 +456,7 @@ class AShuffleStackMove(AtomicMove):
|
|||
def redo(self, game):
|
||||
stack = game.allstacks[self.stack_id]
|
||||
# paranoia
|
||||
assert stack is game.s.talon
|
||||
assert stack is game.s.talon or stack in game.s.internals
|
||||
# shuffle (see random)
|
||||
game.random.setstate(self.state)
|
||||
seq = stack.cards
|
||||
|
|
|
@ -54,5 +54,9 @@ def raise_find_card_dialog(game):
|
|||
pass
|
||||
|
||||
|
||||
def unraise_find_card_dialog():
|
||||
pass
|
||||
|
||||
|
||||
def destroy_find_card_dialog():
|
||||
pass
|
||||
|
|
|
@ -50,7 +50,11 @@ def connect_game_full_picture_dialog(game):
|
|||
pass
|
||||
|
||||
|
||||
def raise_find_card_dialog(game):
|
||||
def raise_full_picture_dialog(game):
|
||||
pass
|
||||
|
||||
|
||||
def unraise_full_picture_dialog():
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
@ -259,7 +259,7 @@ class PysolMenubarTk:
|
|||
]
|
||||
for label, action, opt_name, update_game in (
|
||||
('A&uto drop', 'optautodrop', 'autodrop', False),
|
||||
('Auto &face up', '', 'autofaceup', False),
|
||||
('Auto &face-up', '', 'autofaceup', False),
|
||||
('Auto &deal', '', 'autodeal', False),
|
||||
('&Quick play', '', 'quickplay', False),
|
||||
('Enable &undo', '', 'undo', False),
|
||||
|
|
|
@ -34,6 +34,10 @@ def raise_solver_dialog(game):
|
|||
pass
|
||||
|
||||
|
||||
def unraise_solver_dialog():
|
||||
pass
|
||||
|
||||
|
||||
def destroy_solver_dialog():
|
||||
pass
|
||||
# solver_dialog = None
|
||||
|
|
|
@ -353,7 +353,6 @@ class SelectCardsetDialogWithPreview(MfxDialog):
|
|||
check = ttk.Checkbutton(
|
||||
size_frame, text=_('Auto scaling'),
|
||||
variable=self.auto_scale,
|
||||
takefocus=False,
|
||||
command=self._updateAutoScale
|
||||
)
|
||||
check.grid(row=5, column=0, columnspan=2, sticky='ew',
|
||||
|
@ -364,7 +363,6 @@ class SelectCardsetDialogWithPreview(MfxDialog):
|
|||
self.aspect_check = ttk.Checkbutton(
|
||||
size_frame, text=_('Preserve aspect ratio'),
|
||||
variable=self.preserve_aspect,
|
||||
takefocus=False,
|
||||
# command=self._updateScale
|
||||
)
|
||||
self.aspect_check.grid(row=6, column=0, sticky='ew',
|
||||
|
@ -664,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:
|
||||
|
|
|
@ -95,3 +95,10 @@ def raise_solver_dialog(game):
|
|||
solver_dialog.top.attributes("-topmost", False)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def unraise_solver_dialog():
|
||||
try:
|
||||
solver_dialog.top.attributes("-topmost", False)
|
||||
except Exception:
|
||||
pass
|
||||
|
|
|
@ -109,7 +109,7 @@ class SoundOptionsDialog(MfxDialog):
|
|||
ttk.Label(frame, text=_('Sample volume:'), anchor='w'
|
||||
).grid(row=row, column=0, sticky='ew')
|
||||
w = PysolScale(frame, from_=0, to=128, resolution=1,
|
||||
orient='horizontal', takefocus=0,
|
||||
orient='horizontal',
|
||||
length="3i", # label=_('Sample volume'),
|
||||
variable=self.sample_volume)
|
||||
w.grid(row=row, column=1, sticky='w', padx=5)
|
||||
|
@ -122,7 +122,7 @@ class SoundOptionsDialog(MfxDialog):
|
|||
ttk.Label(frame, text=_('Music volume:'), anchor='w'
|
||||
).grid(row=row, column=0, sticky='ew')
|
||||
w = PysolScale(frame, from_=0, to=128, resolution=1,
|
||||
orient='horizontal', takefocus=0,
|
||||
orient='horizontal',
|
||||
length="3i", # label=_('Music volume'),
|
||||
variable=self.music_volume)
|
||||
w.grid(row=row, column=1, sticky='w', padx=5)
|
||||
|
|
|
@ -72,7 +72,7 @@ class TimeoutsDialog(MfxDialog):
|
|||
row=row, column=0, sticky='we')
|
||||
widget = PysolScale(lframe, from_=0.2, to=9.9, value=var.get(),
|
||||
resolution=0.1, orient='horizontal',
|
||||
length="3i", variable=var, takefocus=0)
|
||||
length="3i", variable=var)
|
||||
widget.grid(row=row, column=1)
|
||||
row += 1
|
||||
#
|
||||
|
|
|
@ -377,7 +377,7 @@ class TreeFormatter(PysolStatsFormatter):
|
|||
return 1
|
||||
|
||||
def writeLog(self, player, prev_games, sort_by='date'):
|
||||
if not player or not prev_games:
|
||||
if not prev_games:
|
||||
return 0
|
||||
num_rows = 0
|
||||
results = self.getLogResults(player, prev_games)
|
||||
|
@ -520,6 +520,8 @@ class LogDialog(MfxDialog):
|
|||
|
||||
kw = self.initKw(kw)
|
||||
title = _('Log')
|
||||
if player is None:
|
||||
title = _('Demo Log')
|
||||
MfxDialog.__init__(self, parent, title, kw.resizable, kw.default)
|
||||
|
||||
self.top.wm_minsize(400, 200)
|
||||
|
|
|
@ -105,8 +105,7 @@ class WizardDialog(MfxDialog):
|
|||
elif w.widget == 'check':
|
||||
if w.variable is None:
|
||||
w.variable = tkinter.BooleanVar()
|
||||
ch = ttk.Checkbutton(frame, variable=w.variable,
|
||||
takefocus=False)
|
||||
ch = ttk.Checkbutton(frame, variable=w.variable)
|
||||
ch.grid(row=row, column=1, sticky='ew', padx=2, pady=2)
|
||||
|
||||
if w.current_value is None:
|
||||
|
|
|
@ -271,7 +271,6 @@ class SelectCardsetDialogWithPreview(MfxDialog):
|
|||
check = tkinter.Checkbutton(
|
||||
left_frame, text=_('Auto scaling'),
|
||||
variable=self.auto_scale,
|
||||
takefocus=False,
|
||||
command=self._updateAutoScale
|
||||
)
|
||||
check.grid(row=3, column=0, columnspan=2, sticky='w',
|
||||
|
@ -282,7 +281,6 @@ class SelectCardsetDialogWithPreview(MfxDialog):
|
|||
self.aspect_check = tkinter.Checkbutton(
|
||||
left_frame, text=_('Preserve aspect ratio'),
|
||||
variable=self.preserve_aspect,
|
||||
takefocus=False,
|
||||
# command=self._updateScale
|
||||
)
|
||||
self.aspect_check.grid(row=4, column=0, sticky='w',
|
||||
|
@ -438,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:
|
||||
|
|
|
@ -109,7 +109,7 @@ class SoundOptionsDialog(MfxDialog):
|
|||
w = tkinter.Label(frame, text=_('Sample volume:'))
|
||||
w.grid(row=row, column=0, sticky='w', padx=5)
|
||||
w = tkinter.Scale(frame, from_=0, to=128, resolution=1,
|
||||
orient='horizontal', takefocus=0,
|
||||
orient='horizontal',
|
||||
length="3i", # label=_('Sample volume'),
|
||||
variable=self.sample_volume)
|
||||
w.grid(row=row, column=1, sticky='ew', padx=5)
|
||||
|
@ -117,7 +117,7 @@ class SoundOptionsDialog(MfxDialog):
|
|||
w = tkinter.Label(frame, text=_('Music volume:'))
|
||||
w.grid(row=row, column=0, sticky='w', padx=5)
|
||||
w = tkinter.Scale(frame, from_=0, to=128, resolution=1,
|
||||
orient='horizontal', takefocus=0,
|
||||
orient='horizontal',
|
||||
length="3i", # label=_('Music volume'),
|
||||
variable=self.music_volume)
|
||||
w.grid(row=row, column=1, sticky='ew', padx=5)
|
||||
|
|
|
@ -71,7 +71,7 @@ class TimeoutsDialog(MfxDialog):
|
|||
).grid(row=row, column=0, sticky='we')
|
||||
widget = tkinter.Scale(frame, from_=0.2, to=9.9,
|
||||
resolution=0.1, orient='horizontal',
|
||||
length="3i", variable=var, takefocus=0)
|
||||
length="3i", variable=var)
|
||||
widget.grid(row=row, column=1)
|
||||
row += 1
|
||||
#
|
||||
|
|
|
@ -94,7 +94,7 @@ class WizardDialog(MfxDialog):
|
|||
if w.variable is None:
|
||||
w.variable = tkinter.BooleanVar()
|
||||
ch = tkinter.Checkbutton(frame, variable=w.variable,
|
||||
takefocus=False, anchor='w')
|
||||
anchor='w')
|
||||
ch.grid(row=row, column=1, sticky='ew', padx=2, pady=2)
|
||||
|
||||
if w.current_value is None:
|
||||
|
|