gnome-games r7552 - in trunk/aisleriot: . help help/C rules



Author: chpe
Date: Tue Mar 25 21:35:54 2008
New Revision: 7552
URL: http://svn.gnome.org/viewvc/gnome-games?rev=7552&view=rev

Log:
	* help/C/aisleriot.xml:
	* help/C/forty_thieves.xml:
	* help/Makefile.am:
	* rules/Makefile.am:
	* rules/forty_thieves.scm:
	* translatable_game_names.h: Add "Forty Thieves" game. Bug #519900,
	patch by Ed Sirett, reviewed by Vincent Povirk.

Added:
   trunk/aisleriot/help/C/forty_thieves.xml
   trunk/aisleriot/rules/forty_thieves.scm
Modified:
   trunk/aisleriot/help/C/aisleriot.xml
   trunk/aisleriot/help/Makefile.am
   trunk/aisleriot/rules/Makefile.am
   trunk/aisleriot/translatable_game_names.h

Modified: trunk/aisleriot/help/C/aisleriot.xml
==============================================================================
--- trunk/aisleriot/help/C/aisleriot.xml	(original)
+++ trunk/aisleriot/help/C/aisleriot.xml	Tue Mar 25 21:35:54 2008
@@ -28,6 +28,7 @@
 <!ENTITY first-law SYSTEM "first_law.xml">
 <!ENTITY fortress SYSTEM "fortress.xml">
 <!ENTITY fortunes SYSTEM "fortunes.xml">
+<!ENTITY forty-thieves SYSTEM "forty_thieves.xml">
 <!ENTITY fourteen SYSTEM "fourteen.xml">
 <!ENTITY freecell SYSTEM "freecell.xml">
 <!ENTITY gaps SYSTEM "gaps.xml">
@@ -312,6 +313,7 @@
   &first-law;
   &fortress;
   &fortunes;
+  &forty-thieves;
   &fourteen;
   &freecell;
   &gaps;

Added: trunk/aisleriot/help/C/forty_thieves.xml
==============================================================================
--- (empty file)
+++ trunk/aisleriot/help/C/forty_thieves.xml	Tue Mar 25 21:35:54 2008
@@ -0,0 +1,103 @@
+<sect1 id="Forty_Thieves"><!--<sect1info>
+		<copyright>
+			<year>2008</year>
+			<holder>Ed Sirett</holder>
+		</copyright>
+		<author>
+			<firstname>Ed Sirett</firstname>
+			<surname>Sirett</surname>
+		</author>
+		<address><email>ed makewrite demon co uk</email></address>
+	</sect1info>-->
+
+	<title>Forty Thieves</title>
+
+  <para>Written by Ed Sirett</para>
+
+          <sect2><title>Setup</title>
+
+
+  <informaltable>
+    <tgroup cols="2">
+      <tbody>
+	<row>
+	  <entry>Type of Deck</entry>
+	  <entry>Double Deck</entry>
+	</row>
+	<row>
+	  <entry>Stock</entry>
+	  <entry>
+	  	Top left pile.  The rest of the deck is placed here after
+	    dealing the Tableau.  Cards are dealt singly to the waste,
+	    The top card of the waste is available for play. 
+	  </entry>
+	</row>
+	<row>
+	  <entry>Foundation</entry>
+	  <entry>
+	  	Eight piles top right.  To be built in suit from Ace to
+	    King. 
+	  </entry>
+	</row>
+	<row>
+	  <entry>Tableau</entry>
+    <entry>
+    	Ten piles.  Deal four rows face up to start.  Tableau can 
+    	be built down in suit.  Cards are moved singly.  Empty 
+    	piles can be filled with any card. 
+     </entry>
+	</row>
+      </tbody>
+    </tgroup>
+  </informaltable>
+
+          </sect2>
+        <sect2><title>Goal</title>
+
+  <para>
+    Move all cards to the Foundation piles.
+  </para>
+
+          </sect2>
+        <sect2><title>Rules</title>
+
+  <para>
+    Cards in Tableau are built down in the same suit.  Cards can only
+    be moved singly. An empty pile in the Tableau can 
+    be filled with any card. As a short cut you can move more than one if
+    there are enough empty spaces. Cards can also be moved in groups to the 
+    Foundation piles.
+  </para>
+  <para>
+    Cards are played singly from the Stock to the waste pile, whose 
+    top card is available for play. There are no redeals.
+  </para>
+  <para>
+    Foundations are built up in suit from Ace to King. Double clicking
+    on a foundation will autoplay cards. Double clicking on a card in 
+    the Tableau or waste will move it to the appropriate Foundation pile
+    if such a move is possible, or to the tableau if possible.
+  </para>
+
+          </sect2>
+        <sect2><title>Scoring</title>
+
+  <para>
+    Each card in the Foundation scores 5 points.  When a Foundation pile
+    is complete (from Ace to King), 60 more points are scored. 
+  </para>
+  <para>
+    Maximum possible score:  1000
+  </para>
+
+          </sect2>
+        <sect2><title>Strategy</title>
+
+  <para>
+    Refrain from bringing cards to the tableau in order to obtain an empty
+    space as soon as possible. Then balance the requirements to maintain
+    empty spaces against the need to save low cards from being buried in
+    the waste. 
+  </para>
+        </sect2>
+</sect1>

