mirror of
https://github.com/shlomif/PySolFC.git
synced 2025-04-05 00:02:29 -04:00
Compare commits
4 commits
c8b6ce0fcd
...
6bc5b53995
Author | SHA1 | Date | |
---|---|---|---|
|
6bc5b53995 | ||
|
dd42ac10ea | ||
|
d6ca6d226b | ||
|
e4e2e99031 |
49 changed files with 177 additions and 561 deletions
|
@ -1,64 +0,0 @@
|
||||||
<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,7 +46,6 @@ fix_gettext()
|
||||||
files = [
|
files = [
|
||||||
('credits.html', 'PySol Credits'),
|
('credits.html', 'PySol Credits'),
|
||||||
('credits_old.html', 'PySol Credits'),
|
('credits_old.html', 'PySol Credits'),
|
||||||
('faq.html', 'PySol - FAQ'),
|
|
||||||
('ganjifa.html', 'PySol - General Ganjifa Card Rules'),
|
('ganjifa.html', 'PySol - General Ganjifa Card Rules'),
|
||||||
('general_rules.html', 'PySol - General Rules'),
|
('general_rules.html', 'PySol - General Rules'),
|
||||||
('glossary.html', 'PySol - Glossary'),
|
('glossary.html', 'PySol - Glossary'),
|
||||||
|
|
|
@ -323,15 +323,6 @@ the deck.</p>
|
||||||
Hearts, and Diamonds.</p>
|
Hearts, and Diamonds.</p>
|
||||||
</dd>
|
</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>
|
<dt><b>TABLEAU</b></dt>
|
||||||
|
|
||||||
<dd>
|
<dd>
|
||||||
|
|
|
@ -55,6 +55,27 @@ 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).
|
The logic involved is not too clever on purpose (i.e. it does not consult the hint system).
|
||||||
</ul>
|
</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>
|
<h2>Some notes about scoring</h2>
|
||||||
<p>
|
<p>
|
||||||
<ul type="disc">
|
<ul type="disc">
|
||||||
|
|
|
@ -19,10 +19,9 @@
|
||||||
<li> <a href="cardset_customization.html">Cardset Customization</a>
|
<li> <a href="cardset_customization.html">Cardset Customization</a>
|
||||||
<li> <a href="plugins.html">Plugins</a>
|
<li> <a href="plugins.html">Plugins</a>
|
||||||
</ul>
|
</ul>
|
||||||
<h2>About</h2>
|
<h2>Misc</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li> <a href="news.html">What's new?</a>
|
<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="report_bug.html">Report a Bug</a>
|
||||||
<li> <a href="license.html">PySol license terms</a>
|
<li> <a href="license.html">PySol license terms</a>
|
||||||
<li> <a href="credits.html">PySol credits</a>
|
<li> <a href="credits.html">PySol credits</a>
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
<h1>Report a Bug</h1>
|
<h1>Report a Bug</h1>
|
||||||
<p>
|
<p>
|
||||||
Before you report a bug, please verify that you are running
|
Before you report a bug, please verify that you are running
|
||||||
the latest version of PySolFC. Also, check the
|
the latest version of PySolFC, and also check the PySolFC site's
|
||||||
<a href="faq.html">FAQ</a>, and issues previously reported
|
<a href="https://pysolfc.sourceforge.io/faq.html">FAQ page</a>,
|
||||||
on GitHub, to ensure that the bug was not previously reported.
|
and issues previously reported on GitHub, to ensure that the bug
|
||||||
|
was not previously reported.
|
||||||
<p>
|
<p>
|
||||||
If you found a bug in PySolFC, the best place to report it
|
If you found a bug in PySolFC, the best place to report it
|
||||||
is on GitHub. To do so, create an issue at
|
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>
|
<h3>Notes</h3>
|
||||||
<p>
|
<p>
|
||||||
Accordion's Revenge is unwinnable if the first or second card is
|
Accordion's Revenge is unwinnable if the first or second card is
|
||||||
declared. As such, PySol will never select either of those cards as
|
declared. As such, PySol will reselect the declared card if it
|
||||||
the target.
|
is chosen.
|
||||||
<p>
|
<p>
|
||||||
The concept of Accordion's Revenge was invented by Mark Masten.
|
The concept of Accordion's Revenge was invented by Mark Masten.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<h1>Big Braid (Der große Zopf)</h1>
|
<h1>Big Braid</h1>
|
||||||
<p>
|
<p>
|
||||||
Napoleon type. 3 decks. 2 redeals.
|
Napoleon type. 3 decks. 2 redeals.
|
||||||
|
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
<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.
|
|
|
@ -1,6 +1,6 @@
|
||||||
<h1>Hurricane</h1>
|
<h1>Hurricane</h1>
|
||||||
<p>
|
<p>
|
||||||
Pairing type. 1 deck. No redeal.
|
Pairing game type. 1 deck. No redeal.
|
||||||
|
|
||||||
<h3>Object</h3>
|
<h3>Object</h3>
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
<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.
|
|
|
@ -1,19 +0,0 @@
|
||||||
<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.
|
|
|
@ -1,12 +0,0 @@
|
||||||
<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.
|
|
|
@ -1,22 +0,0 @@
|
||||||
<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.
|
|
|
@ -1,12 +0,0 @@
|
||||||
<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.
|
|
|
@ -1,13 +0,0 @@
|
||||||
<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>).
|
|
|
@ -2653,7 +2653,7 @@ msgid "Automatic play"
|
||||||
msgstr "Automatisierung"
|
msgstr "Automatisierung"
|
||||||
|
|
||||||
#: pysollib/kivy/menubar.py:513
|
#: pysollib/kivy/menubar.py:513
|
||||||
msgid "Auto face-up"
|
msgid "Auto face up"
|
||||||
msgstr "Automatisch aufdecken"
|
msgstr "Automatisch aufdecken"
|
||||||
|
|
||||||
#: pysollib/kivy/menubar.py:523
|
#: pysollib/kivy/menubar.py:523
|
||||||
|
@ -5174,7 +5174,7 @@ msgstr "Kommentare..."
|
||||||
msgid "Log..."
|
msgid "Log..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Demo log..."
|
msgid "Demo Log..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/ui/tktile/menubar.py:427
|
#: pysollib/ui/tktile/menubar.py:427
|
||||||
|
|
|
@ -2694,7 +2694,7 @@ msgid "Automatic play"
|
||||||
msgstr "Jouer auto"
|
msgstr "Jouer auto"
|
||||||
|
|
||||||
#: pysollib/kivy/menubar.py:513
|
#: pysollib/kivy/menubar.py:513
|
||||||
msgid "Auto face-up"
|
msgid "Auto face up"
|
||||||
msgstr "Retourner auto"
|
msgstr "Retourner auto"
|
||||||
|
|
||||||
#: pysollib/kivy/menubar.py:523
|
#: pysollib/kivy/menubar.py:523
|
||||||
|
@ -5225,7 +5225,7 @@ msgstr "&Commentaires..."
|
||||||
msgid "Log..."
|
msgid "Log..."
|
||||||
msgstr "Journal..."
|
msgstr "Journal..."
|
||||||
|
|
||||||
msgid "Demo log..."
|
msgid "Demo Log..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/ui/tktile/menubar.py:427
|
#: pysollib/ui/tktile/menubar.py:427
|
||||||
|
|
|
@ -2707,7 +2707,7 @@ msgstr "Gioco automatico"
|
||||||
|
|
||||||
#: pysollib/kivy/menubar.py:513
|
#: pysollib/kivy/menubar.py:513
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid "Auto face-up"
|
msgid "Auto face up"
|
||||||
msgstr "Auto &scopri"
|
msgstr "Auto &scopri"
|
||||||
|
|
||||||
#: pysollib/kivy/menubar.py:523
|
#: pysollib/kivy/menubar.py:523
|
||||||
|
@ -5291,7 +5291,7 @@ msgstr "&Commenti..."
|
||||||
msgid "Log..."
|
msgid "Log..."
|
||||||
msgstr "Log..."
|
msgstr "Log..."
|
||||||
|
|
||||||
msgid "Demo log..."
|
msgid "Demo Log..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/ui/tktile/menubar.py:427
|
#: pysollib/ui/tktile/menubar.py:427
|
||||||
|
|
|
@ -2707,7 +2707,7 @@ msgid "Automatic play"
|
||||||
msgstr "Gra &automatyczna"
|
msgstr "Gra &automatyczna"
|
||||||
|
|
||||||
#: pysollib/kivy/menubar.py:513
|
#: pysollib/kivy/menubar.py:513
|
||||||
msgid "Auto face-up"
|
msgid "Auto face up"
|
||||||
msgstr "Odkrywaj automatycznie"
|
msgstr "Odkrywaj automatycznie"
|
||||||
|
|
||||||
#: pysollib/kivy/menubar.py:523
|
#: pysollib/kivy/menubar.py:523
|
||||||
|
@ -5245,7 +5245,7 @@ msgstr "Komentarze..."
|
||||||
msgid "Log..."
|
msgid "Log..."
|
||||||
msgstr "Log..."
|
msgstr "Log..."
|
||||||
|
|
||||||
msgid "Demo log..."
|
msgid "Demo Log..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/ui/tktile/menubar.py:427
|
#: pysollib/ui/tktile/menubar.py:427
|
||||||
|
|
|
@ -2715,7 +2715,7 @@ msgid "Automatic play"
|
||||||
msgstr "Jogar automaticamente"
|
msgstr "Jogar automaticamente"
|
||||||
|
|
||||||
#: pysollib/kivy/menubar.py:513
|
#: pysollib/kivy/menubar.py:513
|
||||||
msgid "Auto face-up"
|
msgid "Auto face up"
|
||||||
msgstr "Virar pra cima automaticamente"
|
msgstr "Virar pra cima automaticamente"
|
||||||
|
|
||||||
#: pysollib/kivy/menubar.py:523
|
#: pysollib/kivy/menubar.py:523
|
||||||
|
@ -5247,7 +5247,7 @@ msgstr "&Comentários..."
|
||||||
msgid "Log..."
|
msgid "Log..."
|
||||||
msgstr "Registro"
|
msgstr "Registro"
|
||||||
|
|
||||||
msgid "Demo log..."
|
msgid "Demo Log..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/ui/tktile/menubar.py:427
|
#: pysollib/ui/tktile/menubar.py:427
|
||||||
|
|
|
@ -2524,7 +2524,7 @@ msgid "Automatic play"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/kivy/menubar.py:513
|
#: pysollib/kivy/menubar.py:513
|
||||||
msgid "Auto face-up"
|
msgid "Auto face up"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/kivy/menubar.py:523
|
#: pysollib/kivy/menubar.py:523
|
||||||
|
@ -4977,7 +4977,7 @@ msgstr ""
|
||||||
msgid "Log..."
|
msgid "Log..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Demo log..."
|
msgid "Demo Log..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/ui/tktile/menubar.py:427
|
#: pysollib/ui/tktile/menubar.py:427
|
||||||
|
|
|
@ -2713,7 +2713,7 @@ msgstr "Настройки &автоматической игры"
|
||||||
|
|
||||||
#: pysollib/kivy/menubar.py:513
|
#: pysollib/kivy/menubar.py:513
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid "Auto face-up"
|
msgid "Auto face up"
|
||||||
msgstr "Автоматически &переворачивать"
|
msgstr "Автоматически &переворачивать"
|
||||||
|
|
||||||
#: pysollib/kivy/menubar.py:523
|
#: pysollib/kivy/menubar.py:523
|
||||||
|
@ -5314,7 +5314,7 @@ msgstr "&Комментарии..."
|
||||||
msgid "Log..."
|
msgid "Log..."
|
||||||
msgstr "Лог..."
|
msgstr "Лог..."
|
||||||
|
|
||||||
msgid "Demo log..."
|
msgid "Demo Log..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pysollib/ui/tktile/menubar.py:427
|
#: pysollib/ui/tktile/menubar.py:427
|
||||||
|
|
|
@ -112,7 +112,7 @@ class GI:
|
||||||
|
|
||||||
# extra flags
|
# extra flags
|
||||||
GT_BETA = 1 << 12 # beta version of game driver
|
GT_BETA = 1 << 12 # beta version of game driver
|
||||||
GT_CHILDREN = 1 << 13
|
GT_CHILDREN = 1 << 13 # *not used*
|
||||||
GT_CONTRIB = 1 << 14 # contributed games under the GNU GPL
|
GT_CONTRIB = 1 << 14 # contributed games under the GNU GPL
|
||||||
GT_HIDDEN = 1 << 15 # not visible in menus, but games can be loaded
|
GT_HIDDEN = 1 << 15 # not visible in menus, but games can be loaded
|
||||||
GT_OPEN = 1 << 16
|
GT_OPEN = 1 << 16
|
||||||
|
@ -320,6 +320,7 @@ class GI:
|
||||||
904: 68, # Lexington Harp
|
904: 68, # Lexington Harp
|
||||||
237: 22231, # Three Peaks
|
237: 22231, # Three Peaks
|
||||||
297: 631, # Alternation/Alternations
|
297: 631, # Alternation/Alternations
|
||||||
|
526: 447, # Australian/Outback Patience
|
||||||
640: 566, # Hypotenuse/Brazilian Patience
|
640: 566, # Hypotenuse/Brazilian Patience
|
||||||
|
|
||||||
# Lost Mahjongg Layouts
|
# Lost Mahjongg Layouts
|
||||||
|
@ -367,12 +368,12 @@ class GI:
|
||||||
# Hamilton, Labyrinth, Treize, Wall
|
# Hamilton, Labyrinth, Treize, Wall
|
||||||
("Gnome AisleRiot", (
|
("Gnome AisleRiot", (
|
||||||
1, 2, 8, 9, 11, 12, 13, 19, 24, 27, 29, 31, 33, 34, 35, 36,
|
1, 2, 8, 9, 11, 12, 13, 19, 24, 27, 29, 31, 33, 34, 35, 36,
|
||||||
38, 40, 41, 42, 43, 44, 45, 48, 58, 65, 67, 89, 91, 92, 93,
|
38, 40, 41, 42, 43, 45, 48, 58, 65, 67, 89, 91, 92, 93, 94,
|
||||||
94, 95, 96, 97, 100, 104, 105, 111, 112, 113, 130, 135, 139,
|
95, 96, 97, 100, 104, 105, 111, 112, 113, 130, 135, 139, 144,
|
||||||
144, 146, 147, 148, 200, 201, 206, 224, 225, 229, 230, 233,
|
146, 147, 148, 200, 201, 206, 224, 225, 229, 230, 233, 257,
|
||||||
257, 258, 277, 280, 281, 282, 283, 284, 334, 384, 479, 495,
|
258, 277, 280, 281, 282, 283, 284, 334, 384, 479, 495, 551,
|
||||||
551, 552, 553, 572, 593, 674, 700, 715, 716, 737, 772, 810,
|
552, 553, 572, 593, 674, 700, 715, 716, 737, 772, 810, 819,
|
||||||
819, 824, 829, 859, 874, 906, 934, 22231,
|
824, 829, 859, 874, 906, 934, 22231,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
# Hoyle Card Games
|
# Hoyle Card Games
|
||||||
|
@ -574,7 +575,7 @@ class GI:
|
||||||
('fc-0.9.0', tuple(range(323, 421))),
|
('fc-0.9.0', tuple(range(323, 421))),
|
||||||
('fc-0.9.1', tuple(range(421, 441))),
|
('fc-0.9.1', tuple(range(421, 441))),
|
||||||
('fc-0.9.2', tuple(range(441, 466))),
|
('fc-0.9.2', tuple(range(441, 466))),
|
||||||
('fc-0.9.3', tuple(range(466, 526)) + tuple(range(527, 661))),
|
('fc-0.9.3', tuple(range(466, 661))),
|
||||||
('fc-0.9.4', tuple(range(661, 671))),
|
('fc-0.9.4', tuple(range(661, 671))),
|
||||||
('fc-1.0', tuple(range(671, 711))),
|
('fc-1.0', tuple(range(671, 711))),
|
||||||
('fc-1.1', tuple(range(711, 759))),
|
('fc-1.1', tuple(range(711, 759))),
|
||||||
|
@ -594,8 +595,7 @@ class GI:
|
||||||
tuple(range(19000, 19012)) + tuple(range(22303, 22311)) +
|
tuple(range(19000, 19012)) + tuple(range(22303, 22311)) +
|
||||||
tuple(range(22353, 22361))),
|
tuple(range(22353, 22361))),
|
||||||
('fc-3.1', tuple(range(961, 971))),
|
('fc-3.1', tuple(range(961, 971))),
|
||||||
('dev', tuple(range(971, 978)) + tuple(range(18005, 18007)) +
|
('dev', tuple(range(971, 973)) + tuple(range(18005, 18007))),
|
||||||
(44, 526,)),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# deprecated - the correct way is to or a GI.GT_XXX flag
|
# deprecated - the correct way is to or a GI.GT_XXX flag
|
||||||
|
|
|
@ -225,7 +225,6 @@ class Vineyard(CastlesInSpain):
|
||||||
|
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
# * Cruel
|
# * Cruel
|
||||||
# * Relaxed Cruel
|
|
||||||
# * Unusual
|
# * Unusual
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
|
|
||||||
|
@ -311,10 +310,6 @@ class Cruel(CastlesInSpain):
|
||||||
shallHighlightMatch = Game._shallHighlightMatch_SS
|
shallHighlightMatch = Game._shallHighlightMatch_SS
|
||||||
|
|
||||||
|
|
||||||
class RelaxedCruel(Cruel):
|
|
||||||
RowStack_Class = StackWrapper(SS_RowStack, base_rank=NO_RANK)
|
|
||||||
|
|
||||||
|
|
||||||
class Unusual(Cruel):
|
class Unusual(Cruel):
|
||||||
|
|
||||||
def createGame(self):
|
def createGame(self):
|
||||||
|
@ -458,6 +453,3 @@ registerGame(GameInfo(876, Vineyard, "Vineyard",
|
||||||
GI.SL_MOSTLY_SKILL))
|
GI.SL_MOSTLY_SKILL))
|
||||||
registerGame(GameInfo(907, Martha, "Stewart",
|
registerGame(GameInfo(907, Martha, "Stewart",
|
||||||
GI.GT_BAKERS_DOZEN, 1, 0, GI.SL_BALANCED))
|
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))
|
|
||||||
|
|
|
@ -646,8 +646,7 @@ registerGame(GameInfo(376, Backbone, "Backbone",
|
||||||
registerGame(GameInfo(377, BackbonePlus, "Backbone +",
|
registerGame(GameInfo(377, BackbonePlus, "Backbone +",
|
||||||
GI.GT_NAPOLEON, 2, 0, GI.SL_BALANCED))
|
GI.GT_NAPOLEON, 2, 0, GI.SL_BALANCED))
|
||||||
registerGame(GameInfo(510, BigBraid, "Big Braid",
|
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",
|
registerGame(GameInfo(694, Casket, "Casket",
|
||||||
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED))
|
||||||
registerGame(GameInfo(717, Well, "Well",
|
registerGame(GameInfo(717, Well, "Well",
|
||||||
|
|
|
@ -383,18 +383,51 @@ class PyramidDozen(Giza):
|
||||||
|
|
||||||
|
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
# * Pyramid Thirteen
|
# * Thirteen
|
||||||
|
# * FIXME: UNFINISHED
|
||||||
|
# * (this doesn't work yet as 2 cards of the Waste should be playable)
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
|
|
||||||
# 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):
|
class Thirteen(Pyramid):
|
||||||
Talon_Class = StackWrapper(Pyramid_Talon, max_rounds=1, max_accept=1)
|
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
#
|
||||||
|
|
||||||
def startGame(self):
|
def startGame(self):
|
||||||
self.startDealSample()
|
self.startDealSample()
|
||||||
|
@ -1758,8 +1791,6 @@ class Hurricane_Reserve(Hurricane_StackMethods, OpenStack):
|
||||||
|
|
||||||
class Hurricane(Pyramid):
|
class Hurricane(Pyramid):
|
||||||
Hint_Class = Hurricane_Hint
|
Hint_Class = Hurricane_Hint
|
||||||
RowStack_Class = Hurricane_RowStack
|
|
||||||
Reserve_Class = Hurricane_Reserve
|
|
||||||
|
|
||||||
def createGame(self):
|
def createGame(self):
|
||||||
# create layout
|
# create layout
|
||||||
|
@ -1777,7 +1808,7 @@ class Hurricane(Pyramid):
|
||||||
(0, 2), (1, 2), (2, 2), (3, 2),
|
(0, 2), (1, 2), (2, 2), (3, 2),
|
||||||
):
|
):
|
||||||
x, y = layout.XM + 1.5*layout.XS + ww*xx, layout.YM + layout.YS*yy
|
x, y = layout.XM + 1.5*layout.XS + ww*xx, layout.YM + layout.YS*yy
|
||||||
stack = self.Reserve_Class(x, y, self, max_accept=1)
|
stack = Hurricane_Reserve(x, y, self, max_accept=1)
|
||||||
stack.CARD_XOFFSET, stack.CARD_YOFFSET = layout.XOFFSET, 0
|
stack.CARD_XOFFSET, stack.CARD_YOFFSET = layout.XOFFSET, 0
|
||||||
s.reserves.append(stack)
|
s.reserves.append(stack)
|
||||||
|
|
||||||
|
@ -1785,7 +1816,7 @@ class Hurricane(Pyramid):
|
||||||
x = layout.XM + 1.5*layout.XS + layout.XS+2*layout.XOFFSET + d//2
|
x = layout.XM + 1.5*layout.XS + layout.XS+2*layout.XOFFSET + d//2
|
||||||
y = layout.YM+layout.YS
|
y = layout.YM+layout.YS
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
stack = self.RowStack_Class(x, y, self, max_accept=1)
|
stack = Hurricane_RowStack(x, y, self, max_accept=1)
|
||||||
s.rows.append(stack)
|
s.rows.append(stack)
|
||||||
x += layout.XS
|
x += layout.XS
|
||||||
|
|
||||||
|
@ -1816,38 +1847,6 @@ class Hurricane(Pyramid):
|
||||||
self.leaveState(old_state)
|
self.leaveState(old_state)
|
||||||
|
|
||||||
|
|
||||||
# ************************************************************************
|
|
||||||
# * 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
|
|
||||||
|
|
||||||
|
|
||||||
# register the game
|
# register the game
|
||||||
registerGame(GameInfo(38, Pyramid, "Pyramid",
|
registerGame(GameInfo(38, Pyramid, "Pyramid",
|
||||||
GI.GT_PAIRING_TYPE, 1, 2, GI.SL_MOSTLY_LUCK))
|
GI.GT_PAIRING_TYPE, 1, 2, GI.SL_MOSTLY_LUCK))
|
||||||
|
@ -1855,8 +1854,8 @@ registerGame(GameInfo(193, RelaxedPyramid, "Relaxed Pyramid",
|
||||||
GI.GT_PAIRING_TYPE | GI.GT_RELAXED, 1, 2,
|
GI.GT_PAIRING_TYPE | GI.GT_RELAXED, 1, 2,
|
||||||
GI.SL_MOSTLY_LUCK,
|
GI.SL_MOSTLY_LUCK,
|
||||||
altnames=("Pyramid's Stones", "Pyramid Clear")))
|
altnames=("Pyramid's Stones", "Pyramid Clear")))
|
||||||
registerGame(GameInfo(44, Thirteen, "Pyramid Thirteen",
|
# registerGame(GameInfo(44, Thirteen, "Thirteen",
|
||||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
|
# GI.GT_PAIRING_TYPE, 1, 0))
|
||||||
registerGame(GameInfo(592, Giza, "Giza",
|
registerGame(GameInfo(592, Giza, "Giza",
|
||||||
GI.GT_PAIRING_TYPE | GI.GT_OPEN, 1, 0, GI.SL_BALANCED))
|
GI.GT_PAIRING_TYPE | GI.GT_OPEN, 1, 0, GI.SL_BALANCED))
|
||||||
registerGame(GameInfo(593, Thirteens, "Thirteens",
|
registerGame(GameInfo(593, Thirteens, "Thirteens",
|
||||||
|
@ -1928,6 +1927,3 @@ registerGame(GameInfo(961, Nines, "Nines",
|
||||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_LUCK))
|
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_LUCK))
|
||||||
registerGame(GameInfo(969, ElevenTriangle, "Eleven Triangle",
|
registerGame(GameInfo(969, ElevenTriangle, "Eleven Triangle",
|
||||||
GI.GT_PAIRING_TYPE, 1, 0, GI.SL_MOSTLY_LUCK))
|
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",)))
|
|
||||||
|
|
|
@ -291,8 +291,7 @@ class Maze(Game):
|
||||||
# register the game
|
# register the game
|
||||||
registerGame(GameInfo(118, SiebenBisAs, "Sieben bis As",
|
registerGame(GameInfo(118, SiebenBisAs, "Sieben bis As",
|
||||||
GI.GT_MONTANA | GI.GT_OPEN | GI.GT_STRIPPED, 1, 0,
|
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",
|
registerGame(GameInfo(144, Maze, "Maze",
|
||||||
GI.GT_MONTANA | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL,
|
GI.GT_MONTANA | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL,
|
||||||
si={"ncards": 48}))
|
si={"ncards": 48}))
|
||||||
|
|
|
@ -1266,12 +1266,10 @@ 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
|
game_type = game_type | GI.GT_DASHAVATARA_GANJIFA
|
||||||
gi = GameInfo(id, gameclass, name, game_type, decks, redeals, skill_level,
|
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)
|
registerGame(gi)
|
||||||
return gi
|
return gi
|
||||||
|
|
||||||
|
|
|
@ -1605,12 +1605,11 @@ class MagicMontana(Montana):
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
|
|
||||||
|
|
||||||
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
|
game_type = game_type | GI.GT_HEXADECK
|
||||||
gi = GameInfo(id, gameclass, name, game_type, decks, redeals, skill_level,
|
gi = GameInfo(id, gameclass, name, game_type, decks, redeals, skill_level,
|
||||||
suits=list(range(4)), ranks=list(range(16)),
|
suits=list(range(4)), ranks=list(range(16)),
|
||||||
trumps=list(range(4)), altnames=altnames)
|
trumps=list(range(4)))
|
||||||
registerGame(gi)
|
registerGame(gi)
|
||||||
return gi
|
return gi
|
||||||
|
|
||||||
|
@ -1634,7 +1633,7 @@ r(16674, HiddenPassages, 'Hidden Passages', GI.GT_HEXADECK, 1, 1,
|
||||||
r(16675, CluitjarsLair, 'Cluitjar\'s Lair', GI.GT_HEXADECK, 1, 0,
|
r(16675, CluitjarsLair, 'Cluitjar\'s Lair', GI.GT_HEXADECK, 1, 0,
|
||||||
GI.SL_BALANCED)
|
GI.SL_BALANCED)
|
||||||
r(16676, MerlinsMeander, 'Merlin\'s Meander', GI.GT_HEXADECK, 2, 2,
|
r(16676, MerlinsMeander, 'Merlin\'s Meander', GI.GT_HEXADECK, 2, 2,
|
||||||
GI.SL_BALANCED, altnames=('Merlin\'s Coil'))
|
GI.SL_BALANCED)
|
||||||
r(16677, MagesGame, 'Mage\'s Game', GI.GT_HEXADECK | GI.GT_OPEN, 1, 0,
|
r(16677, MagesGame, 'Mage\'s Game', GI.GT_HEXADECK | GI.GT_OPEN, 1, 0,
|
||||||
GI.SL_BALANCED)
|
GI.SL_BALANCED)
|
||||||
r(16678, Convolution, 'Convolution', GI.GT_HEXADECK | GI.GT_OPEN, 2, 0,
|
r(16678, Convolution, 'Convolution', GI.GT_HEXADECK | GI.GT_OPEN, 2, 0,
|
||||||
|
|
|
@ -71,7 +71,7 @@ class Memory_RowStack(OpenStack):
|
||||||
def _dropPairMove(self, n, other_stack, frames=-1, shadow=-1):
|
def _dropPairMove(self, n, other_stack, frames=-1, shadow=-1):
|
||||||
game = self.game
|
game = self.game
|
||||||
game.playSample("droppair", priority=200)
|
game.playSample("droppair", priority=200)
|
||||||
game.closed_cards -= 2
|
game.closed_cards = game.closed_cards - 2
|
||||||
game.score = game.score + 5
|
game.score = game.score + 5
|
||||||
|
|
||||||
rightclickHandler = clickHandler
|
rightclickHandler = clickHandler
|
||||||
|
@ -108,7 +108,6 @@ class Memory24(Game):
|
||||||
|
|
||||||
# game extras
|
# game extras
|
||||||
self.other_stack = None
|
self.other_stack = None
|
||||||
self.other_stack2 = None
|
|
||||||
self.closed_cards = -1
|
self.closed_cards = -1
|
||||||
self.score = 0
|
self.score = 0
|
||||||
|
|
||||||
|
@ -256,7 +255,7 @@ class Concentration_RowStack(Memory_RowStack):
|
||||||
def _dropPairMove(self, n, other_stack, frames=-1, shadow=-1):
|
def _dropPairMove(self, n, other_stack, frames=-1, shadow=-1):
|
||||||
game = self.game
|
game = self.game
|
||||||
game.playSample("droppair", priority=200)
|
game.playSample("droppair", priority=200)
|
||||||
game.closed_cards -= 2
|
game.closed_cards = game.closed_cards - 2
|
||||||
game.score = game.score + 5
|
game.score = game.score + 5
|
||||||
#
|
#
|
||||||
old_state = game.enterState(game.S_FILL)
|
old_state = game.enterState(game.S_FILL)
|
||||||
|
@ -272,8 +271,6 @@ class Concentration(Memory24):
|
||||||
WIN_SCORE = 50
|
WIN_SCORE = 50
|
||||||
PERFECT_SCORE = 130 # 5 * (13*4)/2
|
PERFECT_SCORE = 130 # 5 * (13*4)/2
|
||||||
|
|
||||||
RowStack_Class = Concentration_RowStack
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# game layout
|
# game layout
|
||||||
#
|
#
|
||||||
|
@ -284,7 +281,6 @@ class Concentration(Memory24):
|
||||||
|
|
||||||
# game extras
|
# game extras
|
||||||
self.other_stack = None
|
self.other_stack = None
|
||||||
self.other_stack2 = None
|
|
||||||
self.closed_cards = -1
|
self.closed_cards = -1
|
||||||
self.score = 0
|
self.score = 0
|
||||||
|
|
||||||
|
@ -295,12 +291,11 @@ class Concentration(Memory24):
|
||||||
for i in range(self.ROWS):
|
for i in range(self.ROWS):
|
||||||
for j in range(self.COLUMNS):
|
for j in range(self.COLUMNS):
|
||||||
x, y = l.XM + j*l.XS, l.YM + i*l.YS
|
x, y = l.XM + j*l.XS, l.YM + i*l.YS
|
||||||
s.rows.append(self.RowStack_Class(x, y, self,
|
s.rows.append(Concentration_RowStack(x, y, self,
|
||||||
max_move=0, max_accept=0, max_cards=1))
|
max_move=0, max_accept=0, max_cards=1))
|
||||||
x, y = l.XM + self.COLUMNS*l.XS//2, self.height - l.YS
|
x, y = l.XM + self.COLUMNS*l.XS//2, self.height - l.YS
|
||||||
s.talon = InitialDealTalonStack(x, y, self)
|
s.talon = InitialDealTalonStack(x, y, self)
|
||||||
l.createText(s.talon, dx=-10, anchor="sw", text_format="%D")
|
l.createText(s.talon, dx=-10, anchor="sw", text_format="%D")
|
||||||
s.internals.append(InvisibleStack(self))
|
|
||||||
|
|
||||||
# create text
|
# create text
|
||||||
x, y = l.XM, self.height - l.YM
|
x, y = l.XM, self.height - l.YM
|
||||||
|
@ -395,151 +390,6 @@ class MemorySequence(Memory24):
|
||||||
return card1.suit == card2.suit and card1.rank == card2.rank + 1
|
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
|
# register the game
|
||||||
registerGame(GameInfo(886, Memory16, "Memory 16",
|
registerGame(GameInfo(886, Memory16, "Memory 16",
|
||||||
GI.GT_MEMORY | GI.GT_SCORE | GI.GT_CHILDREN, 2, 0,
|
GI.GT_MEMORY | GI.GT_SCORE | GI.GT_CHILDREN, 2, 0,
|
||||||
|
@ -567,7 +417,3 @@ registerGame(GameInfo(178, Concentration, "Concentration",
|
||||||
registerGame(GameInfo(843, MemorySequence, "Memory Sequence",
|
registerGame(GameInfo(843, MemorySequence, "Memory Sequence",
|
||||||
GI.GT_MEMORY | GI.GT_SCORE, 1, 0, GI.SL_SKILL,
|
GI.GT_MEMORY | GI.GT_SCORE, 1, 0, GI.SL_SKILL,
|
||||||
suits=(1,), altnames=('Ace Through King',)))
|
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,12 +1157,10 @@ 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
|
game_type = game_type | GI.GT_MUGHAL_GANJIFA
|
||||||
gi = GameInfo(id, gameclass, name, game_type, decks, redeals, skill_level,
|
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)
|
registerGame(gi)
|
||||||
return gi
|
return gi
|
||||||
|
|
||||||
|
@ -1189,6 +1187,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(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(16003, Makara, 'Makara', GI.GT_MUGHAL_GANJIFA, 1, 0, GI.SL_MOSTLY_SKILL)
|
||||||
r(16004, AshtaDikapala, 'Ashta Dikapala', GI.GT_MUGHAL_GANJIFA, 1, 0,
|
r(16004, AshtaDikapala, 'Ashta Dikapala', GI.GT_MUGHAL_GANJIFA, 1, 0,
|
||||||
GI.SL_BALANCED, altnames=('Eight Guardians'))
|
GI.SL_BALANCED)
|
||||||
|
|
||||||
del r
|
del r
|
||||||
|
|
|
@ -501,11 +501,11 @@ class TrumpsRow(Montana):
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
|
|
||||||
def r(id, gameclass, name, game_type, decks, redeals, skill_level,
|
def r(id, gameclass, name, game_type, decks, redeals, skill_level,
|
||||||
numcards=78, altnames=()):
|
numcards=78):
|
||||||
game_type = game_type | GI.GT_TAROCK | GI.GT_CONTRIB | GI.GT_ORIGINAL
|
game_type = game_type | GI.GT_TAROCK | GI.GT_CONTRIB | GI.GT_ORIGINAL
|
||||||
gi = GameInfo(id, gameclass, name, game_type, decks, redeals, skill_level,
|
gi = GameInfo(id, gameclass, name, game_type, decks, redeals, skill_level,
|
||||||
ranks=list(range(14)), trumps=list(range(22)),
|
ranks=list(range(14)), trumps=list(range(22)),
|
||||||
altnames=altnames, si={"ncards": numcards})
|
si={"ncards": numcards})
|
||||||
registerGame(gi)
|
registerGame(gi)
|
||||||
return gi
|
return gi
|
||||||
|
|
||||||
|
@ -519,8 +519,7 @@ r(13166, Serpent, 'Serpent', GI.GT_TAROCK | GI.GT_OPEN, 2, 0,
|
||||||
GI.SL_MOSTLY_SKILL)
|
GI.SL_MOSTLY_SKILL)
|
||||||
r(13167, Rambling, 'Rambling', GI.GT_TAROCK | GI.GT_OPEN, 2, 0,
|
r(13167, Rambling, 'Rambling', GI.GT_TAROCK | GI.GT_OPEN, 2, 0,
|
||||||
GI.SL_MOSTLY_SKILL)
|
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,
|
r(13169, TrumpsRow, "Trumps Row", GI.GT_TAROCK, 1, 4, GI.SL_MOSTLY_SKILL,
|
||||||
numcards=73)
|
numcards=73)
|
||||||
r(22232, LeGrandeTeton, 'Le Grande Teton', GI.GT_TAROCK, 1, 0, GI.SL_BALANCED)
|
r(22232, LeGrandeTeton, 'Le Grande Teton', GI.GT_TAROCK, 1, 0, GI.SL_BALANCED)
|
||||||
|
|
|
@ -348,16 +348,15 @@ class Scorpion_RowStack(Yukon_SS_RowStack, Spider_RowStack):
|
||||||
|
|
||||||
|
|
||||||
class Scorpion(RelaxedSpider):
|
class Scorpion(RelaxedSpider):
|
||||||
|
|
||||||
Hint_Class = YukonType_Hint
|
Hint_Class = YukonType_Hint
|
||||||
RowStack_Class = StackWrapper(Scorpion_RowStack, base_rank=KING)
|
RowStack_Class = StackWrapper(Scorpion_RowStack, base_rank=KING)
|
||||||
|
|
||||||
FACEDOWNS = (4, 4, 4, 0, 0, 0)
|
|
||||||
|
|
||||||
def createGame(self):
|
def createGame(self):
|
||||||
RelaxedSpider.createGame(self, rows=7, playcards=20)
|
RelaxedSpider.createGame(self, rows=7, playcards=20)
|
||||||
|
|
||||||
def startGame(self):
|
def startGame(self):
|
||||||
for i in self.FACEDOWNS:
|
for i in (4, 4, 4, 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=0, frames=0)
|
||||||
self.s.talon.dealRow(rows=self.s.rows[i:], flip=1, frames=0)
|
self.s.talon.dealRow(rows=self.s.rows[i:], flip=1, frames=0)
|
||||||
self._startAndDealRow()
|
self._startAndDealRow()
|
||||||
|
@ -380,46 +379,46 @@ class ScorpionTail(Scorpion):
|
||||||
shallHighlightMatch = Game._shallHighlightMatch_AC
|
shallHighlightMatch = Game._shallHighlightMatch_AC
|
||||||
|
|
||||||
|
|
||||||
# ************************************************************************
|
|
||||||
# * Double Scorpion
|
|
||||||
# * Triple Scorpion
|
|
||||||
# ************************************************************************
|
|
||||||
|
|
||||||
class DoubleScorpion(Scorpion):
|
class DoubleScorpion(Scorpion):
|
||||||
FACEDOWNS = (5, 5, 5, 5, 0, 0, 0, 0, 0)
|
Talon_Class = InitialDealTalonStack
|
||||||
|
|
||||||
def createGame(self):
|
def createGame(self):
|
||||||
RelaxedSpider.createGame(self, rows=10, playcards=26, texts=0)
|
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):
|
class TripleScorpion(Scorpion):
|
||||||
Talon_Class = InitialDealTalonStack
|
Talon_Class = InitialDealTalonStack
|
||||||
|
|
||||||
FACEDOWNS = (5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0)
|
|
||||||
|
|
||||||
def createGame(self):
|
def createGame(self):
|
||||||
RelaxedSpider.createGame(self, rows=13, playcards=30, texts=0)
|
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):
|
||||||
# * Scorpion II
|
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 ScorpionII(Scorpion):
|
|
||||||
FACEDOWNS = (3, 3, 3, 0, 0, 0)
|
|
||||||
|
|
||||||
|
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
# * Wasp
|
# * Wasp
|
||||||
# * Wasp II
|
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
|
|
||||||
class Wasp(Scorpion):
|
class Wasp(Scorpion):
|
||||||
RowStack_Class = Scorpion_RowStack # anything on an empty space
|
RowStack_Class = Scorpion_RowStack # anything on an empty space
|
||||||
|
|
||||||
|
def startGame(self):
|
||||||
class WaspII(ScorpionII):
|
for i in (3, 3, 3, 0, 0, 0):
|
||||||
RowStack_Class = Scorpion_RowStack
|
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()
|
||||||
|
|
||||||
|
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
|
@ -1125,6 +1124,19 @@ class Incompatibility(Spidike):
|
||||||
self._startDealNumRowsAndDealSingleRow(4)
|
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
|
# * Tarantula
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
|
@ -1659,5 +1671,3 @@ registerGame(GameInfo(917, Astrocyte, "Astrocyte",
|
||||||
registerGame(GameInfo(971, Microbe, "Microbe",
|
registerGame(GameInfo(971, Microbe, "Microbe",
|
||||||
GI.GT_SPIDER | GI.GT_SEPARATE_DECKS, 2, 0,
|
GI.GT_SPIDER | GI.GT_SEPARATE_DECKS, 2, 0,
|
||||||
GI.SL_MOSTLY_SKILL))
|
GI.SL_MOSTLY_SKILL))
|
||||||
registerGame(GameInfo(976, WaspII, "Wasp II",
|
|
||||||
GI.GT_SPIDER, 1, 0, GI.SL_MOSTLY_SKILL))
|
|
||||||
|
|
|
@ -51,18 +51,10 @@ class StHelena_Talon(TalonStack):
|
||||||
# move all cards to the Talon and redeal
|
# move all cards to the Talon and redeal
|
||||||
lr = len(self.game.s.rows)
|
lr = len(self.game.s.rows)
|
||||||
num_cards = 0
|
num_cards = 0
|
||||||
if len(self.cards) > 0:
|
assert 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 r in self.game.s.rows[::-1]:
|
||||||
for i in range(len(r.cards)):
|
for i in range(len(r.cards)):
|
||||||
num_cards += 1
|
num_cards = num_cards + 1
|
||||||
self.game.moveMove(1, r, self, frames=0)
|
self.game.moveMove(1, r, self, frames=0)
|
||||||
assert len(self.cards) == num_cards
|
assert len(self.cards) == num_cards
|
||||||
if num_cards == 0: # game already finished
|
if num_cards == 0: # game already finished
|
||||||
|
@ -177,32 +169,6 @@ class BoxKite(StHelena):
|
||||||
|
|
||||||
shallHighlightMatch = Game._shallHighlightMatch_RKW
|
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
|
# * Les Quatre Coins
|
||||||
|
@ -486,5 +452,3 @@ registerGame(GameInfo(621, RegalFamily, "Regal Family",
|
||||||
registerGame(GameInfo(859, KingsAudience, "King's Audience",
|
registerGame(GameInfo(859, KingsAudience, "King's Audience",
|
||||||
GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_LUCK,
|
GI.GT_1DECK_TYPE, 1, 0, GI.SL_MOSTLY_LUCK,
|
||||||
altnames=("Queen's Audience")))
|
altnames=("Queen's Audience")))
|
||||||
registerGame(GameInfo(975, Louis, "Louis",
|
|
||||||
GI.GT_2DECK_TYPE, 2, 2, GI.SL_BALANCED))
|
|
||||||
|
|
|
@ -472,7 +472,6 @@ class Panopticon(TenAcross):
|
||||||
|
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
# * Australian Patience
|
# * Australian Patience
|
||||||
# * Outback Patience
|
|
||||||
# * Tasmanian Patience
|
# * Tasmanian Patience
|
||||||
# * Canberra
|
# * Canberra
|
||||||
# * Raw Prawn
|
# * Raw Prawn
|
||||||
|
@ -483,9 +482,9 @@ class AustralianPatience(RussianSolitaire):
|
||||||
|
|
||||||
RowStack_Class = StackWrapper(Yukon_SS_RowStack, base_rank=KING)
|
RowStack_Class = StackWrapper(Yukon_SS_RowStack, base_rank=KING)
|
||||||
|
|
||||||
def createGame(self, rows=7, max_rounds=1, num_deal=1, playcards=16):
|
def createGame(self, rows=7, max_rounds=1, num_deal=1):
|
||||||
l, s = Layout(self), self.s
|
l, s = Layout(self), self.s
|
||||||
Layout.klondikeLayout(l, rows=rows, waste=1, playcards=playcards)
|
Layout.klondikeLayout(l, rows=rows, waste=1)
|
||||||
self.setSize(l.size[0], l.size[1])
|
self.setSize(l.size[0], l.size[1])
|
||||||
s.talon = WasteTalonStack(l.s.talon.x, l.s.talon.y, self,
|
s.talon = WasteTalonStack(l.s.talon.x, l.s.talon.y, self,
|
||||||
max_rounds=max_rounds, num_deal=num_deal)
|
max_rounds=max_rounds, num_deal=num_deal)
|
||||||
|
@ -501,14 +500,6 @@ class AustralianPatience(RussianSolitaire):
|
||||||
self._startDealNumRowsAndDealRowAndCards(3)
|
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):
|
class TasmanianPatience(AustralianPatience):
|
||||||
def createGame(self):
|
def createGame(self):
|
||||||
AustralianPatience.createGame(self, max_rounds=-1, num_deal=3)
|
AustralianPatience.createGame(self, max_rounds=-1, num_deal=3)
|
||||||
|
@ -904,7 +895,8 @@ registerGame(GameInfo(387, Roslin, "Roslin",
|
||||||
GI.GT_YUKON, 1, 0, GI.SL_MOSTLY_SKILL,
|
GI.GT_YUKON, 1, 0, GI.SL_MOSTLY_SKILL,
|
||||||
altnames=("Roslyn",)))
|
altnames=("Roslyn",)))
|
||||||
registerGame(GameInfo(447, AustralianPatience, "Australian Patience",
|
registerGame(GameInfo(447, AustralianPatience, "Australian Patience",
|
||||||
GI.GT_YUKON, 1, 0, GI.SL_BALANCED))
|
GI.GT_YUKON, 1, 0, GI.SL_BALANCED,
|
||||||
|
altnames=('Outback Patience',)))
|
||||||
registerGame(GameInfo(450, RawPrawn, "Raw Prawn",
|
registerGame(GameInfo(450, RawPrawn, "Raw Prawn",
|
||||||
GI.GT_YUKON, 1, 0, GI.SL_BALANCED))
|
GI.GT_YUKON, 1, 0, GI.SL_BALANCED))
|
||||||
registerGame(GameInfo(456, BimBom, "Bim Bom",
|
registerGame(GameInfo(456, BimBom, "Bim Bom",
|
||||||
|
@ -917,8 +909,6 @@ registerGame(GameInfo(492, Geoffrey, "Geoffrey",
|
||||||
GI.GT_YUKON, 1, 0, GI.SL_MOSTLY_SKILL))
|
GI.GT_YUKON, 1, 0, GI.SL_MOSTLY_SKILL))
|
||||||
registerGame(GameInfo(525, Queensland, "Queensland",
|
registerGame(GameInfo(525, Queensland, "Queensland",
|
||||||
GI.GT_YUKON, 1, 0, GI.SL_BALANCED))
|
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",
|
registerGame(GameInfo(530, RussianSpider, "Russian Spider",
|
||||||
GI.GT_SPIDER, 1, 0, GI.SL_BALANCED,
|
GI.GT_SPIDER, 1, 0, GI.SL_BALANCED,
|
||||||
altnames=('Ukrainian Solitaire',)))
|
altnames=('Ukrainian Solitaire',)))
|
||||||
|
|
|
@ -571,7 +571,7 @@ class LOptionsMenuGenerator(LTreeGenerator):
|
||||||
LTreeNode(text=_('Automatic play')))
|
LTreeNode(text=_('Automatic play')))
|
||||||
if rg:
|
if rg:
|
||||||
self.addCheckNode(tv, rg,
|
self.addCheckNode(tv, rg,
|
||||||
_('Auto face-up'),
|
_('Auto face up'),
|
||||||
self.menubar.tkopt.autofaceup,
|
self.menubar.tkopt.autofaceup,
|
||||||
self.menubar.mOptAutoFaceUp)
|
self.menubar.mOptAutoFaceUp)
|
||||||
|
|
||||||
|
|
|
@ -456,7 +456,7 @@ class AShuffleStackMove(AtomicMove):
|
||||||
def redo(self, game):
|
def redo(self, game):
|
||||||
stack = game.allstacks[self.stack_id]
|
stack = game.allstacks[self.stack_id]
|
||||||
# paranoia
|
# paranoia
|
||||||
assert stack is game.s.talon or stack in game.s.internals
|
assert stack is game.s.talon
|
||||||
# shuffle (see random)
|
# shuffle (see random)
|
||||||
game.random.setstate(self.state)
|
game.random.setstate(self.state)
|
||||||
seq = stack.cards
|
seq = stack.cards
|
||||||
|
|
|
@ -259,7 +259,7 @@ class PysolMenubarTk:
|
||||||
]
|
]
|
||||||
for label, action, opt_name, update_game in (
|
for label, action, opt_name, update_game in (
|
||||||
('A&uto drop', 'optautodrop', 'autodrop', False),
|
('A&uto drop', 'optautodrop', 'autodrop', False),
|
||||||
('Auto &face-up', '', 'autofaceup', False),
|
('Auto &face up', '', 'autofaceup', False),
|
||||||
('Auto &deal', '', 'autodeal', False),
|
('Auto &deal', '', 'autodeal', False),
|
||||||
('&Quick play', '', 'quickplay', False),
|
('&Quick play', '', 'quickplay', False),
|
||||||
('Enable &undo', '', 'undo', False),
|
('Enable &undo', '', 'undo', False),
|
||||||
|
|
|
@ -353,6 +353,7 @@ class SelectCardsetDialogWithPreview(MfxDialog):
|
||||||
check = ttk.Checkbutton(
|
check = ttk.Checkbutton(
|
||||||
size_frame, text=_('Auto scaling'),
|
size_frame, text=_('Auto scaling'),
|
||||||
variable=self.auto_scale,
|
variable=self.auto_scale,
|
||||||
|
takefocus=False,
|
||||||
command=self._updateAutoScale
|
command=self._updateAutoScale
|
||||||
)
|
)
|
||||||
check.grid(row=5, column=0, columnspan=2, sticky='ew',
|
check.grid(row=5, column=0, columnspan=2, sticky='ew',
|
||||||
|
@ -363,6 +364,7 @@ class SelectCardsetDialogWithPreview(MfxDialog):
|
||||||
self.aspect_check = ttk.Checkbutton(
|
self.aspect_check = ttk.Checkbutton(
|
||||||
size_frame, text=_('Preserve aspect ratio'),
|
size_frame, text=_('Preserve aspect ratio'),
|
||||||
variable=self.preserve_aspect,
|
variable=self.preserve_aspect,
|
||||||
|
takefocus=False,
|
||||||
# command=self._updateScale
|
# command=self._updateScale
|
||||||
)
|
)
|
||||||
self.aspect_check.grid(row=6, column=0, sticky='ew',
|
self.aspect_check.grid(row=6, column=0, sticky='ew',
|
||||||
|
|
|
@ -109,7 +109,7 @@ class SoundOptionsDialog(MfxDialog):
|
||||||
ttk.Label(frame, text=_('Sample volume:'), anchor='w'
|
ttk.Label(frame, text=_('Sample volume:'), anchor='w'
|
||||||
).grid(row=row, column=0, sticky='ew')
|
).grid(row=row, column=0, sticky='ew')
|
||||||
w = PysolScale(frame, from_=0, to=128, resolution=1,
|
w = PysolScale(frame, from_=0, to=128, resolution=1,
|
||||||
orient='horizontal',
|
orient='horizontal', takefocus=0,
|
||||||
length="3i", # label=_('Sample volume'),
|
length="3i", # label=_('Sample volume'),
|
||||||
variable=self.sample_volume)
|
variable=self.sample_volume)
|
||||||
w.grid(row=row, column=1, sticky='w', padx=5)
|
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'
|
ttk.Label(frame, text=_('Music volume:'), anchor='w'
|
||||||
).grid(row=row, column=0, sticky='ew')
|
).grid(row=row, column=0, sticky='ew')
|
||||||
w = PysolScale(frame, from_=0, to=128, resolution=1,
|
w = PysolScale(frame, from_=0, to=128, resolution=1,
|
||||||
orient='horizontal',
|
orient='horizontal', takefocus=0,
|
||||||
length="3i", # label=_('Music volume'),
|
length="3i", # label=_('Music volume'),
|
||||||
variable=self.music_volume)
|
variable=self.music_volume)
|
||||||
w.grid(row=row, column=1, sticky='w', padx=5)
|
w.grid(row=row, column=1, sticky='w', padx=5)
|
||||||
|
|
|
@ -72,7 +72,7 @@ class TimeoutsDialog(MfxDialog):
|
||||||
row=row, column=0, sticky='we')
|
row=row, column=0, sticky='we')
|
||||||
widget = PysolScale(lframe, from_=0.2, to=9.9, value=var.get(),
|
widget = PysolScale(lframe, from_=0.2, to=9.9, value=var.get(),
|
||||||
resolution=0.1, orient='horizontal',
|
resolution=0.1, orient='horizontal',
|
||||||
length="3i", variable=var)
|
length="3i", variable=var, takefocus=0)
|
||||||
widget.grid(row=row, column=1)
|
widget.grid(row=row, column=1)
|
||||||
row += 1
|
row += 1
|
||||||
#
|
#
|
||||||
|
|
|
@ -105,7 +105,8 @@ class WizardDialog(MfxDialog):
|
||||||
elif w.widget == 'check':
|
elif w.widget == 'check':
|
||||||
if w.variable is None:
|
if w.variable is None:
|
||||||
w.variable = tkinter.BooleanVar()
|
w.variable = tkinter.BooleanVar()
|
||||||
ch = ttk.Checkbutton(frame, variable=w.variable)
|
ch = ttk.Checkbutton(frame, variable=w.variable,
|
||||||
|
takefocus=False)
|
||||||
ch.grid(row=row, column=1, sticky='ew', padx=2, pady=2)
|
ch.grid(row=row, column=1, sticky='ew', padx=2, pady=2)
|
||||||
|
|
||||||
if w.current_value is None:
|
if w.current_value is None:
|
||||||
|
|
|
@ -271,6 +271,7 @@ class SelectCardsetDialogWithPreview(MfxDialog):
|
||||||
check = tkinter.Checkbutton(
|
check = tkinter.Checkbutton(
|
||||||
left_frame, text=_('Auto scaling'),
|
left_frame, text=_('Auto scaling'),
|
||||||
variable=self.auto_scale,
|
variable=self.auto_scale,
|
||||||
|
takefocus=False,
|
||||||
command=self._updateAutoScale
|
command=self._updateAutoScale
|
||||||
)
|
)
|
||||||
check.grid(row=3, column=0, columnspan=2, sticky='w',
|
check.grid(row=3, column=0, columnspan=2, sticky='w',
|
||||||
|
@ -281,6 +282,7 @@ class SelectCardsetDialogWithPreview(MfxDialog):
|
||||||
self.aspect_check = tkinter.Checkbutton(
|
self.aspect_check = tkinter.Checkbutton(
|
||||||
left_frame, text=_('Preserve aspect ratio'),
|
left_frame, text=_('Preserve aspect ratio'),
|
||||||
variable=self.preserve_aspect,
|
variable=self.preserve_aspect,
|
||||||
|
takefocus=False,
|
||||||
# command=self._updateScale
|
# command=self._updateScale
|
||||||
)
|
)
|
||||||
self.aspect_check.grid(row=4, column=0, sticky='w',
|
self.aspect_check.grid(row=4, column=0, sticky='w',
|
||||||
|
|
|
@ -109,7 +109,7 @@ class SoundOptionsDialog(MfxDialog):
|
||||||
w = tkinter.Label(frame, text=_('Sample volume:'))
|
w = tkinter.Label(frame, text=_('Sample volume:'))
|
||||||
w.grid(row=row, column=0, sticky='w', padx=5)
|
w.grid(row=row, column=0, sticky='w', padx=5)
|
||||||
w = tkinter.Scale(frame, from_=0, to=128, resolution=1,
|
w = tkinter.Scale(frame, from_=0, to=128, resolution=1,
|
||||||
orient='horizontal',
|
orient='horizontal', takefocus=0,
|
||||||
length="3i", # label=_('Sample volume'),
|
length="3i", # label=_('Sample volume'),
|
||||||
variable=self.sample_volume)
|
variable=self.sample_volume)
|
||||||
w.grid(row=row, column=1, sticky='ew', padx=5)
|
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 = tkinter.Label(frame, text=_('Music volume:'))
|
||||||
w.grid(row=row, column=0, sticky='w', padx=5)
|
w.grid(row=row, column=0, sticky='w', padx=5)
|
||||||
w = tkinter.Scale(frame, from_=0, to=128, resolution=1,
|
w = tkinter.Scale(frame, from_=0, to=128, resolution=1,
|
||||||
orient='horizontal',
|
orient='horizontal', takefocus=0,
|
||||||
length="3i", # label=_('Music volume'),
|
length="3i", # label=_('Music volume'),
|
||||||
variable=self.music_volume)
|
variable=self.music_volume)
|
||||||
w.grid(row=row, column=1, sticky='ew', padx=5)
|
w.grid(row=row, column=1, sticky='ew', padx=5)
|
||||||
|
|
|
@ -71,7 +71,7 @@ class TimeoutsDialog(MfxDialog):
|
||||||
).grid(row=row, column=0, sticky='we')
|
).grid(row=row, column=0, sticky='we')
|
||||||
widget = tkinter.Scale(frame, from_=0.2, to=9.9,
|
widget = tkinter.Scale(frame, from_=0.2, to=9.9,
|
||||||
resolution=0.1, orient='horizontal',
|
resolution=0.1, orient='horizontal',
|
||||||
length="3i", variable=var)
|
length="3i", variable=var, takefocus=0)
|
||||||
widget.grid(row=row, column=1)
|
widget.grid(row=row, column=1)
|
||||||
row += 1
|
row += 1
|
||||||
#
|
#
|
||||||
|
|
|
@ -94,7 +94,7 @@ class WizardDialog(MfxDialog):
|
||||||
if w.variable is None:
|
if w.variable is None:
|
||||||
w.variable = tkinter.BooleanVar()
|
w.variable = tkinter.BooleanVar()
|
||||||
ch = tkinter.Checkbutton(frame, variable=w.variable,
|
ch = tkinter.Checkbutton(frame, variable=w.variable,
|
||||||
anchor='w')
|
takefocus=False, anchor='w')
|
||||||
ch.grid(row=row, column=1, sticky='ew', padx=2, pady=2)
|
ch.grid(row=row, column=1, sticky='ew', padx=2, pady=2)
|
||||||
|
|
||||||
if w.current_value is None:
|
if w.current_value is None:
|
||||||
|
|
|
@ -614,15 +614,14 @@ class PysolMenubarTkCommon:
|
||||||
menu.add_command(
|
menu.add_command(
|
||||||
label=n_("&Statistics..."),
|
label=n_("&Statistics..."),
|
||||||
command=self.mPlayerStats, accelerator=m+"T")
|
command=self.mPlayerStats, accelerator=m+"T")
|
||||||
menu.add_command(
|
|
||||||
label=n_("Log..."),
|
|
||||||
command=lambda: self.mPlayerStats(mode=103))
|
|
||||||
menu.add_separator()
|
|
||||||
menu.add_command(
|
menu.add_command(
|
||||||
label=n_("D&emo statistics..."),
|
label=n_("D&emo statistics..."),
|
||||||
command=lambda: self.mPlayerStats(mode=1101))
|
command=lambda: self.mPlayerStats(mode=1101))
|
||||||
menu.add_command(
|
menu.add_command(
|
||||||
label=n_("Demo log..."),
|
label=n_("Log..."),
|
||||||
|
command=lambda: self.mPlayerStats(mode=103))
|
||||||
|
menu.add_command(
|
||||||
|
label=n_("Demo Log..."),
|
||||||
command=lambda: self.mPlayerStats(mode=1103))
|
command=lambda: self.mPlayerStats(mode=1103))
|
||||||
menu.add_separator()
|
menu.add_separator()
|
||||||
menu.add_command(
|
menu.add_command(
|
||||||
|
@ -667,7 +666,7 @@ class PysolMenubarTkCommon:
|
||||||
command=self.mOptPlayerOptions, accelerator=m+'P')
|
command=self.mOptPlayerOptions, accelerator=m+'P')
|
||||||
submenu = MfxMenu(menu, label=n_("&Automatic play"))
|
submenu = MfxMenu(menu, label=n_("&Automatic play"))
|
||||||
submenu.add_checkbutton(
|
submenu.add_checkbutton(
|
||||||
label=n_("Auto &face-up"), variable=self.tkopt.autofaceup,
|
label=n_("Auto &face up"), variable=self.tkopt.autofaceup,
|
||||||
command=self.mOptAutoFaceUp)
|
command=self.mOptAutoFaceUp)
|
||||||
submenu.add_checkbutton(
|
submenu.add_checkbutton(
|
||||||
label=n_("A&uto drop"), variable=self.tkopt.autodrop,
|
label=n_("A&uto drop"), variable=self.tkopt.autodrop,
|
||||||
|
|
|
@ -65,14 +65,6 @@ class ImportFileTests(unittest.TestCase):
|
||||||
'''<state><move pile="store0" position="0">'''
|
'''<state><move pile="store0" position="0">'''
|
||||||
'''<card id="[0-9]+" rank="four"'''
|
'''<card id="[0-9]+" rank="four"'''
|
||||||
''' suit="clubs" turn="face-up"></card>'''
|
''' suit="clubs" turn="face-up"></card>'''
|
||||||
'''<card id="[0-9]+" rank="two"'''
|
|
||||||
''' suit="clubs" turn="face-up"></card>'''
|
|
||||||
'''<card id="[0-9]+" rank="nine"'''
|
|
||||||
''' suit="clubs" turn="face-up"></card>'''
|
|
||||||
'''<card id="[0-9]+" rank="eight"'''
|
|
||||||
''' suit="clubs" turn="face-up"></card>'''
|
|
||||||
'''<card id="[0-9]+" rank="queen"'''
|
|
||||||
''' suit="spades" turn="face-up"></card>'''
|
|
||||||
),
|
),
|
||||||
blurb='xml import worked')
|
blurb='xml import worked')
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue