Index: iagno/gnothello.h
===================================================================
--- iagno/gnothello.h	(リビジョン 6373)
+++ iagno/gnothello.h	(作業コピー)
@@ -1,6 +1,5 @@
 /*
- * gnothello.h - Header for gnothello.c
- * written by Ian Peters <itp@gnu.org>
+ * gnothello.h
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,71 +18,18 @@
  * For more details see the file COPYING.
  */
 
-#ifndef _GNOTHELLO_H_
-#define _GNOTHELLO_H_
+#ifdef GGZ_CLIENT
 
-#define BLACK_TURN 1
-#define WHITE_TURN 31
-#define PIXMAP_FLIP_DELAY 20
-#define PIXMAP_STAGGER_DELAY 3
-#define COMPUTER_MOVE_DELAY 1000
+#define NETWORK_ENGINE "Iagno"
+#define NETWORK_VERSION "1"
 
-#define OTHER_PLAYER(w) (((w) == WHITE_TURN) ? BLACK_TURN : WHITE_TURN)
+int get_move (void);
 
-#define TILEWIDTH   80
-#define TILEHEIGHT  80
-#define GRIDWIDTH   1
-#define BOARDWIDTH  ((TILEWIDTH+GRIDWIDTH)  * 8)
-#define BOARDHEIGHT ((TILEHEIGHT+GRIDWIDTH) * 8)
+int get_sync (void);
 
-#define MAIN_PAGE           	0
-#define NETWORK_PAGE           	1
-
-gboolean ggz_network_mode;
-int player_id;
-int seat;
-int seats[2];
-char names[2][17];
-
-extern GtkWidget *notebook;
-extern GtkWidget *window;
-
-void new_game_cb (GtkWidget * widget, gpointer data);
-void new_network_game_cb (GtkWidget * widget, gpointer data);
-void on_network_leave (GObject * object, gpointer data);
-void on_player_list (void);
-void on_chat_window (void);
-void quit_game_cb (GtkWidget * widget, gpointer data);
-void undo_move_cb (GtkWidget * widget, gpointer data);
-void redo_move_cb (GtkWidget * widget, gpointer data);
-void black_level_cb (GtkWidget * widget, gpointer data);
-void white_level_cb (GtkWidget * widget, gpointer data);
-void about_cb (GtkWidget * widget, gpointer data);
-void comp_black_cb (GtkWidget * widget, gpointer data);
-void comp_white_cb (GtkWidget * widget, gpointer data);
-void quick_moves_cb (GtkWidget * widget, gpointer data);
-void anim_cb (GtkWidget * widget, gpointer data);
-void anim_stagger_cb (GtkWidget * widget, gpointer data);
-void load_tiles_cb (GtkWidget * widget, gpointer data);
-void set_selection (GtkWidget * widget, void *data);
-void free_str (GtkWidget * widget, void *data);
-void load_tiles_callback (GtkWidget * widget, void *data);
-void cancel (GtkWidget * widget, void *data);
-gint expose_event (GtkWidget * widget, GdkEventExpose * event);
-gint configure_event (GtkWidget * widget, GdkEventConfigure * event);
-gint button_press_event (GtkWidget * widget, GdkEventButton * event);
-void gui_draw_pixmap (gint which, gint x, gint y);
-void gui_draw_pixmap_buffer (gint which, gint x, gint y);
-gint flip_pixmaps (gpointer data);
 void init_new_game (void);
-void clear_board (void);
-void create_window (void);
-void gui_status (void);
-void gui_message (gchar * message);
-guint check_computer_players (void);
-void load_pixmaps (void);
-void properties_cb (GtkWidget * widget, gpointer data);
-void set_bg_color (void);
-void gui_draw_grid (void);
 
+void start_game (void);
+
 #endif
+
Index: iagno/properties.h
===================================================================
--- iagno/properties.h	(リビジョン 6373)
+++ iagno/properties.h	(作業コピー)
@@ -1,7 +1,96 @@
-#ifndef _PROPERTIES_H_
-#define _PROPERTIES_H_
+/*
+ * properties.h
+ *
+ * This program 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 of the License, 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
+ *
+ * For more details see the file COPYING.
+ */
 
+#define MAX_SIZE               8
+#define MAX_ACTIONS            20
+#define MAX_KEYS               15
+#define MAX_SIGNALFUNCS        2
+#define MAX_OPTIONS            7
+#define MAX_TILES              3
+
+#define BOARD_SIZE             519
+#define BOARD_MIN              279
+#define BOARD_W_MAX            1214
+#define BOARD_H_MAX            799
+#define GRIDWIDTH              1
+
+#define PIXMAP_FLIP_DELAY      30
+#define PIXMAP_STAGGER_DELAY   3
+#define COMPUTER_MOVE_DELAY    1000
+
+#define MAIN_PAGE              0
+#define NETWORK_PAGE           1
+
+#define PLAYER2NUMBER(player)  ((player == BLACK)? 0: 1)
+
+gint clamp_int (gint input, gint low, gint high);
+
+void init_interface (guint t_size, guint t_max_depth, gchar ** t_keys,
+		     GCallback *callbacks, GtkSignalFunc *t_signalfuncs);
+
+void gui_status (void);
+
+gboolean redraw_board (gpointer user_data);
+
+void refresh_board (void);
+
+void start_timer (void);
+
+void stop_timer (void);
+
+void continue_timer (void);
+
+void reset_timer (void);
+
+void gui_message (gchar *message);
+
+void gui_entry (gchar *message);
+
+gboolean flip_final_results (gpointer data);
+
+void on_quit_activate (GtkMenuItem *menuitem, gpointer user_data);
+
+void on_properties_activate (GtkMenuItem *menuitem, gpointer user_data);
+
+gboolean
+on_drawing_area_expose_event (GtkWidget *widget,
+			      GdkEventExpose *event, gpointer user_data);
+
+gboolean
+on_drawing_area_configure_event (GtkWidget *widget,
+				 GdkEventConfigure *event,
+				 gpointer user_data);
+
+GtkWidget *create_window (void);
+
 void load_properties (void);
-void show_properties_dialog (void);
 
-#endif
+void save_properties (void);
+
+void reset_properties (void);
+
+void apply_changes (void);
+
+GtkWidget *create_properties_dialog (void);
+
+GtkWidget *create_file_save_dialog (GtkSignalFunc *callback);
+
+GtkWidget *create_file_open_dialog (GtkSignalFunc *callback);
+
Index: iagno/othello.c
===================================================================
--- iagno/othello.c	(リビジョン 6373)
+++ iagno/othello.c	(作業コピー)
@@ -1,8 +1,5 @@
-/* -*- mode:C; indent-tabs-mode:t; tab-width:4; c-basic-offset:8; -*- */
-
 /*
- * othello.c - Othello support routines for iagno
- * written by Ian Peters <itp@gnu.org>
+ * othello.c - AI code for iagno.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,33 +18,22 @@
  * For more details see the file COPYING.
  */
 
-#include <config.h>
 #include <gnome.h>
-#include <string.h>
-#include <games-clock.h>
-#include <games-sound.h>
 
 #include "othello.h"
-#include "gnothello.h"
 
-#define PERFECT   17
-#define VICTORY   19
-#define BEST      56
-#define MAX_DEPTH  7
+#define UL     -11
+#define UU     -10
+#define UR     -9
+#define LL     -1
+#define RR     +1
+#define DL     +9
+#define DD     +10
+#define DR     +11
+#define NDIRS  8
 
