Index: AUTHORS
===================================================================
--- AUTHORS	(revision 6678)
+++ AUTHORS	(working copy)
@@ -24,3 +24,4 @@
 Stephen Brandt <stephen@stephenbrandt.com>
 Daniel Derozier <dcubed20@gmail.com>
 Christian Persch <chpe gnome org>
+Jonathan Bastien-Filiatrault <joe@x2a.org>
Index: aisleriot/window.c
===================================================================
--- aisleriot/window.c	(revision 6678)
+++ aisleriot/window.c	(working copy)
@@ -785,7 +785,20 @@
 #endif /* !HAVE_MAEMO */
 
 static void
-debug_choose_seed_response_cb (GtkWidget *dialog,
+debug_pixbuf_drawing_cb (GtkToggleAction *action,
+                         AisleriotWindow *window)
+{
+  AisleriotWindowPrivate *priv = window->priv;
+  gboolean active;
+
+  active = gtk_toggle_action_get_active (action);
+  aisleriot_board_set_pixbuf_drawing (priv->board, active);
+}
+
+#endif /* ENABLE_DEBUG_UI */
+
+static void
+choose_seed_response_cb (GtkWidget *dialog,
                                int response,
                                AisleriotWindow *window)
 {
@@ -810,7 +823,7 @@
 }
 
 static void
-debug_choose_seed_cb (GtkAction *action,
+choose_seed_cb (GtkAction *action,
                       AisleriotWindow *window)
 {
   AisleriotWindowPrivate *priv = window->priv;
@@ -824,7 +837,7 @@
                                    GTK_BUTTONS_OK_CANCEL,
                                    "Choose game seed");
   g_signal_connect (dialog, "response",
-                    G_CALLBACK (debug_choose_seed_response_cb), window);
+                    G_CALLBACK (choose_seed_response_cb), window);
   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
 
   g_snprintf (str, sizeof (str), "%u", aisleriot_game_get_seed (priv->game));
@@ -839,19 +852,6 @@
 }
 
 static void
-debug_pixbuf_drawing_cb (GtkToggleAction *action,
-                         AisleriotWindow *window)
-{
-  AisleriotWindowPrivate *priv = window->priv;
-  gboolean active;
-
-  active = gtk_toggle_action_get_active (action);
-  aisleriot_board_set_pixbuf_drawing (priv->board, active);
-}
-
-#endif /* ENABLE_DEBUG_UI */
-
-static void
 toolbar_toggled_cb (GtkToggleAction *action,
                     AisleriotWindow *window)
 {
@@ -1686,10 +1686,6 @@
   g_object_set (priv->action[ACTION_HELP_GAME], "label", game_name, NULL);
   g_object_set (priv->action[ACTION_OPTIONS_MENU], "label", game_name, NULL);
 
-  gtk_window_set_title (GTK_WINDOW (window), game_name);
-
-  g_free (game_name);
-
   add_recently_played_game (window, aisleriot_game_get_game_file (game));
 
   install_recently_played_menu (window);
@@ -1722,9 +1718,20 @@
              AisleriotWindow *window)
 {
   AisleriotWindowPrivate *priv = window->priv;
+  char *game_name;
+  char *title;
+  guint seed;
 
   update_statistics_display (window);
+  seed = aisleriot_game_get_seed (game);
 
+  game_name = aisleriot_game_get_name (priv->game);
+  title = g_strdup_printf("%s #%u",game_name, seed);
+  g_free (game_name);
+
+  gtk_window_set_title (GTK_WINDOW (window), title);
+  g_free(title);
+
 #ifdef HAVE_MAEMO
   gtk_label_set_text (priv->game_message_label, NULL);
 #else
@@ -1954,6 +1961,8 @@
       ACTION_ACCEL ("<ctrl>O", NULL),
       ACTION_TOOLTIP (N_("Play a different game")),
       G_CALLBACK (select_game_cb) },
