Index: yahtzee.c
===================================================================
--- yahtzee.c	(revision 6486)
+++ yahtzee.c	(working copy)
@@ -32,15 +32,25 @@
 #include <string.h>
 #include <unistd.h>
 #include <time.h>
+#include <glib.h>
 
 #include <config.h>
 #include "yahtzee.h"
 
 char *ProgramHeader = "Yahtzee Version 2.00 (c)1998 SDH, (c)1992 by zorst";
 
+typedef struct undo_score_element_t {
+    int player;
+    int field;
+    int score;
+    int DiceValues[NUMBER_OF_DICE];
+    int roll;
+} UndoScoreElement;
 
+GList *UndoList = NULL;
+
 /*=== Exported variables ===*/
-DiceInfo DiceValues[5] = { {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0} };
+DiceInfo DiceValues[NUMBER_OF_DICE] = { {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0} };
 Player players[MAX_NUMBER_OF_PLAYERS] = {
   {NULL, {0}, {0}, 0, 0},
   {NULL, {0}, {0}, 0, 0},
@@ -175,6 +185,7 @@
   CurrentPlayer = 0;
   NumberOfRolls = 0;
   LastHumanNumberOfRolls = 0;
+  FreeUndoList();
 
   NumberOfPlayers = NumberOfComputers + NumberOfHumans;
 
@@ -510,6 +521,50 @@
   }
 }
 
+void
+PrependUndoList(gint player, gint field, gint score) {
+    UndoScoreElement *elem = g_new0(UndoScoreElement, 1);
+    gint ii;
+    elem->player = player;
+    elem->field  = field;
+    elem->score  = score;
+
+    for (ii = 0; ii < NUMBER_OF_DICE; ii++)
+        elem->DiceValues[ii] = DiceValues[ii].val;
+    elem->roll = NumberOfRolls;
+
+    UndoList = g_list_prepend(UndoList, elem);
+}
+
+void
+UndoLastMove() {
+    if (UndoList) {
+        gint ii;
+        UndoScoreElement *elem = UndoList->data;
+        players[elem->player].score[elem->field] = 0;
+        players[elem->player].used [elem->field] = 0;
+
+        for (ii = 0; ii < NUMBER_OF_DICE; ii++) {
+            DiceValues[ii].val = elem->DiceValues[ii];
+            DiceValues[ii].sel = 0;
+        }
+
+        NumberOfRolls = elem->roll;
+        ShowPlayer (elem->player, elem->field);
+        g_free(elem);
+        UndoList = g_list_remove(UndoList, elem);
+    }
+}
+
+void
+FreeUndoList() {
+    while (UndoList) {
+        UndoScoreElement *elem = UndoList->data;
+        g_free(elem);
+        UndoList = g_list_remove(UndoList, elem);
+    }
+}
+
 /* Test if we can use suggested score slot */
 int
 play_score (int player, int field)
@@ -540,6 +595,7 @@
     fprintf(stderr, "Unexpected game type %d. Aborting...", game_type);
     exit(1);
   }
+  PrependUndoList(player, field, players[player].score[field]);
 
   ShowPlayer (player, field);
 
Index: yahtzee.h
===================================================================
--- yahtzee.h	(revision 6486)
+++ yahtzee.h	(working copy)
@@ -102,6 +102,9 @@
 extern int GameIsOver (void);
 extern int FindWinner (void);
 int UndoPossible (void);
+extern void UndoLastMove(void);
+void PrependUndoList(gint player, gint field, gint score);
+void FreeUndoList(void);
 
 /* Computer.c */
 extern void ComputerRolling (int player);
@@ -113,6 +116,7 @@
 extern void DeselectAllDice (void);
 extern void ShowPlayer (int num, int field);
 extern void NextPlayer (void);
+extern void PreviousPlayer (void);
 extern void ShowHighScores (void);
 
 enum { SCORE_OK = 0, SLOT_USED, PLAYER_DONE, YAHTZEE_NEWGAME };
Index: gyahtzee.c
===================================================================
--- gyahtzee.c	(revision 6486)
+++ gyahtzee.c	(working copy)
@@ -320,6 +320,36 @@
     UpdateRollLabel ();
 }
 
+/* Go back to the previous player */
+
+void PreviousPlayer(void)
+{
+  NumberOfRolls = 1;
+  ready_to_advance_player = FALSE;
+  ShowoffPlayer (ScoreList, CurrentPlayer, 0);
+
+  /* Find the next player with rolls left */
+  do {
+    UndoLastMove();
+    CurrentPlayer = (CurrentPlayer + 5) % NumberOfPlayers;
+  } while (players[CurrentPlayer].comp);
+
+  ShowoffPlayer (ScoreList, CurrentPlayer, 1);
+
+  if (players[CurrentPlayer].name) {
+    if (players[CurrentPlayer].comp) {
+      say (_("Computer playing for %s"), players[CurrentPlayer].name);
+    } else {
+      say (_("%s! -- You're up."), players[CurrentPlayer].name);
+    }
+  }
+
+  UpdateAllDicePixmaps ();
+  DeselectAllDice ();
+  UpdateRollLabel();
+
+}
+
 void
 ShowPlayer (int num, int field)
 {
@@ -587,6 +617,13 @@
   return FALSE;
 }
 
+static gint undo_callback(GtkAction *action, gpointer data)
+{
+    g_message("Action undo called");
+    PreviousPlayer();
+    return FALSE;
+}
+
 static void
 LoadDicePixmaps (void)
 {
@@ -627,6 +664,8 @@
   {"HelpMenu", NULL, N_("_Help")},
   {"NewGame", GAMES_STOCK_NEW_GAME, NULL, NULL, NULL,
    G_CALLBACK (new_game_callback)},
+  {"Undo", GAMES_STOCK_UNDO_MOVE, NULL, NULL, NULL,
+   G_CALLBACK (undo_callback)},
   {"Scores", GAMES_STOCK_SCORES, NULL, NULL, NULL,
    G_CALLBACK (score_callback)},
   {"Quit", GTK_STOCK_QUIT, NULL, NULL, NULL, G_CALLBACK (quit_game)},
@@ -644,6 +683,7 @@
   "  <menubar name='MainMenu'>"
   "    <menu action='GameMenu'>"
   "      <menuitem action='NewGame'/>"
+  "      <menuitem action='Undo'/>"
   "      <menuitem action='Scores'/>"
   "      <menuitem action='Quit'/>"
   "    </menu>"