-#define BLANK 0
-#define OUTSIDE 128
-#define UL -11
-#define UU -10
-#define UR -9
-#define LL -1
-#define RR +1
-#define DL +9
-#define DD +10
-#define DR +11
-#define NDIRS 8
-
-gint8 squares[64] = { 44, 45, 54, 55, 23, 26, 73, 76,
+static guint8 squares[SIZE * SIZE] = {
+  44, 45, 54, 55, 23, 26, 73, 76,
   32, 62, 37, 67, 13, 16, 31, 61,
   38, 68, 83, 86, 14, 15, 41, 51,
   48, 58, 84, 85, 24, 25, 42, 52,
@@ -57,239 +43,170 @@
   22, 27, 72, 77, 11, 18, 81, 88
 };
 
-static const gint heuristic[100] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 65, -3, 6, 4, 4, 6, -3, 65, 0,
-  0, -3, -29, 3, 1, 1, 3, -29, -3, 0,
-  0, 6, 3, 5, 3, 3, 5, 3, 6, 0,
-  0, 4, 1, 3, 1, 1, 3, 1, 4, 0,
-  0, 4, 1, 3, 1, 1, 3, 1, 4, 0,
-  0, 6, 3, 5, 3, 3, 5, 3, 6, 0,
-  0, -3, -29, 3, 1, 1, 3, -29, -3, 0,
-  0, 65, -3, 6, 4, 4, 6, -3, 65, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+static const gint heuristic[(SIZE + 2) * (SIZE + 2)] = {
+  0,   0,   0, 0, 0, 0, 0,   0,   0, 0,
+  0, 145, -23, 6, 4, 4, 6, -23, 145, 0,
+  0, -23, -65, 3, 2, 2, 3, -65, -23, 0,
+  0,   6,   3, 5, 3, 3, 5,   3,   6, 0,
+  0,   4,   2, 3, 1, 1, 3,   2,   4, 0,
+  0,   4,   2, 3, 1, 1, 3,   2,   4, 0,
+  0,   6,   3, 5, 3, 3, 5,   3,   6, 0,
+  0, -23, -65, 3, 2, 2, 3, -65, -23, 0,
+  0, 145, -23, 6, 4, 4, 6, -23, 145, 0,
+  0,   0,   0, 0, 0, 0, 0,   0,   0, 0
 };
 
 static const gint dirs[] = { UL, UU, UR, LL, RR, DL, DD, DR };
 
-guint flip_final_id = 0;
-gint flip_final;
+/* This array can probably be a lot smaller (< 300). */
+static guint8 history[MAX_HPOINTER];
+static guint  hpointer;
+static guint  vpointer;
+static guint  s_kind;
+static GRand  *rgen;
 
-gint8 board0[100];
-/* This array can probably be a lot smaller (< 600). However, I am absolutely
- * certain that it cannot be more than 1200. So 1200 is what we use. */
-gint8 history[1200];
-gint hpointer;
-gint vsquares[280][2];
-gint vpointer;
-gint s_kind;
-GRand *rgen;
+gint8         board0[(SIZE + 2) * (SIZE + 2)];
+gint          vsquares[MAX_VPOINTER][2];
+guint         move_count;
+guint         whose_turn;
+guint         bcount;
+guint         wcount;
 
-extern guint black_computer_level;
-extern guint white_computer_level;
-
-extern gint animate;
-extern gint animate_stagger;
-extern guint game_in_progress;
-extern gint8 pixmaps[8][8];
-extern gint8 board[8][8];
-extern gint8 move_count;
-extern guint whose_turn;
-extern gint bcount;
-extern gint wcount;
-
-extern guint tiles_to_flip;
-
 /* Initialization of data */
 void
 init (void)
 {
-  gint i, j;
-  gint x;
+  guint i, j, ij = 0;
 
   rgen = g_rand_new ();
 
-  x = 0;
-  for (j = 0; j < 10; j++)
-    for (i = 0; i < 10; i++) {
-      if (j == 0 || j == 9)
-	board0[x] = OUTSIDE;
-      else if (i == 0 || i == 9)
-	board0[x] = OUTSIDE;
+  for (i = 0; i < SIZE + 2; i++)
+    for (j = 0; j < SIZE + 2; j++) {
+      if (!i || i == SIZE + 1 || !j || j == SIZE + 1)
+	board0[ij] = OUTSIDE;
       else
-	board0[x] = BLANK;
-      x++;
+	board0[ij] = BLANK;
+      ij++;
     }
 
-  board0[44] = WHITE_TURN;
-  board0[45] = BLACK_TURN;
-  board0[54] = BLACK_TURN;
-  board0[55] = WHITE_TURN;
+  board0[44] = WHITE;
+  board0[45] = BLACK;
+  board0[54] = BLACK;
+  board0[55] = WHITE;
 
-  hpointer = 0;
-  vpointer = 0;
+  hpointer   = 0;
+  vpointer   = 0;
+  move_count = 0;
+  whose_turn = BLACK;
+  bcount     = 2;
+  wcount     = 2;
 }
 
-/* Copy data from board0 to board */
-void
-board_copy (void)
-{
-  gint i, j;
-
-  for (j = 0; j < 8; j++)
-    for (i = 0; i < 8; i++)
-      board[i][j] = board0[(j + 1) * 10 + i + 1];
-}
-
 /* Check the validity of the move in a given direction. */
-static
-  gint
-is_valid0 (gint xy, gint dir, gint who)
+static gboolean
+is_valid0 (guint who, guint yx, gint dir)
 {
-  gint tmp;
-  gint8 not_me;
+  guint tmp = yx + dir;
+  gint8 not_me = (gint8) OTHER_PLAYER (who);
 
-  not_me = OTHER_PLAYER (who);
 
   /* To be valid, the next counter should not be the current player ... */
-  tmp = xy + dir;
   if (board0[tmp] != not_me)
     return FALSE;
 
   /* ... but eventually we must find a counter that is. */
   do {
     tmp += dir;
-  } while (board0[tmp] == not_me);
+  }
+  while (board0[tmp] == not_me);
 
-  return board0[tmp] == who;
+  return board0[tmp] == (gint8) who;
 }
 
 /* Check if a given (empty) square can provide a valid move */
-static
-  gint
-is_valid (gint xy, gint who)
+gboolean
+is_valid (guint who, guint yx)
 {
-  int i;
+  guint i;
 
   for (i = 0; i < NDIRS; i++)
-    if (is_valid0 (xy, dirs[i], who))
-      return (TRUE);
+    if (is_valid0 (who, yx, dirs[i]))
+      return TRUE;
 
   return FALSE;
 }
 
-/* Check whether the supplied move is a valid one. */
-gint
-is_valid_move (guint x, guint y, guint who)
+static void
+move_board0 (guint yx, gint dir)
 {
-  gint xy;
+  guint tmp = yx + dir;
+  gint8 not_me = (gint8) OTHER_PLAYER (whose_turn);
 
-  xy = (y + 1) * 10 + x + 1;
-  if (board0[xy] != BLANK)
-    return FALSE;
-
-  return is_valid (xy, who);
-}
-
-static
-  void
-move_board0 (gint xy, gint dir)
-{
-  gint8 tmp;
-  guint not_me;
-
-  not_me = OTHER_PLAYER (whose_turn);
-  tmp = xy + dir;
   if (board0[tmp] != not_me)
     return;
+
   /* Find the extent of the move in direction dir. */
   do {
     tmp += dir;
-  } while (board0[tmp] == not_me);
-  if (board0[tmp] != whose_turn)
+  }
+  while (board0[tmp] == not_me);
+
+  if (board0[tmp] != (gint8) whose_turn)
     return;
 
   /* Now walk back to where we started flipping pieces over. */
   tmp -= dir;
-  while (tmp != xy) {
-    board0[tmp] = whose_turn;	/* Flip pieces */
-    history[hpointer++] = tmp;	/* Record history */
+  while (tmp != yx) {
+    board0[tmp] = (gint8) whose_turn;	/* Flip pieces    */
+    history[hpointer++] = (guint8) tmp;	/* Record history */
     tmp -= dir;
   }
 }
 
 /* reverse some pieces */
 void
-move_board (gint xy)
+move_board (guint yx)
 {
-  gint tmp, count;
-  int i;
+  guint i, tmp, count = hpointer;
 
-  count = hpointer;
-
   for (i = 0; i < NDIRS; i++)
-    move_board0 (xy, dirs[i]);
+    move_board0 (yx, dirs[i]);
 
-  board0[xy] = whose_turn;
-  count = hpointer - count;
-  history[hpointer++] = count;	/* make history */
-  history[hpointer++] = whose_turn;
+  count               = hpointer - count;
+  history[hpointer++] = (guint8) count;	/* history[t1,,tn, n,who] */
+  history[hpointer++] = (guint8) whose_turn;
+  board0[yx]          = (gint8)  whose_turn;
 
-  if (whose_turn == WHITE_TURN) {
+  i = move_count++ + 4;
+  tmp = (guint) squares[i];	/* squares[0,1,,move_count+4,,62,63] */
+  squares[i] = (guint8) yx;	/*  [- already put -|- yet blank --] */
+  if (tmp != yx) {		/* sort squares */
+    while (squares[++i] != (guint8) yx);
+    squares[i] = (guint8) tmp;
+  }
+
+  if (whose_turn == WHITE) {
     wcount += count + 1;
     bcount -= count;
   } else {
     bcount += count + 1;
     wcount -= count;
   }
-  tmp = squares[move_count];
-  squares[move_count++] = xy;
-  if (tmp != xy) {
-    count = move_count;
-    while (squares[count] != xy)
-      count++;
-    squares[count] = tmp;
-  }
+
   whose_turn = OTHER_PLAYER (whose_turn);
 }
 
-
-gint
-move (guint x, guint y, guint me)
-{
-  gint tmp;
-
-  tmp = (gint) ((y + 1) * 10 + x + 1);
-  if (board0[tmp] != BLANK)
-    return FALSE;
-  if (!is_valid (tmp, whose_turn))
-    return FALSE;
-  move_board (tmp);
-  board_copy ();
-
-  pixmaps[x][y] = (gint8) me;
-  gui_draw_pixmap (me, x, y);
-
-  gui_status ();
-
-  tiles_to_flip = 1;
-  check_valid_moves ();
-  check_computer_players ();
-
-  games_sound_play ("flip-piece");
-
-  return FALSE;
-}
-
 /* Back to before board0 */
 void
-undo (void)
+back (void)
 {
-  gint8 not_me, count;
+  guint count;
+  gint8 not_me;
 
-  whose_turn = history[--hpointer];	/* history[t1,t2,,,tn, n,who] */
-  count = history[--hpointer];
+  whose_turn = (guint) history[--hpointer];	/* history[t1,,tn,n,who] */
+  count      = (guint) history[--hpointer];
 
-  if (whose_turn == WHITE_TURN) {
+  if (whose_turn == WHITE) {
     wcount -= count + 1;
     bcount += count;
   } else {
@@ -297,427 +214,296 @@
     wcount += count;
   }
 
-  board0[squares[--move_count]] = BLANK;	/* decrease move_count    */
+  board0[squares[--move_count + 4]] = BLANK;
 
-  not_me = OTHER_PLAYER (whose_turn);
-  while (count > 0) {
+  not_me = (gint8) OTHER_PLAYER (whose_turn);
+  while (count-- > 0)
     board0[history[--hpointer]] = not_me;
-    count--;
-  }
 }
 
-/* Sort vsquares by small order */
-static
-  void
-sort (gint l, gint r)
-{
-  gint i, j, v, w, x;
-
-  i = l;
-  j = r;
-  x = vsquares[(l + r) / 2][1];
-  do {
-    while (vsquares[i][1] < x)
-      i++;
-    while (x < vsquares[j][1])
-      j--;
-    if (i < j) {
-      v = vsquares[i][0];
-      w = vsquares[i][1];
-      vsquares[i][0] = vsquares[j][0];
-      vsquares[i][1] = vsquares[j][1];
-      vsquares[j][0] = v;
-      vsquares[j][1] = w;
-    }
-    if (i <= j) {
-      i++;
-      j--;
-    }
-  } while (i <= j);
-
-  if (l < j)
-    sort (l, j);
-  if (i < r)
-    sort (i, r);
-}
-
-static
-  gint
+static gint
 eval_heuristic (void)
 {
-  gint8 i, xy;
+  guint i, yx;
   gint count = 0;
 
-  for (i = 0; i < move_count; i++) {
-    xy = squares[i];
-    count = (board0[xy] == whose_turn) ?
-      count + heuristic[xy] : count - heuristic[xy];
+  for (i = 0; i < move_count + 4; i++) {
+    yx = squares[i];
+    if (board0[yx] == (gint8) whose_turn)
+      count += heuristic[yx];
+    else
+      count -= heuristic[yx];
   }
 
   return count;
 }
 
-static
-  gint
-mobility (void)
+static gint
+mobility (guint who)
 {
-  gint8 i, xy;
+  guint i, yx;
   gint count = 0;
 
-  for (i = move_count; i < 64; i++) {
-    xy = squares[i];
-    if (is_valid (xy, whose_turn))
+  for (i = move_count + 4; i < SIZE * SIZE; i++) {
+    yx = (guint) squares[i];
+    if (is_valid (who, yx))
       count++;
   }
 
   return count;
 }
 
-static
-  gint
-around0 (gint xy)
+static gint
+around0 (guint yx)
 {
+  guint i;
   gint count = 0;
-  int i;
 
   for (i = 0; i < NDIRS; i++)
-    if (board0[xy + dirs[i]] == BLANK)
+    if (board0[yx + dirs[i]] == BLANK)
       count--;
-
   if (!count)
     count = 2;
 
   return count;
 }
 
-static
-  gint
+static gint
 around (void)
 {
-  gint8 i, xy;
+  guint i, yx;
   gint count = 0;
 
-  for (i = 0; i < move_count; i++) {
-    xy = squares[i];
-    count = (board0[xy] == whose_turn) ?
-      count + around0 ((gint) xy) : count - around0 ((gint) xy);
+  for (i = 0; i < move_count + 4; i++) {
+    yx = (guint) squares[i];
+    if (board0[yx] == (gint8) whose_turn)
+      count += around0 (yx);
+    else
+      count -= around0 (yx);
   }
 
   return count;
 }
 
-/* Evaluate the board   */
-static
-  gint
+/* Best evaluation */
+static gint
 b_evaluation (void)
 {
   gint score1, score2, score3;
 
-  score1 = mobility ();
-  whose_turn = OTHER_PLAYER (whose_turn);
-  score1 -= mobility ();
-  whose_turn = OTHER_PLAYER (whose_turn);
-
-  score2 = around ();
-  score3 = eval_heuristic ();
-
-  return score1 + score2 + score3;
+  score1 =  mobility (whose_turn);
+  score1 -= mobility (OTHER_PLAYER (whose_turn));
+  score2 =  around ();
+  score3 =  eval_heuristic ();
+  return score1 * 2 + score2 + score3 / 2;
 }
 
 /* Victory evaluation */
-static
-  gint
+static gint
 v_evaluation (void)
 {
   gint aa;
 
   aa = wcount - bcount;
-  if (whose_turn == BLACK_TURN)
+  if (whose_turn == BLACK)
     aa = -aa;
 
   if (aa > 0)
     return 1;			/* win  */
   if (aa < 0)
-    return -1;			/* lose */
+    return -1;		/* lose */
   return 0;			/* draw */
 }
 
-static
-  gint
+/* Perfect evaluation */
+static gint
 p_evaluation (void)
 {
-
-  if (whose_turn == WHITE_TURN)
+  if (whose_turn == WHITE)
     return wcount - bcount;
-
   return bcount - wcount;
 }
 
-static
-  gint
+/* Win evaluation under best search */
+static gint
 w_evaluation (void)
 {
   gint aa;
 
-  if (!bcount || !wcount) {
-    if (whose_turn == WHITE_TURN && !bcount)
-      return 10000;
-    if (whose_turn == BLACK_TURN && !wcount)
-      return 10000;
-    return -10000;
-  }
-
   aa = wcount - bcount;
-  if (whose_turn == BLACK_TURN)
+  if (whose_turn == BLACK)
     aa = -aa;
 
+  if (!bcount || !wcount) {
+    if (aa > 0)
+      return aa + 10000;
+    return aa - 10000;
+  }
+
   if (aa > 0)
-    return aa + 100;
+    return aa + 1000;
   if (aa < 0)
-    return aa - 100;
-  return (0);
+    return aa - 1000;
+  return 0;
 }
 
+/* entry valid squares */
+guint
+entry_valid_move (void)
+{
+  guint yx, i, j = vpointer;
+
+  for (i = move_count + 4; i < SIZE * SIZE; i++) {
+    yx = (guint) squares[i];
+    if (is_valid (whose_turn, yx)) {
+      vsquares[++j][1] = (gint) yx;
+      move_board (yx);
+      vsquares[j][0] = mobility (whose_turn);	/* simple evaluation */
+      back ();
+    }
+  }
+
+  return j - vpointer;
+}
+
+/* Sort vsquares by small order */
+static void
+sort (guint l, guint r)
+{
+  guint i, j;
+  gint v, w, x;
+
+  i = l;
+  j = r;
+  x = vsquares[(l + r) / 2][0];
+  do {
+    while (vsquares[i][0] < x)
+      i++;
+    while (x < vsquares[j][0])
+      j--;
+    if (i < j) {
+      v = vsquares[i][0];
+      w = vsquares[i][1];
+      vsquares[i][0] = vsquares[j][0];
+      vsquares[i][1] = vsquares[j][1];
+      vsquares[j][0] = v;
+      vsquares[j][1] = w;
+    }
+    if (i <= j) {
+      i++;
+      j--;
+    }
+  }
+  while (i <= j);
+
+  if (l < j)
+    sort (l, j);
+  if (i < r)
+    sort (i, r);
+}
+
 /* alpha-beta search */
-static
-  gint
-search (gint n, gint a, gint b)
+static gint
+search (guint n, gint a, gint b)
 {
-  gint aa, bb, xy, i, j;
+  guint i, j;
+  gint aa, bb;
 
-  if (!n) {
+  if (!n) {			/* end ? */
     switch (s_kind) {
     case PERFECT:
-      return (p_evaluation ());
+      return p_evaluation ();
     case VICTORY:
-      return (v_evaluation ());
+      return v_evaluation ();
     default:
-      return (b_evaluation ());
+      return b_evaluation ();
     }
   }
 
-  aa = a;
-
-  j = vpointer;
-  for (i = (gint) move_count; i < 64; i++) {	/* entry valid squares */
-    xy = (gint) squares[i];
-    if (is_valid (xy, whose_turn)) {
-      vsquares[++j][0] = xy;
-      move_board (xy);
-      vsquares[j][1] = mobility ();
-      undo ();
-    }
-  }
-
-  if (j == vpointer) {		/* pass ?  */
-    whose_turn = (whose_turn == WHITE_TURN) ? BLACK_TURN : WHITE_TURN;
-    if (!mobility ()) {
+  j = entry_valid_move ();
+  if (!j) {			/* pass ? */
+    whose_turn = OTHER_PLAYER (whose_turn);
+    if (!mobility (whose_turn)) {	/* end ?  */
       whose_turn = OTHER_PLAYER (whose_turn);
-
       switch (s_kind) {
       case PERFECT:
-	return (p_evaluation ());
+	return p_evaluation ();
       case VICTORY:
-	return (v_evaluation ());
+	return v_evaluation ();
       default:
-	return (w_evaluation ());
+	return w_evaluation ();
       }
     }
-    aa = -search (n, -b, -aa);
+
+    aa = -search (n, -b, -a);
     whose_turn = OTHER_PLAYER (whose_turn);
-    vsquares[j][0] = 0;		/* mark pass              */
+    vsquares[vpointer][1] = 0;	/* mark pass        */
     return aa;
   }
 
-  sort (vpointer + 1, j);
+  i = vpointer;			/* save vpointer    */
+  vpointer = i + j + 1;		/* new vpointer     */
+  sort (i + 1, vpointer - 1);	/* sort vsquares    */
 
-  i = vpointer;			/* save old vpointer      */
-  vpointer = j + 1;		/* new vpointer           */
-
-  j = i + 1;
-  while (aa < b && j < vpointer) {
-    xy = vsquares[j][0];
-    move_board (xy);
-    bb = -search (n - 1, -b, -aa);	/* evaluate this square  */
-    undo ();
-    if (aa < bb) {
+  aa = a;
+  j = i;
+  while (aa < b && ++j < vpointer) {	/* evaluate squares */
+    move_board (vsquares[j][1]);
+    bb = -search (n - 1, -b, -aa);
+    back ();
+    if (bb > aa) {
       aa = bb;
-      vsquares[i][0] = xy;	/* save this square       */
+      vsquares[i][1] = vsquares[j][1];	/* save this square */
     }
-    j++;
   }
-  vpointer = i;			/* pop vpointer           */
+
+  vpointer = i;			/* pop vpointer     */
   return aa;
 }
 
-static
-  void
+/* for first 6 turns */
+static gint
 random_select (void)
 {
-  gint xy, i, j;
+  guint i, j;
 
-  vsquares[0][0] = 0;
-  j = 0;
-  for (i = move_count; i < 64; i++) {
-    xy = squares[i];
-    if (is_valid (xy, whose_turn))
-      vsquares[j++][0] = xy;
+  j = entry_valid_move ();
+  i = vpointer + 1;
+  if (j > i) {
+    i = g_rand_int_range (rgen, 1, j + 1);    /* If the square is critical */
+    if (heuristic[vsquares[i][1]] < 0)	    /* then select once more,    */
+      i = g_rand_int_range (rgen, 1, j + 1);  /* but not three times.      */
   }
-  if (j) {
-    i = g_rand_int_range (rgen, 0, j);
-    vsquares[0][0] = vsquares[i][0];
-  }
-}
 
-static
-  gint
-computer_move (gint level)
-{
-  gint nn, aa, kind, best_xy;
-
-  vsquares[0][0] = -1;
-  nn = 64 - move_count;
-  if (nn > BEST)
-    random_select ();
-  else {
-    if (nn <= PERFECT - level) {
-      kind = PERFECT;
-      aa = 127;
-    }
-    if (PERFECT - level < nn && nn <= VICTORY - level) {
-      kind = VICTORY;
-      aa = 2;
-    }
-    if (VICTORY - level < nn && nn <= BEST) {
-      kind = BEST;
-      aa = 32767;
-      nn = MAX_DEPTH - level;
-    }
-    s_kind = kind;
-    vsquares[0][1] = search (nn, -aa, aa);
-  }
-
-  best_xy = vsquares[0][0];
-
-  if (best_xy == -1) {		/* If I can't win, then search the best again. */
-    s_kind = BEST;
-    vsquares[0][1] = search (MAX_DEPTH - level, -32767, 32767);
-    best_xy = vsquares[0][0];
-  }
-
-  if (best_xy)
-    move (best_xy % 10 - 1, best_xy / 10 - 1, whose_turn);
-
-  return FALSE;
+  vsquares[0][1] = vsquares[i][1];
+  return 0;
 }
 
 gint
-computer_move_1 (guint me)
+computer_move (guint level)
 {
-  return computer_move (6);
-}
+  guint nn = MAX_MOVE_COUNT - move_count;
 
-gint
-computer_move_2 (guint me)
-{
-  return computer_move (4);
-}
+  vpointer = 0;
 
-gint
-computer_move_3 (guint me)
-{
-  return computer_move (2);
-}
+  if (nn <= PERFECT - MAX_DEPTH + level) {
+    s_kind = PERFECT;
+    vsquares[0][0] = search (nn, -127, 127);
+  } else if (nn <= VICTORY - MAX_DEPTH + level) {
+    s_kind = VICTORY;
+    vsquares[0][0] = search (nn, -1, 1);
+  } else if (nn <= BEST) {
+    s_kind = BEST;
+    vsquares[0][0] = search (level, -32767, 32767);
+  } else
+    vsquares[0][0] = random_select ();
 
-gint
-computer_move_4 (guint me)
-{
-  return computer_move (0);
-}
-
-gboolean
-flip_final_results (gpointer data)
-{
-  guint i;
-  guint white_pieces;
-  guint black_pieces;
-  guint adder = 0;
-
-  white_pieces = wcount;
-  black_pieces = bcount;
-
-  i = 0;
-  for (; i < black_pieces; i++) {
-    board[i % 8][i / 8] = BLACK_TURN;
-    if (pixmaps[i % 8][i / 8] < 1)
-      pixmaps[i % 8][i / 8] = WHITE_TURN;
-    if (pixmaps[i % 8][i / 8] == WHITE_TURN) {
-      pixmaps[i % 8][i / 8] += adder;
-      if (animate_stagger)
-	adder++;
-    }
+  /* If I can't win, then search the best again. */
+  if (s_kind == VICTORY && vsquares[0][0] == -1) {
+    s_kind = BEST;
+    vsquares[0][0] = search (level, -32767, 32767);
   }
-  for (; i < 64 - white_pieces; i++) {
-    board[i % 8][i / 8] = 0;
-    pixmaps[i % 8][i / 8] = 100;
-  }
-  for (; i < 64; i++) {
-    board[i % 8][i / 8] = WHITE_TURN;
-    if (pixmaps[i % 8][i / 8] == 0)
-      pixmaps[i % 8][i / 8] = BLACK_TURN;
-    if (pixmaps[i % 8][i / 8] == BLACK_TURN) {
-      pixmaps[i % 8][i / 8] -= adder;
-      if (animate_stagger)
-	adder++;
-    }
-  }
 
-  tiles_to_flip = 1;
-
-  return FALSE;
+  return vsquares[0][1];
 }
 
-gint
-check_valid_moves (void)
-{
-  guint white_moves = 0;
-  guint black_moves = 0;
-
-  if (!game_in_progress)
-    return TRUE;
-  if (mobility ())
-    return TRUE;
-
-  whose_turn = OTHER_PLAYER (whose_turn);
-
-  if (!mobility ()) {
-    white_moves = wcount;
-    black_moves = bcount;
-    if (white_moves > black_moves)
-      gui_message (_("Light player wins!"));
-    if (black_moves > white_moves)
-      gui_message (_("Dark player wins!"));
-    if (white_moves == black_moves)
-      gui_message (_("The game was a draw."));
-    whose_turn = 0;
-    game_in_progress = 0;
-    if (flip_final)
-      flip_final_id = g_timeout_add (100, flip_final_results, NULL);
-
-    games_sound_play ("gameover");
-
-    return TRUE;
-  }
-
-  if (whose_turn == BLACK_TURN) {
-    gui_message (_("Light must pass, Dark's move"));
-    return TRUE;
-  }
-
-  if (whose_turn == WHITE_TURN) {
-    gui_message (_("Dark must pass, Light's move"));
-    return TRUE;
-  }
-
-  return TRUE;
-}
Index: iagno/server.c
===================================================================
--- iagno/server.c	(リビジョン 6373)
+++ iagno/server.c	(作業コピー)
@@ -1,5 +1,5 @@
 /*
- * File: main.c
+ * File: server.c
  * Author: Ismael Orenstein
  * Project: GGZ Reversi game module
  * Date: 09/17/2000
@@ -26,612 +26,447 @@
 #include "config.h"
 #include <gnome.h>
 #include <ggzdmod.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <unistd.h>
+#include <assert.h>
 
 #include "server.h"
+#include "othello.h"
 
+#define COMPUTER_LEVEL 5
+
+extern gint8 board0[(SIZE + 2) * (SIZE + 2)];
+
+static const gchar *strs[] = {
+  "Can't read message\n",	/* 0 */
+  "Can't send message\n",	/* 1 */
+  "Unknown opcode\n",	/* 2 */
+  "Invalid move\n",		/* 3 */
+  "Wrong turn\n",		/* 4 */
+  "Skip move\n",		/* 5 */
+  "Not playing error\n",	/* 6 */
+  "Play again error\n"	/* 7 */
+};
+
 // Global game variables
-struct rvr_game_t rvr_game;
+static GGZdMod *ggz;
+static int     kifu[MAX_MOVE_COUNT + 1][2];
+static int     state;
 
+extern guint   move_count;
+extern guint   whose_turn;
+extern guint   bcount;
+extern guint   wcount;
 
+
+static int game_make_move (int player, int yx);
+
 // Initializes everything
-void
+static void
 game_init (GGZdMod * ggzdmod)
 {
-  int i;
-  rvr_game.ggz = ggzdmod;
-  rvr_game.black = 2;
-  rvr_game.white = 2;
-  rvr_game.state = RVR_STATE_INIT;
-  rvr_game.turn = EMPTY;
-  for (i = 0; i < 64; i++) {
-    rvr_game.board[i] = EMPTY;
-  }
-  // Initial positions
-  rvr_game.board[CART (4, 4)] = WHITE;
-  rvr_game.board[CART (5, 5)] = WHITE;
-  rvr_game.board[CART (5, 4)] = BLACK;
-  rvr_game.board[CART (4, 5)] = BLACK;
-  // Inits random number generator
-  srand (time (0));
-}
+  init ();
 
-// Handle server messages
-void
-game_handle_ggz_state (GGZdMod * ggz, GGZdModEvent event, const void *data)
-{
-  GGZdModState new_state = ggzdmod_get_state (ggz);
-  const GGZdModState *old_state_ptr = data;
-  const GGZdModState old_state = *old_state_ptr;
+  ggz = ggzdmod;
+  kifu[0][0] = EMPTY;
+  bcount = EMPTY;
+  wcount = EMPTY;
+  state = RVR_STATE_INIT;
 
-  // Check if it's the right time to launch the game and if ggz could do taht
-  if (old_state == GGZDMOD_STATE_CREATED) {
-    /*assert(rvr_game.state == RVR_STATE_INIT); */
-    return;
-  }
-
-  if (new_state == GGZDMOD_STATE_PLAYING) {
-    // Game already going on?
-    if (rvr_game.turn == EMPTY)
-      rvr_game.turn = BLACK;
-
-    // No! Let's start the game!
-    game_start ();
-    game_play ();
-  }
-
-  if (new_state == GGZDMOD_STATE_WAITING) {
-    // That's great! Update the state
-    // Now waiting for people to join
-    rvr_game.state = RVR_STATE_WAIT;
-    ggzdmod_log (rvr_game.ggz, "Waiting for players");
-  }
+  if (ggzdmod_get_seat (ggz, PLAYER2SEAT (BLACK)).type == GGZ_SEAT_BOT)
+    bcount = 1;
+  if (ggzdmod_get_seat (ggz, PLAYER2SEAT (WHITE)).type == GGZ_SEAT_BOT)
+    wcount = 1;
 }
 
-
 static int
-seats_full (void)
+game_check_bot (void)
 {
-  /* This calculation is a bit inefficient, but that's OK */
-  return ggzdmod_count_seats (rvr_game.ggz, GGZ_SEAT_OPEN) == 0
-    && ggzdmod_count_seats (rvr_game.ggz, GGZ_SEAT_RESERVED) == 0
-    && ggzdmod_count_seats (rvr_game.ggz, GGZ_SEAT_ABANDONED) == 0;
-}
+  int seat = PLAYER2SEAT (whose_turn);
 
+  // Is the AI?
+  if (ggzdmod_get_seat (ggz, seat).type != GGZ_SEAT_BOT)
+    // It's not! Wait until the player sends the message...
+    return SERVER_OK;
 
-static int
-seats_empty (void)
-{
-  /* This calculation is a bit inefficient, but that's OK */
-  return ggzdmod_count_seats (rvr_game.ggz, GGZ_SEAT_PLAYER) == 0
-    && ggzdmod_count_spectators (rvr_game.ggz) == 0;
+  // Yes! Wait for a second
+  sleep (1);
+  return game_make_move ((int) whose_turn,
+			 (int) computer_move (COMPUTER_LEVEL));
 }
 
-
-void
-game_handle_ggz_seat (GGZdMod * ggz, GGZdModEvent event, const void *data)
+static int
+game_start (void)
 {
-  const GGZSeat *old_seat = data;
-  GGZSeat new_seat = ggzdmod_get_seat (ggz, old_seat->num);
-  GGZdModState new_state;
+  int fd, seat;
 
-  /* Check the state. */
-  if (seats_full ())
-    new_state = GGZDMOD_STATE_PLAYING;
-  else if (seats_empty ())
-    new_state = GGZDMOD_STATE_DONE;
-  else
-    new_state = GGZDMOD_STATE_WAITING;
+  // Start game variables
+  state = RVR_STATE_PLAYING;
+  bcount = wcount = 2;
 
-  // That's great!! Do stuff
+  for (seat = 0; seat < ggzdmod_get_num_seats (ggz); seat++) {
+    fd = ggzdmod_get_seat (ggz, seat).fd;
+    // Don't send anything if the player is a computer!
+    if (fd != -1 && ggz_write_int (fd, RVR_MSG_START) < 0)
+      return ERROR_CANT_WRITE;
+  }
 
-  if (new_seat.type == GGZ_SEAT_PLAYER)
-    game_send_seat (new_seat.num);
-  game_send_players ();
-
-  if (new_state == GGZDMOD_STATE_PLAYING && rvr_game.turn != EMPTY)
-    game_send_sync (new_seat.num);
-
-  ggzdmod_set_state (ggz, new_state);
+  ggzdmod_log (ggz, "Game has started!\n");
+  return game_check_bot ();
 }
 
-
-int
-game_send_seat (int seat)
+// Puts human players score = 0
+// When they send a REQ_AGAIN message, put it = 1
+// When everyone equal = 1, then starts it all again
+static int
+game_play_again (int seat, int fd)
 {
-  int fd = ggzdmod_get_seat (rvr_game.ggz, seat).fd;
+  ggzdmod_log (ggz, "%d wants to play again!\n", seat);
 
-  ggzdmod_log (rvr_game.ggz, "Sending player %d's his seat number\n", seat);
+  // Check game is finished or not. 
+  if (state != RVR_STATE_DONE && state != RVR_STATE_WAIT) {
+    if (ggz_write_int (fd, RVR_MSG_MOVE) < 0
+	|| ggz_write_int (fd, ERROR_PLAY_AGAIN) < 0)
+      return ERROR_CANT_WRITE;
+    return ERROR_PLAY_AGAIN;
+  }
 
-  if (ggz_write_int (fd, RVR_MSG_SEAT) < 0 || ggz_write_int (fd, seat) < 0) {
-    ggzdmod_log (rvr_game.ggz, "Couldn't send seat!\n");
-    return -1;
+  if (state == RVR_STATE_DONE)
+    game_init (ggz);
+
+  if (SEAT2PLAYER (seat) == WHITE) {
+    wcount = 1;
+    if (fd != -1 && ggz_write_int (fd, RVR_MSG_INIT) < 0)
+      return ERROR_CANT_WRITE;
+  } else if (SEAT2PLAYER (seat) == BLACK) {
+    bcount = 1;
+    if (fd != -1 && ggz_write_int (fd, RVR_MSG_INIT) < 0)
+      return ERROR_CANT_WRITE;
   }
 
-  return 0;
+  if (bcount * wcount)
+    // Starts again
+    return game_start ();
+
+  state = RVR_STATE_WAIT;
+  return SERVER_OK;
 }
 
-int
-game_send_players (void)
+static int
+game_skip_move (void)
 {
-  int i, j, fd;
+  int seat, fd;
 
-  for (j = 0; j < ggzdmod_get_num_seats (rvr_game.ggz); j++) {
-    if ((fd = ggzdmod_get_seat (rvr_game.ggz, j).fd) == -1) {
-      ggzdmod_log (rvr_game.ggz, "Bot seat\n");
-      continue;
-    }
-    ggzdmod_log (rvr_game.ggz, "Sending player list to player %d", j);
-
-    if (ggz_write_int (fd, RVR_MSG_PLAYERS) < 0) {
-      ggzdmod_log (rvr_game.ggz, "Can't send player list!\n");
-      return -1;
-    }
-
-    for (i = 0; i < ggzdmod_get_num_seats (rvr_game.ggz); i++) {
-      if (ggz_write_int (fd, ggzdmod_get_seat (rvr_game.ggz, i).type) < 0)
-	return -1;
-      if (ggzdmod_get_seat (rvr_game.ggz, i).type != GGZ_SEAT_OPEN &&
-	  ggz_write_string (fd,
-			    ggzdmod_get_seat (rvr_game.ggz, i).name) < 0) {
-	ggzdmod_log (rvr_game.ggz, "Can't send player name!\n");
-	return -1;
-      }
-    }
+  for (seat = 0; seat < ggzdmod_get_num_seats (ggz); seat++) {
+    fd = ggzdmod_get_seat (ggz, seat).fd;
+    if (fd != -1 && (ggz_write_int (fd, RVR_MSG_MOVE) < 0
+		     || ggz_write_int (fd, ERROR_SKIP_MOVE) < 0))
+      return ERROR_CANT_WRITE;
   }
 
-  return 0;
+  return game_check_bot ();
 }
 
-int
-game_send_sync (int seat)
+static int
+game_check_over (void)
 {
-  int i, fd = ggzdmod_get_seat (rvr_game.ggz, seat).fd;
+  int seat, fd, winner;
+  GGZGameResult results[2];
 
-  ggzdmod_log (rvr_game.ggz, "Handling sync for player %d", seat);
+  if (entry_valid_move ())
+    return game_check_bot ();
 
-  // Send SYNC message and current turn
+  whose_turn = OTHER_PLAYER (whose_turn);
+  if (entry_valid_move ())
+    return game_skip_move ();
 
-  if (ggz_write_int (fd, RVR_MSG_SYNC) < 0
-      || ggz_write_char (fd, rvr_game.turn) < 0)
-    return -1;
+  if (bcount > wcount) {
+    results[PLAYER2SEAT (BLACK)] = GGZ_GAME_WIN;
+    results[PLAYER2SEAT (WHITE)] = GGZ_GAME_LOSS;
+    winner = BLACK;
+  } else if (wcount > bcount) {
+    results[PLAYER2SEAT (WHITE)] = GGZ_GAME_WIN;
+    results[PLAYER2SEAT (BLACK)] = GGZ_GAME_LOSS;
+    winner = WHITE;
+  } else {
+    winner = EMPTY;
+    results[0] = results[1] = GGZ_GAME_TIE;
+  }
 
-  // Send current board state
+  /* Report game to GGZ */
+  ggzdmod_report_game (ggz, NULL, results, NULL);
 
-  for (i = 0; i < 64; i++) {
-    if (ggz_write_char (fd, rvr_game.board[i]) < 0)
-      return -1;
+  // Send message 
+  for (seat = 0; seat < ggzdmod_get_num_seats (ggz); seat++) {
+    fd = ggzdmod_get_seat (ggz, seat).fd;
+    if (fd != -1 && (ggz_write_int (fd, RVR_MSG_GAMEOVER) < 0
+		     || ggz_write_int (fd, winner) < 0))
+      return ERROR_CANT_WRITE;;
   }
 
-  // That's fine
+  // Ends everything
+  whose_turn = EMPTY;
+  state = RVR_STATE_DONE;
+  ggzdmod_log (ggz, "Game is over. Waiting to see if we should play again\n");
 
-  return 0;
-
+  return GAME_OVER;
 }
 
-int
-game_start (void)
+static int
+game_check_move (int player, int yx)
 {
+  // Check if it's right time
+  if (state != RVR_STATE_PLAYING)
+    return ERROR_NOT_PLAYING;
+  // Check if it's his turn
+  if (player != whose_turn)
+    return ERROR_WRONG_TURN;
+  // Check if out of bounds
+  if (yx < 0 || yx >= (SIZE + 2) * (SIZE + 2))
+    return ERROR_INVALID_MOVE;
+  // Check if duplicated
+  if (board0[yx] != BLANK)
+    return ERROR_INVALID_MOVE;
+  // Check if valid yx
+  if (!is_valid (player, yx))
+    return ERROR_INVALID_MOVE;
 
-  int i, fd;
+  return SERVER_OK;
+}
 
-  // Start game variables
-  rvr_game.state = RVR_STATE_PLAYING;
+static int
+game_make_move (int player, int yx)
+{
+  int fd, seat;
 
-  // Sends out start message
-  for (i = 0; i < ggzdmod_get_num_seats (rvr_game.ggz); i++) {
-    fd = ggzdmod_get_seat (rvr_game.ggz, i).fd;
-    // Don't send anything if the player is a computer!
-    if (fd == -1)
-      continue;
-    if (ggz_write_int (fd, RVR_MSG_START) < 0)
-      return -1;
+  kifu[move_count][0]     = player;
+  kifu[move_count][1]     = yx;
+  kifu[move_count + 1][0] = 0;
+  move_board ((guint) yx);
+
+  for (seat = 0; seat < ggzdmod_get_num_seats (ggz); seat++) {
+    fd = ggzdmod_get_seat (ggz, seat).fd;
+    if (fd != -1 && (ggz_write_int (fd, RVR_MSG_MOVE) < 0
+		     || ggz_write_int (fd, yx) < 0))
+      return ERROR_CANT_WRITE;
   }
 
-  ggzdmod_log (rvr_game.ggz, "Game has started!\n");
-
-  return 0;
+  // Check if game is over
+  return game_check_over ();
 }
 
-/* return -1 on error, 1 on gameover */
-void
-game_handle_player (GGZdMod * ggz, GGZdModEvent event, const void *data)
+static int
+game_send_sync (int seat)
 {
-  const int *seat_ptr = data;
-  const int seat = *seat_ptr;
-  int op, move;
   int fd = ggzdmod_get_seat (ggz, seat).fd;
+  int i;
 
-  if (ggz_read_int (fd, &op) < 0)
-    return;
+  ggzdmod_log (ggz, "Handling sync for player %d", seat);
 
-  switch (op) {
-
-  case RVR_REQ_MOVE:
-    game_handle_move (seat, &move);
-    break;
-
-  case RVR_REQ_SYNC:
-    game_send_sync (seat);
-    break;
-
-  case RVR_REQ_AGAIN:
-    game_play_again (seat);
-    break;
-
-  default:
-    ggzdmod_log (rvr_game.ggz, "ERROR: unknown player opcode %d.", op);
-    break;
+  // Send SYNC message and move_count
+  if (ggz_write_int (fd, RVR_MSG_SYNC) < 0
+      || ggz_write_int (fd, (int) move_count) < 0)
+    return ERROR_CANT_WRITE;
+  // Send kifu
+  for (i = 0; i < move_count; i++) {
+    if (ggz_write_int (fd, kifu[i][0]) < 0
+	|| ggz_write_int (fd, kifu[i][1]) < 0)
+      return ERROR_CANT_WRITE;
   }
+  // Send current turn
+  if (ggz_write_int (fd, (int) whose_turn) < 0)
+    return ERROR_CANT_WRITE;
+
+  // That's fine
+  return SERVER_OK;
 }
 
-int
-game_handle_move (int seat, int *move)
+static int
+game_handle_move (int seat, int *yx)
 {
-  int fd = ggzdmod_get_seat (rvr_game.ggz, seat).fd, status;
+  int status, fd = ggzdmod_get_seat (ggz, seat).fd;
 
-  // Get the move from the message
-  if (ggz_read_int (fd, move) < 0)
-    return -1;
+  // Get the yx from the message
+  if (ggz_read_int (fd, yx) < 0)
+    return ERROR_CANT_READ;
 
-  ggzdmod_log (rvr_game.ggz, "Handling move %d,%dfor player %d\n", X (*move),
-	       Y (*move), seat);
+  ggzdmod_log (ggz, "Handling yx %d, for player %d\n", *yx, seat);
 
-  // Check if it's his turn
-  if (SEAT2PLAYER (seat) != rvr_game.turn) {
-    status = RVR_ERROR_WRONGTURN;
-  } else {
-    // Check if it's valid (status return a negative value if error, the move on sucess)
-    status = game_check_move (SEAT2PLAYER (seat), *move);
+  // Check if it's valid
+  status = game_check_move (SEAT2PLAYER (seat), *yx);
+  if (status < 0) {
+    if (ggz_write_int (fd, RVR_MSG_MOVE) < 0
+	|| ggz_write_int (fd, status) < 0)
+      return ERROR_CANT_WRITE;
+    // If invalid yx, sends sync to the player
+    return game_send_sync (seat);
   }
-
   // Make move if it's valid (also sends it to everyone);
-  game_make_move (SEAT2PLAYER (seat), status);
-
-  return status;
-
+  return game_make_move (SEAT2PLAYER (seat), *yx);
 }
 
-void
-game_play (void)
+static int
+seats_full (void)
 {
-  int move;
-  int seat = PLAYER2SEAT (rvr_game.turn);
-
-  // Is the AI?
-  if (ggzdmod_get_seat (rvr_game.ggz, seat).type == GGZ_SEAT_BOT) {
-    // Yes! Wait for a second
-    sleep (1);
-    move = game_bot_move (rvr_game.turn);
-    game_make_move (rvr_game.turn, move);
-  }
-  // It's not! Wait until the player sends the message...
-
-  return;
+  /* This calculation is a bit inefficient, but that's OK */
+  return !ggzdmod_count_seats (ggz, GGZ_SEAT_OPEN)
+    && !ggzdmod_count_seats (ggz, GGZ_SEAT_RESERVED)
+    && !ggzdmod_count_seats (ggz, GGZ_SEAT_ABANDONED);
 }
 
-int
-game_bot_move (int player)
+static int
+seats_empty (void)
 {
-  int i;
-
-  // Returns a random move between 0 and 63
-  i = (int) (64.0 * rand () / (RAND_MAX + 1.0));
-  if (game_check_move (player, i) >= 0)
-    return i;
-  else
-    return game_bot_move (player);
+  /* This calculation is a bit inefficient, but that's OK */
+  return !ggzdmod_count_seats (ggz, GGZ_SEAT_PLAYER)
+    && !ggzdmod_count_spectators (ggz);
 }
 
-int
-game_check_move (int player, int move)
+static int
+game_send_seat (int seat)
 {
+  int fd = ggzdmod_get_seat (ggz, seat).fd;
 
-  int x = X (move), y = Y (move), status = 0;
+  ggzdmod_log (ggz, "Sending player %d's his seat number\n", seat);
 
-  // Check if it's right time
-  if (rvr_game.state != RVR_STATE_PLAYING)
-    return RVR_ERROR_WRONGTURN;
+  if (ggz_write_int (fd, RVR_MSG_SEAT) < 0 || ggz_write_int (fd, seat) < 0)
+    return ERROR_CANT_WRITE;
 
-  // Check if out of bounds
-  if (move < 0 || move > 63)
-    return RVR_ERROR_INVALIDMOVE;
-
-  // Check if duplicated
-  if (rvr_game.board[move] != EMPTY)
-    return RVR_ERROR_INVALIDMOVE;
-
-  /* CHECK IF THE MOVE IS VALID */
-
-  // Check if it's valid up
-  status += game_check_direction (player, 0, -1, x, y);
-  status += game_check_direction (player, 1, -1, x, y);
-  status += game_check_direction (player, 1, 0, x, y);
-  status += game_check_direction (player, 1, 1, x, y);
-  status += game_check_direction (player, 0, 1, x, y);
-  status += game_check_direction (player, -1, 1, x, y);
-  status += game_check_direction (player, -1, 0, x, y);
-  status += game_check_direction (player, -1, -1, x, y);
-
-  if (status > 0)
-    return move;
-  else
-    return RVR_ERROR_INVALIDMOVE;
-
+  return SERVER_OK;
 }
 
-int
-game_check_direction (int player, int vx, int vy, int x, int y)
+static int
+game_send_players (void)
 {
-  int i, j;
-  for (i = x + vx, j = y + vy; GET (i, j) == -player; i += vx, j += vy) {
-    if (GET (i + vx, j + vy) == player)
-      return 1;
-  }
-  return 0;
-}
+  int i, j, fd;
 
-int
-game_make_move (int player, int move)
-{
-  int x = X (move), y = Y (move);
-  int status = 0;
-  int a, fd;
-
-  // Make the move
-  if (move >= 0) {
-    rvr_game.board[move] = player;
-
-    // Now goes through all directions, marking the board
-
-    status += game_mark_board (player, 0, -1, x, y);
-    status += game_mark_board (player, 1, -1, x, y);
-    status += game_mark_board (player, 1, 0, x, y);
-    status += game_mark_board (player, 1, 1, x, y);
-    status += game_mark_board (player, 0, 1, x, y);
-    status += game_mark_board (player, -1, 1, x, y);
-    status += game_mark_board (player, -1, 0, x, y);
-    status += game_mark_board (player, -1, -1, x, y);
-
-
-    // Change turn
-    rvr_game.turn *= -1;
-
-    game_update_scores ();
-
-  } else
-    status = -1;
-
-  for (a = 0; a < ggzdmod_get_num_seats (rvr_game.ggz); a++) {
-    fd = ggzdmod_get_seat (rvr_game.ggz, a).fd;
-    if (fd == -1)
+  for (j = 0; j < ggzdmod_get_num_seats (ggz); j++) {
+    fd = ggzdmod_get_seat (ggz, j).fd;
+    if (fd == -1) {
+      ggzdmod_log (ggz, "Bot seat\n");
       continue;
-    if (status > 0) {
-      if (ggz_write_int (fd, RVR_MSG_MOVE) < 0
-	  || ggz_write_int (fd, move) < 0)
-	ggzdmod_log (rvr_game.ggz, "Couldn't send message to player\n");
-    } else {
-      if (ggz_write_int (fd, RVR_MSG_MOVE) < 0
-	  || ggz_write_int (fd, RVR_ERROR_INVALIDMOVE) < 0)
-	ggzdmod_log (rvr_game.ggz, "Couldn't send error message to player\n");
     }
-    player *= -1;
-  }
 
-  // Check if game is over
-  if (status >= 0 && !game_check_over ()) {
+    ggzdmod_log (ggz, "Sending player list to player %d", j);
+    if (ggz_write_int (fd, RVR_MSG_PLAYERS) < 0)
+      return ERROR_CANT_WRITE;
 
-    // AI play
-    game_play ();
-
-  }
-  // If couldn`t make the move, sends sync to the player
-  if (status < 0)
-    game_send_sync (PLAYER2SEAT (player));
-
-  return status;
-
-}
-
-int
-game_check_over (void)
-{
-  int i, status = 0;
-
-  // Check if the current player can play
-  for (i = 0; i < 64; i++) {
-    if (game_check_move (rvr_game.turn, i) > 0) {
-      status++;
-      break;
+    for (i = 0; i < ggzdmod_get_num_seats (ggz); i++) {
+      if (ggz_write_int (fd, ggzdmod_get_seat (ggz, i).type) < 0)
+	return ERROR_CANT_WRITE;
+      if (ggzdmod_get_seat (ggz, i).type != GGZ_SEAT_OPEN &&
+	  ggz_write_string (fd, ggzdmod_get_seat (ggz, i).name) < 0)
+	return ERROR_CANT_WRITE;
     }
   }
 
-  // If he can play, the game is not over
-  if (status > 0)
-    return 0;
-
-  // He can't! Check if the opponent can
-  status = 0;
-
-  for (i = 0; i < 64; i++) {
-    if (game_check_move (-rvr_game.turn, i) > 0) {
-      status++;
-      break;
-    }
-  }
-
-  // If he can, then skip the players move.
-  // If he can't, end the game
-
-  if (status > 0)
-    game_skip_move ();
-  else {
-    game_gameover ();
-    return 1;
-  }
-
-  return 0;
+  return SERVER_OK;
 }
 
-
-
-
-
-int
-game_mark_board (int player, int vx, int vy, int x, int y)
+static void
+game_handle_player (GGZdMod * ggzdmod, GGZdModEvent event, const void *data)
 {
-  int i, j;
-  if (!game_check_direction (player, vx, vy, x, y))
-    return 0;
-  for (i = x + vx, j = y + vy; GET (i, j) == -player; i += vx, j += vy) {
-    rvr_game.board[CART (i, j)] *= -1;
-  }
-  return 1;
-}
+  const int *seat_ptr = data;
+  const int seat = *seat_ptr;
+  int op, yx, err;
+  int fd = ggzdmod_get_seat (ggzdmod, seat).fd;
 
-void
-game_skip_move (void)
-{
-  int seat;
+  if (ggz_read_int (fd, &op) < 0)
+    return;
 
-  for (seat = 0; seat < ggzdmod_get_num_seats (rvr_game.ggz); seat++) {
-    int fd = ggzdmod_get_seat (rvr_game.ggz, seat).fd;
-    if (fd != -1) {
-      if (ggz_write_int (fd, RVR_MSG_MOVE) < 0 ||
-	  ggz_write_int (fd, RVR_ERROR_CANTMOVE) < 0)
-	ggzdmod_log (rvr_game.ggz, "Can't skip move");
-    }
+  switch (op) {
+  case RVR_REQ_MOVE:			/* 4 */
+    err = game_handle_move (seat, &yx);
+    break;
+  case RVR_REQ_AGAIN:		/* 8 */
+    err = game_play_again (seat, fd);
+    break;
+  default:
+    err = ERROR_OPCODE;
+    break;
   }
 
-  rvr_game.turn *= -1;
-
-  return;
-
+  if (err < 0)
+    ggzdmod_log (ggzdmod, strs[-err - 1]);
 }
 
-void
-game_gameover (void)
+static void
+game_handle_ggz_seat (GGZdMod * ggzdmod, GGZdModEvent event, const void *data)
 {
-  int seat, fd, winner;
-  GGZGameResult results[2];
+  const GGZSeat *old_seat = data;
+  GGZSeat new_seat = ggzdmod_get_seat (ggzdmod, old_seat->num);
+  GGZdModState new_state;
 
-  // Ends everything
-  rvr_game.turn = EMPTY;
-  rvr_game.state = RVR_STATE_DONE;
+  /* Check the state. */
+  if (seats_full ())
+    new_state = GGZDMOD_STATE_PLAYING;
+  else if (seats_empty ())
+    new_state = GGZDMOD_STATE_DONE;
+  else
+    new_state = GGZDMOD_STATE_WAITING;
 
-  if (rvr_game.black > rvr_game.white) {
-    results[PLAYER2SEAT (BLACK)] = GGZ_GAME_WIN;
-    results[PLAYER2SEAT (WHITE)] = GGZ_GAME_LOSS;
-    winner = BLACK;
-  } else if (rvr_game.white > rvr_game.black) {
-    results[PLAYER2SEAT (WHITE)] = GGZ_GAME_WIN;
-    results[PLAYER2SEAT (BLACK)] = GGZ_GAME_LOSS;
-    winner = WHITE;
-  } else {
-    winner = EMPTY;
-    results[0] = results[1] = GGZ_GAME_TIE;
-  }
+  // That's great!! Do stuff
+  if (new_seat.type == GGZ_SEAT_PLAYER)
+    game_send_seat (new_seat.num);
+  game_send_players ();
 
-  /* Report game to GGZ */
-  ggzdmod_report_game (rvr_game.ggz, NULL, results, NULL);
+  if (new_state == GGZDMOD_STATE_PLAYING && whose_turn != EMPTY)
+    game_send_sync (new_seat.num);
 
-  // Send message 
-  for (seat = 0; seat < ggzdmod_get_num_seats (rvr_game.ggz); seat++) {
-    fd = ggzdmod_get_seat (rvr_game.ggz, seat).fd;
-    if (fd == -1)
-      continue;
-    if (ggz_write_int (fd, RVR_MSG_GAMEOVER) < 0
-	|| ggz_write_int (fd, winner) < 0)
-      ggzdmod_log (rvr_game.ggz, "Can't send gameover message");
-  }
-
-  // What to do now?
-  // Puts human players score = 0
-  // When they send a REQ_AGAIN message, put it = 1
-  // When everyone equal = 1, then starts it all again
-  ggzdmod_log (rvr_game.ggz,
-	       "Game is over. Waiting to see if we should play again\n");
-  rvr_game.white =
-    (ggzdmod_get_seat (rvr_game.ggz, PLAYER2SEAT (WHITE)).type ==
-     GGZ_SEAT_BOT);
-  rvr_game.black =
-    (ggzdmod_get_seat (rvr_game.ggz, PLAYER2SEAT (BLACK)).type ==
-     GGZ_SEAT_BOT);
-
-  return;
-
+  ggzdmod_set_state (ggzdmod, new_state);
 }
 
-int
-game_play_again (int seat)
+// Handle server messages
+static void
+game_handle_ggz_state (GGZdMod * ggzdmod, GGZdModEvent event,
+		       const void *data)
 {
-  ggzdmod_log (rvr_game.ggz, "%d wants to play again! He is a good fellow.\n",
-	       seat);
-  // If game is not finished, forget about it
-  if (rvr_game.state != RVR_STATE_DONE) {
-    ggzdmod_log (rvr_game.ggz, "The game wasn`t over yet! Are you crazy?\n");
-    return RVR_SERVER_ERROR;
-  }
+  GGZdModState new_state = ggzdmod_get_state (ggzdmod);
+  const GGZdModState *old_state_ptr = data;
+  const GGZdModState old_state = *old_state_ptr;
 
-  if (SEAT2PLAYER (seat) == WHITE)
-    rvr_game.white = 1;
-  else if (SEAT2PLAYER (seat) == BLACK)
-    rvr_game.black = 1;
+  // Check if it's the right time to launch the game and
+  // if ggz could do taht
+  if (old_state == GGZDMOD_STATE_CREATED)
+    /*assert(rvr_game.state == RVR_STATE_INIT); */
+    return;
 
-  if (rvr_game.white && rvr_game.black) {
-    // Starts is again
-    game_init (rvr_game.ggz);
+  if (new_state == GGZDMOD_STATE_PLAYING)
+    // Let's start the game!
     game_start ();
-    rvr_game.turn = BLACK;
-    game_play ();
+  else if (new_state == GGZDMOD_STATE_WAITING) {
+    // That's great! Update the state
+    // Now waiting for people to join
+    state = RVR_STATE_WAIT;
+    ggzdmod_log (ggzdmod, "Waiting for players");
   }
-
-
-  return RVR_SERVER_OK;
-
 }
 
-void
-game_update_scores (void)
-{
-  int i;
-  rvr_game.white = 0;
-  rvr_game.black = 0;
-  for (i = 0; i < 64; i++) {
-    if (rvr_game.board[i] == WHITE)
-      rvr_game.white++;
-    if (rvr_game.board[i] == BLACK)
-      rvr_game.black++;
-  }
-}
-
-
 int
 main (void)
 {
-  GGZdMod *ggz = ggzdmod_new (GGZDMOD_GAME);
+  GGZdMod *ggzdmod = ggzdmod_new (GGZDMOD_GAME);
 
-  /* game_init is called at the start of _each_ game, so we must do
+  /* game_init is called at the start of each game, so we must do
    * ggz stuff here. */
-  ggzdmod_set_handler (ggz, GGZDMOD_EVENT_STATE, &game_handle_ggz_state);
-  ggzdmod_set_handler (ggz, GGZDMOD_EVENT_JOIN, &game_handle_ggz_seat);
-  ggzdmod_set_handler (ggz, GGZDMOD_EVENT_LEAVE, &game_handle_ggz_seat);
-  ggzdmod_set_handler (ggz, GGZDMOD_EVENT_SEAT, &game_handle_ggz_seat);
-  ggzdmod_set_handler (ggz, GGZDMOD_EVENT_PLAYER_DATA, &game_handle_player);
+  ggzdmod_set_handler (ggzdmod, GGZDMOD_EVENT_STATE,
+		       (GGZdModHandler) game_handle_ggz_state);
+  ggzdmod_set_handler (ggzdmod, GGZDMOD_EVENT_JOIN,
+		       (GGZdModHandler) game_handle_ggz_seat);
+  ggzdmod_set_handler (ggzdmod, GGZDMOD_EVENT_LEAVE,
+		       (GGZdModHandler) game_handle_ggz_seat);
+  ggzdmod_set_handler (ggzdmod, GGZDMOD_EVENT_SEAT,
+		       (GGZdModHandler) game_handle_ggz_seat);
+  ggzdmod_set_handler (ggzdmod, GGZDMOD_EVENT_PLAYER_DATA,
+		       (GGZdModHandler) game_handle_player);
 
-  game_init (ggz);
+  game_init (ggzdmod);
 
   /* Connect to GGZ server; main loop */
-  if (ggzdmod_connect (ggz) < 0)
+  if (ggzdmod_connect (ggzdmod) < 0)
     return -1;
-  (void) ggzdmod_loop (ggz);
-  (void) ggzdmod_disconnect (ggz);
-  ggzdmod_free (ggz);
+  ggzdmod_loop (ggzdmod);
+  ggzdmod_disconnect (ggzdmod);
+  ggzdmod_free (ggzdmod);
 
   return 0;
 }
+
Index: iagno/othello.h
===================================================================
--- iagno/othello.h	(リビジョン 6373)
+++ iagno/othello.h	(作業コピー)
@@ -1,6 +1,5 @@
 /*
- * othello.h - Header for othello.c
- * written by Ian Peters <itp@gnu.org>
+ * othello.h
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,20 +18,31 @@
  * For more details see the file COPYING.
  */
 
-#ifndef _OTHELLO_H_
-#define _OTHELLO_H_
+#define SIZE            8
+#define BEST            54
+#define VICTORY         21
+#define PERFECT         16
+#define MAX_DEPTH       8
+#define MAX_MOVE_COUNT  SIZE * SIZE - 4
+#define MAX_VPOINTER    (VICTORY + 2) * (VICTORY + 3) / 2
+#define MAX_HPOINTER    (MAX_MOVE_COUNT - 4) * 12
 
-gint is_valid_move (guint, guint, guint);
-gint move (guint, guint, guint);
-void move_board (gint);
-gboolean flip_final_results (gpointer data);
-gint check_valid_moves (void);
-gint computer_move_1 (guint);
-gint computer_move_2 (guint);
-gint computer_move_3 (guint);
-gint computer_move_4 (guint);
+#define BLACK           49
+#define WHITE           79
+#define BLANK           1
+
+#define OUTSIDE           (BLACK + WHITE - 1)
+#define OTHER_PLAYER(who) (OUTSIDE - who + 1)
+
 void init (void);
-void board_copy (void);
-void undo (void);
 
-#endif
+gboolean is_valid (guint who, guint yx);
+
+void move_board (guint yx);
+
+void back (void);
+
+guint entry_valid_move (void);
+
+gint computer_move (guint level);
+
Index: iagno/server.h
===================================================================
--- iagno/server.h	(リビジョン 6373)
+++ iagno/server.h	(作業コピー)
@@ -1,5 +1,5 @@
 /*
- * File: game.h
+ * File: server.h
  * Author: Ismael Orenstein
  * Project: GGZ Reversi game module
  * Date: 09/17/2000
@@ -23,211 +23,41 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
 
-#define BLACK -1
-#define WHITE +1
-#define EMPTY  0
+/* PROTOCOL VERSION 1 */
 
-/* REVERSI PROTOCOL VERSION 0.0.5
- *
- * The server handles everything, from the AI to the validity of moves
- *
- * RVR_STATE_INIT:
- *
- * First, it fetchs from the ggz_server how much seats there are, and how much are open/closed
- *
- * RVR_STATE_JOIN:
- *
- * Then, it waits until some player join . When he does, it sends:
- *
- * To Joining player:
- * 	RVR_MSG_SEAT (int)SEAT_NUM
- * To All Human players:
- * 	RVR_MSG_PLAYERS PLAYER_IDENTIFER[BLACK] PLAYER_IDENTIFIER[WHITE]
- *  where PLAYER_IDENTIFIER is:
- *  	(int)PLAYER_TYPE
- *  	if PLAYER_TYPE == GGZ_SEAT_OPEN
- *  		(str)PLAYER_NAME
- *
- * If the game was already happening, send the current game state to the new player
- *
- * 	RVR_MSG_SYNC (char)TURN BOARD_STATE
- * 	where TURN is the current turn, and:
- * 		BOARD_STATE = (char)POSITION * 64
- *
- * When all the open seats are filled, it enters playing state (state = RVR_STATE_PLAYING) and sends:
- *
- * To All Human players:
- * 	RVR_MSG_START
- *
- * RVR_STATE_PLAYING:
- *
- * If current player is AI:
- *
- * 	doMove(AI_MOVE());
- *
- * If it isn't AI, then it waits until client sends a RVR_REQ_MOVE
- *
- * When client sends a RVR_REQ_MOVE, the server must check if he is the current player and
- * if the move is valid. (The client should do it too, must the server must recheck to avoid cheating)
- * Then the server executes the move, and sends:
- * 
- * To All Human players:
- *
- *	RVR_MSG_MOVE (int)MOVE
- * 	where MOVE can be a array index (0-63) or one of the following error values:
- * 		RVR_ERROR_WRONGTURN
- * 			The player tried to move when it wasn't his turn
- * 		RVR_ERROR_INVALIDMOVE
- * 			The player tried a invalid move (Cheating sign!)
- * 		RVR_ERROR_CANTMOVE
- * 			The player can't move (no possible move)
- *
- * Then the server checks if the game is over (No more valid moves) and who has won. If the game is over,
- * it sends to All Human players:
- *
- * 	RVR_MSG_GAMEOVER (int)WINNER
- * 		where WINNER can be: BLACK, WHITE, EMPTY(draw)
- *
- * If some player left while the game was happening, it sends to all Human players:
- *
- * 	RVR_MSG_PLAYERS
- *
- * And it will wait until someone returns
- *
- * Any time, the server can receive a RVR_REQ_SYNC message from the client.
- *  If this is the case, it sents a RVR_MSG_SYNC to this player.
- *
- * The client (more information should be avaiable on the client's game.h file):
- * 
- * The client waits until a RVR_MSG_SEAT is sent to him, indicating what is his seat.
- * Then it waits until a RVR_MSG_PLAYERS, with the type/name of all the players
- * Then it waits until a RVR_MSG_START is sent.
- *
- * If a RVR_MSG_SYNC message is sent to him, it replaces the current game state with the one sent.
- * 
- * Then he enters playing mode.
- *
- * If it is his turn, The user selects a valid square and the client sends:
- * 	RVR_REQ_MOVE (int)MOVE
- * Then it waits until the server sends:
- * 	RVR_MSG_MOVE (int)MOVE
- * If move >= 0, do the move. Else, tell the player what was the error.
- * 
- * If it isn't his turn, it waits until the server sents a
- * 	RVR_MSG_MOVE (int)MOVE
- * If move >= 0, do the move. Else, tell (if necessary) what was the error.
- * 
- * After the move is done, change to the other turn.	
- *
- * If anyone has left the table, it will receive a RVR_MSG_PLAYERS from the server. Then it enters waiting mode again.
- *
- * When the game is over, it sends a RVR_MSG_GAMEOVER (int)winner to the players, and enters DONE state. If it receives enough RVR_REQ_AGAIN msgs, it sends a RVR_MSG_START to the players.
- *
- * Luckily that's all, this protocol is perfect and it shouldn't be modified anymore. Or so I hope. :) */
+#define RVR_MSG_SEAT        0
+#define RVR_MSG_PLAYERS     1
+#define RVR_MSG_MOVE        2
+#define RVR_MSG_GAMEOVER    3
+#define RVR_REQ_MOVE        4
+#define RVR_MSG_START       5
+#define RVR_MSG_SYNC        6
+#define RVR_MSG_INIT        7
+#define RVR_REQ_AGAIN       8
 
-#include "ggzdmod.h"
-
-// Reversi protocol
-// The numbers aren't on order, because I used the same constants from TicTacToe - simplify testing
-#define RVR_MSG_SEAT 0
-#define RVR_MSG_PLAYERS 1
-#define RVR_MSG_SYNC 6
-#define RVR_REQ_SYNC 7
-#define RVR_REQ_AGAIN 8
-#define RVR_MSG_START 5
-#define RVR_MSG_MOVE 2
-#define RVR_MSG_GAMEOVER 3
-#define RVR_REQ_MOVE 4
-
 // States
-#define RVR_STATE_INIT 0
-#define RVR_STATE_WAIT 1
-#define RVR_STATE_PLAYING 2
-#define RVR_STATE_DONE 3
+#define RVR_STATE_INIT      0
+#define RVR_STATE_WAIT      1
+#define RVR_STATE_PLAYING   2
+#define RVR_STATE_DONE      3
 
-// Responses from server
-#define RVR_SERVER_ERROR -1
-#define RVR_SERVER_OK 0
-#define RVR_SERVER_JOIN 1
-#define RVR_SERVER_LEFT 2
-#define RVR_SERVER_QUIT 3
-
 // Errors
-#define RVR_ERROR_INVALIDMOVE -1
-#define RVR_ERROR_WRONGTURN -2
-#define RVR_ERROR_CANTMOVE -3
+#define GAME_OVER           1
+#define SERVER_OK           0
+#define ERROR_CANT_READ    -1
+#define ERROR_CANT_WRITE   -2
+#define ERROR_OPCODE       -3
+#define ERROR_INVALID_MOVE -4
+#define ERROR_WRONG_TURN   -5
+#define ERROR_SKIP_MOVE    -6
+#define ERROR_NOT_PLAYING  -7
+#define ERROR_PLAY_AGAIN   -8
 
-// Takes cartesian coordinates and transform them into a array index
-#define CART(X,Y) ( (Y-1)*8+(X-1) )
-
-// Takes a index and transform it in cartesians coordinates
-#define X(I) ( (I%8)+1 )
-#define Y(I) ( (I/8)+1 )
-
-// See what's the value at that place (like a 10x10 board)
-#define GET(X,Y) ( (X==0 || Y==0 || X>8 || Y>8) ? EMPTY : rvr_game.board[CART(X,Y)] )
-
 // Takes a seat and transform into a player code
-#define SEAT2PLAYER(seat) ( (seat==0)?BLACK:WHITE )
+#define SEAT2PLAYER(seat)   ((seat == 0)? BLACK: WHITE)
 
 // Takes a player code and transform into a seat index
-#define PLAYER2SEAT(player) ( (player==BLACK)?0:1 )
+#define PLAYER2SEAT(player) ((player == BLACK)? 0: 1)
 
+#define EMPTY               0
 
-struct rvr_game_t {
-  /* GGZ data */
-  GGZdMod *ggz;
-  // Board
-  char board[64];
-  // Score
-  int black;
-  int white;
-  // State
-  char state;
-  // Turn
-  char turn;
-};
-
-// Intializes game variables
-void game_init (GGZdMod * ggzdmod);
-// Handle server messages
-void game_handle_ggz_state (GGZdMod * ggz,
-			    GGZdModEvent event, const void *data);
-void game_handle_ggz_seat (GGZdMod * ggz,
-			   GGZdModEvent event, const void *data);
-// Handle player messages
-void game_handle_player (GGZdMod * ggz, GGZdModEvent event, const void *data);
-// Handle player move
-int game_handle_move (int, int *);
-
-// Send to the player what is his seat
-int game_send_seat (int);
-// Send to everyone who is playing
-int game_send_players (void);
-// Send game state to player
-int game_send_sync (int);
-// Sends the start message and start the game
-int game_start (void);
-
-// Play the game (if it is the AI)
-void game_play (void);
-// AI move
-int game_bot_move (int);
-// Check if move is valid (return a error code or the move)
-int game_check_move (int, int);
-// Check if a move is valid in this direction (return true or false)
-int game_check_direction (int, int, int, int, int);
-// Make the move, mark the board, increases the score and sends out the msg
-int game_make_move (int, int);
-// Mark the board at this direction (and increases the score)
-int game_mark_board (int, int, int, int, int);
-// Check if game is over
-int game_check_over (void);
-// Skip current player move
-void game_skip_move (void);
-// Game is over! Send gameover message and stop everything
-void game_gameover (void);
-// Play again?
-int game_play_again (int);
-// Update scores
-void game_update_scores (void);
Index: iagno/ggz-network.c
===================================================================
--- iagno/ggz-network.c	(リビジョン 6373)
+++ iagno/ggz-network.c	(作業コピー)
@@ -20,189 +20,149 @@
 
 #include "config.h"
 #include <gnome.h>
-#include <gconf/gconf-client.h>
-#include <pwd.h>
 
 #include <ggzmod.h>
 #include <ggz-embed.h>
 #include <ggz-gtk.h>
 
-#include "games-dlg-chat.h"
-#include "games-dlg-players.h"
+#include <games-dlg-chat.h>
+#include <games-dlg-players.h>
 
-#include "gnothello.h"
+#include "properties.h"
 #include "ggz-network.h"
-#include "othello.h"
+#include "gnothello.h"
 
-guint whose_turn = BLACK_TURN;
+static const gchar *strs[] = {
+  N_("Waiting for an opponent to join the game."),	/* 0 */
+  N_("Can't read message!"),	/* 1 */
+  N_("Can't send message!"),	/* 2 */
+  N_("Incorrect opcode!"),		/* 3 */
+  N_("Invalid move!"),		/* 4 */
+  N_("Not your turn!"),		/* 5 */
+  N_("Skip move!"),			/* 6 */
+  N_("Not playing now!"),		/* 7 */
+  N_("Not game over yet!"),		/* 8 */
+  N_("Sync error!"),			/* 9 */
+};
 
-static gboolean
-game_handle_io (GGZMod * mod)
-{
-  int op = -1;
+static GGZMod    *ggzmod;
+static int       seat;
+static int       seats[2];
+static char      names[2][17];
+static GtkWidget *ggzbox;
+static GtkWidget *vpaned;
+static GtkWidget *playerlist;
+static GtkWidget *chat;
 
-  fd = ggzmod_get_server_fd (mod);
+int fd;
 
-  // Read the fd
-  if (ggz_read_int (fd, &op) < 0) {
-    ggz_error_msg ("Couldn't read the game fd");
-    return FALSE;
-  }
+extern GtkWidget *window;
+extern GtkWidget *notebook;
+extern GtkWidget *hpaned;
+extern GtkWidget *properties_dialog;
+extern gboolean  flip_tiles;
+extern gboolean  game_in_progress;
+extern gboolean  ggz_network_mode;
 
-  switch (op) {
-  case RVR_MSG_SEAT:
-    get_seat ();
-    break;
-  case RVR_MSG_PLAYERS:
-    get_players ();
-    /*game.state = RVR_STATE_WAIT; */
-    break;
-  case RVR_MSG_SYNC:
-    get_sync ();
-    init_new_game ();
-    break;
-  case RVR_MSG_START:
-    /*state = RVR_STATE_PLAYING; */
-    ggz_debug ("main", "Game has started");
-    init_new_game ();
-    break;
-  case RVR_MSG_MOVE:
-    get_move ();
-    break;
-  case RVR_MSG_GAMEOVER:
-    get_gameover ();
-    /*game.state = RVR_STATE_DONE; */
-    break;
-  default:
-    ggz_error_msg ("Incorrect opcode\n");
-    break;
-  }
 
-  return TRUE;
+static void
+gui_error (int err)
+{
+  gui_message ((gchar *) strs[-err]);
 }
 
-
-
-
-int
+static int
 get_seat (void)
 {
-
   if (ggz_read_int (fd, &seat) < 0)
-    return -1;
+    return ERROR_CANT_READ;
+  if (!seat)
+    gui_error (WAITING);
 
-  if (seat == 0) {
-    gui_message (_("Waiting for an opponent to join the game."));
-  }
-
-  player_id = SEAT2PLAYER (seat);
-
-  return 0;
+  return SERVER_OK;
 }
 
-int
+static int
 get_players (void)
 {
   int i;
 
   for (i = 0; i < 2; i++) {
     if (ggz_read_int (fd, &seats[i]) < 0)
-      return -1;
-
-    if (seats[i] != GGZ_SEAT_OPEN) {
-      if (ggz_read_string (fd, (char *) &names[i], 17) < 0)
-	return -1;
-    }
+      return ERROR_CANT_READ;
+    if (seats[i] != GGZ_SEAT_OPEN
+	&& ggz_read_string (fd, (char *) &names[i], 17) < 0)
+      return ERROR_CANT_READ;
   }
 
-  return 0;
-
+  return SERVER_OK;
 }
 
-int
-get_gameover ()
+static int
+get_gameover (void)
 {
   int winner;
 
   if (ggz_read_int (fd, &winner) < 0)
-    return -1;
+    return ERROR_CANT_READ;
 
-  return 1;
-
+  return SERVER_OK;
 }
 
-// Get the move from the server and makes it (don't check for validity!!)
-int
-get_move (void)
+static int
+game_handle_io (GGZMod *mod)
 {
-  int move;
+  int err = 0, op = -1;
 
-  if (ggz_read_int (fd, &move) < 0)
-    return -1;
+  fd = ggzmod_get_server_fd (mod);
 
-  if (move == RVR_ERROR_CANTMOVE) {
-    return 1;
+  // Read the fd
+  if (ggz_read_int (fd, &op) < 0) {
+    gui_error (ERROR_CANT_READ);
+    return FALSE;
   }
 
-  if (move < 0) {
-    return -1;
+  switch (op) {
+  case RVR_MSG_SEAT:			/* 0 */
+    err = get_seat ();
+    break;
+  case RVR_MSG_PLAYERS:	       /* 1 */
+    err = get_players ();
+    break;
+  case RVR_MSG_MOVE:			/* 2 */
+    err = get_move ();
+    if (err == ERROR_NOT_PLAYING && game_in_progress) {
+      stop_timer ();
+      game_in_progress = FALSE;
+    }
+    break;
+  case RVR_MSG_GAMEOVER:		/* 3 */
+    err = get_gameover ();
+    break;
+  case RVR_MSG_START:		/* 5 */
+    game_in_progress = FALSE;
+    reset_timer ();
+    start_game ();
+    break;
+  case RVR_MSG_SYNC:			/* 6 */
+    err = get_sync ();
+    break;
+  case RVR_MSG_INIT:			/* 7 */
+    init_new_game ();
+    gui_error (WAITING);
+    break;
+  default:
+    err = ERROR_OPCODE;
+    break;
   }
-  game_make_move (move);
+  if (err < 0)
+    gui_error (err);
 
-  return 0;
-
+  return TRUE;
 }
 
-// make the move
-void
-game_make_move (int pos)
-{
-  int x = X (pos) - 1, y = Y (pos) - 1;
-
-  // iagno move
-  move (x, y, whose_turn);
-
-  return;
-
-}
-
-
-
-void
-send_my_move (int move, guint turn)
-{
-  if (ggz_write_int (fd, RVR_REQ_MOVE) < 0 || ggz_write_int (fd, move) < 0) {
-    gui_message ("Can't send move!");
-    return;
-  }
-
-  ggz_debug ("main", "Sent move: %d", move);
-}
-
-int
-request_sync (void)
-{
-  if (ggz_write_int (fd, RVR_REQ_SYNC) < 0) {
-    // Not that someone would check this return value, but...
-    return -1;
-  } else {
-    gui_message ("Requesting sync from the server");
-  }
-  return 0;
-}
-
-int
-get_sync (void)
-{
-/* FIXME: Not supported yet. */
-  return 0;
-}
-
-
-
-
 static gboolean
-handle_ggzmod (GIOChannel * channel, GIOCondition cond, gpointer data)
+handle_ggzmod (GIOChannel *channel, GIOCondition cond, gpointer data)
 {
   GGZMod *mod = data;
 
@@ -210,7 +170,7 @@
 }
 
 static gboolean
-handle_game_server (GIOChannel * channel, GIOCondition cond, gpointer data)
+handle_game_server (GIOChannel *channel, GIOCondition cond, gpointer data)
 {
   GGZMod *mod = data;
 
@@ -218,7 +178,7 @@
 }
 
 static void
-handle_ggzmod_server (GGZMod * mod, GGZModEvent e, const void *data)
+handle_ggzmod_server (GGZMod *mod, GGZModEvent e, const void *data)
 {
   const int *fd = data;
   GIOChannel *channel;
@@ -228,13 +188,33 @@
   g_io_add_watch (channel, G_IO_IN, handle_game_server, mod);
 }
 
+static void
+network_init (void)
+{
+  GIOChannel *channel;
+
+  if (!ggzmod_is_ggz_mode ())
+    return;
+
+  ggzmod = ggzmod_new (GGZMOD_GAME);
+  ggzmod_set_handler (ggzmod, GGZMOD_EVENT_SERVER, handle_ggzmod_server);
+  if (ggzmod_connect (ggzmod) != 0)
+    return;
+
+  channel = g_io_channel_unix_new (ggzmod_get_fd (ggzmod));
+  g_io_add_watch (channel, G_IO_IN, handle_ggzmod, ggzmod);
+
+  init_player_list (ggzmod);
+  init_chat (ggzmod);
+}
+
 /****************************************************************************
   Callback function that's called by the library when a connection is
   established (or lost) to the GGZ server.  The server parameter gives
   the server (or NULL).
 ****************************************************************************/
 static void
-ggz_connected (GGZServer * server)
+ggz_connected (GGZServer *server)
 {
   /* Nothing useful to do... */
 }
@@ -248,8 +228,10 @@
 ggz_game_launched (void)
 {
   network_init ();
-  init_new_game ();
+
   gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), MAIN_PAGE);
+  init_new_game ();
+
 }
 
 /****************************************************************************
@@ -258,66 +240,76 @@
 static void
 ggz_closed (void)
 {
+  ggzmod_disconnect (ggzmod);
+  ggzmod_free (ggzmod);
+
+  gtk_widget_destroy (ggzbox);
   gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), MAIN_PAGE);
+
   ggz_network_mode = FALSE;
+  load_properties ();
+  reset_properties ();
+  apply_changes ();
   init_new_game ();
 }
 
+
 void
-network_init (void)
+on_network_activate (GtkMenuItem *menuitem, gpointer user_data)
 {
-  GGZMod *mod;
-  GIOChannel *channel;
-  int ret, ggzmodfd;
-
-  if (!ggzmod_is_ggz_mode ())
-    return;
+  if (properties_dialog)
+    gtk_widget_destroy (properties_dialog);
   ggz_network_mode = TRUE;
+  load_properties ();
+  reset_properties ();
+  apply_changes ();
 
-  mod = ggzmod_new (GGZMOD_GAME);
-  ggzmod_set_handler (mod, GGZMOD_EVENT_SERVER, handle_ggzmod_server);
+  ggz_gtk_initialize (FALSE,
+		      ggz_connected, ggz_game_launched, ggz_closed,
+		      NETWORK_ENGINE, NETWORK_VERSION, "iagno.xml",
+		      "GGZ Gaming Zone");
 
-  ret = ggzmod_connect (mod);
-  if (ret != 0) {
-    /* Error: GGZ core client error (e.g. faked GGZMODE env variable) */
-    return;
-  }
+  ggz_embed_ensure_server ("GNOME GGZ", "games.gnome.org", 5688, _("Player"));
 
-  ggzmodfd = ggzmod_get_fd (mod);
-  channel = g_io_channel_unix_new (ggzmodfd);
-  g_io_add_watch (channel, G_IO_IN, handle_ggzmod, mod);
+  ggzbox = ggz_gtk_create_main_area (window);
+  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), ggzbox, NULL);
+  gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), NETWORK_PAGE);
+  gtk_widget_show (ggzbox);
+}
 
-  init_player_list (mod);
-  init_chat (mod);
+void
+on_playerlist_activate (GtkMenuItem *menuitem, gpointer user_data)
+{
+  create_or_raise_dlg_players (GTK_WINDOW (window));
+}
 
+void
+on_chat_activate (GtkMenuItem *menuitem, gpointer user_data)
+{
+  create_or_raise_dlg_chat (GTK_WINDOW (window));
 }
 
 void
-on_network_game (void)
+on_leave_activate (GtkMenuItem *menuitem, gpointer user_data)
 {
-  GtkWidget *ggzbox;
-  struct passwd *pwent;  
+  ggz_embed_leave_table ();
 
+  gtk_widget_destroy (chat);
+  gtk_widget_destroy (playerlist);
+  gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), NETWORK_PAGE);
+}
 
-  if (ggz_network_mode) {
-    gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), NETWORK_PAGE);
-    return;
-  }
+void
+on_again_activate (GtkMenuItem *menuitem, gpointer user_data)
+{
+  if (ggz_write_int (fd, RVR_REQ_AGAIN) < 0)
+    gui_error (ERROR_CANT_WRITE);
+}
 
-  init_new_game ();
-  ggz_network_mode = TRUE;
-
-  ggz_gtk_initialize (FALSE,
-		      ggz_connected, ggz_game_launched, ggz_closed,
-		      NETWORK_ENGINE, NETWORK_VERSION, "iagno.xml",
-		      "GGZ Gaming Zone");
-
-  pwent = getpwuid(getuid());
-
-  ggz_embed_ensure_server ("GGZ Gaming Zone", "gnome.ggzgamingzone.org",
-			   5688, pwent->pw_name);
-
-  ggzbox = ggz_gtk_create_main_area (window);
-  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), ggzbox, NULL);
-  gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), NETWORK_PAGE);
+void
+send_my_move (int yx)
+{
+  if (ggz_write_int (fd, RVR_REQ_MOVE) < 0 || ggz_write_int (fd, yx) < 0)
+    gui_error (ERROR_CANT_WRITE);
 }
+
Index: iagno/ggz-network.h
===================================================================
--- iagno/ggz-network.h	(リビジョン 6373)
+++ iagno/ggz-network.h	(作業コピー)
@@ -16,185 +16,53 @@
  * USA
  */
 
-#define EMPTY  0
+/* PROTOCOL VERSION 1 */
 
-/* REVERSI PROTOCOL VERSION 0.0.5
- *
- * The server handles everything, from the AI to the validity of moves
- *
- * RVR_STATE_INIT:
- *
- * First, it fetchs from the ggz_server how much seats there are, and how much are open/closed
- *
- * RVR_STATE_JOIN:
- *
- * Then, it waits until some player join . When he does, it sends:
- *
- * To Joining player:
- * 	RVR_MSG_SEAT (int)SEAT_NUM
- * To All Human players:
- * 	RVR_MSG_PLAYERS PLAYER_IDENTIFER[BLACK] PLAYER_IDENTIFIER[WHITE]
- *  where PLAYER_IDENTIFIER is:
- *  	(int)PLAYER_TYPE
- *  	if PLAYER_TYPE == GGZ_SEAT_OPEN
- *  		(str)PLAYER_NAME
- *
- * If the game was already happening, send the current game state to the new player
- *
- * 	RVR_MSG_SYNC (char)TURN BOARD_STATE
- * 	where TURN is the current turn, and:
- * 		BOARD_STATE = (char)POSITION * 64
- *
- * When all the open seats are filled, it enters playing state (state = RVR_STATE_PLAYING) and sends:
- *
- * To All Human players:
- * 	RVR_MSG_START
- *
- * RVR_STATE_PLAYING:
- *
- * If current player is AI:
- *
- * 	doMove(AI_MOVE());
- *
- * If it isn't AI, then it waits until client sends a RVR_REQ_MOVE
- *
- * When client sends a RVR_REQ_MOVE, the server must check if he is the current player and
- * if the move is valid. (The client should do it too, must the server must recheck to avoid cheating)
- * Then the server executes the move, and sends:
- * 
- * To All Human players:
- *
- *	RVR_MSG_MOVE (int)MOVE
- * 	where MOVE can be a array index (0-63) or one of the following error values:
- * 		RVR_ERROR_WRONGTURN
- * 			The player tried to move when it wasn't his turn
- * 		RVR_ERROR_INVALIDMOVE
- * 			The player tried a invalid move (Cheating sign!)
- *
- * Then the server checks if the game is over (No more valid moves) and who has won. If the game is over,
- * it sends to All Human players:
- *
- * 	RVR_MSG_GAMEOVER (int)WINNER
- * 		where WINNER can be: BLACK, WHITE, EMPTY(draw)
- *
- * If some player left while the game was happening, it sends to all Human players:
- *
- * 	RVR_MSG_PLAYERS
- *
- * And it will wait until someone returns
- *
- * The client:
- *
- * game_init():
- * - Init variables and set the turn to BLACK (first turn) and the state to init
- *
- * RVR_MSG_SEAT
- * - Store his seat on a safe variable
- *
- * RVR_MSG_PLAYERS
- * - Store (and display) the name of the players
- * - Set the state to wait
- *
- * RVR_MSG_START
- * - Set the state to playing
- *
- * RVR_MSG_SYNC
- * - Believes what the server says and updates everything
- *
- * RVR_MSG_MOVE
- * - Do the move
- *
- * RVR_MSG_GAMEOVER
- * - Display ending message
- * 
- * And sends to the server:
- *
- * RVR_REQ_MOVE
- * - Ask to move
- *
- * RVR_REQ_SYNC
- * - Ask for sync
- *
- * RVR_REQ_AGAIN
- * - Ask for playing again
- *
- * Luckily that's all, this protocol is perfect and it shouldn't be modified anymore. Or so I hope. :) */
+#define RVR_MSG_SEAT       0
+#define RVR_MSG_PLAYERS    1
+#define RVR_MSG_MOVE       2
+#define RVR_MSG_GAMEOVER   3
+#define RVR_REQ_MOVE       4
+#define RVR_MSG_START      5
+#define RVR_MSG_SYNC       6
+#define RVR_MSG_INIT       7
+#define RVR_REQ_AGAIN      8
 
-// Reversi protocol
-// The numbers aren't on order, because I used the same constants from TicTacToe - simplify testing
-
-#include "gnothello.h"
-
-#define RVR_MSG_SEAT 0
-#define RVR_MSG_PLAYERS 1
-#define RVR_MSG_SYNC 6
-#define RVR_REQ_SYNC 7
-#define RVR_REQ_AGAIN 8
-#define RVR_MSG_START 5
-#define RVR_MSG_MOVE 2
-#define RVR_MSG_GAMEOVER 3
-#define RVR_REQ_MOVE 4
-
 // States
-#define RVR_STATE_INIT 0
-#define RVR_STATE_WAIT 1
-#define RVR_STATE_PLAYING 2
-#define RVR_STATE_DONE 3
+#define RVR_STATE_INIT     0
+#define RVR_STATE_WAIT     1
+#define RVR_STATE_PLAYING  2
+#define RVR_STATE_DONE     3
 
-// Responses from server
-#define RVR_SERVER_ERROR -1
-#define RVR_SERVER_OK 0
-#define RVR_SERVER_JOIN 1
-#define RVR_SERVER_LEFT 2
-#define RVR_SERVER_QUIT 3
-
 // Errors
-#define RVR_ERROR_INVALIDMOVE -1
-#define RVR_ERROR_WRONGTURN -2
-#define RVR_ERROR_CANTMOVE -3
+#define WAITING            0
+#define SERVER_OK          0
+#define ERROR_CANT_READ    -1
+#define ERROR_CANT_WRITE   -2
+#define ERROR_OPCODE       -3
+#define ERROR_INVALID_MOVE -4
+#define ERROR_WRONG_TURN   -5
+#define ERROR_SKIP_MOVE    -6
+#define ERROR_NOT_PLAYING  -7
+#define ERROR_PLAY_AGAIN   -8
+#define ERROR_SYNC         -9
 
-// Takes cartesian coordinates and transform them into a array index
-#define CART(X,Y) ( (Y-1)*8+(X-1) )
-
-// Takes a index and transform it in cartesians coordinates
-#define X(I) ( (I%8)+1 )
-#define Y(I) ( (I/8)+1 )
-
-// See what's the value at that place (like a 10x10 board)
-#define GET(X,Y) ( (X==0 || Y==0 || X>8 || Y>8) ? EMPTY : game.board[CART(X,Y)] )
-
 // Takes a seat and transform into a player code
-#define SEAT2PLAYER(seat) ( (seat==0)?BLACK_TURN:WHITE_TURN )
+#define SEAT2PLAYER(seat)  ((seat == 0)? BLACK: WHITE)
 
 // Takes a player code and transform into a seat index
-#define PLAYER2SEAT(player) ( (player==BLACK_TURN)?0:1 )
+#define PLAYER2SEAT(player)  ((player == BLACK)? 0: 1)
 
-#define NETWORK_ENGINE "Iagno"
-#define NETWORK_VERSION "1"
 
-void network_init (void);
-void on_network_game (void);
+void on_network_activate (GtkMenuItem *menuitem, gpointer user_data);
 
-int fd;
+void on_playerlist_activate (GtkMenuItem *menuitem, gpointer user_data);
 
-// Setup functions
-void game_init (void);
+void on_chat_activate (GtkMenuItem *menuitem, gpointer user_data);
 
-// Get stuff from server
-int get_seat (void);
-int get_players (void);
-int get_gameover (void);
-int get_sync (void);
-int get_move (void);
-int get_gameover (void);
+void on_leave_activate (GtkMenuItem *menuitem, gpointer user_data);
 
-// Send stuff to server
-void send_my_move (int move, guint turn);
-int request_sync (void);
+void on_again_activate (GtkMenuItem *menuitem, gpointer user_data);
 
-// Game functions
-void game_make_move (int);
-void game_mark_board (int, int, int, int, int);
-int game_check_direction (int, int, int, int, int);
-int game_check_move (int, int);
-void game_update_scores (void);
+void send_my_move (int yx);
+
Index: iagno/Makefile.am
===================================================================
--- iagno/Makefile.am	(リビジョン 6373)
+++ iagno/Makefile.am	(作業コピー)
@@ -13,7 +13,9 @@
 if GGZ_SERVER
 bin_PROGRAMS = iagno iagnod
 iagnod_SOURCES = server.h   \
-		 server.c   
+		 server.c   \
+		 othello.h  \
+		 othello.c
 
 iagnod_LDFLAGS = @GGZDMOD_LDFLAGS@
 
@@ -51,8 +53,9 @@
 	$(LIB_GGZ_GTK)
 
 pixmap_DATA = \
-	classic.png \
-	woodtrim.png
+	coin.svg \
+	marble.svg \
+	sun_and_star.svg
 
 Games_in_files = iagno.desktop.in
 Games_DATA = $(Games_in_files:.desktop.in=.desktop)
Index: iagno/gnothello.c
===================================================================
--- iagno/gnothello.c	(リビジョン 6373)
+++ iagno/gnothello.c	(作業コピー)
@@ -1,8 +1,5 @@
-/* -*- mode:C; indent-tabs-mode:t; tab-width:8; c-basic-offset:8; -*- */
-
 /*
- * gnothello.c - Main GUI part of iagno
- * written by Ian Peters <itp@gnu.org>
+ * gnothello.c - callbacks and main code for iagno.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,106 +18,109 @@
  * For more details see the file COPYING.
  */
 
-#include <config.h>
+#include "config.h"
 #include <gnome.h>
-#include <gdk/gdkkeysyms.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-
+#include <glib.h>
+#include <gconf/gconf-client.h>
+#include <stdio.h>
+#include <fcntl.h>
 #include <string.h>
+
 #include <games-stock.h>
 #include <games-sound.h>
 
+#include "othello.h"
+#include "properties.h"
+#include "gnothello.h"
+
 #ifdef GGZ_CLIENT
-#include <games-dlg-chat.h>
-#include <games-dlg-players.h>
+#include <ggzmod.h>
+#include <ggz-gtk.h>
 #include "ggz-network.h"
-#include <ggz-embed.h>
+extern int fd;
 #endif
 
-#include "gnothello.h"
-#include "othello.h"
-#include "properties.h"
+static const gchar *strs[] = {
+  N_("Dark's move"),			/* 0 */
+  N_("Light's move"),		/* 1 */
+  N_("Light must pass, Dark's move"),/* 2 */
+  N_("Dark must pass, Light's move"),/* 3 */
+  N_("Light player wins!"),		/* 4 */
+  N_("Dark player wins!"),		/* 5 */
+  N_("The game was a draw."),	/* 6 */
+  N_("Now thinking."),		/* 7 */
+  N_("not iagno's file"),		/* 8 */
+  N_("Invalid move."),		/* 9 */
+  N_("Welcome to Iagno!")		/* 10 */
+};
 
-GnomeAppBar *appbar;
-GtkWidget *window;
-GtkWidget *notebook;
-GtkWidget *drawing_area;
-GtkWidget *tile_dialog;
-GtkWidget *black_score;
-GtkWidget *white_score;
+static const gchar *keys[MAX_KEYS] = {
+  "/apps/iagno/black_level",	/* 0 */
+  "/apps/iagno/white_level",	/* 1 */
+  "/apps/iagno/none_animation",	/* 2 */
+  "/apps/iagno/use_quick_moves",	/* 3 */
+  "/apps/iagno/hide_valid_squares",/* 4 */
+  "/apps/iagno/hide_last_move",	/* 5 */
+  "/apps/iagno/hide_final_results",/* 6 */
+  "/apps/iagno/mute",		/* 7 */
+  "/apps/iagno/hide_toolbar",	/* 8 */
+  "/apps/iagno/tileset",		/* 9 */
+  "/apps/iagno/bg_color_name",	/* 10 */
+  "/apps/iagno/board_width",	/* 11 */
+  "/apps/iagno/board_height",	/* 12 */
+  "iagno",				/* 13 Window title */
+  N_("Iagno Preferences")		/* 14 Properties dialog title */
+};
 
-GdkPixmap *buffer_pixmap = NULL;
-GdkPixmap *tiles_pixmap = NULL;
-GdkPixmap *tiles_mask = NULL;
+static guint     kifu[MAX_MOVE_COUNT + 1][2];
+static guint     t_computer_level[2];
+static gboolean  t_hide_valid_squares;
+static gboolean  t_hide_last_move;
+static guint     computer_id = 0;
+static guint     computer_id1 = 0;
 
-gint flip_pixmaps_id = 0;
-gint statusbar_id;
-guint black_computer_level;
-guint white_computer_level;
-guint black_computer_id = 0;
-guint white_computer_id = 0;
-guint computer_speed = COMPUTER_MOVE_DELAY;
-gint animate;
-gint animate_stagger;
-gint grid = 0;
-guint tiles_to_flip = 0;
 
-gint64 milliseconds_total = 0;
-gint64 milliseconds_current_start = 0;
+extern gint8     pixmaps[MAX_SIZE][MAX_SIZE];
+extern gint8     board[MAX_SIZE][MAX_SIZE];
 
-guint game_in_progress;
+extern GtkWidget *window;
+extern GtkWidget *file_open_dialog;
+extern GtkWidget *file_save_dialog;
+extern GtkWidget *counter;
+extern GtkWidget *score[4];
+extern GtkWidget *entry;
 
-gint8 pixmaps[8][8] = { {0, 0, 0, 0, 0, 0, 0, 0}
-,
-{0, 0, 0, 0, 0, 0, 0, 0}
-,
-{0, 0, 0, 0, 0, 0, 0, 0}
-,
-{0, 0, 0, 0, 0, 0, 0, 0}
-,
-{0, 0, 0, 0, 0, 0, 0, 0}
-,
-{0, 0, 0, 0, 0, 0, 0, 0}
-,
-{0, 0, 0, 0, 0, 0, 0, 0}
-,
-{0, 0, 0, 0, 0, 0, 0, 0}
-};
+extern guint     tile_width;
+extern guint     tile_height;
+extern guint     computer_level[2];
+extern gboolean  hide_valid_squares;
+extern gboolean  hide_last_move;
+extern gboolean  hide_final_results;
+extern guint     computer_speed;
+extern gboolean  game_in_progress;
+extern gboolean  gameover;
+extern gboolean  flip_tiles;
+extern guint     flip_final_id;
+extern gboolean  play_sound;
+extern guint     t_move_count;
+extern guint     t_whose_turn;
+extern guint     t_bcount;
+extern guint     t_wcount;
+extern gboolean  ggz_network_mode;
 
-gint8 board[8][8] = { {0, 0, 0, 0, 0, 0, 0, 0}
-,
-{0, 0, 0, 0, 0, 0, 0, 0}
-,
-{0, 0, 0, 0, 0, 0, 0, 0}
-,
-{0, 0, 0, 0, 0, 0, 0, 0}
-,
-{0, 0, 0, 0, 0, 0, 0, 0}
-,
-{0, 0, 0, 0, 0, 0, 0, 0}
-,
-{0, 0, 0, 0, 0, 0, 0, 0}
-,
-{0, 0, 0, 0, 0, 0, 0, 0}
-};
-guint whose_turn;
-gint8 move_count;
-gint bcount;
-gint wcount;
+extern gint8     board0[(SIZE + 2) * (SIZE + 2)];
+extern gint      vsquares[MAX_VPOINTER][2];
+extern guint     move_count;
+extern guint     whose_turn;
+extern guint     bcount;
+extern guint     wcount;
 
-extern guint flip_final_id;
-extern gint8 squares[64];
 
 int session_flag = 0;
 int session_xpos = -1;
 int session_ypos = -1;
 int session_position = 0;
 
-gchar *tile_set = NULL;
-gchar *tile_set_tmp = NULL;
-
-GdkGC *gridGC[2] = { 0 };
-
 static const GOptionEntry options[] = {
   {"x", 'x', 0, G_OPTION_ARG_INT, &session_xpos, N_("X location of window"),
    N_("X")},
@@ -129,768 +129,653 @@
   {NULL}
 };
 
-GnomeUIInfo game_menu[] = {
-  GNOMEUIINFO_MENU_NEW_GAME_ITEM (new_game_cb, NULL),
+static gboolean move (guint yx);
 
-  GNOMEUIINFO_ITEM (N_("Net_work Game"), NULL, new_network_game_cb, NULL),
-
-  GNOMEUIINFO_SEPARATOR,
-
-  GNOMEUIINFO_MENU_UNDO_MOVE_ITEM (undo_move_cb, NULL),
-
-  GNOMEUIINFO_ITEM (N_("_Player list"), NULL, on_player_list, NULL),
-
-  GNOMEUIINFO_ITEM (N_("_Chat Window"), NULL, on_chat_window, NULL),
-
-  GNOMEUIINFO_SEPARATOR,
-
-  GNOMEUIINFO_ITEM (N_("_Leave Game"), NULL, on_network_leave, NULL),
-
-  GNOMEUIINFO_MENU_QUIT_ITEM (quit_game_cb, NULL),
-
-  GNOMEUIINFO_END
-};
-
-GnomeUIInfo settings_menu[] = {
-  GNOMEUIINFO_MENU_PREFERENCES_ITEM (properties_cb, NULL),
-  GNOMEUIINFO_END
-};
-
-GnomeUIInfo help_menu[] = {
-  GNOMEUIINFO_HELP ("iagno"),
-  GNOMEUIINFO_MENU_ABOUT_ITEM (about_cb, NULL),
-  GNOMEUIINFO_END
-};
-
-GnomeUIInfo mainmenu[] = {
-  GNOMEUIINFO_MENU_GAME_TREE (game_menu),
-  GNOMEUIINFO_MENU_SETTINGS_TREE (settings_menu),
-  GNOMEUIINFO_MENU_HELP_TREE (help_menu),
-  GNOMEUIINFO_END
-};
-
 static void
-undo_set_sensitive (gboolean state)
+copy_board (void)
 {
-  gtk_widget_set_sensitive (game_menu[3].widget, state);
-}
+  guint i, j;
 
-void
-quit_game_cb (GtkWidget * widget, gpointer data)
-{
-  gtk_main_quit ();
-}
+  for (i = 0; i < SIZE; i++)
+    for (j = 0; j < SIZE; j++)
+      board[i][j] = (gint8) board0[(i + 1) * (SIZE + 2) + j + 1];
 
-void
-new_game_cb (GtkWidget * widget, gpointer data)
-{
-  init_new_game ();
+  t_move_count = move_count;
+  t_whose_turn = whose_turn;
+  t_bcount     = bcount;
+  t_wcount     = wcount;
 }
 
-void
-on_player_list (void)
+static void
+gui_hint (gint yx, gint score)
 {
-#ifdef GGZ_CLIENT
-  create_or_raise_dlg_players (GTK_WINDOW (window));
-#endif
-}
+  gchar message[10];
 
-void
-on_chat_window (void)
-{
-#ifdef GGZ_CLIENT
-  create_or_raise_dlg_chat (GTK_WINDOW (window));
-#endif
-}
+  message[0] = (gchar) (yx % (SIZE + 2) + 0x40);
+  message[1] = (gchar) (yx / (SIZE + 2) + 0x30);
+  message[2] = 0x20;
+  sprintf (&message[3], _("%d"), score);
 
-void
-new_network_game_cb (GtkWidget * widget, gpointer data)
-{
-#ifdef GGZ_CLIENT
-  on_network_game ();
-  gtk_widget_hide (mainmenu[0].widget);
-  gtk_widget_hide (mainmenu[1].widget);
-#endif
+  gui_entry (message);
 }
 
-void
-on_network_leave (GObject * object, gpointer data)
+static void
+set_valid_squares (gint i)
 {
-#ifdef GGZ_CLIENT
-  ggz_embed_leave_table ();
-  gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), NETWORK_PAGE);
-#endif
-}
+  gint yx;
 
-void
-undo_move_cb (GtkWidget * widget, gpointer data)
-{
-  gint8 which_computer, xy;
-
-  if ((black_computer_level && white_computer_level) || move_count == 4)
+  for (yx = 0; yx < SIZE * SIZE; yx++)
+    if (board[yx / SIZE][yx % SIZE] == -BLANK)
+      board[yx / SIZE][yx % SIZE] = BLANK;
+  if (hide_valid_squares)
     return;
-   
-  /* Cancel any pending AI operations */
-  if (black_computer_id) {
-    g_source_remove (black_computer_id);
-    black_computer_id = 0;
-  }
-  if (white_computer_id) {
-    g_source_remove (white_computer_id);
-    white_computer_id = 0;
-  }
 
-  if (flip_final_id) {
-    g_source_remove (flip_final_id);
-    flip_final_id = 0;
+  while (i > 0) {
+    yx = vsquares[i--][1];
+    board[yx / (SIZE + 2) - 1][yx % (SIZE + 2) - 1] = -BLANK;
   }
+};
 
-  game_in_progress = 1;
-
-  which_computer = OTHER_PLAYER (whose_turn);
-  undo ();
-  board_copy ();
-  xy = squares[move_count];
-  pixmaps[xy % 10 - 1][xy / 10 - 1] = 100;
-  if ((((whose_turn == WHITE_TURN) && white_computer_level) ||
-       ((whose_turn == BLACK_TURN) && black_computer_level))
-      && (move_count > 4)) {
-    undo ();
-    board_copy ();
-    xy = squares[move_count];
-    pixmaps[xy % 10 - 1][xy / 10 - 1] = 100;
-  }
-
-  gui_status ();
-  tiles_to_flip = 1;
-  check_computer_players ();
-}
-
-void
-black_level_cb (GtkWidget * widget, gpointer data)
+static void
+set_last_move (void)
 {
-  int tmp;
+  guint yx;
 
-  tmp = atoi ((gchar *) data);
+  if (move_count < 1 || move_count > MAX_MOVE_COUNT)
+    return;
 
-  gnome_config_set_int ("/iagno/Preferences/blacklevel", tmp);
-  gnome_config_sync ();
-
-  black_computer_level = tmp;
-
-  check_computer_players ();
+  yx = kifu[move_count - 1][1];
+  board[yx / (SIZE + 2) - 1][yx % (SIZE + 2) - 1] =
+    (gint8) kifu[move_count - 1][0] * ((!hide_last_move) ? -1 : 1);
 }
 
-void
-white_level_cb (GtkWidget * widget, gpointer data)
+static gboolean
+check_game_over (void)
 {
-  int tmp;
+  gint i;
 
-  tmp = atoi ((gchar *) data);
+  gui_entry (" ");
+  gtk_entry_set_position ((GtkEntry *) entry, 0);
+  set_last_move ();
 
-  gnome_config_set_int ("/iagno/Preferences/whitelevel", tmp);
-  gnome_config_sync ();
+  i = entry_valid_move ();
+  if (i) {
+    set_valid_squares (i);
+    gui_message ((gchar *) strs[PLAYER2NUMBER (whose_turn)]);
+    continue_timer ();
+    return FALSE;
+  }
 
-  white_computer_level = tmp;
+  t_whose_turn = whose_turn = OTHER_PLAYER (whose_turn);
+  i = entry_valid_move ();
+  if (i) {
+    set_valid_squares (i);
+    gui_message ((gchar *) strs[2 + PLAYER2NUMBER (whose_turn)]);
+    continue_timer ();
+    return FALSE;
+  }
 
-  check_computer_players ();
-}
+  if (wcount > bcount)
+    gui_message ((gchar *) strs[4]);
+  if (bcount > wcount)
+    gui_message ((gchar *) strs[5]);
+  if (wcount == bcount)
+    gui_message ((gchar *) strs[6]);
 
-void
-about_cb (GtkWidget * widget, gpointer data)
-{
-  const gchar *authors[] = { "Ian Peters", NULL };
+  t_whose_turn     = whose_turn = 0;
+  game_in_progress = FALSE;
+  gameover         = TRUE;
 
-  const gchar *documenters[] = { "Eric Baudais", NULL };
+  if (!hide_final_results)
+    flip_final_id = g_timeout_add (computer_speed, flip_final_results, NULL);
 
-  gchar *license = games_get_license (_("Iagno"));
-
-
-  gtk_show_about_dialog (GTK_WINDOW (window),
-			 "name", _("Iagno"),
-			 "version", VERSION,
-			 "copyright",
-			 "Copyright \xc2\xa9 1998-2007 Ian Peters", "license",
-			 license, "comments",
-			 _("A disk flipping game derived from Reversi."),
-			 "authors", authors, "documenters", documenters,
-			 "translator_credits", _("translator-credits"),
-			 "logo-icon-name", "gnome-iagno", "website",
-			 "http://www.gnome.org/projects/gnome-games/",
-			 "wrap-license", TRUE, NULL);
-  g_free (license);
+  return TRUE;
 }
 
-void
-properties_cb (GtkWidget * widget, gpointer data)
+static gboolean
+t_computer_move (gpointer level)
 {
-  show_properties_dialog ();
+  if (game_in_progress)
+    move (computer_move (GPOINTER_TO_INT (level)));
+  computer_id = 0;
+  return FALSE;
 }
 
-gint
-expose_event (GtkWidget * widget, GdkEventExpose * event)
+static gboolean
+check_computer_players (void)
 {
-  gdk_draw_drawable (widget->window,
-		     widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
-		     buffer_pixmap,
-		     event->area.x, event->area.y,
-		     event->area.x, event->area.y,
-		     event->area.width, event->area.height);
+  guint level;
 
-  return (FALSE);
+  if (computer_id) {
+    g_source_remove (computer_id);
+    computer_id = 0;
+  }
+
+  level = computer_level[PLAYER2NUMBER (whose_turn)];
+  if (level) {
+    gui_entry ((gchar *) strs[7]);
+    computer_id = g_timeout_add (computer_speed,
+				 (GSourceFunc) t_computer_move,
+				 GINT_TO_POINTER (level));
+  }
+
+  return FALSE;
 }
 
-gboolean
-configure_event (GtkWidget * widget, GdkEventConfigure * event)
+static gboolean
+check_computer_level_changed (gpointer user_data)
 {
-  static int old_width = 0, old_height = 0;
-  guint i, j;
-
-  if (old_width == event->width && old_height == event->height) {
-    return TRUE;
-  } else {
-    old_width = event->width;
-    old_height = event->height;
+  if (t_hide_valid_squares != hide_valid_squares) {
+    t_hide_valid_squares = hide_valid_squares;
+    set_valid_squares (entry_valid_move ());
+    flip_tiles = TRUE;
   }
-
-  if (gridGC[0] != 0) {
-    gdk_draw_rectangle (buffer_pixmap, gridGC[0], 1,
-			0, 0, BOARDWIDTH, BOARDHEIGHT);
-    for (i = 0; i < 8; i++)
-      for (j = 0; j < 8; j++)
-	gui_draw_pixmap_buffer (pixmaps[i][j], i, j);
-    gui_draw_grid ();
+  if (t_hide_last_move != hide_last_move) {
+    t_hide_last_move = hide_last_move;
+    set_last_move ();
+    flip_tiles = TRUE;
   }
+  if (t_computer_level[0] == computer_level[0]
+      && t_computer_level[1] == computer_level[1])
+    return TRUE;
 
+  t_computer_level[0] = computer_level[0];
+  t_computer_level[1] = computer_level[1];
+  if (game_in_progress)
+    check_computer_players ();
+
   return TRUE;
-}
+};
 
-gint
-button_press_event (GtkWidget * widget, GdkEventButton * event)
+static void
+set_computerid1 (void)
 {
-  guint x, y;
+  t_computer_level[0]  = computer_level[0];
+  t_computer_level[1]  = computer_level[1];
+  t_hide_valid_squares = hide_valid_squares;
+  t_hide_last_move     = hide_last_move;
+  computer_id1         = g_timeout_add (500,
+			   (GSourceFunc) check_computer_level_changed, NULL);
+};
 
-  if (game_in_progress == 0)
-    return TRUE;
+static gboolean
+check_valid_move (guint who, guint yx)
+{
+  if (computer_level[PLAYER2NUMBER (whose_turn)])
+    return FALSE;
+  if (who != whose_turn)
+    return FALSE;
+  if (yx >= (SIZE + 2) * (SIZE + 2))
+    return FALSE;
+  if (board0[yx] != BLANK)
+    return FALSE;
 
-  if (!ggz_network_mode && (whose_turn == WHITE_TURN) && white_computer_level)
-    return TRUE;
+  return is_valid (who, yx);
+}
 
-  if (!ggz_network_mode && (whose_turn == BLACK_TURN) && black_computer_level)
-    return TRUE;
+static gboolean
+move (guint yx)
+{
+  if (game_in_progress) {
+    stop_timer ();
+    kifu[move_count][0]     = whose_turn;
+    kifu[move_count][1]     = yx;
+    kifu[move_count + 1][0] = 0;
+  }
 
-  if (event->button == 1) {
-    x = event->x / (TILEWIDTH + GRIDWIDTH);
-    y = event->y / (TILEHEIGHT + GRIDWIDTH);
-    if (ggz_network_mode && player_id == whose_turn
-	&& is_valid_move (x, y, whose_turn)) {
-#ifdef GGZ_CLIENT
-      send_my_move (CART (x + 1, y + 1), whose_turn);
-#endif
-    } else if (!ggz_network_mode && is_valid_move (x, y, whose_turn)) {
-      move (x, y, whose_turn);
-    } else {
-      gui_message (_("Invalid move."));
-    }
+  move_board (yx);
 
-  }
+  copy_board ();
+  gui_status ();
+  check_game_over ();
+  flip_tiles = TRUE;
+  play_sound = TRUE;
+  if (!game_in_progress)
+    return FALSE;
 
-  return TRUE;
+  return check_computer_players ();
 }
 
-void
-gui_draw_pixmap (gint which, gint x, gint y)
+static void
+check_back (void)
 {
-  gdk_draw_drawable (drawing_area->window, gridGC[0], tiles_pixmap,
-		     (which % 8) * TILEWIDTH, (which / 8) * TILEHEIGHT,
-		     x * (TILEWIDTH + GRIDWIDTH),
-		     y * (TILEHEIGHT + GRIDWIDTH), TILEWIDTH, TILEHEIGHT);
-  gdk_draw_drawable (buffer_pixmap, gridGC[0], tiles_pixmap,
-		     (which % 8) * TILEWIDTH, (which / 8) * TILEHEIGHT,
-		     x * (TILEWIDTH + GRIDWIDTH),
-		     y * (TILEHEIGHT + GRIDWIDTH), TILEWIDTH, TILEHEIGHT);
+  if (flip_final_id) {
+    g_source_remove (flip_final_id);
+    flip_final_id = 0;
+  }
+  if (computer_id) {
+    g_source_remove (computer_id);
+    computer_id = 0;
+  }
+  if (game_in_progress) {
+    stop_timer ();
+    game_in_progress = FALSE;
+  }
 }
 
 void
-gui_draw_pixmap_buffer (gint which, gint x, gint y)
+init_new_game (void)
 {
-  gdk_draw_drawable (buffer_pixmap, gridGC[0], tiles_pixmap,
-		     (which % 8) * TILEWIDTH, (which / 8) * TILEHEIGHT,
-		     x * (TILEWIDTH + GRIDWIDTH),
-		     y * (TILEHEIGHT + GRIDWIDTH), TILEWIDTH, TILEHEIGHT);
+  check_back ();
+  reset_timer ();
+  init ();
+  copy_board ();
+  check_game_over ();
+  redraw_board (NULL);
 }
 
 void
-gui_draw_grid (void)
+start_game (void)
 {
-  int i;
+  if (game_in_progress)
+    return;
+  game_in_progress = TRUE;
+  start_timer ();
+  if (check_game_over ())
+    return;
 
-  for (i = 1; i < 8; i++) {
-    gdk_draw_line (buffer_pixmap, gridGC[grid],
-		   i * BOARDWIDTH / 8 - 1, 0,
-		   i * BOARDWIDTH / 8 - 1, BOARDHEIGHT);
-    gdk_draw_line (buffer_pixmap, gridGC[grid],
-		   0, i * BOARDHEIGHT / 8 - 1,
-		   BOARDWIDTH, i * BOARDHEIGHT / 8 - 1);
-  }
+  kifu[move_count][0] = 0;
+  flip_tiles          = TRUE;
 
-  gdk_draw_drawable (drawing_area->window, gridGC[0], buffer_pixmap,
-		     0, 0, 0, 0, BOARDWIDTH, BOARDHEIGHT);
+  check_computer_players ();
 }
 
-void
-load_pixmaps (void)
+#ifdef GGZ_CLIENT
+int
+get_move (void)
 {
-  GdkPixbuf *image;
-  GError *error = NULL;
-  gchar *tmp;
-  gchar *fname;
+  int yx;
 
-  g_return_if_fail (tile_set != NULL && tile_set[0] != '0');
+  if (ggz_read_int (fd, &yx) < 0)
+    return ERROR_CANT_READ;
+  if (yx == ERROR_SKIP_MOVE)
+    return SERVER_OK;
+  if (yx < 0)
+    return yx;
+  if (!check_valid_move (whose_turn, (guint) yx))
+    return ERROR_INVALID_MOVE;
 
-  tmp = g_build_filename ("iagno", tile_set, NULL);
-  fname = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_APP_PIXMAP,
-				     tmp, FALSE, NULL);
-  g_free (tmp);
+  move ((guint) yx);
+  return SERVER_OK;
+}
 
-  if (!g_file_test (fname, G_FILE_TEST_EXISTS)) {
-    g_free (fname);
-    fname = gnome_program_locate_file (NULL,
-				       GNOME_FILE_DOMAIN_APP_PIXMAP,
-				       "iagno/classic.png", FALSE, NULL);
+int
+get_sync (void)
+{
+  int i, who, yx, count;
+  guint t_kifu[MAX_MOVE_COUNT + 1][2];
+  gboolean err;
+
+  if (ggz_read_int (fd, &count) < 0 || count < 0 || count > MAX_MOVE_COUNT)
+    return ERROR_CANT_READ;
+  for (i = 0; i < count; i++) {
+    if (ggz_read_int (fd, &who) < 0 || ggz_read_int (fd, &yx) < 0)
+      return ERROR_CANT_READ;
+    t_kifu[i][0] = (guint) who;
+    t_kifu[i][1] = (guint) yx;
   }
+  t_kifu[i][0] = 0;
+  if (ggz_read_int (fd, &who) < 0)
+    return ERROR_CANT_READ;
 
-  if (!g_file_test (fname, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
-    g_print (_("Could not find \'%s\' pixmap file\n"), fname);
-    exit (1);
+  i = 0;
+  err = (move_count != (guint) count);
+  while (!err && i < count) {
+    err = (kifu[i][0] != t_kifu[i][0] || kifu[i][1] != t_kifu[i][1]);
+    i++;
   }
+  if (!err)
+    err = (whose_turn != (guint) who);
+  if (!err)
+    return SERVER_OK;
 
-  image = gdk_pixbuf_new_from_file (fname, &error);
-  if (error) {
-    g_warning (G_STRLOC ": gdk-pixbuf error %s\n", error->message);
-    g_error_free (error);
-    error = NULL;
+/* auto recovery */
+  stop_timer ();
+  init ();
+  i = 0;
+  while (t_kifu[i][0]) {
+    kifu[i][0] = t_kifu[i][0];
+    kifu[i][1] = t_kifu[i][1];
+    whose_turn = kifu[i][0];
+    move_board (kifu[i++][1]);
   }
+  kifu[i][0] = 0;
 
-  gdk_pixbuf_render_pixmap_and_mask_for_colormap (image,
-						  gdk_colormap_get_system (),
-						  &tiles_pixmap,
-						  &tiles_mask, 127);
-
-  gdk_pixbuf_unref (image);
-  g_free (fname);
+  copy_board ();
+  check_game_over ();
+  redraw_board (NULL);
+  return SERVER_OK;
 }
+#endif
 
-gint
-flip_pixmaps (gpointer data)
+static void
+on_new_activate (GtkMenuItem *menuitem, gpointer user_data)
 {
-  guint i, j;
-  guint flipped_tiles = 0;
+#ifdef GGZ_CLIENT
+  if (ggz_network_mode)
+    return on_again_activate (menuitem, user_data);
+#endif
 
-  if (!tiles_to_flip)
-    return TRUE;
+  init_new_game ();
+  start_game ();
+}
 
-  for (i = 0; i < 8; i++)
-    for (j = 0; j < 8; j++) {
-      /* This first case only happens when undoing the "final flip". */
-      if ((pixmaps[i][j] == 101) && (board[i][j] != 0)) {
-	pixmaps[i][j] = board[i][j];
-	gui_draw_pixmap (pixmaps[i][j], i, j);
-	flipped_tiles = 1;
-      } else if ((pixmaps[i][j] == 100)
-		 || ((pixmaps[i][j] != 101) && (board[i][j] == 0))) {
-	pixmaps[i][j] = 101;
-	gui_draw_pixmap (0, i, j);
-	flipped_tiles = 1;
-      } else if (pixmaps[i][j] < board[i][j]) {
-	if (animate == 0) {
-	  if (pixmaps[i][j] == BLACK_TURN)
-	    pixmaps[i][j] = board[i][j];
-	  else
-	    pixmaps[i][j]++;
-	} else if (animate == 1) {
-	  if (pixmaps[i][j] < 1)
-	    pixmaps[i][j] += 2;
-	  else if (pixmaps[i][j] >= 1 && pixmaps[i][j] < 8)
-	    pixmaps[i][j] = 8;
-	  else if (pixmaps[i][j] >= 8 && pixmaps[i][j] < 16)
-	    pixmaps[i][j] = 16;
-	  else if (pixmaps[i][j] >= 16 && pixmaps[i][j] < 23)
-	    pixmaps[i][j] = 23;
-	  else if (pixmaps[i][j] >= 23 && pixmaps[i][j] < 31)
-	    pixmaps[i][j] = 31;
-	  else if (pixmaps[i][j] > 31)
-	    pixmaps[i][j] = 31;
-	} else if (animate == 2)
-	  pixmaps[i][j]++;
-	if (pixmaps[i][j] > 0)
-	  gui_draw_pixmap (pixmaps[i][j], i, j);
-	flipped_tiles = 1;
-      } else if (pixmaps[i][j] > board[i][j] && pixmaps[i][j] != 101) {
-	if (animate == 0) {
-	  if (pixmaps[i][j] == WHITE_TURN)
-	    pixmaps[i][j] = board[i][j];
-	  else
-	    pixmaps[i][j]--;
-	} else if (animate == 1) {
-	  if (pixmaps[i][j] > 31)
-	    pixmaps[i][j] -= 2;
-	  else if (pixmaps[i][j] <= 31 && pixmaps[i][j] > 23)
-	    pixmaps[i][j] = 23;
-	  else if (pixmaps[i][j] <= 23 && pixmaps[i][j] > 16)
-	    pixmaps[i][j] = 16;
-	  else if (pixmaps[i][j] <= 16 && pixmaps[i][j] > 8)
-	    pixmaps[i][j] = 8;
-	  else if (pixmaps[i][j] <= 8 && pixmaps[i][j] > 1)
-	    pixmaps[i][j] = 1;
-	  else if (pixmaps[i][j] < 1)
-	    pixmaps[i][j] = 1;
-	} else if (animate == 2)
-	  pixmaps[i][j]--;
-	if (pixmaps[i][j] < 32)
-	  gui_draw_pixmap (pixmaps[i][j], i, j);
-	flipped_tiles = 1;
-      }
-    }
+static void
+on_head_activate (GtkMenuItem *menuitem, gpointer user_data)
+{
+  check_back ();
+  if (move_count < 1)
+    return;
 
-  if (!flipped_tiles)
-    tiles_to_flip = 0;
-
-  return TRUE;
+  init ();
+  copy_board ();
+  check_game_over ();
+  redraw_board (NULL);
 }
 
 static void
-redraw_board (void)
+on_back_activate (GtkMenuItem *menuitem, gpointer user_data)
 {
-  guint i, j;
+  check_back ();
+  if (move_count < 1)
+    return;
 
+  back ();
+  copy_board ();
+  check_game_over ();
   gui_status ();
+  flip_tiles = TRUE;
+  play_sound = TRUE;
+}
 
-  for (i = 0; i < 8; i++)
-    for (j = 0; j < 8; j++)
-      gui_draw_pixmap_buffer (pixmaps[i][j], i, j);
+static gboolean
+check_forward (void)
+{
+  if (game_in_progress)
+    return FALSE;
+  if (move_count >= MAX_MOVE_COUNT)
+    return FALSE;
+  if (!kifu[move_count][0])
+    return FALSE;
 
-  gui_draw_grid ();
+  return TRUE;
 }
 
-void
-clear_board (void)
+static void
+on_forward_activate (GtkMenuItem *menuitem, gpointer user_data)
 {
-  guint i, j;
+  if (!check_forward ())
+    return;
 
-  if (flip_final_id) {
-    g_source_remove (flip_final_id);
-    flip_final_id = 0;
-  }
+  move (kifu[move_count][1]);
+}
 
-  if (black_computer_id) {
-    g_source_remove (black_computer_id);
-    black_computer_id = 0;
-  }
+static void
+on_last_activate (GtkMenuItem *menuitem, gpointer user_data)
+{
+  if (!check_forward ())
+    return;
 
-  if (white_computer_id) {
-    g_source_remove (white_computer_id);
-    white_computer_id = 0;
+  while (kifu[move_count][0]) {
+    whose_turn = kifu[move_count][0];
+    move_board (kifu[move_count][1]);
   }
 
-  game_in_progress = 0;
-  move_count = 0;
-  for (i = 0; i < 8; i++)
-    for (j = 0; j < 8; j++)
-      board[i][j] = 0;
+  copy_board ();
+  check_game_over ();
+  redraw_board (NULL);
+}
 
-  memcpy (pixmaps, board, sizeof (gint8) * 8 * 8);
+static void
+on_hint_activate (GtkMenuItem *menuitem, gpointer user_data)
+{
+  gint best_yx;
 
-  bcount = 0;
-  wcount = 0;
+  if (move_count >= MAX_MOVE_COUNT)
+    return;
+  if (!entry_valid_move ())
+    return;
 
-  redraw_board ();
+  best_yx = computer_move (MAX_DEPTH);
+  gui_hint (best_yx, vsquares[0][0]);
 }
 
-void
-init_new_game (void)
+static void
+on_redo_activate (GtkMenuItem *menuitem, gpointer user_data)
 {
-  clear_board ();
-  game_in_progress = 1;
-  move_count = 4;
+  start_game ();
+}
 
-  undo_set_sensitive (FALSE);
+static void
+read_kifu (int fd)
+{
+  gchar buf[9];
+  guint i = 0;
+  ssize_t err;
 
-  board[3][3] = WHITE_TURN;
-  board[3][4] = BLACK_TURN;
-  board[4][3] = BLACK_TURN;
-  board[4][4] = WHITE_TURN;
+  err = read (fd, buf, 6);
+  buf[6] = 0;
+  if (!g_str_equal (buf, _("iagno\n"))) {
+    gui_message ((gchar *) strs[8]);
+    return;
+  }
 
-  bcount = 2;
-  wcount = 2;
-  init ();
+  err = read (fd, buf, 8);
+  while (err > 0) {
+    kifu[i][0] = (buf[3] == 0x42) ? BLACK : WHITE;
+    kifu[i++][1] = (guint) ((buf[6] - 0x30) * 10 + buf[5] - 0x40);
+    err = read (fd, buf, 8);
+  }
 
-  memcpy (pixmaps, board, sizeof (gint8) * 8 * 8);
+  kifu[i][0] = 0;
+}
 
-  redraw_board ();
+static void
+on_open_clicked (GtkButton *button, gpointer user_data)
+{
+  gchar *filename;
+  int fd;
 
-  whose_turn = BLACK_TURN;
-  gui_status ();
-  gtk_widget_show (mainmenu[0].widget);
-  gtk_widget_show (mainmenu[1].widget);
+  filename =
+    gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_open_dialog));
+  fd = open (filename, 0, 0644);
+  if (fd) {
+    read_kifu (fd);
+    close (fd);
+  }
 
-  check_computer_players ();
+  gtk_widget_destroy (file_open_dialog);
+  g_free (filename);
+  on_head_activate (NULL, NULL);
 }
 
-void
-create_window (void)
+static void
+on_open_activate (GtkMenuItem *menuitem, gpointer user_data)
 {
-  GtkWidget *table;
+  game_in_progress = FALSE;
+  reset_timer ();
 
-  window = gnome_app_new ("iagno", _("Iagno"));
+  file_open_dialog =
+    create_file_open_dialog ((GtkSignalFunc *) on_open_clicked);
+  gtk_widget_show (file_open_dialog);
+}
 
-  notebook = gtk_notebook_new ();
-  gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
+static void
+write_kifu (int fd)
+{
+  gchar buf[10] = { 0, 0, 0x20, 0, 0x20, 0, 0, 0x0A, 0, 0 };
+  guint i = 0;
+  ssize_t err;
 
-  gtk_widget_realize (window);
-  gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
-  g_signal_connect (G_OBJECT (window), "delete_event",
-		    G_CALLBACK (quit_game_cb), NULL);
+  err = write (fd, _("iagno\n"), 6);
+  while (kifu[i][0] && err > 0) {
+    buf[0] = (gchar) ((i + 1) / 10 + 0x30);
+    buf[1] = (gchar) ((i + 1) % 10 + 0x30);
+    buf[3] = (kifu[i][0] == BLACK) ? 0x42 : 0x57;
+    buf[5] = (gchar) (kifu[i][1] % 10 + 0x40);
+    buf[6] = (gchar) (kifu[i++][1] / 10 + 0x30);
 
-  gnome_app_create_menus (GNOME_APP (window), mainmenu);
-
-  drawing_area = gtk_drawing_area_new ();
-
-  gtk_widget_pop_colormap ();
-
-  gnome_app_set_contents (GNOME_APP (window), notebook);
-  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), drawing_area, NULL);
-  gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), MAIN_PAGE);
-
-  gtk_widget_set_size_request (GTK_WIDGET (drawing_area),
-			       BOARDWIDTH, BOARDHEIGHT);
-  g_signal_connect (G_OBJECT (drawing_area), "expose_event",
-		    G_CALLBACK (expose_event), NULL);
-  g_signal_connect (G_OBJECT (window), "configure_event",
-		    G_CALLBACK (configure_event), NULL);
-  g_signal_connect (G_OBJECT (drawing_area), "button_press_event",
-		    G_CALLBACK (button_press_event), NULL);
-  gtk_widget_set_events (drawing_area,
-			 GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
-  /* We do our own double-buffering. */
-  gtk_widget_set_double_buffered (drawing_area, FALSE);
-
-  gtk_widget_show (drawing_area);
-
-  appbar = GNOME_APPBAR (gnome_appbar_new (FALSE, TRUE, FALSE));
-  gnome_app_set_statusbar (GNOME_APP (window), GTK_WIDGET (appbar));
-  gnome_app_install_menu_hints (GNOME_APP (window), mainmenu);
-
-  table = gtk_table_new (1, 8, FALSE);
-
-  black_score = gtk_label_new (_("Dark:"));
-  gtk_widget_show (black_score);
-
-  gtk_table_attach (GTK_TABLE (table), black_score, 1, 2, 0, 1, 0, 0, 3, 1);
-
-  black_score = gtk_label_new ("00");
-  gtk_widget_show (black_score);
-
-  gtk_table_attach (GTK_TABLE (table), black_score, 2, 3, 0, 1, 0, 0, 3, 1);
-
-  white_score = gtk_label_new (_("Light:"));
-  gtk_widget_show (white_score);
-
-  gtk_table_attach (GTK_TABLE (table), white_score, 4, 5, 0, 1, 0, 0, 3, 1);
-
-  white_score = gtk_label_new ("00");
-  gtk_widget_show (white_score);
-
-  gtk_table_attach (GTK_TABLE (table), white_score, 5, 6, 0, 1, 0, 0, 3, 1);
-  undo_set_sensitive (FALSE);
-
-  gtk_widget_show (table);
-
-  gtk_box_pack_start (GTK_BOX (appbar), table, FALSE, TRUE, 0);
-
-  gnome_appbar_set_status (GNOME_APPBAR (appbar), _("Welcome to Iagno!"));
+    err = write (fd, buf, 8);
+  }
 }
 
-void
-gui_status (void)
+static void
+on_save_clicked (GtkButton *button, gpointer user_data)
 {
-  gchar message[3];
+  gchar *filename;
+  int fd;
 
-  sprintf (message, _("%.2d"), bcount);
-  gtk_label_set_text (GTK_LABEL (black_score), message);
-  sprintf (message, _("%.2d"), wcount);
-  gtk_label_set_text (GTK_LABEL (white_score), message);
-  undo_set_sensitive (move_count > 0);
+  filename =
+    gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_save_dialog));
 
-  if (ggz_network_mode) {
-    gtk_widget_hide (game_menu[0].widget);
-    gtk_widget_hide (game_menu[1].widget);
-    gtk_widget_hide (game_menu[2].widget);
-    gtk_widget_hide (game_menu[3].widget);
-    gtk_widget_show (game_menu[4].widget);
-    gtk_widget_show (game_menu[5].widget);
-    gtk_widget_show (game_menu[7].widget);
-  } else {
-    gtk_widget_show (game_menu[0].widget);
-    gtk_widget_show (game_menu[1].widget);
-    gtk_widget_show (game_menu[2].widget);
-    gtk_widget_show (game_menu[3].widget);
-    gtk_widget_hide (game_menu[4].widget);
-    gtk_widget_hide (game_menu[5].widget);
-    gtk_widget_hide (game_menu[7].widget);
+  fd = creat (filename, 0644);
+  if (fd) {
+    write_kifu (fd);
+    close (fd);
   }
 
-  gtk_widget_set_sensitive (settings_menu[0].widget, !ggz_network_mode);
+  gtk_widget_destroy (file_save_dialog);
+  g_free (filename);
+}
 
-#ifndef GGZ_CLIENT
-  gtk_widget_set_sensitive (game_menu[1].widget, FALSE);
-#endif
+static void
+on_save_activate (GtkMenuItem *menuitem, gpointer user_data)
+{
+  GDate *date;
+  gchar filename[17];
 
-  if (ggz_network_mode) {
-    if (whose_turn == player_id && whose_turn == BLACK_TURN) {
-      gui_message (_("It is your turn to place a dark piece"));
-    } else if (whose_turn == player_id && whose_turn == WHITE_TURN) {
-      gui_message (_("It is your turn to place a light piece"));
-    } else {
-      gchar *str;
-      str = g_strdup_printf (_("Waiting for %s to move"),
-			     names[(seat + 1) % 2]);
-      gui_message (str);
-      g_free (str);
-    }
-  } else {
-    if (whose_turn == BLACK_TURN) {
-      gui_message (_("Dark's move"));
-    } else if (whose_turn == WHITE_TURN) {
-      gui_message (_("Light's move"));
-    }
+  date = g_date_new ();
+  g_date_set_time_t (date, time (NULL));
+  g_date_strftime (filename, 17, _("%y%m%d%H"), date);
 
-  }
+  file_save_dialog =
+    create_file_save_dialog ((GtkSignalFunc *) on_save_clicked);
+  gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (file_save_dialog),
+				     filename);
+  gtk_widget_show (file_save_dialog);
+  g_date_free (date);
+}
 
-
+static void
+on_help_activate (GtkMenuItem *menuitem, gpointer user_data)
+{
+  gnome_help_display ("iagno.xml", NULL, NULL);
 }
 
-void
-gui_message (gchar * message)
+static void
+on_about_activate (GtkMenuItem *menuitem, gpointer user_data)
 {
-  gnome_appbar_pop (GNOME_APPBAR (appbar));
-  gnome_appbar_push (GNOME_APPBAR (appbar), message);
+  const gchar *authors[] = { "Ian Peters", NULL };
+  const gchar *documenters[] = { "Eric Baudais", NULL };
+  gchar *license = games_get_license (_("Iagno"));
+
+  gtk_show_about_dialog (GTK_WINDOW (window),
+			 "name", _("Iagno"),
+			 "version", VERSION,
+			 "copyright",
+			 "Copyright \xc2\xa9 1998-2007 Ian Peters", "license",
+			 license, "comments",
+			 _("A disk flipping game derived from Reversi."),
+			 "authors", authors, "documenters", documenters,
+			 "translator_credits", _("translator-credits"),
+			 "logo-icon-name", "gnome-iagno", "website",
+			 "http://www.gnome.org/projects/gnome-games/",
+			 "wrap-license", TRUE, NULL);
+  g_free (license);
 }
 
-guint
-check_computer_players (void)
+static gboolean
+check_event_move (guint x, guint y)
 {
+  guint yx = y * (SIZE + 2) + x;
 
+#ifdef GGZ_CLIENT
   if (ggz_network_mode) {
-    black_computer_id = 0;
-    white_computer_id = 0;
-    return TRUE;
+    send_my_move ((int) yx);
+    return FALSE;
   }
-  if (black_computer_level && whose_turn == BLACK_TURN)
-    switch (black_computer_level) {
-    case 1:
-      black_computer_id =
-	g_timeout_add (computer_speed, (GSourceFunc) computer_move_1,
-		       (gpointer) BLACK_TURN);
-      break;
-    case 2:
-      black_computer_id =
-	g_timeout_add (computer_speed, (GSourceFunc) computer_move_2,
-		       (gpointer) BLACK_TURN);
-      break;
-    case 3:
-      black_computer_id =
-	g_timeout_add (computer_speed, (GSourceFunc) computer_move_3,
-		       (gpointer) BLACK_TURN);
-      break;
-    }
+#endif
 
-  if (white_computer_level && whose_turn == WHITE_TURN)
-    switch (white_computer_level) {
-    case 1:
-      white_computer_id =
-	g_timeout_add (computer_speed, (GSourceFunc) computer_move_1,
-		       (gpointer) WHITE_TURN);
-      break;
-    case 2:
-      white_computer_id =
-	g_timeout_add (computer_speed, (GSourceFunc) computer_move_2,
-		       (gpointer) WHITE_TURN);
-      break;
-    case 3:
-      white_computer_id =
-	g_timeout_add (computer_speed, (GSourceFunc) computer_move_3,
-		       (gpointer) WHITE_TURN);
-      break;
-    }
+  if (!game_in_progress)
+    return FALSE;
+  if (check_valid_move (whose_turn, yx))
+    return move (yx);
 
-  return TRUE;
+  gui_message ((gchar *) strs[9]);
+  return FALSE;
 }
 
-void
-set_bg_color (void)
+static gboolean
+on_drawing_area_button_press_event (GtkWidget *widget,
+				    GdkEventButton *event,
+				    gpointer user_data)
 {
-  GdkImage *tmpimage;
-  GdkColor bgcolor;
+  guint x, y;
 
-  tmpimage = gdk_drawable_get_image (tiles_pixmap, 0, 0, 1, 1);
-  bgcolor.pixel = gdk_image_get_pixel (tmpimage, 0, 0);
-  gdk_window_set_background (drawing_area->window, &bgcolor);
+  if (event->button != 1)
+    return FALSE;
 
-  if (gridGC[0])
-    g_object_unref (gridGC[0]);
-  gridGC[0] = gdk_gc_new (drawing_area->window);
-  if (gridGC[1])
-    g_object_unref (gridGC[1]);
-  gridGC[1] = gdk_gc_new (drawing_area->window);
+  x = event->x / (tile_width + GRIDWIDTH) + 1;
+  y = event->y / (tile_height + GRIDWIDTH) + 1;
 
-  gdk_gc_copy (gridGC[0], drawing_area->style->bg_gc[0]);
-  gdk_gc_copy (gridGC[1], drawing_area->style->bg_gc[0]);
-
-  gdk_gc_set_background (gridGC[0], &bgcolor);
-  gdk_gc_set_foreground (gridGC[0], &bgcolor);
-
-  /* Create a complementary color to use for the ON state */
-  bgcolor.pixel = 0xFFFFFF - bgcolor.pixel;
-  gdk_gc_set_background (gridGC[1], &bgcolor);
-  gdk_gc_set_foreground (gridGC[1], &bgcolor);
-
-  gdk_gc_set_line_attributes (gridGC[1], 0,
-			      GDK_LINE_ON_OFF_DASH,
-			      GDK_CAP_BUTT, GDK_JOIN_MITER);
-
-  g_object_unref (tmpimage);
+  return check_event_move (x, y);
 }
 
-static int
-save_state (GnomeClient * client, gint phase, GnomeRestartStyle save_style,
-	    gint shutdown, GnomeInteractStyle interact_style,
-	    gint fast, gpointer client_data)
+static gboolean
+on_entry_key_press_event (GtkWidget *widget,
+			  GdkEventKey *event, gpointer user_data)
 {
-  char *argv[20];
-  int i;
-  gint xpos, ypos;
+  gchar *ch;
+  guint x, y;
 
-  gdk_window_get_origin (window->window, &xpos, &ypos);
+  ch = (gchar *) gtk_entry_get_text (GTK_ENTRY (entry));
+  x = (guint) ((*ch++ & 0xdf) - 0x40);
+  if (!*ch)
+    return FALSE;
+  y = (guint) (*ch - 0x30);
+  if (y < 1 || y > SIZE)
+    return FALSE;
 
-  i = 0;
-  argv[i++] = (char *) client_data;
-  argv[i++] = "-x";
-  argv[i++] = g_strdup_printf ("%d", xpos);
-  argv[i++] = "-y";
-  argv[i++] = g_strdup_printf ("%d", ypos);
+  return check_event_move (x, y);
+}
 
-  gnome_client_set_restart_command (client, i, argv);
-  gnome_client_set_clone_command (client, 0, NULL);
+const GCallback callbacks[MAX_ACTIONS] = {
+  NULL,
+  (GCallback) on_new_activate,
+#ifdef GGZ_CLIENT
+  (GCallback) on_network_activate,
+  (GCallback) on_playerlist_activate,
+  (GCallback) on_chat_activate,
+  (GCallback) on_leave_activate,
+#else
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+#endif
+  (GCallback) on_head_activate,
+  (GCallback) on_back_activate,
+  (GCallback) on_forward_activate,
+  (GCallback) on_last_activate,
+  (GCallback) on_hint_activate,
+  (GCallback) on_redo_activate,
+  (GCallback) on_open_activate,
+  (GCallback) on_save_activate,
+  (GCallback) on_quit_activate,
+  NULL,
+  (GCallback) on_properties_activate,
+  NULL,
+  (GCallback) on_help_activate,
+  (GCallback) on_about_activate
+};
 
-  g_free (argv[2]);
-  g_free (argv[4]);
+const GtkSignalFunc signalfuncs[MAX_SIGNALFUNCS] = {
+  (GtkSignalFunc) on_drawing_area_button_press_event,
+  (GtkSignalFunc) on_entry_key_press_event,
+};
 
-  return TRUE;
-}
-
 int
-main (int argc, char **argv)
+main (int argc, char *argv[])
 {
   GnomeClient *client;
   GnomeProgram *program;
@@ -912,43 +797,23 @@
 				GNOME_PARAM_GOPTION_CONTEXT, context,
 				GNOME_PARAM_APP_DATADIR, DATADIR, NULL);
 
+  games_stock_init ();
   gtk_window_set_default_icon_name ("gnome-iagno");
 
-  client = gnome_master_client ();
+  init_interface (SIZE, MAX_DEPTH, (gchar **) keys,
+		  (GCallback *) callbacks, (GtkSignalFunc *) signalfuncs);
 
-  g_object_ref (G_OBJECT (client));
-
-  g_signal_connect (G_OBJECT (client), "save_yourself",
-		    G_CALLBACK (save_state), argv[0]);
-  g_signal_connect (G_OBJECT (client), "die",
-		    G_CALLBACK (quit_game_cb), argv[0]);
-
-  create_window ();
-
   load_properties ();
+  window = create_window ();
+  reset_properties ();
+  apply_changes ();
+  set_computerid1 ();
 
-  load_pixmaps ();
-
-  gtk_widget_show (window);
-
-#ifdef GGZ_CLIENT
-  network_init ();
-#endif
-
-  if (session_xpos >= 0 && session_ypos >= 0) {
-    gdk_window_move (window->window, session_xpos, session_ypos);
-  }
-
-  buffer_pixmap = gdk_pixmap_new (drawing_area->window,
-				  BOARDWIDTH, BOARDHEIGHT, -1);
-
-  set_bg_color ();
-
   init_new_game ();
-
+  gui_message ((gchar *) strs[10]);
   gtk_main ();
 
   g_object_unref (program);
-
   return 0;
 }
+
Index: iagno/properties.c
===================================================================
--- iagno/properties.c	(リビジョン 6373)
+++ iagno/properties.c	(作業コピー)
@@ -1,7 +1,5 @@
-/* -*- mode:C; indent-tabs-mode:t; tab-width:8; c-basic-offset:8; -*- */
-
 /*
- * Properties.c - Properties and preferences part of iagno
+ * properties.c - user interface code.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,65 +18,175 @@
  * For more details see the file COPYING.
  */
 
-#include <config.h>
+#define BLACK  49
+#define WHITE  79
+#define BLANK   1
+
+#include "config.h"
 #include <gnome.h>
+#include <glib.h>
+#include <gconf/gconf-client.h>
+#include <stdio.h>
+#include <fcntl.h>
 #include <string.h>
-#include <gconf/gconf-client.h>
-#include <games-gconf.h>
-#include <games-frame.h>
+
+#include <games-stock.h>
+#include <games-preimage.h>
+#include <games-sound.h>
 #include <games-files.h>
-#include <games-sound.h>
-
 #include "properties.h"
-#include "gnothello.h"
-#include "othello.h"
 
-#define KEY_TILESET "/apps/iagno/tileset"
-#define KEY_BLACK_LEVEL "/apps/iagno/black_level"
-#define KEY_WHITE_LEVEL "/apps/iagno/white_level"
-#define KEY_QUICK_MOVES "/apps/iagno/quick_moves"
-#define KEY_ANIMATE "/apps/iagno/animate"
-#define KEY_ANIMATE_STAGGER "/apps/iagno/animate_stagger"
-#define KEY_SHOW_GRID "/apps/iagno/show_grid"
-#define KEY_FLIP_FINAL_RESULTS "/apps/iagno/flip_final_results"
-#define KEY_SOUND "/apps/iagno/sound"
+static const char manager_definition[] = {
+  "<ui>"
+    "  <menubar name='MenuBar'>"
+    "    <menu name='GameMenu'      action='game_menu'>"
+    "      <menuitem name='New'     action='new'/>"
+    "      <menuitem name='Network' action='network'/>"
+    "      <menuitem name='Playerlist'  action='playerlist'/>"
+    "      <menuitem name='Chat'    action='chat'/>"
+    "      <menuitem name='Leave'   action='leave'/>"
+    "      <separator/>"
+    "      <menuitem name='Head'    action='head'/>"
+    "      <menuitem name='Back'    action='back'/>"
+    "      <menuitem name='Forward' action='forward'/>"
+    "      <menuitem name='Last'    action='last'/>"
+    "      <separator/>"
+    "      <menuitem name='Hint'    action='hint'/>"
+    "      <menuitem name='Redo'    action='redo'/>"
+    "      <separator/>"
+    "      <menuitem name='Open'    action='open'/>"
+    "      <menuitem name='Save'    action='save'/>"
+    "      <separator/>"
+    "      <menuitem name='Quit_Game'   action='quit'/>"
+    "    </menu>"
+    "    <menu name='SettingsMenu'      action='settings_menu'>"
+    "      <menuitem name='Preferences' action='preferences'/>"
+    "    </menu>"
+    "    <menu name='HelpMenu'          action='help_menu'>"
+    "      <menuitem name='Contents'    action='help'/>"
+    "      <menuitem name='About'       action='about'/>"
+    "    </menu>"
+    "  </menubar>"
+    "  <toolbar  name='ToolBar'>"
+    "      <toolitem name='Head'    action='head'/>"
+    "      <toolitem name='Back'    action='back'/>"
+    "      <toolitem name='Forward' action='forward'/>"
+    "      <toolitem name='Last'    action='last'/>"
+    "      <toolitem name='Hint'    action='hint'/>"
+    "      <toolitem name='Redo'    action='redo'/>"
+    "      <toolitem name='New'     action='new'/>"
+    "      <toolitem name='Quit'    action='quit'/>"
+    "  </toolbar>"
+ "</ui>"
+};
 
+static GtkActionEntry entries[MAX_ACTIONS] = {
+  {"game_menu",  NULL, N_("_Game")},
+  {"new",        GAMES_STOCK_NEW_GAME,      NULL, "<CTRL>N", "New Game", NULL},
+  {"network",    GAMES_STOCK_NETWORK_GAME,  NULL, NULL,      NULL,   NULL},
+  {"playerlist", NULL, N_("_Player list"),        NULL,      NULL,   NULL},
+  {"chat",       NULL, N_("_Chat Window"),        NULL,      NULL,   NULL},
+  {"leave",      GAMES_STOCK_NETWORK_LEAVE, NULL, NULL,      NULL,   NULL},
+  {"head",       GTK_STOCK_GOTO_FIRST,      NULL, "<CTRL>T", "Top",  NULL},
+  {"back",       GTK_STOCK_GO_BACK,         NULL, "<CTRL>B", "Back", NULL},
+  {"forward",    GTK_STOCK_GO_FORWARD,      NULL, "<CTRL>F", "Forward", NULL},
+  {"last",       GTK_STOCK_GOTO_LAST,       NULL, "<CTRL>L", "Last", NULL},
+  {"hint",       GAMES_STOCK_HINT,          NULL, "<CTRL>H", "Hint", NULL},
+  {"redo",       GAMES_STOCK_REDO_MOVE,     NULL, "<CTRL>R", "Redo", NULL},
+  {"open",       GTK_STOCK_OPEN,            NULL, "<CTRL>O", NULL,   NULL},
+  {"save",       GTK_STOCK_SAVE,            NULL, "<CTRL>S", NULL,   NULL},
+  {"quit",       GTK_STOCK_QUIT,            NULL, "<CTRL>Q", "Quit", NULL},
+  {"settings_menu", NULL, N_("_Settings")},
+  {"preferences", GTK_STOCK_PREFERENCES,    NULL, "<CTRL>P", NULL,   NULL},
+  {"help_menu",  NULL, N_("_Help")},
+  {"help",       GAMES_STOCK_CONTENTS,      NULL, NULL,      NULL,   NULL},
+  {"about",      GTK_STOCK_ABOUT,           NULL, "<CTRL>A", NULL,   NULL}
+};
 
-extern GtkWidget *window;
-extern guint black_computer_level;
-extern guint white_computer_level;
-extern guint computer_speed;
-extern guint black_computer_id;
-extern guint white_computer_id;
-extern gchar *tile_set;
-extern gchar *tile_set_tmp;
-extern gint8 pixmaps[8][8];
-extern gint animate;
-extern gint animate_stagger;
-extern gint flip_pixmaps_id;
-extern gint flip_final;
-extern gint grid;
-gint sound;
+static gchar     *keys[MAX_KEYS];
+static GtkSignalFunc signalfuncs[MAX_SIGNALFUNCS];
+static guint     size;
+static guint     max_depth;
 
-guint t_black_computer_level;
-guint t_white_computer_level;
-gint t_animate;
-gint t_quick_moves;
-gint t_animate_stagger;
-gint t_flip_final;
-gint t_grid;
+static GtkWidget *drawing_area;
+static GtkWidget *menubar;
+static GtkWidget *toolbar;
+static GtkWidget *statusbar;
+static GdkGC     *gridGC[2] = { 0 };
+static GdkColor  bg_color[3] = {
+  {0, 0, 0, 0},			/* background color */
+  {0xffffffff, 0xffff, 0xffff, 0xffff},	/* grid color */
+  {0, 0, 0, 0}			/* tmp color  */
+};
 
-static GamesFileList *theme_file_list = NULL;
+static guint     board_width;
+static guint     board_height;
+static gboolean  none_animation;
+static gboolean  use_quick_moves;
+static gboolean  mute;
+static gchar     *tile_set;
+static gchar     *bg_color_name;
+static guint     flip_speed;
+static GdkPixmap *buffer_pixmap = NULL;
+static GdkPixmap *tiles_pixmap = NULL;
+static guint     context_id = 0;
+static guint     flip_pixmaps_id = 0;
+static guint     timer_id = 0;
+static guint     redraw_id = 0;
 
-static void apply_changes (void);
+static GtkActionGroup *action_group;
+static GtkUIManager *manager;
+static GtkAction *network_action;
+static GtkAction *playerlist_action;
+static GtkAction *chat_action;
+static GtkAction *leave_action;
+static GtkAction *head_action;
+static GtkAction *back_action;
+static GtkAction *forward_action;
+static GtkAction *last_action;
+static GtkAction *redo_action;
+static GtkAction *hint_action;
+static GtkAction *open_action;
 
-/*
- * FIXME:
- * 	This was only a quick port to gconf.
- *	It doesn't abide by the HIG.
- */
+static guint     t_computer_level[2];
+static gboolean  t_options[MAX_OPTIONS];
+static gchar     *t_tile_set;
+static gchar     *t_bg_color_name;
 
-static gint
+gint8            pixmaps[MAX_SIZE][MAX_SIZE];
+gint8            board[MAX_SIZE][MAX_SIZE];
+
+GtkWidget        *window;
+GtkWidget        *properties_dialog = NULL;
+GtkWidget        *file_open_dialog;
+GtkWidget        *file_save_dialog;
+GtkWidget        *notebook;
+GtkWidget        *hpaned;
+GtkWidget        *counter;
+GtkWidget        *score[4];
+GtkWidget        *entry;
+GTimer           *timer[2];
+
+guint            tile_width;
+guint            tile_height;
+guint            computer_level[2];
+gboolean         hide_valid_squares;
+gboolean         hide_last_move;
+gboolean         hide_final_results;
+gboolean         hide_toolbar;
+guint            computer_speed;
+gboolean         game_in_progress;
+gboolean         play_sound = FALSE;
+gboolean         gameover = FALSE;
+gboolean         flip_tiles = FALSE;
+guint            flip_final_id = 0;
+guint            t_move_count;
+guint            t_whose_turn;
+guint            t_bcount;
+guint            t_wcount;
+gboolean         ggz_network_mode = FALSE;
+
+gint
 clamp_int (gint input, gint low, gint high)
 {
   if (input < low)
@@ -90,625 +198,1162 @@
 }
 
 void
-load_properties (void)
+init_interface (guint t_size, guint t_max_depth, gchar ** t_keys,
+		GCallback * callbacks, GtkSignalFunc * t_signalfuncs)
 {
-  GConfClient *client;
-  GError *error = NULL;
+  guint i;
 
-  client = gconf_client_get_default ();
-  if (!games_gconf_sanity_check_string (client, KEY_TILESET)) {
-    exit (1);
-  }
-  black_computer_level =
-    gconf_client_get_int (client, KEY_BLACK_LEVEL, &error);
-  if (error) {
-    g_warning (G_STRLOC ": gconf error: %s\n", error->message);
-    g_error_free (error);
-    error = NULL;
-  }
-  black_computer_level = clamp_int (black_computer_level, 0, 3);
+  size = t_size;
+  max_depth = t_max_depth;
 
-  white_computer_level =
-    gconf_client_get_int (client, KEY_WHITE_LEVEL, &error);
-  if (error) {
-    g_warning (G_STRLOC ": gconf error: %s\n", error->message);
-    g_error_free (error);
-    error = NULL;
-  }
-  white_computer_level = clamp_int (white_computer_level, 0, 3);
+  for (i = 0; i < MAX_KEYS; i++)
+    keys[i] = t_keys[i];
 
-  if (gconf_client_get_bool (client, KEY_QUICK_MOVES, &error))
-    computer_speed = COMPUTER_MOVE_DELAY / 2;
-  else
-    computer_speed = COMPUTER_MOVE_DELAY;
+  for (i = 0; i < MAX_ACTIONS; i++)
+    if (callbacks[i])
+      entries[i].callback = (GCallback) callbacks[i];
 
-  if (error) {
-    g_warning (G_STRLOC ": gconf error: %s\n", error->message);
-    g_error_free (error);
-    error = NULL;
-  }
+  for (i = 0; i < MAX_SIGNALFUNCS; i++)
+    signalfuncs[i] = (GtkSignalFunc) t_signalfuncs[i];
+};
 
-  if (tile_set)
-    g_free (tile_set);
+/******* for main window *******/
 
-  tile_set = gconf_client_get_string (client, KEY_TILESET, &error);
-  if (error) {
-    g_warning (G_STRLOC ": gconf error: %s\n", error->message);
-    g_error_free (error);
-    error = NULL;
-  }
-  if (tile_set == NULL)
-    tile_set = g_strdup ("classic.png");
+static void
+copy_pixmaps (void)
+{
+  guint i, j;
 
-  animate = gconf_client_get_int (client, KEY_ANIMATE, &error);
-  if (error) {
-    g_warning (G_STRLOC ": gconf error: %s\n", error->message);
-    g_error_free (error);
-    error = NULL;
-  }
-  animate = clamp_int (animate, 0, 2);
+  for (i = 0; i < size; i++)
+    for (j = 0; j < size; j++)
+      pixmaps[i][j] = board[i][j];
+}
 
-  animate_stagger =
-    gconf_client_get_bool (client, KEY_ANIMATE_STAGGER, &error);
-  if (error) {
-    g_warning (G_STRLOC ": gconf error: %s\n", error->message);
-    g_error_free (error);
-    error = NULL;
-  }
+static void
+clear_board (void)
+{
+  guint i, j;
 
-  sound = gconf_client_get_bool (client, KEY_SOUND, &error);
-  if (error) {
-    g_warning (G_STRLOC ": gconf error: %s\n", error->message);
-    g_error_free (error);
-    error = NULL;
-  }
+  for (i = 0; i < size; i++)
+    for (j = 0; j < size; j++)
+      board[i][j] = BLANK;
 
-  grid = gconf_client_get_bool (client, KEY_SHOW_GRID, &error);
-  if (error) {
-    g_warning (G_STRLOC ": gconf error: %s\n", error->message);
-    g_error_free (error);
-    error = NULL;
-  }
+  game_in_progress = FALSE;
+  t_move_count = 0;
+  t_whose_turn = 0;
+  t_bcount = 0;
+  t_wcount = 0;
+}
 
-  flip_final = gconf_client_get_bool (client, KEY_FLIP_FINAL_RESULTS, &error);
-  if (error) {
-    g_warning (G_STRLOC ": gconf error: %s\n", error->message);
-    g_error_free (error);
-    error = NULL;
+static void
+set_board_size (void)
+{
+  gint depth = -1;
+
+  board_width = clamp_int (board_width, BOARD_MIN, BOARD_W_MAX);
+  board_height = clamp_int (board_height, BOARD_MIN, BOARD_H_MAX);
+  tile_width = (board_width - GRIDWIDTH * (size - 1)) / size;
+  tile_height = (board_height - GRIDWIDTH * (size - 1)) / size;
+  board_width = tile_width * size + GRIDWIDTH * (size - 1);
+  board_height = tile_height * size + GRIDWIDTH * (size - 1);
+  save_properties ();
+
+  gtk_widget_set_size_request (drawing_area, board_width, board_height);
+
+  if (buffer_pixmap) {
+    g_object_unref (buffer_pixmap);
+    depth = gdk_drawable_get_depth ((GdkDrawable *) drawing_area->window);
   }
+  buffer_pixmap = gdk_pixmap_new (drawing_area->window,
+				  board_width, board_height, depth);
+}
 
-  switch (animate) {
-  case 0:
-    flip_pixmaps_id = g_timeout_add (100, flip_pixmaps, &error);
-    break;
-  case 1:
-    flip_pixmaps_id =
-      g_timeout_add (PIXMAP_FLIP_DELAY * 8, flip_pixmaps, NULL);
-    break;
-  default:
-  case 2:
-    flip_pixmaps_id = g_timeout_add (PIXMAP_FLIP_DELAY, flip_pixmaps, NULL);
-    break;
+static void
+set_bg_color (void)
+{
+  gint i;
+
+  gdk_color_parse (bg_color_name, &bg_color[0]);
+  gdk_colormap_alloc_color (gtk_widget_get_colormap (drawing_area),
+			    &bg_color[0], FALSE, TRUE);
+
+  for (i = 0; i < 2; i++) {
+    if (gridGC[i])
+      g_object_unref (gridGC[i]);
+    gridGC[i] = gdk_gc_new (drawing_area->window);
+    gdk_gc_copy (gridGC[i], drawing_area->style->bg_gc[0]);
+    gdk_gc_set_background (gridGC[i], &bg_color[i]);
+    gdk_gc_set_foreground (gridGC[i], &bg_color[i]);
   }
 
-  g_object_unref (client);
+  gdk_draw_rectangle (buffer_pixmap, gridGC[0], TRUE, 0, 0,
+		      board_width, board_height);
 }
 
-static void
-reset_properties (void)
+static GamesPreimage *
+load_image (gchar * tileset)
 {
-  GConfClient *client;
   GError *error = NULL;
+  gchar *fname;
+  gchar *pathname;
 
-  client = gconf_client_get_default ();
+  fname = g_build_filename ("iagno", tileset, NULL);
+  pathname = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_APP_PIXMAP,
+					fname, TRUE, NULL);
+  g_free (fname);
+  return games_preimage_new_from_file (pathname, &error);
+}
 
-  black_computer_level =
-    gconf_client_get_int (client, KEY_BLACK_LEVEL, &error);
-  if (error) {
-    g_warning (G_STRLOC ": gconf error: %s\n", error->message);
-    g_error_free (error);
-    error = NULL;
-  }
-  t_black_computer_level = black_computer_level
-    = clamp_int (black_computer_level, 0, 3);
+static void
+load_pixmaps (void)
+{
+  GamesPreimage *t_image;
+  GdkPixbuf *image;
+  gint depth = -1;
+  GdkGC *gc;
 
-  white_computer_level =
-    gconf_client_get_int (client, KEY_WHITE_LEVEL, &error);
-  if (error) {
-    g_warning (G_STRLOC ": gconf error: %s\n", error->message);
-    g_error_free (error);
-    error = NULL;
+  t_image = load_image (tile_set);
+  if (!t_image) {
+    if (tile_set)
+      g_free (tile_set);
+    tile_set = g_strdup ("sun_and_star.svg");
+    t_image = load_image (tile_set);
+    if (!t_image) {
+      g_print ("Could not find \'%s\' pixmap file\n",
+	       "iagno/sun_and_star.svg");
+      exit (1);
+    }
+    save_properties ();
+    reset_properties ();
   }
-  t_white_computer_level = white_computer_level
-    = clamp_int (white_computer_level, 0, 3);
 
-  t_quick_moves = gconf_client_get_bool (client, KEY_QUICK_MOVES, &error);
-  if (error) {
-    g_warning (G_STRLOC ": gconf error: %s\n", error->message);
-    g_error_free (error);
-    error = NULL;
+  image = games_preimage_render (t_image, tile_width * 8, tile_height * 4);
+
+  if (tiles_pixmap) {
+    g_object_unref (tiles_pixmap);
+    depth = gdk_drawable_get_depth ((GdkDrawable *) drawing_area->window);
   }
+  tiles_pixmap = gdk_pixmap_new (drawing_area->window,
+				 tile_width * 8, tile_height * 4, depth);
 
-  if (tile_set_tmp)
-    g_free (tile_set_tmp);
+  gc = gdk_gc_new (tiles_pixmap);
+  gdk_gc_set_foreground (gc, &bg_color[0]);
+  gdk_gc_set_background (gc, &bg_color[0]);
 
-  tile_set_tmp = gconf_client_get_string (client, KEY_TILESET, &error);
-  if (error) {
-    g_warning (G_STRLOC ": gconf error: %s\n", error->message);
-    g_error_free (error);
-    error = NULL;
-  }
-  if (tile_set_tmp == NULL)
-    tile_set_tmp = g_strdup ("classic.png");
+  gdk_draw_rectangle (tiles_pixmap, gc, TRUE, 0, 0,
+		      tile_width * 8, tile_height * 4);
+  gdk_draw_pixbuf (tiles_pixmap, gc, image, 0, 0, 0, 0,
+		   tile_width * 8, tile_height * 4, GDK_RGB_DITHER_NONE, 0,
+		   0);
 
-  t_animate = animate;
-  t_animate_stagger = animate_stagger;
-  t_grid = grid;
-  t_flip_final = flip_final;
-
-  g_object_unref (client);
+  g_object_unref (t_image);
+  g_object_unref (image);
 }
 
 static void
-black_computer_level_select (GtkWidget * widget, gpointer data)
+gui_draw_pixmap_buffer (guint x, guint y, guint which)
 {
-  if ((GPOINTER_TO_INT (data) != t_black_computer_level)
-      && (GTK_TOGGLE_BUTTON (widget)->active)) {
-    t_black_computer_level = GPOINTER_TO_INT (data);
-    apply_changes ();
-  }
+  gdk_draw_drawable (buffer_pixmap, gridGC[0], tiles_pixmap,
+		     tile_width * (which % 8), tile_height * (which / 8),
+		     (tile_width + GRIDWIDTH) * x,
+		     (tile_height + GRIDWIDTH) * y, tile_width, tile_height);
 }
 
 static void
-white_computer_level_select (GtkWidget * widget, gpointer data)
+gui_draw_pixmap (guint x, guint y, guint which)
 {
-  if ((GPOINTER_TO_INT (data) != t_white_computer_level)
-      && (GTK_TOGGLE_BUTTON (widget)->active)) {
-    t_white_computer_level = GPOINTER_TO_INT (data);
-    apply_changes ();
-  }
+  gui_draw_pixmap_buffer (x, y, which);
+  gdk_draw_drawable (drawing_area->window, gridGC[0], tiles_pixmap,
+		     tile_width * (which % 8), tile_height * (which / 8),
+		     (tile_width + GRIDWIDTH) * x,
+		     (tile_height + GRIDWIDTH) * y, tile_width, tile_height);
 }
 
 static void
-sound_select (GtkWidget * widget, gpointer data)
+gui_draw_arc (guint x, guint y)
 {
-  sound = GTK_TOGGLE_BUTTON (widget)->active;
-  apply_changes ();
+  gdk_draw_arc ((GdkDrawable *) drawing_area->window, gridGC[1], TRUE,
+		(tile_width + GRIDWIDTH) * x + tile_width * 13 / 16,
+		(tile_height + GRIDWIDTH) * y + tile_height * 13 / 16,
+		tile_width / 8, tile_height / 8, 0, 64 * 360);
+
+  gdk_draw_arc ((GdkDrawable *) buffer_pixmap, gridGC[1], TRUE,
+		(tile_width + GRIDWIDTH) * x + tile_width * 13 / 16,
+		(tile_height + GRIDWIDTH) * y + tile_height * 13 / 16,
+		tile_width / 8, tile_height / 8, 0, 64 * 360);
 }
 
 static void
-quick_moves_select (GtkWidget * widget, gpointer data)
+gui_draw_grid (void)
 {
-  if (GTK_TOGGLE_BUTTON (widget)->active)
-    t_quick_moves = 1;
-  else
-    t_quick_moves = 0;
-  apply_changes ();
+  guint i;
+
+  gdk_gc_set_line_attributes (gridGC[1], GRIDWIDTH, GDK_LINE_ON_OFF_DASH,
+			      GDK_CAP_BUTT, GDK_JOIN_MITER);
+
+  for (i = tile_height; i < board_height; i += tile_height + GRIDWIDTH)
+    gdk_draw_line (buffer_pixmap, gridGC[1], 0, i, board_width, i);
+  for (i = tile_width; i < board_width; i += tile_width + GRIDWIDTH)
+    gdk_draw_line (buffer_pixmap, gridGC[1], i, 0, i, board_height);
 }
 
-static void
-flip_final_select (GtkWidget * widget, gpointer data)
+void
+gui_status (void)
 {
-  if (GTK_TOGGLE_BUTTON (widget)->active)
-    t_flip_final = 1;
-  else
-    t_flip_final = 0;
-  apply_changes ();
+  gchar message[5];
+
+  sprintf (message, "%.2d", t_move_count);
+  gtk_label_set_text (GTK_LABEL (counter), message);
+  sprintf (message, "%.2d", t_bcount);
+  gtk_label_set_text (GTK_LABEL (score[0]), message);
+  sprintf (message, "%.2d", t_wcount);
+  gtk_label_set_text (GTK_LABEL (score[1]), message);
 }
 
+gboolean
+redraw_board (gpointer user_data)
+{
+  gint i, j, state, which;
+
+  load_pixmaps ();
+  copy_pixmaps ();
+
+  for (i = 0; i < size; i++)
+    for (j = 0; j < size; j++) {
+      state = 0;
+      which = (gint) pixmaps[i][j];
+      if (which < 0) {
+	state = -1;
+	which = -which;
+      }
+      if (which == BLANK)
+	which = 0;
+      else
+	which -= BLACK - 1;
+      gui_draw_pixmap_buffer (j, i, which);
+      if (state < 0)
+	gui_draw_arc (j, i);
+    }
+  gtk_widget_queue_draw_area (drawing_area, 0, 0, board_width, board_height);
+
+  gui_status ();
+  redraw_id = 0;
+  return FALSE;
+}
+
 static void
-animate_stagger_select (GtkWidget * widget, gpointer data)
+set_redraw (void)
 {
-  if (GTK_TOGGLE_BUTTON (widget)->active)
-    t_animate_stagger = 1;
+  if (redraw_id)
+    g_source_remove (redraw_id);
+
+  redraw_id = g_timeout_add (500, (GSourceFunc) redraw_board, NULL);
+}
+
+void
+refresh_board (void)
+{
+  if (!hide_toolbar)
+    gtk_widget_show (toolbar);
   else
-    t_animate_stagger = 0;
-  apply_changes ();
+    gtk_widget_hide (toolbar);
+
+  set_board_size ();
+  set_bg_color ();
+  gui_draw_grid ();
+  set_redraw ();
 }
 
 static void
-grid_select (GtkWidget * widget, gpointer data)
+sprint_time (gchar *message, GTimer *timer)
 {
-  if (GTK_TOGGLE_BUTTON (widget)->active)
-    t_grid = 1;
-  else
-    t_grid = 0;
-  apply_changes ();
+  gint mm, ss;
+
+  ss = (gint) g_timer_elapsed (timer, NULL);
+  mm = ss / 60;
+  ss -= mm * 60;
+  sprintf (message, "%.2d:%.2d", mm, ss);
 }
 
 static void
-animate_select (GtkWidget * widget, gpointer data)
+gui_timer (void)
 {
-  if (GTK_TOGGLE_BUTTON (widget)->active) {
-    t_animate = GPOINTER_TO_INT (data);
+  gchar message[9];
+  guint i;
+
+  for (i = 0; i < 2; i++) {
+    sprint_time (message, timer[i]);
+    gtk_label_set_text (GTK_LABEL (score[i + 2]), message);
   }
-  apply_changes ();
 }
 
-static void
-save_properties (void)
+void
+start_timer (void)
 {
-  GConfClient *client;
+  gui_timer ();
 
-  client = gconf_client_get_default ();
+  if (timer_id)
+    g_source_remove (timer_id);
+  timer_id = g_timeout_add (500, (GSourceFunc) gui_timer, NULL);
+}
 
-  gconf_client_set_int (client, KEY_BLACK_LEVEL, black_computer_level, NULL);
-  gconf_client_set_int (client, KEY_WHITE_LEVEL, white_computer_level, NULL);
+void
+continue_timer (void)
+{
+  if (game_in_progress)
+    g_timer_continue (timer[PLAYER2NUMBER (t_whose_turn)]);
+}
 
-  gconf_client_set_bool (client, KEY_QUICK_MOVES, t_quick_moves, NULL);
+void
+stop_timer (void)
+{
+  if (game_in_progress)
+    g_timer_stop (timer[PLAYER2NUMBER (t_whose_turn)]);
+}
 
-  gconf_client_set_string (client, KEY_TILESET, tile_set_tmp, NULL);
+void
+reset_timer (void)
+{
+  guint i;
 
-  gconf_client_set_int (client, KEY_ANIMATE, animate, NULL);
+  if (timer_id)
+    g_source_remove (timer_id);
+  timer_id = 0;
+  for (i = 0; i < 2; i++) {
+    g_timer_start (timer[i]);
+    g_timer_stop (timer[i]);
+  }
 
-  gconf_client_set_bool (client, KEY_ANIMATE_STAGGER, animate_stagger, NULL);
-  gconf_client_set_bool (client, KEY_SHOW_GRID, grid, NULL);
-  gconf_client_set_bool (client, KEY_FLIP_FINAL_RESULTS, flip_final, NULL);
-  gconf_client_set_bool (client, KEY_SOUND, sound, NULL);
+  gui_timer ();
 }
 
-static void
-apply_changes (void)
+void
+gui_message (gchar *message)
 {
-  guint i, j;
+  if (context_id)
+    gtk_statusbar_pop (GTK_STATUSBAR (statusbar), context_id);
+  context_id =
+    gtk_statusbar_get_context_id (GTK_STATUSBAR (statusbar), message);
+  gtk_statusbar_push (GTK_STATUSBAR (statusbar), context_id, message);
+}
 
-  black_computer_level = t_black_computer_level;
-  white_computer_level = t_white_computer_level;
+void
+gui_entry (gchar *message)
+{
+  gtk_entry_set_text (GTK_ENTRY (entry), message);
+}
 
-  if (black_computer_id) {
-    g_source_remove (black_computer_id);
-    black_computer_id = 0;
+static void
+check_sound (void)
+{
+  if (play_sound) {
+    games_sound_play ("flip-piece");
+    play_sound = FALSE;
   }
-
-  if (white_computer_id) {
-    g_source_remove (white_computer_id);
-    white_computer_id = 0;
+  if (gameover) {
+    games_sound_play ("gameover");
+    gameover = FALSE;
   }
+}
 
-  if (t_quick_moves)
-    computer_speed = COMPUTER_MOVE_DELAY / 2;
-  else
-    computer_speed = COMPUTER_MOVE_DELAY;
+static gboolean
+flip_pixmaps (gpointer data)
+{
+  guint i, j, state;
+  gint which;
 
-  if (strcmp (tile_set, tile_set_tmp)) {
-    g_free (tile_set);
-    tile_set = g_strdup (tile_set_tmp);
-    load_pixmaps ();
-    set_bg_color ();
-    for (i = 0; i < 8; i++)
-      for (j = 0; j < 8; j++)
-	if (pixmaps[i][j] >= BLACK_TURN && pixmaps[i][j] <= WHITE_TURN)
-	  gui_draw_pixmap_buffer (pixmaps[i][j], i, j);
+  check_sound ();
+
+  if (!flip_tiles || redraw_id)
+    return TRUE;
+  flip_tiles = FALSE;
+
+  for (i = 0; i < size; i++)
+    for (j = 0; j < size; j++) {
+      if (pixmaps[i][j] == board[i][j])
+	continue;
+
+      if (pixmaps[i][j] < board[i][j] && pixmaps[i][j] > BLANK) {
+	if (none_animation) {
+	  if (pixmaps[i][j] == BLACK)
+	    pixmaps[i][j] = WHITE;
+	  else
+	    pixmaps[i][j]++;
+	} else
+	  pixmaps[i][j]++;
+      } else if (pixmaps[i][j] > board[i][j] && board[i][j] > BLANK) {
+	if (none_animation) {
+	  if (pixmaps[i][j] == WHITE)
+	    pixmaps[i][j] = BLACK;
+	  else
+	    pixmaps[i][j]--;
+	} else
+	  pixmaps[i][j]--;
+      } else {
+	if (pixmaps[i][j] < -BLANK && board[i][j] > BLANK)
+	  pixmaps[i][j] *= -1;
 	else
-	  gui_draw_pixmap_buffer (0, i, j);
-    gui_draw_grid ();
+	  pixmaps[i][j] = board[i][j];
+      }
+
+      state = 0;
+      which = pixmaps[i][j];
+      if (which < 0) {
+	which *= -1;
+	state = 1;
+    }
+    if (which == BLANK)
+	which = 0;
+    else
+	which = clamp_int (which, BLACK, WHITE) - BLACK + 1;
+
+    gui_draw_pixmap (j, i, which);
+
+    if (state)
+	gui_draw_arc (j, i);
+    flip_tiles = TRUE;
   }
 
-  animate = t_animate;
+  return TRUE;
+}
 
-  if (flip_pixmaps_id) {
+static void
+set_flip_pixmaps_id (void)
+{
+  if (flip_pixmaps_id)
     g_source_remove (flip_pixmaps_id);
-    flip_pixmaps_id = 0;
-  }
 
-  switch (animate) {
-  case 0:
+  if (none_animation)
     flip_pixmaps_id = g_timeout_add (100, flip_pixmaps, NULL);
-    break;
-  case 1:
-    flip_pixmaps_id = g_timeout_add (PIXMAP_FLIP_DELAY * 8,
-				     flip_pixmaps, NULL);
-    break;
-  case 2:
-    flip_pixmaps_id = g_timeout_add (PIXMAP_FLIP_DELAY, flip_pixmaps, NULL);
-    break;
-  }
+  else
+    flip_pixmaps_id = g_timeout_add (flip_speed, flip_pixmaps, NULL);
+}
 
-  animate_stagger = t_animate_stagger;
+gboolean
+flip_final_results (gpointer data)
+{
+  guint i = 0;
+  gint8 adder = 0;
 
-  flip_final = t_flip_final;
-
-  if (grid != t_grid) {
-    grid = t_grid;
-    gui_draw_grid ();
+  for (; i < t_bcount; i++) {
+    board[i / size][i % size] = BLACK;
+    if (pixmaps[i / size][i % size] == BLANK)
+      pixmaps[i / size][i % size] = WHITE;
+    if (pixmaps[i / size][i % size] == WHITE) {
+      pixmaps[i / size][i % size] += adder;
+      adder++;
+    }
   }
 
-  games_sound_enable (sound);
+  for (; i < size * size - t_wcount; i++)
+    board[i / size][i % size] = BLANK;
 
-  check_computer_players ();
+  for (; i < size * size; i++) {
+    board[i / size][i % size] = WHITE;
+    if (pixmaps[i / size][i % size] == BLANK)
+      pixmaps[i / size][i % size] = BLACK;
+    if (pixmaps[i / size][i % size] == BLACK) {
+      pixmaps[i / size][i % size] -= adder;
+      adder++;
+    }
+  }
 
-  save_properties ();
+  flip_tiles = TRUE;
+  flip_final_id = 0;
+  return FALSE;
 }
 
-static gboolean
-close_cb (GtkWidget * widget)
+static void
+network_gui_update (void)
 {
-  gtk_widget_hide (widget);
+#ifdef GGZ_CLIENT
+  gtk_action_set_visible (network_action, !ggz_network_mode);
+  gtk_action_set_visible (playerlist_action, ggz_network_mode);
+  gtk_action_set_visible (chat_action, ggz_network_mode);
+  gtk_action_set_visible (leave_action, ggz_network_mode);
+#else
+  gtk_action_set_visible (network_action, FALSE);
+  gtk_action_set_visible (playerlist_action, FALSE);
+  gtk_action_set_visible (chat_action, FALSE);
+  gtk_action_set_visible (leave_action, FALSE);
+#endif
+  gtk_action_set_visible (head_action, !ggz_network_mode);
+  gtk_action_set_visible (back_action, !ggz_network_mode);
+  gtk_action_set_visible (forward_action, !ggz_network_mode);
+  gtk_action_set_visible (last_action, !ggz_network_mode);
+  gtk_action_set_visible (hint_action, !ggz_network_mode);
+  gtk_action_set_visible (redo_action, !ggz_network_mode);
+  gtk_action_set_visible (open_action, !ggz_network_mode);
+}
 
-  return TRUE;
+void
+on_quit_activate (GtkMenuItem *menuitem, gpointer user_data)
+{
+  gtk_main_quit ();
 }
 
 void
-set_selection (GtkWidget * widget, gpointer data)
+on_properties_activate (GtkMenuItem *menuitem, gpointer user_data)
 {
-  gchar *filename;
+  if (properties_dialog)
+    return;
+  properties_dialog = create_properties_dialog ();
+  gtk_widget_show (properties_dialog);
+}
 
-  if (tile_set_tmp)
-    g_free (tile_set_tmp);
+gboolean
+on_drawing_area_expose_event (GtkWidget *widget,
+			      GdkEventExpose *event, gpointer user_data)
+{
+  gdk_draw_drawable (drawing_area->window, gridGC[0], buffer_pixmap,
+		     event->area.x, event->area.y,
+		     event->area.x, event->area.y,
+		     event->area.width, event->area.height);
+  return FALSE;
+}
 
-  filename = games_file_list_get_nth (theme_file_list,
-				      gtk_combo_box_get_active (GTK_COMBO_BOX
-								(widget)));
+gboolean
+on_drawing_area_configure_event (GtkWidget *widget,
+				 GdkEventConfigure *event,
+				 gpointer user_data)
+{
+  board_width  = (event->width * 99) / 100;
+  board_height = (event->height * 99) / 100;
 
-  tile_set_tmp = g_strdup (filename);
+  refresh_board ();
+  return FALSE;
+}
 
-  apply_changes ();
+static void
+set_actions (void)
+{
+  network_action    = gtk_action_group_get_action (action_group, "network");
+  playerlist_action = gtk_action_group_get_action (action_group, "playerlist");
+  chat_action       = gtk_action_group_get_action (action_group, "chat");
+  leave_action      = gtk_action_group_get_action (action_group, "leave");
+  head_action       = gtk_action_group_get_action (action_group, "head");
+  back_action       = gtk_action_group_get_action (action_group, "back");
+  forward_action    = gtk_action_group_get_action (action_group, "forward");
+  last_action       = gtk_action_group_get_action (action_group, "last");
+  hint_action       = gtk_action_group_get_action (action_group, "hint");
+  redo_action       = gtk_action_group_get_action (action_group, "redo");
+  open_action       = gtk_action_group_get_action (action_group, "open");
 }
 
-void
-free_str (GtkWidget * widget, void *data)
+GtkWidget *
+create_window (void)
 {
-  g_free (data);
+  const gchar *strs[] = {
+    N_("Dark:"),		/* 0 */
+    N_("Light:"),		/* 1 */
+    _("00"),			/* 2 */
+    _("00:00"),			/* 3 */
+  };
+
+  GtkWidget *window;
+  GtkWidget *vbox1;
+  GtkWidget *vbox3;
+  GtkWidget *hbox;
+  GtkWidget *label;
+  GtkAccelGroup *accel_group;
+
+  gint i, j;
+  gchar name[2] = { 0, 0 };
+  gchar *markup;
+
+  GError *error = NULL;
+
+  clear_board ();
+
+  accel_group = gtk_accel_group_new ();
+
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title (GTK_WINDOW (window), keys[13]);
+  g_signal_connect ((gpointer) window, "destroy",
+		    G_CALLBACK (on_quit_activate), NULL);
+
+  manager = gtk_ui_manager_new ();
+  gtk_ui_manager_add_ui_from_string (manager, manager_definition, -1, &error);
+  action_group = gtk_action_group_new ("ActionGroup");
+  gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
+  gtk_action_group_add_actions (action_group, entries, G_N_ELEMENTS (entries),
+				window);
+  gtk_ui_manager_insert_action_group (manager, action_group, 0);
+  gtk_window_add_accel_group (GTK_WINDOW (window),
+			      gtk_ui_manager_get_accel_group (manager));
+  set_actions ();
+
+  notebook = gtk_notebook_new ();
+  gtk_container_add (GTK_CONTAINER (window), notebook);
+  gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
+
+  vbox1 = gtk_vbox_new (FALSE, 0);
+  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox1, NULL);
+  gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), MAIN_PAGE);
+
+  menubar = gtk_ui_manager_get_widget (manager, "/MenuBar");
+  toolbar = gtk_ui_manager_get_widget (manager, "/ToolBar");
+  gtk_box_pack_start (GTK_BOX (vbox1), menubar, FALSE, FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox1), toolbar, FALSE, FALSE, 0);
+  gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS);
+  for (i = 0; i < 8; i++) {
+    gtk_tool_item_set_expand (gtk_toolbar_get_nth_item
+			      ((GtkToolbar *) toolbar, i), TRUE);
+    gtk_tool_item_set_homogeneous (gtk_toolbar_get_nth_item
+				   ((GtkToolbar *) toolbar, i), FALSE);
+  }
+
+  hbox = gtk_hbox_new (FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox1), hbox, TRUE, TRUE, 0);
+
+  label = gtk_label_new (_("  "));
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+  gtk_widget_set_size_request (label, 17, 17);
+
+  for (*name = 0x41; *name < 0x41 + size; (*name)++) {
+    label = gtk_label_new (name);
+    gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+    gtk_widget_set_size_request (label, -1, 17);
+    markup =
+      g_markup_printf_escaped ("<span foreground=\"red\">%s</span>", name);
+    gtk_label_set_markup_with_mnemonic ((GtkLabel *) label, markup);
+    g_free (markup);
+  }
+
+  hbox = gtk_hbox_new (FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox1), hbox, TRUE, TRUE, 0);
+
+  vbox3 = gtk_vbox_new (FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (hbox), vbox3, TRUE, TRUE, 0);
+
+  for (*name = 0x31; *name < 0x31 + size; (*name)++) {
+    label = gtk_label_new (name);
+    gtk_box_pack_start (GTK_BOX (vbox3), label, TRUE, TRUE, 0);
+    gtk_widget_set_size_request (label, 17, -1);
+    markup =
+      g_markup_printf_escaped ("<span foreground=\"red\">%s</span>", name);
+    gtk_label_set_markup_with_mnemonic ((GtkLabel *) label, markup);
+    g_free (markup);
+  }
+
+  drawing_area = gtk_drawing_area_new ();
+  /**** We do our own double-buffering. ****/
+  gtk_widget_set_double_buffered (drawing_area, FALSE);
+  gtk_widget_set_size_request (drawing_area, board_width, board_height);
+  gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
+  gtk_widget_set_events (drawing_area, GDK_BUTTON_PRESS_MASK);
+  g_signal_connect ((gpointer) drawing_area, "expose_event",
+		    G_CALLBACK (on_drawing_area_expose_event), NULL);
+  g_signal_connect ((gpointer) drawing_area, "configure_event",
+		    G_CALLBACK (on_drawing_area_configure_event), NULL);
+  g_signal_connect ((gpointer) drawing_area, "button_press_event",
+		    G_CALLBACK (signalfuncs[0]), NULL);
+
+  hbox = gtk_hbox_new (FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox1), hbox, FALSE, FALSE, 0);
+
+  counter = gtk_label_new (_("00"));
+  gtk_box_pack_start (GTK_BOX (hbox), counter, TRUE, TRUE, 0);
+
+  for (i = 0; i < 2; i++)
+    for (j = 0; j < 2; j++) {
+      label = gtk_label_new (strs[j]);
+      gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+      markup =
+	g_markup_printf_escaped ("<span foreground=\"blue\">%s</span>",
+				 strs[j]);
+      gtk_label_set_markup_with_mnemonic ((GtkLabel *) label, markup);
+      g_free (markup);
+      score[i * 2 + j] = gtk_label_new (strs[i + 2]);
+      gtk_box_pack_start (GTK_BOX (hbox), score[i * 2 + j], TRUE, TRUE, 0);
+    }
+
+  hbox = gtk_hbox_new (FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox1), hbox, TRUE, FALSE, 0);
+
+  statusbar = gtk_statusbar_new ();
+  gtk_box_pack_start (GTK_BOX (hbox), statusbar, TRUE, TRUE, 0);
+  gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (statusbar), FALSE);
+
+  entry = gtk_entry_new ();
+  gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
+  gtk_widget_set_events (entry, GDK_KEY_PRESS_MASK);
+  g_signal_connect ((gpointer) entry, "key_press_event",
+		    G_CALLBACK (signalfuncs[1]), NULL);
+
+  gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
+
+  gtk_widget_show_all (window);
+  gtk_widget_grab_focus (entry);
+
+  timer[0] = g_timer_new ();
+  timer[1] = g_timer_new ();
+  return window;
 }
 
-static GtkWidget *
-fill_menu (void)
+/******* for properties dialog *******/
+
+void
+load_properties (void)
 {
-  gchar *dname = NULL;
+  GConfClient *client;
 
-  /* FIXME: we need to check that both dname is valid and that
-   * games_file_list_new_images returns something. */
+  client = gconf_client_get_default ();
 
-  dname = gnome_program_locate_file (NULL,
-				     GNOME_FILE_DOMAIN_APP_PIXMAP,
-				     "iagno", FALSE, NULL);
+  if (tile_set)
+    g_free (tile_set);
+  if (bg_color_name)
+    g_free (bg_color_name);
 
-  if (theme_file_list)
-    g_object_unref (theme_file_list);
+  computer_level[0] =
+    clamp_int (gconf_client_get_int (client, keys[0], NULL), 0, max_depth - 1);
+  computer_level[1] =
+    clamp_int (gconf_client_get_int (client, keys[1], NULL), 0, max_depth - 1);
+  none_animation     = gconf_client_get_bool   (client, keys[2], NULL);
+  use_quick_moves    = gconf_client_get_bool   (client, keys[3], NULL);
+  hide_valid_squares = gconf_client_get_bool   (client, keys[4], NULL);
+  hide_last_move     = gconf_client_get_bool   (client, keys[5], NULL);
+  hide_final_results = gconf_client_get_bool   (client, keys[6], NULL);
+  mute               = gconf_client_get_bool   (client, keys[7], NULL);
+  hide_toolbar       = gconf_client_get_bool   (client, keys[8], NULL);
+  tile_set           = gconf_client_get_string (client, keys[9], NULL);
+  bg_color_name      = gconf_client_get_string (client, keys[10], NULL);
+  board_width        = gconf_client_get_int    (client, keys[11], NULL);
+  board_height       = gconf_client_get_int    (client, keys[12], NULL);
 
-  theme_file_list = games_file_list_new_images (dname, NULL);
-  g_free (dname);
+  if (!bg_color_name)
+    bg_color_name    = g_strdup (_("#000066660000"));
+  if (!board_width || !board_height)
+    board_width = board_height = BOARD_SIZE;
+  if (ggz_network_mode) {
+    computer_level[0] = 0;
+    computer_level[1] = 0;
+    hide_toolbar = TRUE;
+  }
 
-  games_file_list_transform_basename (theme_file_list);
+  g_object_unref (client);
+}
 
-  return games_file_list_create_widget (theme_file_list, tile_set,
-					GAMES_FILE_LIST_REMOVE_EXTENSION |
-					GAMES_FILE_LIST_REPLACE_UNDERSCORES);
+void
+save_properties (void)
+{
+  GConfClient *client;
+
+  client = gconf_client_get_default ();
+  if (!ggz_network_mode) {
+    gconf_client_set_int  (client, keys[0], computer_level[0],  NULL);
+    gconf_client_set_int  (client, keys[1], computer_level[1],  NULL);
+    gconf_client_set_bool (client, keys[8], hide_toolbar,       NULL);
+  }
+  gconf_client_set_bool   (client, keys[2], none_animation,     NULL);
+  gconf_client_set_bool   (client, keys[3], use_quick_moves,    NULL);
+  gconf_client_set_bool   (client, keys[4], hide_valid_squares, NULL);
+  gconf_client_set_bool   (client, keys[5], hide_last_move,     NULL);
+  gconf_client_set_bool   (client, keys[6], hide_final_results, NULL);
+  gconf_client_set_bool   (client, keys[7], mute,               NULL);
+  gconf_client_set_string (client, keys[9], tile_set,           NULL);
+  gconf_client_set_string (client, keys[10], bg_color_name,     NULL);
+  gconf_client_set_int    (client, keys[11], board_width,       NULL);
+  gconf_client_set_int    (client, keys[12], board_height,      NULL);
+
+  g_object_unref (client);
 }
 
 void
-show_properties_dialog (void)
+reset_properties (void)
 {
-  GtkWidget *notebook;
-  GtkWidget *hbox;
-  GtkWidget *label;
-  GtkWidget *label2;
-  GtkWidget *table;
-  GtkWidget *button;
-  GtkWidget *frame;
-  GtkWidget *vbox, *vbox2;
-  GtkWidget *propbox = NULL;
-  GtkWidget *option_menu;
+  if (t_tile_set)
+    g_free (t_tile_set);
+  if (t_bg_color_name)
+    g_free (t_bg_color_name);
 
-  if (propbox) {
-    gtk_window_present (GTK_WINDOW (propbox));
-    return;
+  t_computer_level[0] = computer_level[0];
+  t_computer_level[1] = computer_level[1];
+  t_options[0]        = none_animation;
+  t_options[1]        = use_quick_moves;
+  t_options[2]        = hide_valid_squares;
+  t_options[3]        = hide_last_move;
+  t_options[4]        = hide_final_results;
+  t_options[5]        = mute;
+  t_options[6]        = hide_toolbar;
+  t_tile_set          = g_strdup (tile_set);
+  t_bg_color_name     = g_strdup (bg_color_name);
+  gdk_color_parse (t_bg_color_name, &bg_color[2]);
+  if (drawing_area)
+    gdk_colormap_alloc_color (gtk_widget_get_colormap (drawing_area),
+			      &bg_color[2], FALSE, TRUE);
+}
+
+void
+apply_changes (void)
+{
+  if (bg_color_name)
+    g_free (bg_color_name);
+  if (tile_set)
+    g_free (tile_set);
+
+  computer_level[0]  = t_computer_level[0];
+  computer_level[1]  = t_computer_level[1];
+  none_animation     = t_options[0];
+  use_quick_moves    = t_options[1];
+  hide_valid_squares = t_options[2];
+  hide_last_move     = t_options[3];
+  hide_final_results = t_options[4];
+  mute               = t_options[5];
+  hide_toolbar       = t_options[6];
+  tile_set           = g_strdup (t_tile_set);
+  bg_color_name      = g_strdup (t_bg_color_name);
+  computer_speed     = COMPUTER_MOVE_DELAY;
+  flip_speed         = PIXMAP_FLIP_DELAY;
+
+  if (use_quick_moves) {
+    computer_speed /= 2;
+    flip_speed     /= 2;
   }
+  set_flip_pixmaps_id ();
+  games_sound_enable (!mute);
 
-  reset_properties ();
+  refresh_board ();
+  network_gui_update ();
+}
 
-  propbox = gtk_dialog_new_with_buttons (_("Iagno Preferences"),
-					 GTK_WINDOW (window),
-					 0,
-					 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
-					 NULL);
+static void
+on_computer_level_changed (GtkToggleButton *togglebutton, gpointer user_data)
+{
+  if (togglebutton->active)
+    t_computer_level[GPOINTER_TO_INT (user_data) / 16] =
+      GPOINTER_TO_INT (user_data) % 16;
+}
 
-  gtk_dialog_set_has_separator (GTK_DIALOG (propbox), FALSE);
-  gtk_container_set_border_width (GTK_CONTAINER (propbox), 5);
-  gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (propbox)->vbox), 2);
-  gtk_window_set_resizable (GTK_WINDOW (propbox), FALSE);
-  notebook = gtk_notebook_new ();
-  gtk_container_set_border_width (GTK_CONTAINER (notebook), 5);
-  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (propbox)->vbox), notebook);
+static void
+on_options_toggled (GtkToggleButton *togglebutton, gpointer user_data)
+{
+  t_options[GPOINTER_TO_INT (user_data)] = togglebutton->active;
+}
 