Modified: trunk/aisleriot/help/Makefile.am
==============================================================================
--- trunk/aisleriot/help/Makefile.am	(original)
+++ trunk/aisleriot/help/Makefile.am	Tue Mar 25 21:35:54 2008
@@ -35,6 +35,7 @@
 	first_law.xml \
 	fortress.xml \
 	fortunes.xml \
+	forty_thieves.xml \
 	fourteen.xml \
 	freecell.xml \
 	gaps.xml \

Modified: trunk/aisleriot/rules/Makefile.am
==============================================================================
--- trunk/aisleriot/rules/Makefile.am	(original)
+++ trunk/aisleriot/rules/Makefile.am	Tue Mar 25 21:35:54 2008
@@ -30,6 +30,7 @@
 	first_law.scm		\
 	fortress.scm		\
 	fortunes.scm		\
+	forty_thieves.scm	\
 	fourteen.scm		\
 	freecell.scm		\
 	gaps.scm		\

Added: trunk/aisleriot/rules/forty_thieves.scm
==============================================================================
--- (empty file)
+++ trunk/aisleriot/rules/forty_thieves.scm	Tue Mar 25 21:35:54 2008
@@ -0,0 +1,455 @@
+; AisleRiot - forty_thieves.scm
+; Copyright (C) 2008 Ed Sirett  <ed makewrite demon co uk>
+;
+; This game is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, write to the Free Software
+; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+; USA
+
+(define (new-game)
+  (initialize-playing-area)
+  (set-ace-low)
+  (make-standard-double-deck)
+  (shuffle-deck)
+
+  (add-normal-slot DECK)
+
+  (add-blank-slot)
+; the foundations
+  (add-normal-slot '())
+  (add-normal-slot '())
+  (add-normal-slot '())
+  (add-normal-slot '())
+  (add-normal-slot '())
+  (add-normal-slot '())
+  (add-normal-slot '())
+  (add-normal-slot '())
+
+  (add-carriage-return-slot)
+; the waste pile
+  (add-extended-slot '() right)
+  (add-carriage-return-slot)
+
+; the tableau
+  (add-extended-slot '() down)
+  (add-extended-slot '() down)
+  (add-extended-slot '() down)
+  (add-extended-slot '() down)
+  (add-extended-slot '() down)
+  (add-extended-slot '() down)
+  (add-extended-slot '() down)
+  (add-extended-slot '() down)
+  (add-extended-slot '() down)
+  (add-extended-slot '() down)
+
+; these are the forty theives in the tableau
+  (deal-cards-face-up 0 '(10 11 12 13 14 15 16 17 18 19))
+  (deal-cards-face-up 0 '(10 11 12 13 14 15 16 17 18 19))
+  (deal-cards-face-up 0 '(10 11 12 13 14 15 16 17 18 19))
+  (deal-cards-face-up 0 '(10 11 12 13 14 15 16 17 18 19))
+
+  (give-status-message)
+; this is the return list of (new-game) and sets the size of the 
+; the playing field.
+  (list 10 4.5)
+)
+
+(define (in-tableau? slot) 
+  (and (>= slot 10) (<= slot 19))
+)
+
+(define (in-foundation? slot) 
+  (and (>= slot 1) (<= slot 8))
+)
+
+(define (in-tableau-or-waste? slot) 
+  (or (in-tableau? slot) (= slot waste-pile))
+)
+
+(define waste-pile 9)
+(define stock-pile 0) 
+(define start-with-waste 9)
+(define start-with-tableau 10)
+
+(define (<> a b) 
+   (not (= a b))
+)
+
+(define (give-status-message)
+  (set-statusbar-message (get-stock-no-string)))
+
+(define (get-stock-no-string)
+  (string-append (_"Stock left:") " " 
+		 (number->string (length (get-cards 0)))
+  )
+)
+
+; Apparently this is used to allow a group of cards to be dragged. 
+; if it returns #t then the cards are picked.
+; single cards can always be pulled from waste or tableau
+; multiple cards must be straight suit descending
+; (droppable?) will sort out more restrictions later
+ (define (button-pressed slot-id card-list)
+  (and (not (empty-slot? slot-id))
+       (in-tableau-or-waste? slot-id)
+       ( or (= (length card-list) 1)
+       	    (and (in-tableau? slot-id)
+       	         (check-straight-descending-list card-list)
+                 (check-same-suit-list card-list)	
+	    )
+       )
+  )
+)
+
+;scoring  5*cards + 13 per suit completed.
+(define (foundation-score slot-id prev-total)
+  (define (current-total)
+    (+ prev-total
+       (* (length (get-cards slot-id)) 5)
+       (if (= (length (get-cards slot-id)) 13)
+           60
+           0)))
+  (if (= slot-id 8)
+      (current-total)
+      (foundation-score (+ slot-id 1) (current-total))))
+       
+(define (recalculate-score)
+  (set-score!  (foundation-score 1 0)))
+
+; counts empty slots in tableau
+(define (space-score slot-id prev)
+ (define (curtot previous) (+ previous (if (empty-slot? slot-id) 1 0)))
+ (if (= slot-id 19) (curtot prev) (space-score (+ slot-id 1) (curtot prev)))
+)
+(define (tableau-spaces) 
+   (space-score start-with-tableau 0)
+)
+
+; To save effort a pile of correctly descending same suit cards can be moved
+; from the tableau to a foundation in one go.
+
+( define (foundation-droppable? card-list f-slot) 
+   (and (check-same-suit-list card-list)
+        (check-straight-descending-list card-list) 
+	(cond ( (empty-slot? f-slot)  
+                    (= (get-value (car card-list)) ace) 
+              )
+              (	( = (get-value (car card-list)) (+ (get-value (get-top-card f-slot)) 1))
+		    ( = (get-suit (get-top-card f-slot)) (get-suit (car card-list)))
+	      )	
+              (else #f)
+	)
+   )
+)
+
+; the maximum number of cards you can move as a short cut in one go 
+; depends on the number of free tableau slot (it's 2^tableau slots)
+; if the pile is going to an empty-slot than that slot is not really 
+; an empty slot. If the pile is the entire contents of a tableau slot
+; then (tableau-spaces) reports a 'false' extra space. hence the 
+; extra code.
+( define (max-move-in-tableau from-slot to-slot)
+    (expt 2 (max 0 
+                 (- 
+		    (- (tableau-spaces) (if (empty-slot? to-slot) 1 0))
+		       (if (empty-slot? from-slot) 1 0)
+		 )
+            )		
+    )
+)
+
+; A bunch of cards may be dropped on to a tableau slot iff
+; They are a descending same suit sequence that fits the top
+; card of the tableau slot or an empty slot.
+; this is a short cut to save moving cards individually
+( define (tableau-droppable? s-slot card-list t-slot) 
+   (and 
+	(check-same-suit-list card-list)
+        (check-straight-descending-list card-list)
+	(<= (length card-list) (max-move-in-tableau s-slot t-slot))
+	(cond ( (empty-slot? t-slot)  #t )
+              (	( = (+ (get-value (car card-list)) (length card-list)) (get-value (get-top-card t-slot)) )
+		    ( = (get-suit (get-top-card t-slot)) (get-suit (car card-list)))
+	      )	
+              (else #f) 
+	)
+   )
+)
+
+
+; droppable means that a list of cards coming from start-slot 
+; and going to end-slot are valid to be moved. 
+; picking up and dropping cards where they are is a null move.
+; picking things off a foundation is a not permitted.
+; dropping a valid pile onto a foundation is OK.
+; if we are dropping onto another tableau pile sometimes OK.
+; dropping card(s) elsewhere is not permitted.
+
+(define (droppable?  start-slot card-list  end-slot) 
+  (cond ( (= end-slot start-slot)  #f)
+	( (in-foundation? start-slot) #f)
+        ( (in-foundation? end-slot) (foundation-droppable? card-list end-slot) )
+	( (in-tableau? end-slot) (tableau-droppable? start-slot card-list end-slot) )
+	(else #f)
+  )
+)
+
+;drop the dragged card(s) a pile of cards have to be revered 
+; onto a foundation
+(define (button-released start-slot card-list end-slot)
+  (and (droppable? start-slot card-list end-slot)
+       (if (in-tableau? end-slot) 
+             (move-n-cards! start-slot end-slot card-list)
+             (move-n-cards! start-slot end-slot (reverse card-list) )
+       )
+       (recalculate-score)
+   )
+)
+
+; return "a move" if a card can be moved from from-slot to a foundation
+; a move is a list either (#f) or (#t from-slot to-slot)
+; no cards are actually moved this is a helper for both double-click
+; and get-hint features.
+
+(define (try-all-foundations from-slot card )
+    (if (not (empty-slot? from-slot))
+      (if (foundation-droppable? (list card) 1) 
+        (list #t from-slot 1)
+        (if (foundation-droppable? (list card) 2) 
+	  (list #t from-slot 2)
+          (if (foundation-droppable? (list card) 3) 
+	    (list #t from-slot 3)
+            (if (foundation-droppable? (list card) 4) 
+	      (list #t from-slot 4)
+              (if (foundation-droppable? (list card) 5) 
+	         (list #t from-slot 5)
+                 (if (foundation-droppable? (list card) 6) 
+	           (list #t from-slot 6)
+		   (if (foundation-droppable? (list card) 7) 
+	             (list #t from-slot 7)
+                     (if (foundation-droppable? (list card) 8) 
+	               (list #t from-slot 8)
+                       (list #f)
+       ) ) ) ) ) ) ) )
+       (list #f)
+     )
+)
+
+
+; return a move if a card can be moved from from-slot to a tableau
+; slot. This is a helper for hint, and double-click
+(define (find-tableau-place from-slot card )
+    (if (not (empty-slot? from-slot))
+      (if (and (tableau-droppable? from-slot (list card) 10) (<> from-slot 10) )
+        (list #t from-slot 10)
+        (if (and (tableau-droppable? from-slot (list card) 11) (<> from-slot 11) )
+	  (list #t from-slot 11)
+          (if (and (tableau-droppable? from-slot (list card) 12) (<> from-slot 12) )
+	    (list #t from-slot 12)
+            (if (and (tableau-droppable? from-slot (list card) 13) (<> from-slot 13) )
+	      (list #t from-slot 13)
+              (if (and (tableau-droppable? from-slot (list card) 14) (<> from-slot 14) )
+	        (list #t from-slot 14)
+                (if (and (tableau-droppable? from-slot (list card) 15) (<> from-slot 15) )
+	          (list #t from-slot 15)
+                  (if (and (tableau-droppable? from-slot (list card) 16) (<> from-slot 16) )
+	            (list #t from-slot 16)
+                    (if (and (tableau-droppable? from-slot (list card) 17) (<> from-slot 17) )
+	              (list #t from-slot 17)
+                      (if (and (tableau-droppable? from-slot (list card) 18) (<> from-slot 18) )
+	                (list #t from-slot 18)
+                        (if (and (tableau-droppable? from-slot (list card) 19) (<> from-slot 19) )
+	                  (list #t from-slot 19)
+                          (list #f)
+      ) ) ) ) ) ) ) ) ) ) 
+      (list #f)
+    )
+)
+
+
+
+
+;deals cards from deck to waste
+(define (button-clicked slot-id)
+  (and (= slot-id stock-pile)
+       (not (empty-slot? slot-id))
+       (deal-cards-face-up stock-pile (list waste-pile))
+       (recalculate-score)
+  )
+)
+
+; if we can find a move to the foundations do it and return #t or #f.
+(define (move-to-foundation) 
+       (let ((move (find-any-move-to-foundation waste-pile))) 
+	  (if (car move) (deal-cards-face-up (car (cdr move)) (list (car (reverse move))) ) #f ) 
+       )
+)
+
+; search for any valid move to a foundation 
+; helper code for both hint, autoplay
+(define (find-any-move-to-foundation begin-slot) 
+  (if (in-tableau-or-waste? begin-slot)
+        (let ((test (try-all-foundations begin-slot (get-top-card begin-slot)) ))
+             (if (car test) 
+                 test 
+                 (find-any-move-to-foundation (+ begin-slot 1)) 
+             )
+        )
+        (list #f) 	
+  )
+)
+
+; search for any valid move around the tableau 
+; helper code for hint
+(define (find-any-move-in-tableau begin-slot) 
+  (if (in-tableau-or-waste? begin-slot)
+        (let ((test (find-tableau-place begin-slot (get-top-card begin-slot)) ))
+             (if (car test) 
+                 test 
+                 (find-any-move-in-tableau (+ begin-slot 1)) 
+             )
+        )
+        (list #f) 	
+  )
+)
+
+
+
+(define (autoplay-foundations)
+(if (move-to-foundation) (autoplay-foundations) (recalculate-score))
+)
+
+; double click foundation for autoplay, otherwise does auto
+; single move to foundation, or waste to tableau if poss.
+(define (button-double-clicked slot-id)
+  (cond ( (in-foundation? slot-id ) (autoplay-foundations))
+        ( (in-tableau-or-waste? slot-id) 
+            (let ((test (try-all-foundations slot-id (get-top-card slot-id)) ))
+	      (if (car test) 
+                 (deal-cards-face-up (car (cdr test)) (list (car (reverse test))) ) 
+                 (let ((jump (find-tableau-place slot-id (get-top-card slot-id)) ))
+                    (if (car jump) 
+                       (deal-cards-face-up (car (cdr jump)) (list (car (reverse jump))) )
+                       #f
+                    )
+                 )
+              ) 
+            )
+          )
+	(else #f)
+   )
+)
+
+
+; To check that a game is continuable we need any of the following
+; cards to deal, something to move to a foundation,
+; top waste card movable, something to move around the tableau;
+; as well as game not won
+
+(define (game-continuable)
+  (give-status-message)
+  (and (not (game-won))
+       (or
+          (not (empty-slot? stock-pile))
+          (car (find-any-move-to-foundation start-with-waste))
+          (and (not (empty-slot? waste-pile))
+               (car (find-tableau-place waste-pile (get-top-card waste-pile) ) ) 
+          )
+          (car (find-any-move-in-tableau start-with-tableau) ) 
+       )
+  )
+)
+
+(define (game-won)
+  (and (= (length (get-cards 1)) 13)
+       (= (length (get-cards 2)) 13)
+       (= (length (get-cards 3)) 13)
+       (= (length (get-cards 4)) 13)
+       (= (length (get-cards 5)) 13)
+       (= (length (get-cards 6)) 13)
+       (= (length (get-cards 7)) 13)
+       (= (length (get-cards 8)) 13)
+  )
+)
+
+
+;this is the last-straw hint maker
+(define (check-for-deal)
+  (if (not (empty-slot? stock-pile)) 
+         (list 0 (_"Deal a card from stock"))
+         (list 0 (_"Try undoing and playing differently?"))
+  )
+)
+
+; turn a 'move' into a text description for get-hint.
+(define (make-destination-hint slot)
+    (if (in-foundation? slot)
+       (if (empty-slot? slot) 
+                (_"an empty foundation") 
+		(get-name (get-top-card slot))
+       )
+       (if (empty-slot? slot) 
+		(_"an empty space")
+		(get-name (get-top-card slot)) 
+       )
+    )
+) 
+
+(define (make-hint move)
+    (if (car move) 
+       (list 2 (get-name (get-top-card (car (cdr move))))
+               (make-destination-hint (car (reverse move))) 
+       )     
+       (list 0 (_"Bug! make-hint called on false move.") )
+    )
+)
+
+
+
+; hint  suggests the following in order:
+;  a move to a foundation from waste or tableau
+;  move the top waste card to a valid tableau space or pile
+;  move some other tableau card to another tableau space or pile 
+;  deal a card or at end backup and try alternatives.
+; these are not intended to be a the best moves simply to show 
+; possible moves to help learn the rules.
+(define (get-hint)
+  (cond ( (car (find-any-move-to-foundation start-with-waste))
+          (make-hint (find-any-move-to-foundation start-with-waste)) 
+        ) 
+        ( (and (not (empty-slot? waste-pile)) 
+               (car (find-tableau-place waste-pile (get-top-card waste-pile) ) ) 
+          )
+          (make-hint (find-tableau-place waste-pile (get-top-card waste-pile)))
+        )
+        ( (car (find-any-move-in-tableau start-with-tableau) ) 
+          (make-hint (find-any-move-in-tableau start-with-tableau ) )
+        )
+        (else (check-for-deal))
+  )
+)
+
+(define (get-options) 
+  #f)
+
+(define (apply-options options) 
+  #f)
+
+(define (timeout) 
+  #f)
+
+(set-features droppable-feature)
+
+(set-lambda new-game button-pressed button-released button-clicked
+button-double-clicked game-continuable game-won get-hint get-options
+apply-options timeout droppable?)

Modified: trunk/aisleriot/translatable_game_names.h
==============================================================================
--- trunk/aisleriot/translatable_game_names.h	(original)
+++ trunk/aisleriot/translatable_game_names.h	Tue Mar 25 21:35:54 2008
@@ -25,6 +25,7 @@
 gchar *s = N_("First Law")
 gchar *s = N_("Fortress")
 gchar *s = N_("Fortunes")
+gchar *s = N_("Forty Thieves")
 gchar *s = N_("Fourteen")
 gchar *s = N_("Freecell")
 gchar *s = N_("Gaps")



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]