+    { "ChooseSeed", GTK_STOCK_JUMP_TO, _("_Choose seed"), NULL, NULL,
+      G_CALLBACK (choose_seed_cb) },
     { "RecentMenu", NULL, N_("_Recently Played") },
     { "Statistics", GTK_STOCK_ADD, N_("S_tatistics"), NULL,
       ACTION_TOOLTIP (N_("Show gameplay statistics")),
@@ -1989,8 +1998,6 @@
 #ifdef ENABLE_DEBUG_UI
     /* Debug UI actions */
     { "DebugMenu", NULL, "_Debug" },
-    { "DebugChooseSeed", NULL, "_Choose seed", NULL, NULL,
-      G_CALLBACK (debug_choose_seed_cb) },
 #ifndef HAVE_MAEMO
     { "DebugMoveNextScreen", NULL, "_Move to next screen", NULL, NULL,
        G_CALLBACK (move_to_next_screen_cb) },
@@ -2060,6 +2067,7 @@
           "<menuitem action='RestartGame'/>"
           "<menuitem action='Statistics'/>"
           "<menuitem action='Select'/>"
+          "<menuitem action='ChooseSeed'/>"
           "<separator />"
           "<placeholder name='RecentMenu'/>"
           "<separator/>"
@@ -2087,7 +2095,6 @@
         "</menu>"
 #ifdef ENABLE_DEBUG_UI
         "<menu action='DebugMenu'>"
-          "<menuitem action='DebugChooseSeed'/>"
           "<menuitem action='DebugPixbufDrawing'/>"
         "</menu>"
 #endif /* ENABLE_DEBUG_UI */
@@ -2100,6 +2107,7 @@
           "<menuitem action='RestartGame'/>"
           "<menuitem action='Statistics'/>"
           "<menuitem action='Select'/>"
+          "<menuitem action='ChooseSeed'/>"
           "<menu action='RecentMenu'/>"
           "<separator/>"
           "<menuitem action='CloseWindow'/>"
@@ -2129,7 +2137,6 @@
         "<menu action='DebugMenu'>"
           "<menuitem action='DebugPixbufDrawing'/>"
           "<separator/>"
-          "<menuitem action='DebugChooseSeed'/>"
           "<menuitem action='DebugMoveNextScreen'/>"
           "<menuitem action='DebugDelayedMoveNextScreen'/>"
           "<menuitem action='DebugException'/>"
@@ -2142,6 +2149,7 @@
         "<toolitem action='NewGame'/>"
         "<toolitem action='RestartGame'/>"
         "<toolitem action='Select'/>"
+        "<toolitem action='ChooseSeed'/>"
         "<separator/>"
         "<toolitem action='UndoMove'/>"
         "<toolitem action='RedoMove'/>"
@@ -2600,6 +2608,8 @@
 {
   AisleriotWindowPrivate *priv = window->priv;
   LoadIdleData *data;
+  char *game_name;
+  char *title;
 
   /* We'll do this on idle */
   if (priv->load_idle_id != 0) {
@@ -2611,6 +2621,14 @@
   data->game_file = g_strdup (game_file);
   data->seed = seed;
   
+  game_name = aisleriot_util_get_display_filename(game_file);
+
+  title = g_strdup_printf("%s #%u",game_name, seed);
+  g_free (game_name);
+
+  gtk_window_set_title (GTK_WINDOW (window), title);
+  g_free(title);
+
   priv->load_idle_id = g_idle_add_full (G_PRIORITY_LOW,
                                         (GSourceFunc) load_idle_cb,
                                         data,
Index: aisleriot/rules/freecell.scm
===================================================================
--- aisleriot/rules/freecell.scm	(revision 6678)
+++ aisleriot/rules/freecell.scm	(working copy)
@@ -97,8 +97,51 @@
 
 (define (opposite-color color)
   (if (eq? color red) black red))
-      
 
+(define redmond-seed 0)
+
+(define (redmond-srand s)
+  (set! redmond-seed s))
+
+;; Redmond PRNG, parameters from http://www.codeproject.com/useritems/PRNG.asp
+(define (redmond-rand)
+  (set! redmond-seed
+	(+ (* redmond-seed 214013) 2531011))
+  (modulo (ash redmond-seed -16)
+	  (expt 2 15)))
+
+(define (make-redmond-deck)
+  (set! DECK (make-deck-list-redmond 0)))
+
+;; We need the cards in AC AD AH AS 2C 2D 2H 2S 3C... order
+(define (make-deck-list-redmond value)
+  (if (eq? value 51)
+      (list (make-card (+ (quotient value 4) 1) (modulo value 4)))
+      (cons (make-card (+ (quotient value 4) 1) (modulo value 4))
+	    (make-deck-list-redmond (+ 1 value)))))
+
+(define (shuffle-deck-redmond gamenum)
+  (redmond-srand gamenum)
+  (set! DECK (shuffle-deck-list-redmond DECK)))
+
+;; Shuffle the deck with the Redmond PRNG,
+;; inspired by http://www.solitairelaboratory.com/mshuffle.txt
+(define (shuffle-deck-list-redmond deck)
+  (let ((n (modulo (redmond-rand) (length deck))))
+    (if (eq? 1 (length deck))
+	deck
+	(cons (list-ref deck n )
+	      (shuffle-deck-list-redmond
+	       (redmond-adjust-list deck n))))))
+
+(define (redmond-adjust-list deck n)
+  (if (eq? n (- (length deck) 1))
+      (list-head deck (- (length deck) 1))
+      (append (list-head deck n)
+	      (last-pair deck)
+	      (cdr (list-tail (list-head deck (- (length deck) 1)) n)))))
+
+
 ;;
 ;; Utilities for the homecells
 ;;
@@ -318,8 +361,8 @@
 (define (new-game)
   (initialize-playing-area)
   (set-ace-low)
-  (make-standard-deck)
-  (shuffle-deck)
+  (make-redmond-deck)
+  (shuffle-deck-redmond SEED)
   
   ;; set up the board
 
Index: aisleriot/game.c
===================================================================
--- aisleriot/game.c	(revision 6678)
+++ aisleriot/game.c	(working copy)
@@ -1588,6 +1588,7 @@
                          guint *seed)
 {
   GObject *object = G_OBJECT (game);
+  char *seed_scm;
 
   g_return_if_fail (game->state > GAME_UNINITIALISED);
 
@@ -1624,6 +1625,10 @@
     } else {
       game->seed = g_random_int ();
     }
+    seed_scm = g_strdup_printf("(set-seed %u)", game->seed);
+    scm_c_eval_string(seed_scm);
+    g_free(seed_scm);
+
     seed = NULL;
 
     /* FIXMEchpe: We should NOT re-seed here, but just get another random number! */
Index: aisleriot/sol.scm
===================================================================
--- aisleriot/sol.scm	(revision 6678)
+++ aisleriot/sol.scm	(working copy)
@@ -534,12 +534,17 @@
 (define HISTORY '())
 (define FUTURE '())
 (define IN-GAME #f)
+(define SEED #f)
 
 ; called from C:
 (define (start-game)
   (set! IN-GAME #t))
 
 ; called from C:
+(define (set-seed seed)
+  (set! SEED seed))
+
+; called from C:
 (define (end-move)
   (if (not (= 0 (length MOVE)))
       (begin