-  label = gtk_label_new (_("Game"));
+static void
+on_tile_set_box_changed (GtkComboBox *combobox, gpointer user_data)
+{
+  if (t_tile_set)
+    g_free (t_tile_set);
+  t_tile_set = gtk_combo_box_get_active_text (combobox);
+}
 
-  vbox = gtk_vbox_new (FALSE, 18);
-  gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
-  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label);
+static void
+on_color_button_color_set (GtkColorButton *colorbutton, gpointer user_data)
+{
+  gtk_color_button_get_color (colorbutton, &bg_color[2]);
+  if (t_bg_color_name)
+    g_free (t_bg_color_name);
+  t_bg_color_name = g_strdup_printf ("#%04X%04X%04X",
+				     bg_color[2].red, bg_color[2].green,
+				     bg_color[2].blue);
+}
 
-  table = gtk_table_new (1, 2, FALSE);
-  gtk_table_set_col_spacings (GTK_TABLE (table), 18);
-  gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
+static void
+on_apply_button_clicked (GtkButton *button, gpointer user_data)
+{
+  apply_changes ();
+  save_properties ();
+}
 
-  vbox2 = gtk_vbox_new (FALSE, 0);
-  gtk_box_pack_start (GTK_BOX (vbox), vbox2, FALSE, FALSE, 0);
+static void
+on_properties_cancel_clicked (GtkButton *button, gpointer user_data)
+{
+  reset_properties ();
+  gtk_widget_destroy (properties_dialog);
+  properties_dialog = NULL;
+}
 
-  button = gtk_check_button_new_with_mnemonic (_("_Use quick moves"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
-				(computer_speed == COMPUTER_MOVE_DELAY / 2));
-  g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK
-		    (quick_moves_select), NULL);
+static void
+on_ok_button_clicked (GtkButton *button, gpointer user_data)
+{
+  apply_changes ();
+  save_properties ();
+  gtk_widget_destroy (properties_dialog);
+  properties_dialog = NULL;
+}
 
-  gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
+/******************************************************/
+static GamesFileList *theme_file_list = NULL;
 
-  button = gtk_check_button_new_with_mnemonic (_("E_nable sounds"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), sound);
-  g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK
-		    (sound_select), NULL);
+static GtkWidget *
+fill_menu (void)
+{
+  gchar *dname = NULL;
 
-  gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
+  dname = gnome_program_locate_file (NULL,
+				     GNOME_FILE_DOMAIN_APP_PIXMAP,
+				     "iagno", FALSE, NULL);
 
-  frame = games_frame_new (_("Dark"));
-  gtk_table_attach_defaults (GTK_TABLE (table), frame, 0, 1, 0, 1);
+  if (theme_file_list)
+    g_object_unref (theme_file_list);
 
-  vbox = gtk_vbox_new (FALSE, 6);
+  theme_file_list = games_file_list_new_images (dname, NULL);
+  g_free (dname);
 
-  button = gtk_radio_button_new_with_label (NULL, _("Human"));
-  if (black_computer_level == 0)
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
-  g_signal_connect (G_OBJECT (button), "toggled",
-		    G_CALLBACK (black_computer_level_select), (gpointer) 0);
+  games_file_list_transform_basename (theme_file_list);
+  return games_file_list_create_widget (theme_file_list, t_tile_set, 0);
+}
+/*******************************************************/
 
-  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
-  button = gtk_radio_button_new_with_label (gtk_radio_button_get_group
-					    (GTK_RADIO_BUTTON (button)),
-					    _("Level one"));
-  if (black_computer_level == 1)
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
-  g_signal_connect (G_OBJECT (button), "toggled",
-		    G_CALLBACK (black_computer_level_select), (gpointer) 1);
+GtkWidget *
+create_properties_dialog (void)
+{
+  const gchar *strs[] = {
+    N_("_None animation"),	/* 0 */
+    N_("Use _Quick moves"),	/* 1 */
+    N_("Hide _Valid squares"),	/* 2 */
+    N_("Hide _Last move mark"),	/* 3 */
+    N_("Don't flip _Final results"),/* 4 */
+    N_("_Mute"),		/* 5 */
+    N_("Hide _Toolbar"),	/* 6 */
+    N_("Tile set:"),		/* 7 */
+    N_("Background color:"),/* 8 */
+    N_("Human"),		/* 9 */
+    N_("Level "),		/* 10 */
+    N_("Options"),		/* 11 */
+    N_("Options"),		/* 12 */
+    N_("Dark"),		/* 13 */
+    N_("Light"),		/* 14 */
+    N_("Appearance"),	/* 15 */
+    N_("Players"),		/* 16 */
+    _("gtk-apply"),		/* 17 */
+    _("gtk-cancel"),		/* 18 */
+    _("gtk-ok"),		/* 19 */
+  };
 
-  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
-  button = gtk_radio_button_new_with_label (gtk_radio_button_get_group
-					    (GTK_RADIO_BUTTON (button)),
-					    _("Level two"));
-  if (black_computer_level == 2)
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
-  g_signal_connect (G_OBJECT (button), "toggled",
-		    G_CALLBACK (black_computer_level_select), (gpointer) 2);
+  const GtkSignalFunc *signalfunc[3] = {
+    (GtkSignalFunc *) on_apply_button_clicked,
+    (GtkSignalFunc *) on_properties_cancel_clicked,
+    (GtkSignalFunc *) on_ok_button_clicked
+  };
 
-  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
-  button = gtk_radio_button_new_with_label (gtk_radio_button_get_group
-					    (GTK_RADIO_BUTTON (button)),
-					    _("Level three"));
-  if (black_computer_level == 3)
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
-  g_signal_connect (G_OBJECT (button), "toggled",
-		    G_CALLBACK (black_computer_level_select), (gpointer) 3);
+  GtkWidget *properties_dialog;
+  GtkWidget *dialog_vbox;
+  GtkWidget *notebook;
+  GtkWidget *hbox;
+  GtkWidget *frame;
+  GtkWidget *alignment;
+  GtkWidget *vbox;
+  GtkWidget *button;
+  GtkWidget *label;
+  GSList    *human_group[2] = { NULL, NULL };
+  GtkWidget *table;
+  GtkWidget *tile_set_box;
+  GtkWidget *color_button;
+  GtkWidget *dialog_action_area;
+  GString   *string;
 
-  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
-  gtk_container_add (GTK_CONTAINER (frame), vbox);
+  gint n, f, v;
 
-  frame = games_frame_new (_("Light"));
-  gtk_table_attach_defaults (GTK_TABLE (table), frame, 1, 2, 0, 1);
+  properties_dialog = gtk_dialog_new ();
+  gtk_window_set_title (GTK_WINDOW (properties_dialog), keys[14]);
+  gtk_window_set_resizable (GTK_WINDOW (properties_dialog), FALSE);
+  gtk_window_set_type_hint (GTK_WINDOW (properties_dialog),
+			    GDK_WINDOW_TYPE_HINT_DIALOG);
+  g_signal_connect ((gpointer) properties_dialog, "destroy",
+		    G_CALLBACK (on_properties_cancel_clicked), NULL);
 
-  vbox = gtk_vbox_new (FALSE, 6);
+  dialog_vbox = GTK_DIALOG (properties_dialog)->vbox;
 
-  button = gtk_radio_button_new_with_label (NULL, _("Human"));
-  if (white_computer_level == 0)
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
-  g_signal_connect (G_OBJECT (button), "toggled",
-		    G_CALLBACK (white_computer_level_select), (gpointer) 0);
+  notebook = gtk_notebook_new ();
+  gtk_box_pack_start (GTK_BOX (dialog_vbox), notebook, TRUE, TRUE, 0);
 
-  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
-  button = gtk_radio_button_new_with_label (gtk_radio_button_get_group
-					    (GTK_RADIO_BUTTON (button)),
-					    _("Level one"));
-  if (white_computer_level == 1)
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
-  g_signal_connect (G_OBJECT (button), "toggled",
-		    G_CALLBACK (white_computer_level_select), (gpointer) 1);
+  for (n = 0; n < 2; n++) {
+    hbox = gtk_hbox_new (FALSE, 0);
+    gtk_container_add (GTK_CONTAINER (notebook), hbox);
 
-  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
-  button = gtk_radio_button_new_with_label (gtk_radio_button_get_group
-					    (GTK_RADIO_BUTTON (button)),
-					    _("Level two"));
-  if (white_computer_level == 2)
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
-  g_signal_connect (G_OBJECT (button), "toggled",
-		    G_CALLBACK (white_computer_level_select), (gpointer) 2);
+    for (f = 0; f < 2; f++) {
+      frame = gtk_frame_new (NULL);
+      gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
+      gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
 
-  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
-  button = gtk_radio_button_new_with_label (gtk_radio_button_get_group
-					    (GTK_RADIO_BUTTON (button)),
-					    _("Level three"));
-  if (white_computer_level == 3)
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
-  g_signal_connect (G_OBJECT (button), "toggled",
-		    G_CALLBACK (white_computer_level_select), (gpointer) 3);
+      alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
+      gtk_container_add (GTK_CONTAINER (frame), alignment);
+      gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 12, 0);
 
-  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+      vbox = gtk_vbox_new (FALSE, 0);
+      gtk_container_add (GTK_CONTAINER (alignment), vbox);
 
-  gtk_container_add (GTK_CONTAINER (frame), vbox);
+      if (n == 0) {
+	if (f == 0) {
+	  for (v = 0; v < MAX_OPTIONS; v++) {
+	    if (ggz_network_mode && v == MAX_OPTIONS - 1)
+	      continue;
+	    button = gtk_check_button_new_with_mnemonic (strs[v]);
+	    gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+	    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
+					  (button), t_options[v]);
+	    g_signal_connect ((gpointer) button, "toggled",
+			      G_CALLBACK (on_options_toggled),
+			      GINT_TO_POINTER (v));
+	  }
+	} else {
+	  table = gtk_table_new (2, 2, FALSE);
+	  gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);
 
+	  for (v = 0; v < 2; v++) {
+	    label = gtk_label_new (strs[v + 7]);
+	    gtk_table_attach (GTK_TABLE (table), label, 0, 1, v,
+			      v + 1, (GtkAttachOptions) (0),
+			      (GtkAttachOptions) (0), 0, 0);
+	    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+	  }
 
-  label = gtk_label_new (_("Appearance"));
+         tile_set_box = fill_menu ();
+	  gtk_table_attach (GTK_TABLE (table), tile_set_box, 1, 2, 0, 1, 
+	                 (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0);
+	  g_signal_connect ((gpointer) tile_set_box, "changed",
+			    G_CALLBACK (on_tile_set_box_changed), NULL);
 
-  table = gtk_table_new (1, 2, FALSE);
-  gtk_table_set_col_spacings (GTK_TABLE (table), 18);
-  gtk_container_set_border_width (GTK_CONTAINER (table), 12);
+	  color_button = gtk_color_button_new ();
+	  gtk_table_attach (GTK_TABLE (table), color_button,
+			    1, 2, 1, 2, (GtkAttachOptions) (0),
+			    (GtkAttachOptions) (0), 0, 0);
+	  gtk_color_button_set_color ((GtkColorButton *) color_button,
+				      &bg_color[2]);
+	  g_signal_connect ((gpointer) color_button, "color_set",
+			    G_CALLBACK (on_color_button_color_set), NULL);
+	}
+      } else {
+	for (v = 0; v < max_depth; v++) {
+	  if (!v)
+	    button = gtk_radio_button_new_with_mnemonic (NULL, strs[9]);
+	  else {
+	    string = g_string_new (strs[10]);
+	    g_string_append_printf (string, "%d", v);
+	    button = gtk_radio_button_new_with_mnemonic (NULL, string->str);
+	    g_string_free (string, TRUE);
+	  }
+	  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+	  gtk_radio_button_set_group (GTK_RADIO_BUTTON (button),
+				      human_group[f]);
+	  human_group[f] =
+	    gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
+	  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+					(t_computer_level[f] == v));
+	  g_signal_connect ((gpointer) button, "toggled",
+			    G_CALLBACK (on_computer_level_changed),
+			    GINT_TO_POINTER (f * 16 + v));
+	}
+      }
 
-  frame = games_frame_new (_("Animation"));
+      label = gtk_label_new (strs[n * 2 + f + 11]);
+      gtk_frame_set_label_widget (GTK_FRAME (frame), label);
+      gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+    }
+    label = gtk_label_new (strs[n + 15]);
+    gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook),
+				gtk_notebook_get_nth_page (GTK_NOTEBOOK
+						       (notebook), n), label);
+  }
 
-  vbox = gtk_vbox_new (FALSE, 6);
+  if (ggz_network_mode)
+    gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
 
-  button = gtk_radio_button_new_with_label (NULL, _("None"));
-  if (animate == 0)
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
-  g_signal_connect (G_OBJECT (button), "toggled",
-		    G_CALLBACK (animate_select), (gpointer) 0);
+  dialog_action_area = GTK_DIALOG (properties_dialog)->action_area;
+  gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area),
+			     GTK_BUTTONBOX_END);
 
-  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
-  button = gtk_radio_button_new_with_label (gtk_radio_button_get_group
-					    (GTK_RADIO_BUTTON (button)),
-					    _("Partial"));
-  if (animate == 1)
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
-  g_signal_connect (G_OBJECT (button), "toggled",
-		    G_CALLBACK (animate_select), (gpointer) 1);
+  for (n = 0; n < 3; n++) {
+    button = gtk_button_new_from_stock (strs[n + 17]);
+    gtk_dialog_add_action_widget (GTK_DIALOG (properties_dialog),
+				  button, GTK_RESPONSE_APPLY);
+    GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+    g_signal_connect ((gpointer) button, "clicked",
+		      G_CALLBACK (signalfunc[n]), NULL);
+  }
 
-  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
-  button = gtk_radio_button_new_with_label (gtk_radio_button_get_group
-					    (GTK_RADIO_BUTTON (button)),
-					    _("Complete"));
-  if (animate == 2)
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
-  g_signal_connect (G_OBJECT (button), "toggled",
-		    G_CALLBACK (animate_select), (gpointer) 2);
+  gtk_widget_show_all (properties_dialog);
+  return properties_dialog;
+}
 
-  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+/******* for file save dialog *******/
 
-  gtk_container_add (GTK_CONTAINER (frame), vbox);
-  gtk_table_attach_defaults (GTK_TABLE (table), frame, 0, 1, 0, 1);
+GtkWidget *
+create_file_save_dialog (GtkSignalFunc *callback)
+{
+  GtkWidget *file_save_dialog;
+  GtkWidget *dialog_vbox;
+  GtkWidget *dialog_action_area;
+  GtkWidget *save_cancel;
+  GtkWidget *save;
 
-  frame = games_frame_new (_("Options"));
-  vbox = gtk_vbox_new (FALSE, 6);
-  gtk_container_add (GTK_CONTAINER (frame), vbox);
-  button = gtk_check_button_new_with_mnemonic (_("_Stagger flips"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
-				t_animate_stagger);
-  g_signal_connect (G_OBJECT (button), "toggled",
-		    G_CALLBACK (animate_stagger_select), NULL);
+  file_save_dialog =
+    gtk_file_chooser_dialog_new ("", (GtkWindow *) window,
+				 GTK_FILE_CHOOSER_ACTION_SAVE, NULL, NULL);
+  gtk_window_set_type_hint (GTK_WINDOW (file_save_dialog),
+			    GDK_WINDOW_TYPE_HINT_DIALOG);
+  g_signal_connect ((gpointer) file_save_dialog, "destroy",
+		    G_CALLBACK (gtk_widget_destroy), NULL);
 
-  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+  dialog_vbox = GTK_DIALOG (file_save_dialog)->vbox;
 
-  button = gtk_check_button_new_with_mnemonic (_("S_how grid"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), t_grid);
-  g_signal_connect (G_OBJECT (button), "toggled",
-		    G_CALLBACK (grid_select), NULL);
+  dialog_action_area = GTK_DIALOG (file_save_dialog)->action_area;
+  gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area),
+			     GTK_BUTTONBOX_END);
 
-  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+  save_cancel = gtk_button_new_from_stock ("gtk-cancel");
+  gtk_dialog_add_action_widget (GTK_DIALOG (file_save_dialog),
+				save_cancel, GTK_RESPONSE_CANCEL);
+  GTK_WIDGET_SET_FLAGS (save_cancel, GTK_CAN_DEFAULT);
+  g_signal_connect_swapped ((gpointer) save_cancel, "clicked",
+			    G_CALLBACK (gtk_widget_destroy),
+			    (gpointer) file_save_dialog);
 
-  button = gtk_check_button_new_with_mnemonic (_("_Flip final results"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), t_flip_final);
-  g_signal_connect (G_OBJECT (button), "toggled",
-		    G_CALLBACK (flip_final_select), NULL);
+  save = gtk_button_new_from_stock ("gtk-save");
+  gtk_dialog_add_action_widget (GTK_DIALOG (file_save_dialog), save,
+				GTK_RESPONSE_OK);
+  GTK_WIDGET_SET_FLAGS (save, GTK_CAN_DEFAULT);
+  g_signal_connect ((gpointer) save, "clicked", G_CALLBACK (callback), NULL);
 
-  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+  gtk_widget_show_all (file_save_dialog);
+  gtk_widget_grab_default (save);
+  return file_save_dialog;
+}
 
-  hbox = gtk_hbox_new (FALSE, 12);
+/******* for file open dialog *******/
 
-  label2 = gtk_label_new_with_mnemonic (_("_Tile set:"));
+GtkWidget *
+create_file_open_dialog (GtkSignalFunc *callback)
+{
+  GtkWidget *file_open_dialog;
+  GtkWidget *dialog_vbox;
+  GtkWidget *dialog_action_area;
+  GtkWidget *open_cancel;
+  GtkWidget *open;
 
-  gtk_box_pack_start (GTK_BOX (hbox), label2, FALSE, FALSE, 0);
+  file_open_dialog =
+    gtk_file_chooser_dialog_new ("", (GtkWindow *) window,
+				 GTK_FILE_CHOOSER_ACTION_OPEN, NULL, NULL);
+  gtk_window_set_type_hint (GTK_WINDOW (file_open_dialog),
+			    GDK_WINDOW_TYPE_HINT_DIALOG);
+  g_signal_connect ((gpointer) file_open_dialog, "destroy",
+		    G_CALLBACK (gtk_widget_destroy), NULL);
 
-  option_menu = fill_menu ();
-  gtk_label_set_mnemonic_widget (GTK_LABEL (label2), option_menu);
-  g_signal_connect (G_OBJECT (option_menu), "changed",
-		    G_CALLBACK (set_selection), NULL);
-  gtk_box_pack_start (GTK_BOX (hbox), option_menu, TRUE, TRUE, 0);
+  dialog_vbox = GTK_DIALOG (file_open_dialog)->vbox;
 
-  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+  dialog_action_area = GTK_DIALOG (file_open_dialog)->action_area;
+  gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area),
+			     GTK_BUTTONBOX_END);
 
-  gtk_table_attach_defaults (GTK_TABLE (table), frame, 1, 2, 0, 1);
+  open_cancel = gtk_button_new_from_stock ("gtk-cancel");
+  gtk_dialog_add_action_widget (GTK_DIALOG (file_open_dialog),
+				open_cancel, GTK_RESPONSE_CANCEL);
+  GTK_WIDGET_SET_FLAGS (open_cancel, GTK_CAN_DEFAULT);
+  g_signal_connect_swapped ((gpointer) open_cancel, "clicked",
+			    G_CALLBACK (gtk_widget_destroy),
+			    (gpointer) file_open_dialog);
 
-  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), table, label);
+  open = gtk_button_new_from_stock ("gtk-open");
+  gtk_dialog_add_action_widget (GTK_DIALOG (file_open_dialog), open,
+				GTK_RESPONSE_OK);
+  GTK_WIDGET_SET_FLAGS (open, GTK_CAN_DEFAULT);
+  g_signal_connect ((gpointer) open, "clicked", G_CALLBACK (callback), NULL);
 
-  g_signal_connect (G_OBJECT (propbox), "response", G_CALLBACK
-		    (close_cb), NULL);
-  g_signal_connect (G_OBJECT (propbox), "delete_event", G_CALLBACK
-		    (close_cb), NULL);
+  gtk_widget_show_all (file_open_dialog);
+  gtk_widget_grab_default (open);
+  return file_open_dialog;
+}
 
-  gtk_widget_show_all (propbox);
-}
