After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 444602 - iagno new version
iagno new version
Status: RESOLVED INCOMPLETE
Product: gnome-games-superseded
Classification: Deprecated
Component: iagno
2.19.x
Other Linux
: Normal enhancement
: ---
Assigned To: Jason Clinton
GNOME Games maintainers
Depends on:
Blocks:
 
 
Reported: 2007-06-06 06:13 UTC by mars1
Modified: 2009-02-22 00:30 UTC
See Also:
GNOME target: ---
GNOME version: 2.17/2.18


Attachments
iagno new patch (176.83 KB, patch)
2007-06-06 06:25 UTC, mars1
none Details | Review
Screenshot (166.08 KB, image/jpeg)
2007-06-06 06:26 UTC, mars1
  Details
coin.svg (32.21 KB, image/svg+xml)
2007-06-06 06:27 UTC, mars1
  Details
marble.svg (30.93 KB, image/svg+xml)
2007-06-06 06:28 UTC, mars1
  Details
sun_and_star.svg (26.09 KB, image/svg+xml)
2007-06-06 06:28 UTC, mars1
  Details
old-protocol.patch (121.99 KB, patch)
2007-06-10 07:30 UTC, mars1
none Details | Review
new-protocol.patch (167.65 KB, patch)
2007-06-10 07:31 UTC, mars1
none Details | Review
with-save-open-menu.patch (173.92 KB, patch)
2007-06-10 17:00 UTC, mars1
none Details | Review
old-protocol.patch (123.71 KB, patch)
2007-06-12 02:56 UTC, mars1
none Details | Review
old-protocol.patch (129.59 KB, patch)
2007-06-14 15:35 UTC, mars1
none Details | Review
Screenshot (173.71 KB, image/jpeg)
2007-06-16 13:25 UTC, mars1
  Details
old-protocol.patch (129.41 KB, patch)
2007-06-16 13:27 UTC, mars1
none Details | Review
Screenshot2 (170.70 KB, image/jpeg)
2007-06-17 12:08 UTC, mars1
  Details
old-protocol.patch (126.53 KB, patch)
2007-06-17 12:09 UTC, mars1
none Details | Review
Iagno screen design (mandatory) (30.35 KB, image/png)
2007-06-17 18:59 UTC, Andreas Røsdal
  Details
Screenshot3 (164.08 KB, image/jpeg)
2007-06-19 02:57 UTC, mars1
  Details
old-protocol.patch (124.95 KB, patch)
2007-06-19 02:58 UTC, mars1
none Details | Review
new.patch (180.76 KB, patch)
2007-06-25 01:16 UTC, mars1
none Details | Review
new-protocol.patch (181.17 KB, patch)
2007-06-27 12:31 UTC, mars1
none Details | Review
new-protocol.patch (56.20 KB, patch)
2007-07-01 09:56 UTC, mars1
none Details | Review
new-iagno.patch (178.28 KB, patch)
2007-07-01 10:08 UTC, mars1
none Details | Review
new protocol patch (56.23 KB, patch)
2007-07-03 19:31 UTC, mars1
none Details | Review
new-iagno.patch (178.60 KB, patch)
2007-07-08 12:20 UTC, mars1
none Details | Review
Screenshot (156.92 KB, image/jpeg)
2007-07-08 12:22 UTC, mars1
  Details
disk.svg (32.95 KB, image/svg+xml)
2007-07-22 06:06 UTC, mars1
  Details
new-iagno.patch (215.16 KB, patch)
2007-07-22 06:10 UTC, mars1
needs-work Details | Review
new-iagno.patch (181.04 KB, patch)
2007-09-11 17:48 UTC, mars1
none Details | Review
new-iagno.patch (181.62 KB, patch)
2007-10-05 06:43 UTC, mars1
none Details | Review
new-iagno.patch.0 (114.75 KB, patch)
2007-10-13 13:39 UTC, mars1
none Details | Review
new-iagno.patch.2 (172.97 KB, patch)
2007-10-13 13:49 UTC, mars1
none Details | Review
new-iagno.patch.2 (173.59 KB, patch)
2007-11-04 03:39 UTC, mars1
rejected Details | Review
new-iagno.patch.0 (101.11 KB, patch)
2007-11-11 04:29 UTC, mars1
none Details | Review
new-iagno.patch.3 (188.22 KB, patch)
2008-02-11 01:41 UTC, mars1
none Details | Review
new-iagno.patch.0 (104.85 KB, patch)
2008-02-12 13:05 UTC, mars1
rejected Details | Review
current-iagno.patch (4.25 KB, patch)
2008-02-18 11:59 UTC, mars1
rejected Details | Review
Screenshot (122.19 KB, image/jpeg)
2008-02-24 04:12 UTC, mars1
  Details
new-iagno.patch.3 (186.30 KB, patch)
2008-02-24 04:14 UTC, mars1
none Details | Review
new-iagno.patch.3 (186.37 KB, patch)
2008-03-16 03:19 UTC, mars1
none Details | Review
new-iagno.patch.3 (186.07 KB, patch)
2008-06-11 15:22 UTC, mars1
rejected Details | Review

Description mars1 2007-06-06 06:13:56 UTC
+++ This bug was initially created as a clone of Bug #350068 +++

I made iagno new version. Please try this patch.
file save, file open, sound, network supported.
keyboard input supported but not compleat.
resizeable window is not supported yet.

diff -uNr gnome-games-2.14.1.org/iagno/gnothello.c gnome-games-2.14.1/iagno/gnothello.c
--- gnome-games-2.14.1.org/iagno/gnothello.c	2006-08-05 15:32:11.000000000 +0900
+++ gnome-games-2.14.1/iagno/gnothello.c	2006-08-05 23:00:46.000000000 +0900
@@ -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
  *
  * 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,776 +18,1254 @@
  * For more details see the file COPYING.
  */
 
-#include <config.h>
-#include <gnome.h>
-#include <libgnomeui/gnome-window-icon.h>
-#include <gdk/gdkkeysyms.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
 
-#include <string.h>
+#include <gnome.h>
+#include <gconf/gconf-client.h>
+#include <glib.h>
+#include <stdio.h>
+#include <fcntl.h>
 
 #include "gnothello.h"
 #include "othello.h"
 #include "properties.h"
-#include "games-network.h"
 #include "network.h"
+#include "games-network.h"
+#include "games-clock.h"
 
-GnomeAppBar *appbar;
-GtkWidget *window;
-GtkWidget *drawing_area;
-GtkWidget *tile_dialog;
-GtkWidget *black_score;
-GtkWidget *white_score;
+gint8 pixmaps[8][8];
+gint8 board[8][8];
+guint8 kifu[61][2];
 
+GtkWidget *window;
+GtkWidget *propaties_dialog;
+GtkWidget *file_open_dialog;
+GtkWidget *file_save_dialog;
 GdkPixmap *buffer_pixmap = NULL;
 GdkPixmap *tiles_pixmap = NULL;
 GdkPixmap *tiles_mask = NULL;
+GdkGC *gridGC[2] = { 0 };
+GtkWidget *b_timer;
+GtkWidget *w_timer;
+
+gchar *flip_sound;
+gchar *gameover_sound;
+gboolean play_sound = FALSE;
 
-gint flip_pixmaps_id = 0;
-gint statusbar_id;
 guint black_computer_level;
 guint white_computer_level;
+guint quick_moves;
+guint animate;
+gboolean animate_stagger;
+guint grid;
+gboolean flip_final;
+gchar *tile_set;
+guint computer_speed;
+guint flip_speed;
+
+guint t_black_computer_level;
+guint t_white_computer_level;
+guint t_quick_moves;
+guint t_animate;
+gboolean t_animate_stagger;
+guint t_grid;
+gboolean t_flip_final;
+gchar *t_tile_set;
+
+gboolean tiles_to_flip = FALSE;
+guint context_id1 = 0;
+guint context_id2 = 0;
 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;
+guint flip_pixmaps_id = 0;
+guint flip_final_id = 0;
 
 guint game_in_progress;
+extern guint whose_turn;
 
-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}};
-
-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 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 void new_network_game_cb(GtkWidget *widget, gpointer data);
-
-static const struct poptOption options[] = {
-  {NULL, 'x', POPT_ARG_INT, &session_xpos, 0, NULL, NULL},
-  {NULL, 'y', POPT_ARG_INT, &session_ypos, 0, NULL, NULL},
-  {"server", 's', POPT_ARG_STRING, &game_server, 0, N_("Iagno server to use")},
-  {NULL, '\0', 0, NULL, 0}
-};
-
-GnomeUIInfo game_menu[] = {
-        GNOMEUIINFO_MENU_NEW_GAME_ITEM(new_game_cb, NULL),
-
-	GNOMEUIINFO_ITEM(N_("New Net_work Game"), NULL, new_network_game_cb, NULL),
-
-	GNOMEUIINFO_SEPARATOR,
-
-	GNOMEUIINFO_MENU_UNDO_MOVE_ITEM(undo_move_cb, NULL),
-	
-	GNOMEUIINFO_SEPARATOR,
-
-        GNOMEUIINFO_MENU_QUIT_ITEM(quit_game_cb, NULL),
-
-	GNOMEUIINFO_END
-};
-
-GnomeUIInfo settings_menu[] = {
-        GNOMEUIINFO_MENU_PREFERENCES_ITEM (properties_cb, NULL),
-        GNOMEUIINFO_END
-};
+extern GtkWidget *drawingarea;
+extern GtkWidget *b_score_status;
+extern GtkWidget *w_score_status;
+extern GtkWidget *info_status;
+extern GtkWidget *entry;
+extern GtkWidget *b_time_status;
+extern GtkWidget *w_time_status;
+
+extern guint board0[100];
+extern guint squares[64];
+extern gint vsquares[280][2];
+extern guint hpointer;
+extern guint vpointer;
+extern guint s_kind;
+extern guint bcount;
+extern guint wcount;
+extern guint move_count;
+
+#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"
 
-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)
+void
+on_open_activate (GtkMenuItem *menuitem, gpointer user_data)
 {
-	gtk_widget_set_sensitive (game_menu[3].widget, state);
+  network_stop ();
+  game_in_progress = FALSE;
+  games_clock_stop (GAMES_CLOCK(b_time_status));
+  games_clock_stop (GAMES_CLOCK(w_time_status));
+  games_clock_set_seconds (GAMES_CLOCK(b_time_status), 0);
+  games_clock_set_seconds (GAMES_CLOCK(w_time_status), 0);
+  kifu [0][0] = 0;
+  file_open_dialog = create_file_open_dialog ();
+  gtk_widget_show (file_open_dialog);
 }
 
 void
-quit_game_cb (GtkWidget *widget, gpointer data)
+on_save_activate (GtkMenuItem *menuitem, gpointer user_data)
 {
-  games_kill_server ();
-  gtk_main_quit ();
+  GDate *date;
+  gchar filename[17];
+
+  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 ();
+  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
-new_network_game_cb (GtkWidget *widget, gpointer data)
+void
+on_quit_activate (GtkMenuItem *menuitem, gpointer user_data)
 {
-  network_new (window);
+  games_kill_server ();
+  gtk_main_quit ();
 }
 
 void
-new_game_cb (GtkWidget *widget, gpointer data)
+on_new_game_activate (GtkMenuItem *menuitem, gpointer user_data)
 {
   network_stop ();
   init_new_game ();
 }
 
 void
-undo_move_cb (GtkWidget *widget, gpointer data)
+on_new_network_game_activate (GtkMenuItem *menuitem, gpointer user_data)
 {
-	gint8 which_computer, xy;
-
-	if ((black_computer_level && white_computer_level) || move_count == 4)
-		return;
-
-	if (flip_final_id) {
-		g_source_remove (flip_final_id);
-		flip_final_id = 0;
-	}
-
-	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;
-	}
-
-	if (whose_turn == WHITE_TURN)
-		gui_message (_("Light's move"));
-	else
-		gui_message (_("Dark's move"));
-
-	gui_status ();
-	tiles_to_flip = 1;
-	check_computer_players ();
+  network_new (window);
 }
 
 void
-black_level_cb (GtkWidget *widget, gpointer data)
+on_undo_activate (GtkMenuItem *menuitem, gpointer user_data)
 {
-        int tmp;
+  on_undobutton_clicked (NULL, NULL);
+}
 
-        tmp = atoi ((gchar *)data);
+void
+on_hint_activate (GtkMenuItem *menuitem, gpointer user_data)
+{
+  on_infobutton_clicked (NULL, NULL);
+}
 
-        gnome_config_set_int ("/iagno/Preferences/blacklevel", tmp);
-        gnome_config_sync ();
+void
+on_preference_activate (GtkMenuItem *menuitem, gpointer user_data)
+{
+  propaties_dialog = create_propaties_dialog ();
+  gtk_widget_show (propaties_dialog);
+}
 
-        black_computer_level = tmp;
+void
+on_about_activate (GtkMenuItem *menuitem, gpointer user_data)
+{
+  GtkWidget *about_dialog;
 
-        check_computer_players ();
+  about_dialog = create_about_dialog ();
+  gtk_widget_show (about_dialog);
 }
 
 void
-white_level_cb (GtkWidget *widget, gpointer data)
+on_newbutton_clicked (GtkToolButton *toolbutton, gpointer user_data)
 {
-        int tmp;
+  on_new_game_activate (NULL, NULL);
+}
 
-        tmp = atoi ((gchar *)data);
+void
+on_undobutton_clicked (GtkToolButton *toolbutton, gpointer user_data)
+{
+  guint who;
 
-        gnome_config_set_int ("/iagno/Preferences/whitelevel", tmp);
-        gnome_config_sync ();
+  if (is_network_running ())
+    return;
+  if (!network_allow ())
+    network_stop ();
+  if (move_count <= 4)
+    return;
+  if (black_computer_level && white_computer_level)
+    return;
+
+  if (flip_final_id)
+  {
+    g_source_remove (flip_final_id);
+    flip_final_id = 0;
+  }
+  game_in_progress = TRUE;
+  games_clock_stop (GAMES_CLOCK(b_time_status));
+  games_clock_stop (GAMES_CLOCK(w_time_status));
+
+  back ();
+  kifu [move_count - 4][0] = 0;
+  copy_board ();
+  who = OTHER_PLAYER (whose_turn);
+  while ((whose_turn != who) && (move_count > 4))
+  {
+    back ();
+    kifu [move_count - 4][0] = 0;
+    copy_board ();
+  }
+
+  gui_status ();
+  tiles_to_flip = TRUE;
+  play_sound = TRUE;
+  check_valid_moves ();
+  check_computer_players ();
+}
 
-        white_computer_level = tmp;
+void
+on_headbutton_clicked (GtkToolButton *toolbutton, gpointer user_data)
+{
+  if (is_network_running ())
+    return;
+  if (flip_final_id)
+  {
+    g_source_remove (flip_final_id);
+    flip_final_id = 0;
+  }
+  game_in_progress = FALSE;
+  init ();
+  copy_board ();
+  copy_pixmaps ();
+  redraw_board ();
+  gui_message (_("Dark's move"));
+}
 
-        check_computer_players ();
+void
+on_backbutton_clicked (GtkToolButton *toolbutton, gpointer user_data)
+{
+  if (is_network_running ())
+    return;
+  if (move_count <= 4)
+    return;
+  if (flip_final_id)
+  {
+    g_source_remove (flip_final_id);
+    flip_final_id = 0;
+  }
+  game_in_progress = FALSE;
+  back ();
+  copy_board ();
+  gui_status ();
+  tiles_to_flip = TRUE;
+  play_sound = TRUE;
+  check_valid_moves ();
 }
 
 void
-about_cb (GtkWidget *widget, gpointer data)
+on_forwardbutton_clicked (GtkToolButton *toolbutton, gpointer user_data)
 {
-	const gchar *authors[] = {"Ian Peters", NULL};
+  guint xy, me;
+  
+  if (is_network_running ())
+    return;
+  game_in_progress = FALSE;
+  me = (guint) kifu[move_count - 4][0];
+  if (!me)
+  {
+    if (check_valid_moves ())
+      game_in_progress = TRUE;
+    return;
+  }
+  whose_turn = me;
+  xy = (guint) kifu[move_count - 4][1];
+  move (xy % 10, xy / 10);
+  check_valid_moves ();
+}
 
-	gtk_show_about_dialog (GTK_WINDOW (window),
-			       "name", _("Iagno"),
-			       "version", VERSION,
-			       "copyright", "Copyright \xc2\xa9 1998-2004 Ian Peters",
-			       "comments",_("A disk flipping game derived from Reversi."),
-			       "authors", authors, 
-			       "translator_credits", _("translator-credits"),
-			       NULL);
+void
+on_lastbutton_clicked (GtkToolButton *toolbutton, gpointer user_data)
+{  
+  if (is_network_running ())
+    return;
+  game_in_progress = FALSE;
+  while (kifu[move_count - 4][0])
+  {
+    whose_turn = (guint) kifu[move_count - 4][0];
+    move_board ((guint) kifu[move_count - 4][1]);
+  }
+  copy_board ();
+  copy_pixmaps ();
+  redraw_board ();
+  if (check_valid_moves ())
+    game_in_progress = TRUE;
 }
 
 void
-properties_cb (GtkWidget *widget, gpointer data)
+on_infobutton_clicked (GtkToolButton *toolbutton, gpointer user_data)
 {
-	show_properties_dialog ();
+  guint tmp;
+	
+  if (move_count < 4 || move_count > 63)
+    return;
+  if (!mobility (whose_turn))
+    return;
+
+  tmp = game_in_progress;
+  game_in_progress = FALSE;
+  computer_move (4);
+  game_in_progress = tmp;
+  gui_hint (vsquares[0][0], vsquares[0][1]);
 }
 
-gint
-expose_event (GtkWidget *widget, GdkEventExpose *event)
-{
-	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);
 
-	return(FALSE);
+void
+on_quitbutton_clicked (GtkToolButton *toolbutton, gpointer user_data)
+{
+  on_quit_activate (NULL, NULL);
 }
 
-gint
-configure_event (GtkWidget *widget, GdkEventConfigure *event)
+gboolean
+on_drawingarea_expose_event (GtkWidget *widget,
+           GdkEventExpose *event, gpointer user_data)
 {
-	static int old_width = 0, old_height = 0;
-	guint i, j;
+  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);
 
-	if (old_width == event->width && old_height == event->height) {
-		return TRUE;
-	} else {
-		old_width = event->width;
-		old_height = event->height;
-	}
-	
-	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 ();
-	}
-	
-	return TRUE;
+  return FALSE;
 }
 
-gint
-button_press_event (GtkWidget *widget, GdkEventButton *event)
+gboolean
+on_drawingarea_button_press_event (GtkWidget *widget,
+           GdkEventButton *event, gpointer user_data)
 {
-	guint x, y;
+  guint x, y;
 
-	if (game_in_progress == 0)
-		return TRUE;
+  if (!network_allow ())
+    return FALSE;
+  if (!game_in_progress)
+    return FALSE;
+  if ((whose_turn == WHITE_TURN) && white_computer_level)
+    return FALSE;
+  if ((whose_turn == BLACK_TURN) && black_computer_level)
+    return FALSE;
 
-	if (!network_allow ())
-		return TRUE;
-	
-	if ((whose_turn == WHITE_TURN) && white_computer_level)
-		return TRUE;
+  if (event->button)
+  {
+    x = event->x / (TILEWIDTH + GRIDWIDTH) + 1;
+    y = event->y / (TILEHEIGHT + GRIDWIDTH) + 1;
+    if (is_valid_move (x, y, whose_turn))
+      game_move (x, y, whose_turn);
+  }
 
-	if ((whose_turn == BLACK_TURN) && black_computer_level)
-		return TRUE;
+  return FALSE;
+}
+
+void
+on_entry_notify (GObject *gobject, GParamSpec *arg1, gpointer user_data)
+{
+  gchar *ch;
+  guint x, y;
 
-	if (event->button == 1) {
-		x = event->x / (TILEWIDTH + GRIDWIDTH);
-		y = event->y / (TILEHEIGHT + GRIDWIDTH);
-		if (is_valid_move (x, y, whose_turn))
-			game_move (x, y, whose_turn);
-	}
+  ch = gtk_entry_get_text (entry);
+  y = (guint)(ch[0] - 0x60);
+  x = (guint)(ch[1] - 0x30);
+  if (x < 1 || x > 8 || y < 1 || y > 8)
+    return;
+  if (is_valid_move (x, y, whose_turn))
+    game_move (x, y, whose_turn);
 
-	return TRUE;
 }
 
 void
-gui_draw_pixmap (gint which, gint x, gint y)
+on_bcomputer_level_changed (GtkToggleButton *togglebutton, gpointer user_data)
 {
-	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 (is_network_running ())
+    return;
+  t_black_computer_level = clamp_int (GPOINTER_TO_INT(user_data), 0, 3);
 }
 
 void
-gui_draw_pixmap_buffer (gint which, gint x, gint y)
+on_wcomputer_level_changed (GtkToggleButton *togglebutton,
+          gpointer user_data)
 {
-	gdk_draw_drawable (buffer_pixmap, gridGC[0], tiles_pixmap,
-			   (which % 8) * TILEWIDTH, (which / 8) * TILEHEIGHT,
-			   x * (TILEWIDTH + GRIDWIDTH),
-			   y * (TILEHEIGHT + GRIDWIDTH),
-			   TILEWIDTH, TILEHEIGHT);
+  if (is_network_running ())
+    return;
+  t_white_computer_level = clamp_int (GPOINTER_TO_INT(user_data), 0, 3);
 }
 
 void
-gui_draw_grid (void)
+on_quick_moves_toggled (GtkToggleButton *togglebutton, gpointer user_data)
 {
-	int i;
-        
-	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);
-	}
-	
-	gdk_draw_drawable (drawing_area->window, gridGC[0], buffer_pixmap,
-			   0, 0, 0, 0, BOARDWIDTH, BOARDHEIGHT);
+  if (togglebutton->active)
+    t_quick_moves = 2;
+  else
+    t_quick_moves = 1;
 }
 
 void
-load_pixmaps (void)
+on_animate_changed (GtkToggleButton *togglebutton, gpointer user_data)
 {
-	GdkPixbuf *image;
-	GError    *error = NULL;
-	gchar      *tmp;
-	gchar      *fname;
-
-	g_return_if_fail (tile_set != NULL && tile_set [0] != '0');
-
-	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);
-
-	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);
-	}
-
-	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);
-	}
-
-	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;
-	}
-
-	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);
+  t_animate = clamp_int (GPOINTER_TO_INT (user_data), 0, 2);
 }
 
-gint
-flip_pixmaps (gpointer data)
+void
+on_stagger_flips_toggled (GtkToggleButton *togglebutton, gpointer user_data)
 {
-	guint i, j;
-	guint flipped_tiles = 0;
-
-	if (! tiles_to_flip)
-		return TRUE;
-	
-	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;
-			}
-		}
-
-	if (! flipped_tiles)
-		tiles_to_flip = 0;
-
-	return TRUE;
+  if (togglebutton->active)
+    t_animate_stagger = TRUE;
+  else
+    t_animate_stagger = FALSE;
 }
 
-static void
-redraw_board (void)
+void
+on_show_grid_toggled (GtkToggleButton *togglebutton, gpointer user_data)
 {
-	guint i, j;
+  if (togglebutton->active)
+    t_grid = 1;
+  else
+    t_grid = 0;
+}
 
-	gui_status();
+void
+on_flip_final_results_toggled (GtkToggleButton *togglebutton,
+             gpointer user_data)
+{
+  if (togglebutton->active)
+    t_flip_final = TRUE;
+  else
+    t_flip_final = FALSE;
+}
 
-	for (i = 0; i < 8; i++)
-		for (j = 0; j < 8; j++)
-			gui_draw_pixmap_buffer (pixmaps[i][j], i, j);
+void
+on_tile_set_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);
+}
 
-	gui_draw_grid ();
+void
+on_apply_button_clicked (GtkButton *button, gpointer user_data)
+{
+  apply_changes ();
+  save_properties ();
 }
 
 void
-clear_board (void)
+on_propaties_cancel_clicked (GtkButton *button, gpointer user_data)
 {
-	guint i, j;
+  reset_properties ();
+  gtk_widget_destroy (propaties_dialog);
+}
 
-	if (flip_final_id) {
-		g_source_remove (flip_final_id);
-		flip_final_id = 0;
-	}
-
-	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;
-	}
-
-	game_in_progress = 0;
-	move_count = 0;
-	for (i = 0; i < 8; i++)
-		for (j = 0; j < 8; j++)
-			board[i][j] = 0;
+void
+on_ok_button_clicked (GtkButton *button, gpointer user_data)
+{
+  apply_changes ();
+  save_properties ();
+  gtk_widget_destroy (propaties_dialog);
+}
 
-	memcpy (pixmaps, board, sizeof (gint8) * 8 * 8);
+void
+on_file_open_cancel_clicked (GtkButton *button, gpointer user_data)
+{
+  gtk_widget_destroy (file_open_dialog);
+}
 
-	bcount = 0;
-	wcount = 0;
+void
+on_open_button_clicked (GtkButton *button, gpointer user_data)
+{
+  gchar *filename;
+  int fd;
 
-	redraw_board ();
+  filename =
+        gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_open_dialog));
+  fd = open (filename, 0, 0644);
+  if (fd)
+  {
+    read_kifu (fd);
+    close (fd);
+  }
+  gtk_widget_destroy (file_open_dialog);
+  g_free (filename);
+  on_headbutton_clicked (NULL, NULL);
 }
 
 void
-init_new_game (void)
+on_file_save_cancel_clicked (GtkButton *button, gpointer user_data)
 {
-	clear_board ();
-	game_in_progress = 1;
-	move_count = 4;
+  gtk_widget_destroy (file_save_dialog);
+}
 
-	undo_set_sensitive (FALSE);
-	
-	board[3][3] = WHITE_TURN;
-	board[3][4] = BLACK_TURN;
-	board[4][3] = BLACK_TURN;
-	board[4][4] = WHITE_TURN;
+void
+on_save_button_clicked (GtkButton *button, gpointer user_data)
+{
+  gchar *filename;
+  int fd;
+  
+  filename =
+    gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_save_dialog));
+  
+  fd = creat (filename, 0644);
+  if (fd)
+  {
+    write_kifu (fd);
+    close (fd);
+  }
+  gtk_widget_destroy (file_save_dialog);      
+  g_free (filename);
+}
 
-	bcount = 2;
-	wcount = 2;
-	init();
+/* From here appended to callbacks.c made by glade */
+gint
+clamp_int (gint input, gint low, gint high)
+{
+  if (input < low)
+    input = low;
+  if (input > high)
+    input = high;
 
-	memcpy (pixmaps, board, sizeof (gint8) * 8 * 8);
+  return input;
+}
 
-	redraw_board ();
+void
+load_properties (void)
+{
+  GConfClient *client;
+  GError *error = NULL;
 
-	whose_turn = BLACK_TURN;
-	gui_message (_("Dark's move"));
+  client = gconf_client_get_default ();
+  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);
+
+  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);
+
+  quick_moves = gconf_client_get_int (client, KEY_QUICK_MOVES, &error);
+  if (error)
+  {
+    g_warning (G_STRLOC ": gconf error: %s\n", error->message);
+    g_error_free (error);
+    error = NULL;
+  }
+  quick_moves = clamp_int (quick_moves, 1, 2);
+  computer_speed = COMPUTER_MOVE_DELAY / quick_moves;
+  flip_speed = PIXMAP_FLIP_DELAY / quick_moves;
+
+  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);
+
+  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;
+  }
+
+  grid = gconf_client_get_int (client, KEY_SHOW_GRID, &error);
+  if (error)
+  {
+    g_warning (G_STRLOC ": gconf error: %s\n", error->message);
+    g_error_free (error);
+    error = NULL;
+  }
+  grid = clamp_int (grid, 0, 1);
+
+  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;
+  }
+
+  if (tile_set)
+    g_free (tile_set);
+  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");
 
-	check_computer_players ();
+  set_flip_pixmaps_id ();
+  g_object_unref (client);
 }
 
 void
-create_window (void)
+save_properties (void)
 {
-	GtkWidget *table;
+  GConfClient *client;
 
-	window = gnome_app_new ("iagno", _("Iagno"));
+  client = gconf_client_get_default ();
 
-	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);
+  gconf_client_set_int (client, KEY_BLACK_LEVEL, black_computer_level, NULL);
+  gconf_client_set_int (client, KEY_WHITE_LEVEL, white_computer_level, NULL);
+  gconf_client_set_int (client, KEY_QUICK_MOVES, quick_moves, NULL);
+  gconf_client_set_int (client, KEY_ANIMATE, animate, NULL);
+  gconf_client_set_bool (client, KEY_ANIMATE_STAGGER, animate_stagger, NULL);
+  gconf_client_set_int (client, KEY_SHOW_GRID, grid, NULL);
+  gconf_client_set_bool (client, KEY_FLIP_FINAL_RESULTS, flip_final, NULL);
+  gconf_client_set_string (client, KEY_TILESET, tile_set, NULL);
+}
 
-	gnome_app_create_menus (GNOME_APP (window), mainmenu);
+void
+reset_properties (void)
+{
+  t_black_computer_level = black_computer_level;
+  t_white_computer_level = white_computer_level;
+  t_quick_moves = quick_moves;
+  t_animate = animate;
+  t_animate_stagger = animate_stagger;
+  t_grid = grid;
+  t_flip_final = flip_final;
+
+  if (t_tile_set != NULL)
+    g_free (t_tile_set);
+  if (g_str_equal (tile_set, _("woodtrim.png")))
+    t_tile_set = g_strdup ("woodtrim.png");
+  else
+    t_tile_set = g_strdup ("classic.png");
+}
 
-	drawing_area = gtk_drawing_area_new ();
+void
+set_flip_pixmaps_id (void)
+{
+  if (flip_pixmaps_id)
+    g_source_remove (flip_pixmaps_id);
 
-	gtk_widget_pop_colormap ();
+  switch (animate)
+  {
+    case 0:
+      flip_pixmaps_id = g_timeout_add (100, flip_pixmaps, NULL);
+      break;
+    case 1:
+      flip_pixmaps_id = g_timeout_add (flip_speed * 8, flip_pixmaps, NULL);
+      break;
+    default:
+    case 2:
+      flip_pixmaps_id = g_timeout_add (flip_speed, flip_pixmaps, NULL);
+      break;
+  }
+}
 
-	gnome_app_set_contents (GNOME_APP (window), drawing_area);
+void
+apply_changes (void)
+{
+  black_computer_level = t_black_computer_level;
+  white_computer_level = t_white_computer_level;
+  quick_moves = t_quick_moves;
+  computer_speed = COMPUTER_MOVE_DELAY / quick_moves;
+  flip_speed = PIXMAP_FLIP_DELAY / quick_moves;
+  animate = t_animate;
+  set_flip_pixmaps_id ();
+  animate_stagger = t_animate_stagger;
+  if (grid != t_grid)
+  {
+    grid = t_grid;
+    redraw_board();
+  }
+  flip_final = t_flip_final;
+  if (!g_str_equal (tile_set, t_tile_set))
+  {
+    if (tile_set)
+      g_free (tile_set);
+    tile_set = g_strdup (t_tile_set);
+    load_pixmaps ();
+    redraw_board();
+  }
+  if (game_in_progress)
+    check_computer_players();
+}
 
-	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);
-	gtk_widget_show (drawing_area);
+void
+load_pixmaps (void)
+{
+  GdkPixbuf *image;
+  gchar *fname;
 
-	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);
+  fname = g_build_filename ("iagno", tile_set, NULL);
+  image = create_pixbuf (fname);
+  if (!image)
+    exit (1);
+
+  if (tiles_pixmap)
+    g_object_unref (tiles_pixmap);
+  gdk_pixbuf_render_pixmap_and_mask_for_colormap (image,
+              gdk_colormap_get_system (),
+              &tiles_pixmap,
+              &tiles_mask, 127);
 
-	table = gtk_table_new (1, 8, FALSE);
+  g_object_unref (image);
+  g_free (fname);
+}
 
-	black_score = gtk_label_new (_("Dark:"));
-	gtk_widget_show (black_score);
+void
+write_kifu (int fd)
+{
+  gchar buf[9];
+  gint8 i;
+  ssize_t err;
+
+  i = 0;
+  buf[2] = buf[4] = 0x20;
+  buf[7] = 0x0A;
+  buf[8] = 0;
+  
+  err = write (fd, _("iagno\n"), 6);
+  while (kifu[i][0] && err > 0)
+  {
+    buf[0] = (i + 1) / 10 + 0x30;
+    buf[1] = (i + 1) % 10 + 0x30;
+    buf[3] = (kifu[i][0] == BLACK_TURN)? 0x42: 0x57;
+    buf[5] = kifu[i][1] / 10 + 0x40;
+    buf[6] = kifu[i][1] % 10 + 0x30;
+
+    err = write (fd, buf, 8);
+    i++;
+  }
+}
 
-	gtk_table_attach (GTK_TABLE (table), black_score, 1, 2, 0, 1, 0, 0, 3, 1);
+void
+read_kifu (int fd)
+{
+  gchar buf[9];
+  gint8 i = 0;
+  ssize_t err;
+
+  err = read (fd, buf, 6);
+  buf[6] = 0;
+  if (!g_str_equal(buf, _("iagno\n")))
+  {
+    gui_message (_("not iagno's file"));
+    return;
+  }
+  err = read (fd, buf, 8);
+  while (err > 0)
+  {
+    i = (buf[0] - 0x30) * 10 + buf[1] - 0x30 - 1;
+    kifu[i][0] = (buf[3] == 0x42)? BLACK_TURN : WHITE_TURN;
+    kifu[i][1] = (buf[5] - 0x40) * 10 + buf[6] - 0x30;
+    err = read (fd, buf, 8);
+  }
+  kifu[i + 1][0] = 0;
+}
 
-	black_score = gtk_label_new ("00");
-	gtk_widget_show (black_score);
+static void
+set_bg_color (void)
+{
+  GdkImage *tmpimage;
+  GdkColor bgcolor;
 
-	gtk_table_attach (GTK_TABLE (table), black_score, 2, 3, 0, 1, 0, 0, 3, 1);
+  tmpimage = gdk_drawable_get_image (tiles_pixmap, 0, 0, 1, 1);
+  bgcolor.pixel = gdk_image_get_pixel (tmpimage, 0, 0);
+  gdk_window_set_background (drawingarea->window, &bgcolor);
+
+  if (gridGC[0])
+    g_object_unref (gridGC[0]);
+  gridGC[0] = gdk_gc_new (drawingarea->window);
+  if (gridGC[1])
+    g_object_unref (gridGC[1]);
+  gridGC[1] = gdk_gc_new (drawingarea->window);
+
+  gdk_gc_copy (gridGC[0], drawingarea->style->bg_gc[0]);
+  gdk_gc_copy (gridGC[1], drawingarea->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);
 
-	white_score = gtk_label_new (_("Light:"));
-	gtk_widget_show (white_score);
+  gdk_gc_set_line_attributes (gridGC[1], 0, GDK_LINE_ON_OFF_DASH,
+            GDK_CAP_BUTT, GDK_JOIN_MITER);
 
-	gtk_table_attach (GTK_TABLE (table), white_score, 4, 5, 0, 1, 0, 0, 3, 1);
+  g_object_unref (tmpimage);
+}
 
-	white_score = gtk_label_new ("00");
-	gtk_widget_show (white_score);
+void
+gui_draw_pixmap (guint which, guint x, guint y)
+{
+  gdk_draw_drawable (drawingarea->window, gridGC[0], tiles_pixmap,
+        TILEWIDTH * (which % 8), TILEHEIGHT * (which / 8),
+        (TILEWIDTH + GRIDWIDTH) * x, (TILEHEIGHT + GRIDWIDTH) * y,
+        TILEWIDTH, TILEHEIGHT);
+  gdk_draw_drawable (buffer_pixmap, gridGC[0], tiles_pixmap,
+        TILEWIDTH * (which % 8), TILEHEIGHT * (which / 8),
+        (TILEWIDTH + GRIDWIDTH) * x, (TILEHEIGHT + GRIDWIDTH) * y,
+        TILEWIDTH, TILEHEIGHT);
+}
 
-	gtk_table_attach (GTK_TABLE (table), white_score, 5, 6, 0, 1, 0, 0, 3, 1);
-	undo_set_sensitive (FALSE);
+void
+gui_draw_pixmap_buffer (guint which, guint x, guint y)
+{
+  gdk_draw_drawable (buffer_pixmap, gridGC[0], tiles_pixmap,
+        TILEWIDTH * (which % 8), TILEHEIGHT * (which / 8),
+        (TILEWIDTH + GRIDWIDTH) * x, (TILEHEIGHT + GRIDWIDTH) * y,
+        TILEWIDTH, TILEHEIGHT);
+}
 
-	gtk_widget_show (table);
+static void
+gui_draw_grid (void)
+{
+  guint i;
 
-	gtk_box_pack_start (GTK_BOX (appbar), table, FALSE, TRUE, 0);
+  for (i = 1; i < 8; i++)
+  {
+    gdk_draw_line (buffer_pixmap, gridGC[grid],
+             (BOARDWIDTH / 8) * i - GRIDWIDTH, 0,
+             (BOARDWIDTH / 8) * i - GRIDWIDTH, BOARDHEIGHT);
+    gdk_draw_line (buffer_pixmap, gridGC[grid],
+             0, (BOARDHEIGHT / 8) * i - GRIDWIDTH,
+             BOARDWIDTH, (BOARDHEIGHT / 8) * i - GRIDWIDTH);
+  }
 
-	gnome_appbar_set_status (GNOME_APPBAR (appbar),
-				 _("Welcome to Iagno!"));
+  gdk_draw_drawable (drawingarea->window, gridGC[0], buffer_pixmap,
+         0, 0, 0, 0, BOARDWIDTH, BOARDHEIGHT);
 }
 
 void
 gui_status (void)
 {
-	gchar message[3];
+  gchar message[3];
 
-	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 && !is_network_running ());
+  sprintf (message, _("%.2d"), bcount);
+  gtk_label_set_text (GTK_LABEL (b_score_status), message);
+  sprintf (message, _("%.2d"), wcount);
+  gtk_label_set_text (GTK_LABEL (w_score_status), message);
 }
 
 void
 gui_message (gchar *message)
 {
-	gnome_appbar_pop (GNOME_APPBAR (appbar));
-        gnome_appbar_push (GNOME_APPBAR (appbar), message);
+  if (context_id1)
+    gtk_statusbar_pop ((GtkStatusbar *) info_status, context_id1);
+  context_id1 =
+    gtk_statusbar_get_context_id ((GtkStatusbar *) info_status, message);
+  gtk_statusbar_push ((GtkStatusbar *) info_status, context_id1, message);
 }
 
-guint
-check_computer_players (void)
+void
+gui_hint (gint xy, gint score)
 {
-	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;
-		}
-	
-	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;
-		}
-
-	return TRUE;
+  gchar message[10];
+  
+  message[0] = (gchar) (xy / 10 + 0x40);
+  message[1] = (gchar) (xy % 10 + 0x30);
+  message[2] = 0x20;
+  sprintf (&message[3], _("%d"), score);
+  
+  gtk_entry_set_text (entry, message);
 }
 
 void
-set_bg_color (void)
+redraw_board (void)
 {
-	GdkImage *tmpimage;
-	GdkColor bgcolor;
+  guint i, j, which;
 
-	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 (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);
-
-	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);
+  copy_pixmaps ();
+  for (i = 0; i < 8; i++)
+    for (j = 0; j < 8; j++)
+    {
+      if (pixmaps[i][j] != BLANK)
+        which = (guint) (pixmaps[i][j] - BLACK_TURN + 1);
+      else
+        which = 0;
+      gui_draw_pixmap (which, i, j);
+    }
+  gui_draw_grid ();
+  gui_status ();
 }
 
-static int
-save_state (GnomeClient *client, gint phase, GnomeRestartStyle save_style,
-	    gint shutdown, GnomeInteractStyle interact_style,
-	    gint fast, gpointer client_data)
+void
+clear_board (void)
 {
-	char *argv[20];
-	int i;
-	gint xpos, ypos;
-
-	gdk_window_get_origin (window->window, &xpos, &ypos);
+  guint i, j;
 
-	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);
 
-	gnome_client_set_restart_command (client, i, argv);
-	gnome_client_set_clone_command (client, 0, NULL);
+  game_in_progress = FALSE;
+  move_count = 0;
+  for (i = 0; i < 8; i++)
+    for (j = 0; j < 8; j++)
+      board[i][j] = BLANK;
 
-	g_free (argv[2]);
-	g_free (argv[4]);
+  bcount = 0;
+  wcount = 0;
 
-	return TRUE;
+  redraw_board ();
 }
 
-int
-main (int argc, char **argv)
+void
+init_new_game (void)
 {
-	GnomeClient *client;
-
-	gnome_score_init ("iagno");
-
-	bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
-	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
-	textdomain (GETTEXT_PACKAGE);
-
-	gnome_program_init ("iagno", VERSION,
-			    LIBGNOMEUI_MODULE,
-			    argc, argv,
-			    GNOME_PARAM_POPT_TABLE, options,
-			    GNOME_PARAM_APP_DATADIR, DATADIR, NULL);
-	gnome_window_icon_set_default_from_file (GNOME_ICONDIR"/iagno.png");
-	client= gnome_master_client ();
+  if (flip_final_id)
+  {
+    g_source_remove (flip_final_id);
+    flip_final_id = 0;
+  }
+  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;
+  }
+  kifu [0][0] = 0;
+  init ();
+  copy_board ();
+  games_clock_stop (GAMES_CLOCK(b_time_status));
+  games_clock_stop (GAMES_CLOCK(w_time_status));
+  games_clock_set_seconds (GAMES_CLOCK(b_time_status), 0);
+  games_clock_set_seconds (GAMES_CLOCK(w_time_status), 0);
+  redraw_board ();
+  game_in_progress = TRUE;
+  gui_message (_("Dark's move"));
+  games_clock_start (GAMES_CLOCK(b_time_status));
+  check_computer_players ();
+}
+
+gboolean
+check_valid_moves (void)
+{
+  if (mobility (whose_turn))
+  {
+    if (whose_turn == BLACK_TURN)
+    {
+      gui_message (_("Dark's move"));
+      if (game_in_progress)
+        games_clock_start (GAMES_CLOCK(b_time_status));
+    }
+    else if (whose_turn == WHITE_TURN)
+    {
+      gui_message (_("Light's move"));
+      if (game_in_progress)
+        games_clock_start (GAMES_CLOCK(w_time_status));
+    }
+    return TRUE;
+  }
+
+  whose_turn = OTHER_PLAYER (whose_turn);
+  if (!mobility (whose_turn))
+  {
+    if (wcount > bcount)
+      gui_message (_("Light player wins!"));
+    if (bcount > wcount)
+      gui_message (_("Dark player wins!"));
+    if (wcount == bcount)
+      gui_message (_("The game was a draw."));
+    game_in_progress = FALSE;
+    
+    if (flip_final)
+      flip_final_id = g_timeout_add (computer_speed, flip_final_results, NULL);
+
+    gnome_sound_play (gameover_sound);
+    return FALSE;
+  }
+
+  if (whose_turn == BLACK_TURN)
+  {
+    gui_message (_("Light must pass, Dark's move"));
+    if (game_in_progress)
+      games_clock_start (GAMES_CLOCK(b_time_status));
+  }
+  else if (whose_turn == WHITE_TURN)
+  {
+    gui_message (_("Dark must pass, Light's move"));
+    if (game_in_progress)
+      games_clock_start (GAMES_CLOCK(w_time_status));
+  }
+  return TRUE;
+}
 
-	g_object_ref (G_OBJECT (client));
+gboolean
+check_computer_players (void)
+{
+  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 (black_computer_level && whose_turn == BLACK_TURN)
+    black_computer_id =  g_timeout_add (computer_speed,
+               (GSourceFunc) computer_move,
+               (gpointer) black_computer_level);
+
+  else if (white_computer_level && whose_turn == WHITE_TURN)
+    white_computer_id =  g_timeout_add (computer_speed,
+               (GSourceFunc) computer_move,
+               (gpointer) white_computer_level);
+
+  return FALSE;
+}
+
+gboolean
+move (guint x, guint y)
+{
+  guint xy;
+
+  if (!is_valid_move (x, y, whose_turn))
+    return FALSE;
+
+  xy = y * 10 + x;
+
+  if (game_in_progress)
+  {
+    kifu [move_count - 4][0] = (guint8) whose_turn;
+    kifu [move_count - 4][1] = (guint8) xy;
+    kifu [move_count - 3][0] = 0;
+    if (whose_turn == BLACK_TURN)
+      games_clock_stop (GAMES_CLOCK(b_time_status));
+    else
+      games_clock_stop (GAMES_CLOCK(w_time_status));
+  }
+  move_board (xy);
+  copy_board ();
+  gui_status ();
+  tiles_to_flip = TRUE;
+  play_sound = TRUE;
+  check_valid_moves ();
+  if (game_in_progress)
+    return check_computer_players ();
 
-	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]);
+  return FALSE;
+}
 
-	create_window ();
-	
-	load_properties ();
+gboolean
+flip_pixmaps (gpointer data)
+{
+  guint i, j, which;
 
-	load_pixmaps ();
+  if (!tiles_to_flip)
+    return TRUE;
 
-	if (session_xpos >= 0 && session_ypos >= 0) {
-		gdk_window_move (window->window, session_xpos, session_ypos);
-	}
+  if (play_sound)
+  {
+    gnome_sound_play (flip_sound);
+    play_sound = FALSE;
+  }
+
+  tiles_to_flip = FALSE;
+  for (i = 0; i < 8; i++)
+    for (j = 0; j < 8; j++)
+    {
+      if (pixmaps[i][j] == BLANK && board[i][j] != BLANK)
+      {
+        pixmaps[i][j] = board[i][j];
+        which = clamp_int ((gint) pixmaps[i][j], BLACK_TURN, WHITE_TURN);
+        gui_draw_pixmap (which - BLACK_TURN + 1, i, j);
+        tiles_to_flip = TRUE;
+      }
+      else if (pixmaps[i][j] != BLANK && board[i][j] == BLANK)
+      {
+        pixmaps[i][j] = BLANK;
+        gui_draw_pixmap (0, i, j);
+        tiles_to_flip = TRUE;
+      }
+      else if (pixmaps[i][j] < board[i][j] && board[i][j] != BLANK)
+      {
+        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] < BLACK_TURN)
+            pixmaps[i][j]++;
+          else if (pixmaps[i][j]>=BLACK_TURN && pixmaps[i][j]<BLACK_TURN+7)
+            pixmaps[i][j] = BLACK_TURN+7;
+          else if (pixmaps[i][j]>=BLACK_TURN+7 && pixmaps[i][j]<BLACK_TURN+15)
+            pixmaps[i][j] = BLACK_TURN+15;
+          else if (pixmaps[i][j]>=BLACK_TURN+15 && pixmaps[i][j]<BLACK_TURN+23)
+            pixmaps[i][j] = BLACK_TURN+23;
+          else if (pixmaps[i][j]>=BLACK_TURN+23 && pixmaps[i][j]<WHITE_TURN)
+            pixmaps[i][j] = WHITE_TURN;
+          else if (pixmaps[i][j]>WHITE_TURN)
+            pixmaps[i][j] = WHITE_TURN;
+        }
+        else if (animate == 2)
+          pixmaps[i][j]++;
+
+        which = clamp_int ((gint) pixmaps[i][j], BLACK_TURN, WHITE_TURN);
+        gui_draw_pixmap (which - BLACK_TURN + 1, i, j);
+        tiles_to_flip = TRUE;
+      }
+      else if (pixmaps[i][j] > board[i][j] && pixmaps[i][j] != BLANK)
+      {
+        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] > WHITE_TURN)
+            pixmaps[i][j]--;
+          else if (pixmaps[i][j]<=WHITE_TURN && pixmaps[i][j]>BLACK_TURN+23)
+            pixmaps[i][j] = BLACK_TURN+23;
+          else if (pixmaps[i][j]<=BLACK_TURN+23 && pixmaps[i][j]>BLACK_TURN+15)
+            pixmaps[i][j] = BLACK_TURN+15;
+          else if (pixmaps[i][j]<=BLACK_TURN+15 && pixmaps[i][j]>BLACK_TURN+7)
+            pixmaps[i][j] = BLACK_TURN+7;
+          else if (pixmaps[i][j]<=BLACK_TURN+7 && pixmaps[i][j]>BLACK_TURN)
+            pixmaps[i][j] = BLACK_TURN;
+          else if (pixmaps[i][j]<BLACK_TURN)
+            pixmaps[i][j] = BLACK_TURN;
+        }
+        else if (animate == 2)
+          pixmaps[i][j]--;
+
+        which = clamp_int ((gint) pixmaps[i][j], BLACK_TURN, WHITE_TURN);
+        gui_draw_pixmap (which - BLACK_TURN + 1, i, j);
+        tiles_to_flip = TRUE;
+      }
+    }
+
+  return TRUE;
+}
+
+gboolean
+flip_final_results (gpointer data)
+{
+  guint i;
+  gint8 adder = 0;
+
+  i = 0;
+  for (; i < bcount; i++)
+  {
+    board[i % 8][i / 8] = BLACK_TURN;
+    if (pixmaps[i % 8][i / 8] == BLANK)
+      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++;
+    }
+  }
+  for (; i < 64 - wcount; i++)
+  {
+    board[i % 8][i / 8] = BLANK;
+  }
+  for (; i < 64; i++)
+  {
+    board[i % 8][i / 8] = WHITE_TURN;
+    if (pixmaps[i % 8][i / 8] == BLANK)
+      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++;
+     }
+  }
 
-	gtk_widget_show (window);
+  tiles_to_flip = TRUE;
 
-	buffer_pixmap = gdk_pixmap_new (drawing_area->window,
-					BOARDWIDTH, BOARDHEIGHT, -1);
+  return FALSE;
+}
 
-	set_bg_color ();
+int
+main (int argc, char *argv[])
+{
+  gchar *tmp;
 
-	init_new_game ();
+  gnome_score_init ("iagno");
 
-	gtk_main ();
+#ifdef ENABLE_NLS
+  bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+  textdomain (GETTEXT_PACKAGE);
+#endif
+
+  gnome_program_init ("iagno", VERSION, LIBGNOMEUI_MODULE,
+          argc, argv, GNOME_PARAM_APP_DATADIR, DATADIR, NULL);
+
+  window = create_window ();
+  gtk_widget_show (window);
+
+  buffer_pixmap = gdk_pixmap_new (drawingarea->window,
+          BOARDWIDTH, BOARDHEIGHT, -1);
+  
+  tmp = g_build_filename ("iagno", _("flip-piece.wav"), NULL);
+  flip_sound = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_APP_SOUND,
+					tmp, TRUE, NULL);
+  g_free (tmp);
+  tmp = g_build_filename ("iagno", _("gameover.wav"), NULL);
+  gameover_sound = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_APP_SOUND,
+					tmp, TRUE, NULL);
+  g_free (tmp);
+
+  load_properties ();
+  reset_properties ();
+  load_pixmaps ();
+  set_bg_color ();
+  grid = 0;
+  clear_board ();
+  grid = t_grid;
+  gui_message (_("Welcome to Iagno!"));
+  redraw_board ();
 
-	return 0;
+  gtk_main ();
+  return 0;
 }
-
diff -uNr gnome-games-2.14.1.org/iagno/gnothello.h gnome-games-2.14.1/iagno/gnothello.h
--- gnome-games-2.14.1.org/iagno/gnothello.h	2006-08-05 15:32:11.000000000 +0900
+++ gnome-games-2.14.1/iagno/gnothello.h	2006-08-05 22:17:26.000000000 +0900
@@ -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
@@ -22,53 +21,108 @@
 #ifndef _GNOTHELLO_H_
 #define _GNOTHELLO_H_
 
-#define BLACK_TURN 1
-#define WHITE_TURN 31
-#define PIXMAP_FLIP_DELAY 20
-#define PIXMAP_STAGGER_DELAY 3
-#define COMPUTER_MOVE_DELAY 1000
-
-#define OTHER_PLAYER(w) (((w) == WHITE_TURN) ? BLACK_TURN : WHITE_TURN)
+/* For fast CPU, set CS = 0,
+   for slow CPU, set CS = 1 */
+#define CS          0
+#define BEST       54
+#define VICTORY   (20 - CS)
+#define PERFECT   (18 - CS)
+#define MAX_DEPTH ( 8 - CS)
+
+#define BLACK_TURN   1
+#define WHITE_TURN  31
+#define BLANK      127
+#define OUTSIDE (BLACK_TURN + WHITE_TURN)
+#define OTHER_PLAYER(who) (OUTSIDE - who)
+
+#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 TILEWIDTH   60
 #define TILEHEIGHT  60
-#define GRIDWIDTH   1
-#define BOARDWIDTH  ((TILEWIDTH+GRIDWIDTH)  * 8)
-#define BOARDHEIGHT ((TILEHEIGHT+GRIDWIDTH) * 8)
-
-void new_game_cb (GtkWidget *widget, gpointer data);
-void new_net_game_cb (GtkWidget *widget, gpointer data);
-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);
+#define GRIDWIDTH    1
+#define BOARDWIDTH  ((TILEWIDTH + GRIDWIDTH) * 8)
+#define BOARDHEIGHT ((TILEHEIGHT + GRIDWIDTH) * 8)
+#define PIXMAP_FLIP_DELAY     20
+#define PIXMAP_STAGGER_DELAY   3
+#define COMPUTER_MOVE_DELAY  800
+
+void on_open_activate (GtkMenuItem *menuitem, gpointer user_data);
+void on_save_activate (GtkMenuItem *menuitem, gpointer user_data);
+void on_quit_activate (GtkMenuItem *menuitem, gpointer user_data);
+void on_new_game_activate (GtkMenuItem *menuitem, gpointer user_data);
+void on_new_network_game_activate (GtkMenuItem *menuitem, gpointer user_data);
+void on_undo_activate (GtkMenuItem *menuitem, gpointer user_data);
+void on_hint_activate (GtkMenuItem *menuitem, gpointer user_data);
+void on_preference_activate (GtkMenuItem *menuitem, gpointer user_data);
+void on_about_activate (GtkMenuItem *menuitem, gpointer user_data);
+void on_newbutton_clicked (GtkToolButton *toolbutton, gpointer user_data);
+void on_undobutton_clicked (GtkToolButton *toolbutton, gpointer user_data);
+void on_headbutton_clicked (GtkToolButton *toolbutton, gpointer user_data);
+void on_backbutton_clicked (GtkToolButton *toolbutton, gpointer user_data);
+void on_forwardbutton_clicked (GtkToolButton *toolbutton, gpointer user_data);
+void on_lastbutton_clicked (GtkToolButton *toolbutton, gpointer user_data);
+void on_infobutton_clicked (GtkToolButton *toolbutton, gpointer user_data);
+void on_quitbutton_clicked (GtkToolButton *toolbutton, gpointer user_data);
+gboolean
+on_drawingarea_expose_event (GtkWidget *widget,
+			     GdkEventExpose *event, gpointer user_data);
+gboolean
+on_drawingarea_button_press_event (GtkWidget *widget,
+				   GdkEventButton *event, gpointer user_data);
+void
+on_entry_notify (GObject *gobject, GParamSpec *arg1, gpointer user_data);
+void
+on_bcomputer_level_changed (GtkToggleButton *togglebutton, gpointer user_data);
+void
+on_wcomputer_level_changed (GtkToggleButton *togglebutton, gpointer user_data);
+void
+on_quick_moves_toggled (GtkToggleButton *togglebutton, gpointer user_data);
+void
+on_animate_changed (GtkToggleButton *togglebutton, gpointer user_data);
+void
+on_stagger_flips_toggled (GtkToggleButton *togglebutton, gpointer user_data);
+void
+on_show_grid_toggled (GtkToggleButton *togglebutton, gpointer user_data);
+void
+on_flip_final_results_toggled (GtkToggleButton *togglebutton,
+						gpointer user_data);
+void on_tile_set_changed (GtkComboBox *combobox, gpointer user_data);
+void on_apply_button_clicked (GtkButton *button, gpointer user_data);
+void on_propaties_cancel_clicked (GtkButton *button, gpointer user_data);
+void on_ok_button_clicked (GtkButton *button, gpointer user_data);
+void on_file_open_cancel_clicked (GtkButton *button, gpointer user_data);
+void on_open_button_clicked (GtkButton *button, gpointer user_data);
+void on_file_save_cancel_clicked (GtkButton *button, gpointer user_data);
+void on_save_button_clicked (GtkButton *button, gpointer user_data);
+gint clamp_int (gint input, gint low, gint high);
+void load_properties (void);
+void set_flip_pixmaps_id (void);
 void load_pixmaps (void);
-void properties_cb (GtkWidget *widget, gpointer data);
-void set_bg_color (void);
-void gui_draw_grid (void);
+void reset_properties (void);
+void save_properties (void);
+void apply_changes (void);
+void write_kifu (int fd);
+void read_kifu (int fd);
+void gui_draw_pixmap (guint which, guint x, guint y);
+void gui_draw_pixmap_buffer (guint which, guint x, guint y);
+void gui_message (gchar * message);
+void gui_status (void);
+void gui_hint (gint xy, gint score);
+void redraw_board (void);
+void clear_board (void);
+void init_new_game (void);
+gboolean check_valid_moves (void);
+gboolean check_computer_players (void);
+gboolean move (guint x, guint y);
+gboolean flip_pixmaps (gpointer data);
+gboolean flip_final_results (gpointer data);
 
 #endif
Comment 1 mars1 2007-06-06 06:24:19 UTC
I made new iagno patch. Please try this patch.

Input next three svg files into iagno directory.

	coin.svg, marble.svg, sun_and_star.svg

My system are Fedore 7 and ggz-server-0.0.14 in /usr,

and configure options are next.

	# ./configure --with-ggz-dir=/usr --with-ggz-server

After installed files,

	$ cp /usr/local/etc/ggzd/games/* /etc/ggzd/rooms
	$ cp /usr/local/etc/ggzd/rooms/* /etc/ggzd/rooms

Please see appended screenshot.jpg.

I changed network protocol to new version.
Comment 2 mars1 2007-06-06 06:25:46 UTC
Created attachment 89447 [details] [review]
iagno new patch

iagno new patch
Comment 3 mars1 2007-06-06 06:26:47 UTC
Created attachment 89448 [details]
Screenshot

Screenshot
Comment 4 mars1 2007-06-06 06:27:50 UTC
Created attachment 89449 [details]
coin.svg

coin.svg
Comment 5 mars1 2007-06-06 06:28:24 UTC
Created attachment 89450 [details]
marble.svg

marble.svg
Comment 6 mars1 2007-06-06 06:28:58 UTC
Created attachment 89451 [details]
sun_and_star.svg

sun_and_star.svg
Comment 7 Andreas Røsdal 2007-06-06 17:09:04 UTC
Please document:

 - what is changed since the previous version of your patch
 - Why are these steps necessary?
      cp /usr/local/etc/ggzd/games/* /etc/ggzd/rooms
 - Why did you change the network protocol?
 - Please modify the patch so that only sun_and_star is installed. The other themes go in gnome-games-extra-data.
 - Did you fix the bugs and crashes that I reported in the previous version of the patch?


Comment 8 mars1 2007-06-07 04:58:17 UTC
Thank your comment, and I reply
 
I.   Changed

	1.	changed players list and chat from paned to dialog. 
	2.	added mute option in property dialog.
	3.	changed sound_play from gnome_sound_play to games_sound_play
	4.	changed tile_set_box from combo_box to fill_menu

II.  I mistook, next exactly.

	cp /usr/local/etc/ggzd/games/* /etc/ggzd/games

III. Reason of why I changed network protocol.

	1. more simple
	2. sync become more easy
	3. record history. 

IV.  Please remove other files from Makefile.am. 

V.   Maybe fixed.
Comment 9 mars1 2007-06-09 05:57:59 UTC
network game's bug

In network game's login window, game freeze.

1. Open network login window
2. Change Authentication type.
3. Change profile combo_box.

freeze

bugfix

In dependencies/login.c file comment out next 4 parts.
(function login_entry_changed, login_normal_toggled, login_guest_toggled
login_first_toggled)

/*
	if (!entries_update) {
		tmp = ggz_lookup_widget(login_dialog, "profile_entry");
		gtk_entry_set_text(GTK_ENTRY(tmp), "");
	}
*/
Comment 10 Andreas Røsdal 2007-06-09 07:45:21 UTC
Hello Mars1,

I have tested the patch, and I've had a look at the changes that you propose.
I must say that it is much better than the previous patch, but there still are many problems. Therefore, I must insist that we do these changes in several steps, and that we split the patch into smaller parts, so that we do only one mayor change at a time. I will commit each part to Subversion once I am satisfied with the result. The patch should therefore be split into these parts:

1. Main window improvements (resizable window, new toolbar, board numbering).
2. New preference dialog.
3. Saving/Loading, Redo support.
4. Network protocol changes

So please submit a patch which implements step 1 above. Then I will review it, and commit that to our Subversion repository. Once this change is approved, then we will move on to the next steps.
Comment 11 mars1 2007-06-10 07:29:37 UTC
I made old-protocol.patch and new-protocol.patch.

But in old protocol, network game crash when player move invalid position,
because get_sync are not implemented.

Maybe new-protocol have no problem.

I removed save and load menu.

Preference dialog are new, because it's difficult to put back to previews version.

Comment 12 mars1 2007-06-10 07:30:31 UTC
Created attachment 89677 [details] [review]
old-protocol.patch

old-protocol.patch
Comment 13 mars1 2007-06-10 07:31:23 UTC
Created attachment 89678 [details] [review]
new-protocol.patch

new-protocol.patch
Comment 14 Andreas Røsdal 2007-06-10 10:54:11 UTC
Thanks for the update. Please fix the crash, then I will review your patch. 
Comment 15 mars1 2007-06-10 16:58:17 UTC
I'm sorry, I can't fix up old protocol on my program,
because my program record history, but old protocol's
get_sync don't record history.
Therefore if I use old protocol, my program crash necessarily. 
My program have to use new protocol necessarily.

Now new protocol have no problem, but old have many.

I think new protocol are better than old for my program.
Comment 16 mars1 2007-06-10 17:00:52 UTC
Created attachment 89705 [details] [review]
with-save-open-menu.patch

new protocol and with save open menu patch
Comment 17 Andreas Røsdal 2007-06-10 17:03:45 UTC
Please listen to the feedback I give, or else the patch will never get accepted.
It's all described in comment #10.
Comment 18 mars1 2007-06-12 02:56:09 UTC
Created attachment 89788 [details] [review]
old-protocol.patch

This patch use old protocol and don't crash, but don't support get_sync,
and use new preference dialog, and save and open menu are removed.
Comment 19 Andreas Røsdal 2007-06-12 17:44:16 UTC
Thanks for the updated patch, mars1. I like it very much.

Now, I would like to see these improvements to the patch:

1. Resizing the window to a smaller size is very slow, compared to resizing the window to a larger size. So making the main window smaller takes a long time. Could you please try to improve the performance or update speed when scaling the main window to a smaller size?

2. When starting Iagno, a new game should be started automatically. With your patch, I have to click select "New" on the Game menu first. It would be better if the game started automatically when Iagno has started. As your patch is now, clicking on the pieces on the board immediately after Iagno has been started has no effect, which is confusing to me.

3. Please keep the old preference dialog for now. I want the new preference dialog in a separate patch, because I have many comments about your preference dialog. Please see our plan in Comment #10. If you have deprecated some of the alternatives in the old preference dialog with your patch, then you can comment out those alternatives from the old preference dialog.

4. I would _really_ like if you could put the green "top", "back", "forward" and "last" buttons on the bottom of the screen. And put the statusbar in the middle. What I am describing here is consistent with the other games, such as glChess. Take a look at a screenshot of glChess here: http://live.gnome.org/glChess  If you could give the new Iagno an identical toolbar on the bottom of the screen, that would be excellent. The toolbar on the top should contain the buttons "New", "Hint", and "End game".

We both want the new Iagno to be very good, so we should cooperate, and have a good process for improving Iagno. Good luck with your next patch.
Comment 20 mars1 2007-06-14 15:35:53 UTC
Created attachment 89956 [details] [review]
old-protocol.patch

1. Resizing the window are too slow.
        I changed to faster resizing program. 

2. Start automatically.
        I changed so.

3. Preference dialog.
        New version's options are many different from current.
        therefor preference dialog should be different from current.
        I think that new preference dialog are more better than current.
        ( Options are effective in default.)

4. Toolbar.
        In network game mode toolbar are hide, and with option done so.
        therefore toolbar should be one.
        And it's usually thing that toolbar are under the menu bar,
        glchess should do so.
        "Back" stop the game, and "Redo" are necessary to restart the game
        from that point.
Comment 21 Andreas Røsdal 2007-06-14 16:21:12 UTC
Hello Mars1,

Thanks for the updated patch. You have changed two of the four requests that I had in Comment #19. 


3. Preference dialog:

You must remove the new preference dialog from the patch. There are many obvious problems with the new preference dialog, which need to be fixed before it can be accepted. I therefore want this is a separate patch. For example, the preference dialog contains several bad spelling errors ("None animation"), and bad problems related to the GNOME Human Interface Guidelines (wrong usage of buttons and duplicated frame-titles). Your changes will NOT get accepted with the new preference dialog. Please remove the new preference dialog from the patch, and keep the old. This is not negotiable.


4. Toolbar:

I really like consistency between the games in gnome-games. This new toolbar is different from all the other other games in gnome-games, and you haven't given any arguments for why it should be different. These are changes which are non-negotiable:  
4.1 There should be only one statusbar at the bottom of the screen in Iagno. Your patch results in two statusbars at the bottom; the regular and a textfield. 
4.2 Rearrange the items on the toolbar to be consistent with the other games in gnome-games. For example, "New Game" should be to the left, and the redo button should be removed.

So please read comment #10 and #19 again, and send an updated patch. Your changes will not get accepted until they meet these requirements. 
I'm looking forward to your next patch.
Comment 22 mars1 2007-06-16 13:25:27 UTC
Created attachment 90068 [details]
Screenshot

3. Preference dialog:

I put back preference dialog's style to current style.
Of course computer level number and options are different from current,
so that are not same as current at all. but the style are same as current.
Please see screenshot-1.jpg.

4. Toolbar:

4.1 Two statusbars.
Textfield are necessary to display hint and to input from keyboard.

4.2 "Redo" and "New Game".
I removed "Redo" and moved "New Game" button to the left,

I changed "Top", "Back", "Forward" and "Last" to sensitive
only when those are effective.
And I changed to show toolbar in network game mode too.
Toolbar are hide by only option. 
I changed tool-tips to same as gnome games stocks,
 and appended a fullscreen menu.
Comment 23 mars1 2007-06-16 13:27:39 UTC
Created attachment 90069 [details] [review]
old-protocol.patch

old-protocol.patch
Comment 24 Andreas Røsdal 2007-06-16 14:25:53 UTC
Keep the old preference dialog and statusbar. Please read comment #21, and resubmit the patch. 
Comment 25 mars1 2007-06-17 12:08:23 UTC
Created attachment 90134 [details]
Screenshot2

3. Dialog

I changed dialog to current. It's same as current.
I only changed 3 radio buttons to check buttons.
But now player can't select background color.

4. Textfield.

I moved textfield to under the toolbar.
Now there are only one line at bottom of window.
Comment 26 mars1 2007-06-17 12:09:22 UTC
Created attachment 90135 [details] [review]
old-protocol.patch

old-protocol.patch
Comment 27 Andreas Røsdal 2007-06-17 18:58:49 UTC
I have now tested the patch again. There are many obvious mistakes that you should have fixed yourself, before submitting an updated patch. Here are my comments on the latest patch:

- Main game window
Please make the main game window according to the screen design which I will attach next. It closely matches the current design. You can submit more changes to the main window in a later patch. This is not negotiable.

- Compilation warning:
properties.c:270: warning: ‘on_color_button_color_set’ defined but not used
This is something you should have spotted and fixed yourself before submitting a patch.

- Preference dialog:
You should keep the old preference dialog, and it should still continue to work with Iagno as it used to previously. The alternatives in the preference dialog doesn't work with your patch. When I open the preference dialog, this assertion is triggered:
(iagno:11158): GLib-CRITICAL **: g_timer_continue: assertion `timer->active == FALSE' failed

- Network games:
The toolbar of Iagno in network games contains the button "Chat window". However, it is without any icon, while all the other buttons on the toolbar have icons. This looks bad.

-GGZ changes:
I would like the GGZ changes in a separate patch later.

Good luck with the next patch. Please test it properly, make sure that it doesn't contain any compilation warnings, runtime assertions or memory leaks. I will not commit a poor quality patch. I will continue to ask for improvements until it is good enough, so you might just as well get things right the first time.
Comment 28 Andreas Røsdal 2007-06-17 18:59:38 UTC
Created attachment 90158 [details]
Iagno screen design (mandatory)
Comment 29 Andreas Røsdal 2007-06-17 19:02:20 UTC
One more comment, which I forgot to say in comment #27:

- When the main window is too small to fit all the buttons on the toolbar,
then you should remove all the 4 green "back" and "forward" buttons on the toolbar. Once the main window is large enough to fit them all, then you can add the 4 navigation buttons again.
Comment 30 mars1 2007-06-19 02:57:02 UTC
Created attachment 90250 [details]
Screenshot3

- Main game window and Comment #29
I changed so, please see screenshot-3.

- Compilation warning:
I fixed.

- Preference dialog:
I changed so.

Assertion.
I fixed.

- Network games:
I removed "Chat" button.


For dialog options.

Use quick moves   --->  Use quick moves
Enable sounds     --->  Enable sounds
Animation-None    --->  Show timer
Animation-Complete -->  Hide last move mark
Stagger flips     --->  Hide valid squares
Show grid         --->  Show toolbar
Flip final results -->  Flip final results
And I request a color_button.

I think it's better that options are effective in default.
For example, "Hide toolbar" is better than "Show toolbar". 

In network game mode, the dialog dont display "Game" page.
Comment 31 mars1 2007-06-19 02:58:52 UTC
Created attachment 90251 [details] [review]
old-protocol.patch
Comment 32 mars1 2007-06-20 06:51:07 UTC
Network game's bug. (iagno, gnibbles, glines)

Inputing <ctrl> L or <ctrl> E at not networkgame mode, crash the game.

Bug fix.
In menu select callbacks,

void
on_playerlist_activate (GtkMenuItem *menuitem, gpointer user_data)
{
  if (!ggz_network_mode)  <----
    return;               <----  
  create_or_raise_dlg_players (GTK_WINDOW (window));
}

void
on_chat_activate (GtkMenuItem *menuitem, gpointer user_data)
{
  if (!ggz_network_mode)  <----
    return;               <----
  create_or_raise_dlg_chat (GTK_WINDOW (window));
}

void
on_leave_activate (GtkMenuItem *menuitem, gpointer user_data)
{
  if (!ggz_network_mode)  <----
    return;               <----
  ggz_embed_leave_table ();
  gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), NETWORK_PAGE);
}
Comment 33 Andreas Røsdal 2007-06-24 16:16:47 UTC
Here's a summary of my opinion of this patch currently:

- I would like this new version of Iagno to be ready to be committed to SVN initially during the GNOME 2.21.x development cycle, which means around September 24th 2007. It's not stable enough to be committed during this development cycle.

- I would also really like some feedback from others on this patch.

So Mars1, you can continue to improve this patch until September. Do not add new features, only make sure that it is stable and without bugs.
Comment 34 mars1 2007-06-25 01:16:41 UTC
Created attachment 90597 [details] [review]
new.patch

Some bug fixed.

1. The current protocol have some bugs.

In the file server.c, even if the function "game_handle_move" return error,
the function "game_handle_player" haven't any processing for that error.
and return nothing to the client. The client can't understand why the game stopped.


I changed the new protocol to upper compatible with the current protocol.
Now the new client can connect with the old server, and the old client can connect
with the new server too. And the new server support sync with the new client.

On the new protocol, even after one player disconnect with the server on the game,
if he connect with the server again, he can restart the game with another player.

2. "ggz-gtk" bug.

Connecting with same name as already used in server, crash the game.

(iagno:29982): Pango-CRITICAL **: pango_layout_set_text: assertion `layout != NULL' failed
(iagno:29982): Pango-CRITICAL **: pango_layout_get_pixel_extents: assertion `PANGO_IS_LAYOUT (layout)' failed
Comment 35 mars1 2007-06-27 12:31:56 UTC
Created attachment 90748 [details] [review]
new-protocol.patch
Comment 36 Andreas Røsdal 2007-06-27 13:34:22 UTC
What do you mean "new-protocol" in comment #35? If you want to change the network protocol, then please submit this as a separate patch.
Comment 37 mars1 2007-07-01 09:56:14 UTC
Created attachment 90959 [details] [review]
new-protocol.patch

Only the new protocol parts.

This patch change the current iagnos protocol to the new protocol.

This protocol are upper convertible with the current protocol.
The new client can connect with the old server,
and the old client can connect with the new server too.
The new client can sync with the new server.
On the new protocol, even after one player disconnect with
the server on the game, if he connect with the server again,
he can restart the game with the another player.
Comment 38 mars1 2007-07-01 10:08:56 UTC
Created attachment 90960 [details] [review]
new-iagno.patch
Comment 39 mars1 2007-07-03 14:47:57 UTC
Comment on attachment 90959 [details] [review]
new-protocol.patch

>Index: iagno/gnothello.h
>===================================================================
>--- iagno/gnothello.h	(リビジョン 6478)
>+++ iagno/gnothello.h	(作業コピー)
>@@ -40,10 +40,6 @@
> #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;
>@@ -83,5 +79,5 @@
> void properties_cb (GtkWidget * widget, gpointer data);
> void set_bg_color (void);
> void gui_draw_grid (void);
>-
>+void redraw_board (void);
> #endif
>Index: iagno/server.c
>===================================================================
>--- iagno/server.c	(リビジョン 6478)
>+++ iagno/server.c	(作業コピー)
>@@ -1,5 +1,7 @@
>+/* -*- mode:C; indent-tabs-mode:t; tab-width:8; c-basic-offset:8; -*- */
>+
> /*
>- * File: main.c
>+ * File: server.c
>  * Author: Ismael Orenstein
>  * Project: GGZ Reversi game module
>  * Date: 09/17/2000
>@@ -26,612 +28,610 @@
> #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"
> 
>-// Global game variables
>-struct rvr_game_t rvr_game;
>+#define BLACK           49
>+#define WHITE           79
>+#define BLANK           1
>+#define OUTSIDE           (BLACK + WHITE - 1)
>+#define OTHER_PLAYER(who) (OUTSIDE - who + 1)
> 
>+#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
> 
>-// Initializes everything
>-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));
>-}
>+static const gint dirs[] = { UL, UU, UR, LL, RR, DL, DD, DR };
> 
>-// 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;
>+static const gchar *strs[] = {
>+  "Invalid move\n",              /* -1 */
>+  "Wrong turn\n",                /* -2 */
>+  "Skip move\n",                 /* -3 */
>+  "Can't read message\n",        /* -4 */
>+  "Can't send message\n",        /* -5 */
>+  "Not playing error\n",         /* -6 */
>+  "Play again error\n",          /* -7 */
>+  "Unknown opcode\n"             /* -8 */
>+};
> 
>-  // 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;
>-  }
>+// Global game variables
>+static guint8 squares[] = {
>+  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,
>+  74, 75, 47, 57, 36, 63, 33, 35,
>+  53, 66, 46, 64, 34, 43, 56, 65,
>+  12, 17, 21, 71, 28, 78, 82, 87,
>+  22, 27, 72, 77, 11, 18, 81, 88
>+};
> 
>-  if (new_state == GGZDMOD_STATE_PLAYING) {
>-    // Game already going on?
>-    if (rvr_game.turn == EMPTY)
>-      rvr_game.turn = BLACK;
>+static gint8   board0[100];
>+static gint    vsquares[40];
>+static guint   move_count;
>+static guint   whose_turn;
>+static guint   bcount;
>+static guint   wcount;
>+static guint   count;
>+static int     kifu[61][2];
>+static GGZdMod *ggz;
>+static int     state;
> 
>-    // 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");
>-  }
>-}
>+static int game_make_move (int player, int yx);
> 
>+/**** Othello AI program ****/
> 
>-static int
>-seats_full (void)
>+/* Initialization of data */
>+static void
>+init (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;
>-}
>+  guint i, j, ij = 0;
> 
>+  for (i = 0; i < 10; i++)
>+    for (j = 0; j < 10; j++) {
>+      if (i == 0 || i == 9 || j == 0 || j == 9)
>+        board0[ij++] = OUTSIDE;
>+      else
>+        board0[ij++] = BLANK;
>+    }
>+  board0[44] = WHITE;
>+  board0[45] = BLACK;
>+  board0[54] = BLACK;
>+  board0[55] = WHITE;
> 
>-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;
>+  move_count = 0;
>+  bcount     = 2;
>+  wcount     = 2;
>+  whose_turn = BLACK;
> }
> 
>-
>-void
>-game_handle_ggz_seat (GGZdMod * ggz, GGZdModEvent event, const void *data)
>+static gboolean
>+is_valid0 (guint who, guint yx, gint dir)
> {
>-  const GGZSeat *old_seat = data;
>-  GGZSeat new_seat = ggzdmod_get_seat (ggz, old_seat->num);
>-  GGZdModState new_state;
>+  guint tmp = yx + dir;
>+  gint8 not_me = (gint8) OTHER_PLAYER (who);
> 
>-  /* 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 (board0[tmp] != not_me)
>+    return FALSE;
> 
>-  // That's great!! Do stuff
>+  do {
>+    tmp += dir;
>+  } while (board0[tmp] == not_me);
> 
>-  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);
>+  return board0[tmp] == (gint8) who;
> }
> 
>-
>-int
>-game_send_seat (int seat)
>+/* Check if a given (empty) square can provide a valid move */
>+static gboolean
>+is_valid (guint who, guint yx)
> {
>-  int fd = ggzdmod_get_seat (rvr_game.ggz, seat).fd;
>+  guint i;
> 
>-  ggzdmod_log (rvr_game.ggz, "Sending player %d's his seat number\n", seat);
>+  for (i = 0; i < NDIRS; i++)
>+    if (is_valid0 (who, yx, dirs[i]))
>+      return TRUE;
> 
>-  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;
>-  }
>-
>-  return 0;
>+  return FALSE;
> }
> 
>-int
>-game_send_players (void)
>+static void
>+move_board0 (guint yx, gint dir)
> {
>-  int i, j, fd;
>+  guint tmp = yx + dir;
>+  gint8 not_me = (gint8) OTHER_PLAYER (whose_turn);
> 
>-  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 (board0[tmp] != not_me)
>+    return;
> 
>-    if (ggz_write_int (fd, RVR_MSG_PLAYERS) < 0) {
>-      ggzdmod_log (rvr_game.ggz, "Can't send player list!\n");
>-      return -1;
>-    }
>+  do {
>+    tmp += dir;
>+  } while (board0[tmp] == not_me);
> 
>-    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;
>-      }
>-    }
>+  if (board0[tmp] != (gint8) whose_turn)
>+    return;
>+
>+  tmp -= dir;
>+  while (tmp != yx) {
>+    board0[tmp] = (gint8) whose_turn;
>+    count++;
>+    tmp -= dir;
>   }
>-
>-  return 0;
> }
> 
>-int
>-game_send_sync (int seat)
>+/* reverse some pieces */
>+static void
>+move_board (guint yx)
> {
>-  int i, fd = ggzdmod_get_seat (rvr_game.ggz, seat).fd;
>+  guint i, tmp;
> 
>-  ggzdmod_log (rvr_game.ggz, "Handling sync for player %d", seat);
>+  count = 0;
>+  for (i = 0; i < NDIRS; i++)
>+    move_board0 (yx, dirs[i]);
> 
>-  // Send SYNC message and current turn
>+  board0[yx] = (gint8) whose_turn;
> 
>-  if (ggz_write_int (fd, RVR_MSG_SYNC) < 0
>-      || ggz_write_char (fd, rvr_game.turn) < 0)
>-    return -1;
>+  i = move_count++ + 4;
>+  tmp = (guint) squares[i];
>+  squares[i] = (guint8) yx;
>+  if (tmp != yx) {
>+    while (squares[++i] != (guint8) yx);
>+    squares[i] = (guint8) tmp;
>+  }
> 
>-  // Send current board state
>-
>-  for (i = 0; i < 64; i++) {
>-    if (ggz_write_char (fd, rvr_game.board[i]) < 0)
>-      return -1;
>+  if (whose_turn == WHITE) {
>+    wcount += count + 1;
>+    bcount -= count;
>+  } else {
>+    bcount += count + 1;
>+    wcount -= count;
>   }
> 
>-  // That's fine
>-
>-  return 0;
>-
>+  whose_turn = OTHER_PLAYER (whose_turn);
> }
> 
>-int
>-game_start (void)
>+static guint
>+entry_valid_move (void)
> {
>+  guint yx, i, j = 0;
> 
>-  int i, fd;
>+  for (i = move_count + 4; i < 64; i++) {
>+    yx = (guint) squares[i];
>+    if (is_valid (whose_turn, yx)) {
>+      vsquares[j++] = (gint) yx;
>+    }
>+  }
> 
>-  // Start game variables
>-  rvr_game.state = RVR_STATE_PLAYING;
>+  return j;
>+}
> 
>-  // 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;
>-  }
>+/**** Server program ****/
> 
>-  ggzdmod_log (rvr_game.ggz, "Game has started!\n");
>-
>-  return 0;
>+// Initializes everything
>+static void
>+game_init (GGZdMod *ggzdmod)
>+{
>+  init ();
>+  /* move_count = 0; bcount = wcount = 2; whose_turn = BLACK; */
>+  ggz        = ggzdmod;
>+  kifu[0][0] = 0;
>+  state      = RVR_STATE_INIT;
> }
> 
>-/* return -1 on error, 1 on gameover */
>-void
>-game_handle_player (GGZdMod * ggz, GGZdModEvent event, const void *data)
>+static int
>+game_check_bot (void)
> {
>-  const int *seat_ptr = data;
>-  const int seat = *seat_ptr;
>-  int op, move;
>-  int fd = ggzdmod_get_seat (ggz, seat).fd;
>+  int seat = PLAYER2SEAT (whose_turn);
> 
>-  if (ggz_read_int (fd, &op) < 0)
>-    return;
>+  // 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;
> 
>-  switch (op) {
>+  // Yes! Wait for a second
>+  sleep (1);
>+  return game_make_move ((int) whose_turn, (int) vsquares[0]);
>+}
> 
>-  case RVR_REQ_MOVE:
>-    game_handle_move (seat, &move);
>-    break;
>+static int
>+game_skip_move (void)
>+{
>+  int seat, fd;
> 
>-  case RVR_REQ_SYNC:
>-    game_send_sync (seat);
>-    break;
>+  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, RVR_ERROR_CANTMOVE) < 0))
>+      return RVR_ERROR_CANTWRITE;
>+  }
> 
>-  case RVR_REQ_AGAIN:
>-    game_play_again (seat);
>-    break;
>-
>-  default:
>-    ggzdmod_log (rvr_game.ggz, "ERROR: unknown player opcode %d.", op);
>-    break;
>-  }
>+  return game_check_bot ();
> }
> 
>-int
>-game_handle_move (int seat, int *move)
>+static int
>+game_check_over (void)
> {
>-  int fd = ggzdmod_get_seat (rvr_game.ggz, seat).fd, status;
>+  int seat, fd, winner;
>+  GGZGameResult results[2];
> 
>-  // Get the move from the message
>-  if (ggz_read_int (fd, move) < 0)
>-    return -1;
>+  if (entry_valid_move ())
>+    return game_check_bot ();
> 
>-  ggzdmod_log (rvr_game.ggz, "Handling move %d,%dfor player %d\n", X (*move),
>-	       Y (*move), seat);
>+  whose_turn = OTHER_PLAYER (whose_turn);
>+  if (entry_valid_move ())
>+    return game_skip_move ();
> 
>-  // Check if it's his turn
>-  if (SEAT2PLAYER (seat) != rvr_game.turn) {
>-    status = RVR_ERROR_WRONGTURN;
>+  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 {
>-    // Check if it's valid (status return a negative value if error, the move on sucess)
>-    status = game_check_move (SEAT2PLAYER (seat), *move);
>+    winner = 0;
>+    results[0] = results[1] = GGZ_GAME_TIE;
>   }
> 
>-  // Make move if it's valid (also sends it to everyone);
>-  game_make_move (SEAT2PLAYER (seat), status);
>+  // Report game to GGZ 
>+  ggzdmod_report_game (ggz, NULL, results, NULL);
> 
>-  return status;
>+  // 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 RVR_ERROR_CANTWRITE;;
>+  }
> 
>+  // Ends everything
>+  game_init (ggz);
>+  state = RVR_STATE_DONE;
>+  whose_turn = 0;
>+  bcount = wcount = 0;
>+  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;
>+  ggzdmod_log (ggz,
>+  "Game is over. Waiting to see if we should play again\n");
>+
>+  return SERVER_OK;
> }
> 
>-void
>-game_play (void)
>+static int
>+game_start (void)
> {
>-  int move;
>-  int seat = PLAYER2SEAT (rvr_game.turn);
>+  int fd, seat;
> 
>-  // 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);
>+  // Start game variables
>+  state = RVR_STATE_PLAYING;
>+
>+  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 RVR_ERROR_CANTWRITE;
>   }
>-  // It's not! Wait until the player sends the message...
> 
>-  return;
>+  ggzdmod_log (ggz, "Game has started!\n");
>+  return game_check_over ();
> }
> 
>-int
>-game_bot_move (int player)
>+// 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 i;
>+  ggzdmod_log (ggz, "%d wants to play again!\n", seat);
> 
>-  // 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);
>+  // Check game is finished or not. 
>+  if (whose_turn) {
>+    if (ggz_write_int (fd, RVR_MSG_MOVE) < 0
>+        || ggz_write_int (fd, RVR_ERROR_PLAYAGAIN) < 0)
>+      return RVR_ERROR_CANTWRITE;
>+    return RVR_ERROR_PLAYAGAIN;
>+  }
>+
>+  if (fd != -1 && ggz_write_int (fd, RVR_MSG_INIT) < 0)
>+      return RVR_ERROR_CANTWRITE;
>+
>+  if (SEAT2PLAYER (seat) == WHITE) 
>+    wcount = 1;
>+  else if (SEAT2PLAYER (seat) == BLACK)
>+    bcount = 1;
>+
>+  if (!bcount || !wcount) {
>+    state = RVR_STATE_WAITING;
>+    return SERVER_OK;
>+  }
>+
>+  // Starts again
>+  bcount = wcount = 2;
>+  whose_turn = BLACK;
>+ return game_start ();
> }
> 
>-int
>-game_check_move (int player, int move)
>+static int
>+game_check_move (int player, int yx)
> {
>-
>-  int x = X (move), y = Y (move), status = 0;
>-
>   // Check if it's right time
>-  if (rvr_game.state != RVR_STATE_PLAYING)
>+  if (state != RVR_STATE_PLAYING)
>+    return RVR_ERROR_NOTPLAYING;
>+  // Check if it's his turn
>+  if (player != whose_turn)
>     return RVR_ERROR_WRONGTURN;
>-
>   // Check if out of bounds
>-  if (move < 0 || move > 63)
>+  if (yx < 0 || yx > 99)
>     return RVR_ERROR_INVALIDMOVE;
>-
>   // Check if duplicated
>-  if (rvr_game.board[move] != EMPTY)
>+  if (board0[yx] != BLANK)
>     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
>+  // Check if valid yx
>+  if (!is_valid (player, yx))
>     return RVR_ERROR_INVALIDMOVE;
> 
>+  return SERVER_OK;
> }
> 
>-int
>-game_check_direction (int player, int vx, int vy, int x, int y)
>+static int
>+game_make_move (int player, int yx)
> {
>-  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 fd, seat;
> 
>-int
>-game_make_move (int player, int move)
>-{
>-  int x = X (move), y = Y (move);
>-  int status = 0;
>-  int a, fd;
>+  kifu[move_count][0]     = player;
>+  kifu[move_count][1]     = yx;
>+  kifu[move_count + 1][0] = 0;
>+  move_board ((guint) yx);
> 
>-  // 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)
>-      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;
>+  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, NEW2OLD (yx))) < 0)
>+      return RVR_ERROR_CANTWRITE;
>   }
> 
>   // Check if game is over
>-  if (status >= 0 && !game_check_over ()) {
>+  return game_check_over ();
>+}
> 
>-    // AI play
>-    game_play ();
>+static int
>+game_send_sync (int seat)
>+{
>+  int fd = ggzdmod_get_seat (ggz, seat).fd;
>+  int i = 0;
> 
>+  ggzdmod_log (ggz, "Handling sync for player %d", seat);
>+
>+  // Send SYNC message
>+  if (ggz_write_int (fd, RVR_MSG_SYNC) < 0)
>+    return RVR_ERROR_CANTWRITE;
>+  // Send kifu
>+  while (kifu[i][0]) {
>+    if (ggz_write_int (fd, kifu[i][0]) < 0
>+        || ggz_write_int (fd, kifu[i++][1]) < 0)
>+      return RVR_ERROR_CANTWRITE;
>   }
>-  // If couldn`t make the move, sends sync to the player
>-  if (status < 0)
>-    game_send_sync (PLAYER2SEAT (player));
>+  // Send end mark and current turn.
>+  // For the compatibility with the old protocol.
>+  // Old client are waiting for the seat, therefor send dummy seat.
>+  if (ggz_write_int (fd, 0) < 0 || ggz_write_int (fd, whose_turn) < 0)
>+    return RVR_ERROR_CANTWRITE;
> 
>-  return status;
>-
>+  // That's fine
>+  return SERVER_OK;
> }
> 
>-int
>-game_check_over (void)
>+static int
>+game_handle_move (int seat, int *move)
> {
>-  int i, status = 0;
>+  int yx, status, fd = ggzdmod_get_seat (ggz, seat).fd;
> 
>-  // Check if the current player can play
>-  for (i = 0; i < 64; i++) {
>-    if (game_check_move (rvr_game.turn, i) > 0) {
>-      status++;
>-      break;
>-    }
>-  }
>+  // Get the yx from the message
>+  if (ggz_read_int (fd, move) < 0)
>+    return RVR_ERROR_CANTREAD;
> 
>-  // If he can play, the game is not over
>-  if (status > 0)
>-    return 0;
>+  yx = OLD2NEW (*move);
>+  ggzdmod_log (ggz, "Handling move %d, for player %d\n", yx, seat);
> 
>-  // 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;
>-    }
>+  // Check if it's valid
>+  status = game_check_move (SEAT2PLAYER (seat), yx);
>+  if (status < 0) {
>+    // If invalid yx, sends sync and status to the player.
>+    game_send_sync (seat);
>+    if (ggz_write_int (fd, RVR_MSG_MOVE) < 0
>+        || ggz_write_int (fd, status) < 0)
>+      return RVR_ERROR_CANTWRITE;
>+    return SERVER_OK;
>   }
>+  // Make move if it's valid (also sends it to everyone);
>+  return game_make_move (SEAT2PLAYER (seat), yx);
>+}
> 
>-  // If he can, then skip the players move.
>-  // If he can't, end the game
>+static int
>+seats_full (void)
>+{
>+  /* 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);
>+}
> 
>-  if (status > 0)
>-    game_skip_move ();
>-  else {
>-    game_gameover ();
>-    return 1;
>-  }
>-
>-  return 0;
>+static int
>+seats_empty (void)
>+{
>+  /* This calculation is a bit inefficient, but that's OK */
>+  return !ggzdmod_count_seats (ggz, GGZ_SEAT_PLAYER)
>+    && !ggzdmod_count_spectators (ggz);
> }
> 
>+static int
>+game_send_seat (int seat)
>+{
>+  int fd = ggzdmod_get_seat (ggz, seat).fd;
> 
>+  ggzdmod_log (ggz, "Sending player %d's his seat number\n", seat);
> 
>+  if (ggz_write_int (fd, RVR_MSG_SEAT) < 0
>+      || ggz_write_int (fd, seat) < 0)
>+    return RVR_ERROR_CANTWRITE;
> 
>-
>-int
>-game_mark_board (int player, int vx, int vy, int x, int y)
>-{
>-  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;
>+  return SERVER_OK;
> }
> 
>-void
>-game_skip_move (void)
>+static int
>+game_send_players (void)
> {
>-  int seat;
>+  int i, j, fd;
> 
>-  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");
>+  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;
>     }
>-  }
> 
>-  rvr_game.turn *= -1;
>+    ggzdmod_log (ggz, "Sending player list to player %d", j);
>+    if (ggz_write_int (fd, RVR_MSG_PLAYERS) < 0)
>+      return RVR_ERROR_CANTWRITE;
> 
>-  return;
>+    for (i = 0; i < ggzdmod_get_num_seats (ggz); i++) {
>+      if (ggz_write_int (fd, ggzdmod_get_seat (ggz, i).type) < 0)
>+        return RVR_ERROR_CANTWRITE;
>+      if (ggzdmod_get_seat (ggz, i).type != GGZ_SEAT_OPEN &&
>+          ggz_write_string (fd, ggzdmod_get_seat (ggz, i).name) < 0)
>+        return RVR_ERROR_CANTWRITE;
>+    }
>+  }
> 
>+  return SERVER_OK;
> }
> 
>-void
>-game_gameover (void)
>+static void
>+game_handle_player (GGZdMod *ggzdmod, GGZdModEvent event,
>+                    const void *data)
> {
>-  int seat, fd, winner;
>-  GGZGameResult results[2];
>+  const int *seat_ptr = data;
>+  const int seat = *seat_ptr;
>+  int op, yx, err;
>+  int fd = ggzdmod_get_seat (ggzdmod, seat).fd;
> 
>-  // Ends everything
>-  rvr_game.turn = EMPTY;
>-  rvr_game.state = RVR_STATE_DONE;
>+  if (ggz_read_int (fd, &op) < 0)
>+    return;
> 
>-  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;
>+  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 = RVR_ERROR_OPCODE;
>+    break;
>   }
> 
>-  /* Report game to GGZ */
>-  ggzdmod_report_game (rvr_game.ggz, NULL, results, NULL);
>+  if (err < RVR_ERROR_OPCODE)
>+    err = RVR_ERROR_OPCODE;
>+  if (err < 0)
>+    ggzdmod_log (ggzdmod, strs[-err - 1]);
>+}
> 
>-  // 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");
>-  }
>+static void
>+game_handle_ggz_seat (GGZdMod *ggzdmod, GGZdModEvent event,
>+                      const void *data)
>+{
>+  const GGZSeat *old_seat = data;
>+  GGZSeat new_seat = ggzdmod_get_seat (ggzdmod, old_seat->num);
>+  GGZdModState new_state;
> 
>-  // 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);
>+  // 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;
> 
>-  return;
>+  // For the compatibility with the old protocol,
>+  // game_send_sync should be before game_send_seat.
>+  // New sync make for the old client to mitake get_seat.
>+  if (new_state == GGZDMOD_STATE_PLAYING && whose_turn != 0)
>+    game_send_sync (new_seat.num);
> 
>+  // That's great!! Do stuff
>+  if (new_seat.type == GGZ_SEAT_PLAYER)
>+    game_send_seat (new_seat.num);
>+  game_send_players ();
>+
>+  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_WAITING) {
>+    // That's great! Update the state
>+    // Now waiting for people to join
>+    state = RVR_STATE_WAITING;
>+    ggzdmod_log (ggzdmod, "Waiting for players");
>+  } else if (new_state == GGZDMOD_STATE_PLAYING) {
>+    // Let's start the game!
>     game_start ();
>-    rvr_game.turn = BLACK;
>-    game_play ();
>   }
>-
>-
>-  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
>-   * 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);
>+  // game_init is called at the start of each game, so we must do
>+  // ggz stuff here.
>+  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)
>+  // Connect to GGZ server; main loop
>+  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/server.h
>===================================================================
>--- iagno/server.h	(リビジョン 6478)
>+++ 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,42 @@
>  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
>  */
> 
>-#define BLACK -1
>-#define WHITE +1
>-#define EMPTY  0
>+/* PROTOCOL VERSION 2 */
> 
>-/* 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_WAITING   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 SERVER_OK              0
> #define RVR_ERROR_INVALIDMOVE -1
>-#define RVR_ERROR_WRONGTURN -2
>-#define RVR_ERROR_CANTMOVE -3
>+#define RVR_ERROR_WRONGTURN   -2
>+#define RVR_ERROR_CANTMOVE    -3
>+#define RVR_ERROR_CANTREAD    -4
>+#define RVR_ERROR_CANTWRITE   -5
>+#define RVR_ERROR_NOTPLAYING  -6
>+#define RVR_ERROR_PLAYAGAIN   -7
>+#define RVR_ERROR_OPCODE      -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)
> 
>+// For the compatibility with the old protocol.
>+#define OLD2NEW(yx)  (yx / 8 + 1) * 10 + (yx % 8) + 1
>+#define NEW2OLD(yx)  (yx / 10 - 1) * 8 + (yx % 10 - 1)
> 
>-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	(リビジョン 6478)
>+++ iagno/ggz-network.c	(作業コピー)
>@@ -1,3 +1,5 @@
>+/* -*- mode:C; indent-tabs-mode:t; tab-width:8; c-basic-offset:8; -*- */
>+
> /* ggz-network.c
>  *
>  * Copyright (C) 2006 -  Andreas Røsdal <andrearo@pvv.ntnu.no>
>@@ -26,182 +28,221 @@
> #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 "properties.h"
>+#include "othello.h"
> #include "gnothello.h"
> #include "ggz-network.h"
>-#include "othello.h"
> 
>-guint whose_turn = BLACK_TURN;
>+#define BLACK           49
> 
>-static gboolean
>-game_handle_io (GGZMod * mod)
>-{
>-  int op = -1;
>+static const gchar *strs[] = {
>+  N_("Invalid move!"),                /* 1 */
>+  N_("Not your turn!"),               /* 2 */
>+  N_("Skip move!"),                   /* 3 */
>+  N_("Can't read message!"),          /* 4 */
>+  N_("Can't send message!"),          /* 5 */
>+  N_("Waiting for an opponent to join the game."), /* -6 */
>+  N_("Not game over yet!"),           /* -7 */
>+  N_("Incorrect opcode!")             /* -8 */
>+};
> 
>-  fd = ggzmod_get_server_fd (mod);
>+static GtkWidget *ggzbox;
>+static GGZMod    *ggzmod;
>+static int fd;
>+static int seats[2];
> 
>-  // Read the fd
>-  if (ggz_read_int (fd, &op) < 0) {
>-    ggz_error_msg ("Couldn't read the game fd");
>-    return FALSE;
>-  }
>+int    seat;
>+guint player_id;
>+char names[2][17];
> 
>-  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;
>-  }
>+extern GtkWidget *window;
>+extern GtkWidget *notebook;
>+extern gboolean  game_in_progress;
>+extern gboolean  ggz_network_mode;
>+extern gint8 pixmaps[8][8];
>+extern gint8 board[8][8];
> 
>-  return TRUE;
>+extern guint whose_turn;
>+extern gint8 move_count;
>+extern gint bcount;
>+extern gint wcount;
>+
>+static void
>+gui_error (int err)
>+{
>+  if (err > RVR_ERROR_OPCODE)
>+    gui_message ((gchar *) strs[-err - 1]);
> }
> 
>-
>-
>-
>-int
>+static int
> get_seat (void)
> {
>-
>   if (ggz_read_int (fd, &seat) < 0)
>-    return -1;
>+    return RVR_ERROR_CANTREAD;
> 
>-  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;
>+      return RVR_ERROR_CANTREAD;
> 
>     if (seats[i] != GGZ_SEAT_OPEN) {
>       if (ggz_read_string (fd, (char *) &names[i], 17) < 0)
>-	return -1;
>+        return RVR_ERROR_CANTREAD;
>+     } else {
>+      gui_message ((gchar *) strs[-RVR_ERROR_NOTPLAYING - 1]);
>     }
>   }
>-
>-  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 RVR_ERROR_CANTREAD;
> 
>-  return 1;
>-
>+  return SERVER_OK;
> }
> 
>-// Get the move from the server and makes it (don't check for validity!!)
>-int
>+static int
> get_move (void)
> {
>-  int move;
>+  int yx;
> 
>-  if (ggz_read_int (fd, &move) < 0)
>-    return -1;
>+  if (ggz_read_int (fd, &yx) < 0)
>+    return RVR_ERROR_CANTREAD;
>+  if (yx == RVR_ERROR_CANTMOVE)
>+    return SERVER_OK;
>+  if (yx == RVR_ERROR_NOTPLAYING)
>+    game_in_progress = FALSE;
>+  if (yx < 0)
>+    return yx;
> 
>-  if (move == RVR_ERROR_CANTMOVE) {
>-    return 1;
>-  }
>+  if (!is_valid_move (yx % 8, yx / 8, whose_turn))
>+    return RVR_ERROR_INVALIDMOVE;
> 
>-  if (move < 0) {
>-    return -1;
>-  }
>-  game_make_move (move);
>+  move (yx % 8, yx / 8, whose_turn);
> 
>-  return 0;
>-
>+  return SERVER_OK;
> }
> 
>-// make the move
>-void
>-game_make_move (int pos)
>+static int
>+get_sync (void)
> {
>-  int x = X (pos) - 1, y = Y (pos) - 1;
>+  int who, yx, i = 0;
>+  guint kifu[61][2];
> 
>-  // iagno move
>-  move (x, y, whose_turn);
>+  // Get kifu
>+  do {
>+    if (ggz_read_int (fd, &who) < 0 || ggz_read_int (fd, &yx) < 0)
>+      return RVR_ERROR_CANTREAD;
>+    kifu[i][0] = who;
>+    kifu[i++][1] = yx;
>+  }  while (who) ;
> 
>-  return;
>+  // Auto recovery
>+  init ();
>+  move_count = 4;
>+  bcount = wcount = 2;
>+   
>+  i = 0;
>+  while (kifu[i][0]) {
>+    whose_turn = ((kifu[i][0] == BLACK)? BLACK_TURN: WHITE_TURN);
>+    move_board (kifu[i++][1]);
>+  }
>+  whose_turn = ((kifu[i][1] == BLACK)? BLACK_TURN: WHITE_TURN);
> 
>+  board_copy ();
>+  memcpy (pixmaps, board, sizeof (gint8) * 8 * 8);
>+  redraw_board ();
>+  return SERVER_OK;
> }
> 
>-
>-
>-void
>-send_my_move (int move, guint turn)
>+static int
>+get_start (void)
> {
>-  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);
>+  game_in_progress = TRUE;
>+  gui_status ();
>+  check_valid_moves ();
>+  return SERVER_OK;
> }
> 
>-int
>-request_sync (void)
>+static int
>+get_init (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;
>+  init ();
>+  move_count = 4;
>+  bcount = wcount = 2;
>+  whose_turn = BLACK_TURN;
>+  board_copy ();
>+  memcpy (pixmaps, board, sizeof (gint8) * 8 * 8);
>+  redraw_board ();
>+  gui_status ();
>+  game_in_progress = FALSE;
>+  return SERVER_OK;
> }
> 
>-int
>-get_sync (void)
>+
>+static int
>+game_handle_io (GGZMod *mod)
> {
>-/* FIXME: Not supported yet. */
>-  return 0;
>-}
>+  int err, op = -1;
> 
>+  fd = ggzmod_get_server_fd (mod);
> 
>+  // Read the fd
>+  if (ggz_read_int (fd, &op) < 0) {
>+    gui_error (RVR_ERROR_CANTREAD);
>+    return FALSE;
>+  }
> 
>+  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 ();
>+    break;
>+  case RVR_MSG_GAMEOVER:                    /* 3 */
>+    err = get_gameover ();
>+    break;
>+  case RVR_MSG_START:                       /* 5 */
>+    err = get_start ();
>+    break;
>+  case RVR_MSG_SYNC:                        /* 6 */
>+    err = get_sync ();
>+    break;
>+  case RVR_MSG_INIT:                        /* 7 */
>+    err = get_init ();
>+    break;
>+  default:
>+    err = RVR_ERROR_OPCODE;
>+    break;
>+  }
>+  if (err < 0)
>+    gui_error (err);
> 
>+  return TRUE;
>+}
>+
> static gboolean
>-handle_ggzmod (GIOChannel * channel, GIOCondition cond, gpointer data)
>+handle_ggzmod (GIOChannel *channel, GIOCondition cond, gpointer data)
> {
>   GGZMod *mod = data;
> 
>@@ -209,7 +250,8 @@
> }
> 
> static gboolean
>-handle_game_server (GIOChannel * channel, GIOCondition cond, gpointer data)
>+handle_game_server (GIOChannel *channel, GIOCondition cond,
>+                    gpointer data)
> {
>   GGZMod *mod = data;
> 
>@@ -217,7 +259,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;
>@@ -227,13 +269,34 @@
>   g_io_add_watch (channel, G_IO_IN, handle_game_server, mod);
> }
> 
>+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... */
> }
>@@ -247,8 +310,9 @@
> ggz_game_launched (void)
> {
>   network_init ();
>+
>+  gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), MAIN_PAGE);
>   init_new_game ();
>-  gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), MAIN_PAGE);
> }
> 
> /****************************************************************************
>@@ -257,66 +321,60 @@
> 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;
>-  init_new_game ();
>+  init_new_game();
> }
> 
> void
>-network_init (void)
>+on_network_game (void)
> {
>-  GGZMod *mod;
>-  GIOChannel *channel;
>-  int ret, ggzmodfd;
>+  struct passwd *pwent;  
> 
>-  if (!ggzmod_is_ggz_mode ())
>+  if (ggz_network_mode)
>     return;
>+  
>+  init_new_game();
>   ggz_network_mode = TRUE;
> 
>-  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;
>-  }
>+  pwent = getpwuid(getuid());
>+  ggz_embed_ensure_server ("GGZ Gaming Zone", "games.gnome.org",
>+                           5688, pwent->pw_name);
> 
>-  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_again_activate (void)
>+{
>+  if (ggz_write_int (fd, RVR_REQ_AGAIN) < 0)
>+    return gui_error (RVR_ERROR_CANTWRITE);
> }
> 
> void
>-on_network_game (void)
>+send_my_move (guint move, guint turn)
> {
>-  GtkWidget *ggzbox;
>-  struct passwd *pwent;  
>+  if (turn != player_id)
>+    return gui_error (RVR_ERROR_WRONGTURN);
>+  if (ggz_write_int (fd, RVR_REQ_MOVE) < 0
>+      || ggz_write_int (fd, move) < 0)
>+    return gui_error (RVR_ERROR_CANTWRITE);
> 
>+  ggz_debug ("main", "Sent move: %d", move);
>+}
> 
>-  if (ggz_network_mode) {
>-    gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), NETWORK_PAGE);
>-    return;
>-  }
> 
>-  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);
>-}
>Index: iagno/ggz-network.h
>===================================================================
>--- iagno/ggz-network.h	(リビジョン 6478)
>+++ iagno/ggz-network.h	(作業コピー)
>@@ -16,185 +16,57 @@
>  * USA
>  */
> 
>-#define EMPTY  0
>+/* PROTOCOL VERSION 2 */
> 
>-/* 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_WAITING  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 GAME_OVER              1
>+#define SERVER_OK              0
> #define RVR_ERROR_INVALIDMOVE -1
>-#define RVR_ERROR_WRONGTURN -2
>-#define RVR_ERROR_CANTMOVE -3
>+#define RVR_ERROR_WRONGTURN   -2
>+#define RVR_ERROR_CANTMOVE    -3
>+#define RVR_ERROR_CANTREAD    -4
>+#define RVR_ERROR_CANTWRITE   -5
>+#define RVR_ERROR_NOTPLAYING  -6
>+#define RVR_ERROR_PLAYAGAIN   -7
>+#define RVR_ERROR_OPCODE      -8
> 
>+#define NETWORK_ENGINE 	 "Iagno"
>+#define NETWORK_VERSION 	 "1"
>+
> // 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_TURN: WHITE_TURN)
> 
> // Takes a player code and transform into a seat index
>-#define PLAYER2SEAT(player) ( (player==BLACK_TURN)?0:1 )
>+#define PLAYER2SEAT(player)  ((player == BLACK_TURN)? 0: 1)
> 
>-#define NETWORK_ENGINE "Iagno"
>-#define NETWORK_VERSION "1"
>+// For the compatibility with the old protocol.
>+#define OLD2NEW(yx)  (yx / 8 + 1) * 10 + (yx % 8) + 1
>+#define NEW2OLD(yx)  (yx / 10 - 1) * 8 + (yx % 10 - 1)
> 
> void network_init (void);
>+
> void on_network_game (void);
> 
>-int fd;
>+void on_again_activate (void);
> 
>-// Setup functions
>-void game_init (void);
>+void send_my_move (guint move, guint turn);
> 
>-// 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);
>-
>-// Send stuff to server
>-void send_my_move (int move, guint turn);
>-int request_sync (void);
>-
>-// 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);
>Index: iagno/gnothello.c
>===================================================================
>--- iagno/gnothello.c	(リビジョン 6478)
>+++ iagno/gnothello.c	(作業コピー)
>@@ -34,8 +34,11 @@
> #ifdef GGZ_CLIENT
> #include <games-dlg-chat.h>
> #include <games-dlg-players.h>
>+#include <ggz-embed.h>
> #include "ggz-network.h"
>-#include <ggz-embed.h>
>+extern int     seat;
>+extern guint  player_id;
>+extern char  names[2][17];
> #endif
> 
> #include "gnothello.h"
>@@ -188,6 +191,10 @@
> void
> new_game_cb (GtkWidget * widget, gpointer data)
> {
>+#ifdef GGZ_CLIENT
>+  if (ggz_network_mode)
>+    return on_again_activate ();
>+#endif
>   init_new_game ();
> }
> 
>@@ -534,7 +541,7 @@
>   return TRUE;
> }
> 
>-static void
>+void
> redraw_board (void)
> {
>   guint i, j;
>@@ -700,7 +707,6 @@
>   undo_set_sensitive (move_count > 0);
> 
>   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);
>@@ -708,7 +714,6 @@
>     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);
Comment 40 mars1 2007-07-03 19:31:58 UTC
Created attachment 91138 [details] [review]
new protocol patch

I'm sorry, I mistook. Please delete comment#39.
Comment 41 mars1 2007-07-08 12:20:50 UTC
Created attachment 91425 [details] [review]
new-iagno.patch

New iagno patch

If you don't want to use the new protocol, please return back server.c,
server.h and Makefile.am to current files. There are no problem
to use new ggz-network.c and ggz-network.h on the current protocol.
Offcorse, these files have only the same functions as the current files
at that time.

If you don't want to use file save, file open and keyboard menu,
please change next three lines to follows,

gnothello.c 1023 line

  gtk_action_set_visible   (open_action,         TRUE);
  gtk_action_set_visible   (save_action,         TRUE);
  gtk_action_set_visible   (keyboard_action,     TRUE);
to
  gtk_action_set_visible   (open_action,         FALSE);
  gtk_action_set_visible   (save_action,         FALSE);
  gtk_action_set_visible   (keyboard_action,     FALSE);

Thank you.
Comment 42 mars1 2007-07-08 12:22:48 UTC
Created attachment 91427 [details]
Screenshot

New iagno features.

1. have resizable window.
2. background color selectable.
3. toolbar appended.
4. row and column label appended.
5. hint supported.
6. timer supported.
7. file-save, file-open supported.
8. reproduction of the game supported.
9. can restart from on the way.
10  can display valid squares.
11. can display last move mark
12. network supported.
13. sound supported.
14. keyboard inputting supported.

15. more stronger than current iagno.
Comment 43 mars1 2007-07-22 06:06:49 UTC
Created attachment 92141 [details]
disk.svg
Comment 44 mars1 2007-07-22 06:10:13 UTC
Created attachment 92142 [details] [review]
new-iagno.patch

Iagno is too old.

When I met iagno at first time, I surprised iagnos animation.
But, now iagno is too old.


New iagno install process.

1. $ cd ~/gnome/gnome-games
2. $ cp ../../disk.svg iagno/
3. $ cp ../../marble.svg iagno/
4. $ cp ../../sun_and_star.svg iagno/
    (I changed DEFAULT_TILESET to sun_and_star.svg.)
5. $ patch -p0 < ../../new-iagno.patch
6. $ ./autogen.sh
   (I changed Makefile.am.)
7. $ ./configure --with-ggz-dir=/usr --with-ggz-server
   (My system is Fedora 7 and ggz-0.0.14 installed in /usr.)
8. $ make
9. $ su
11. # make install
12. # cp /usr/local/etc/ggzd/games/* /etc/ggzd/games
13. # cp /usr/local/etc/ggzd/rooms/* /etc/ggzd/rooms
14. # ggzd
15. # exit
16. $ /usr/local/bin/iagno

If you don't want to use the new protocol, please return back server.c, and
server.h to current files. There are no problem to use new ggz-network.c and
ggz-network.h on the current protocol.

If you don't want to use file save, file open and keyboard menu,
please change next three lines to follows,

gnothello.c 1016 line

  gtk_action_set_visible   (open_action,         TRUE);
  gtk_action_set_visible   (save_action,         TRUE);
  gtk_action_set_visible   (keyboard_action,     TRUE);
to
  gtk_action_set_visible   (open_action,         FALSE);
  gtk_action_set_visible   (save_action,         FALSE);
  gtk_action_set_visible   (keyboard_action,     FALSE);

Thank you.
Comment 45 Andreas Røsdal 2007-08-10 21:39:54 UTC
Thanks for the updated patch, it is very much improved.

I think the patch now is good enough to be committed after GNOME 2.20.0 has been released, which means after September this year. A full development cycle is needed to give this patch enough testing.

Some changes I request:
- Preference dialog: Change all checkbox labels from "Hide" to "Show", and from "Disable" to "Enable". The logical value should be opposite. Please read the GNOME Human Interface guidelines. 
- Remove file save, file open and keyboard menu
- Remove all changes to server.c and server.h from the patch.
- Theme list: Remove ".svg" suffix from filenames in the theme list.

* Bonus point:
 - How would Iagno look with a nice tiled background? Something like the tiled background from Aisleriot?


Remember: As a developer, it is your responsibility to test the quality of the code you submit. So please test it again, in single player, AI games, and network games. I am still able to reproduce several crashes.

The new maintainer, Thomas, might also have some opinions on this patch, so be prepared to improve it further.
Comment 46 Andreas Røsdal 2007-08-10 21:44:02 UTC
Another comment:

- I'm not sure that the small white "hint" circles look very good. Could you try to make some better-looking hint graphics? Use your imagination. Something small and subtle, yet good-looking and informative. Or perhaps remove those hint graphics?
Comment 47 mars1 2007-09-11 17:48:44 UTC
Created attachment 95373 [details] [review]
new-iagno.patch
Comment 48 mars1 2007-10-05 06:43:55 UTC
Created attachment 96677 [details] [review]
new-iagno.patch

Some bugs fixed.
Comment 49 Andreas Røsdal 2007-10-05 16:21:08 UTC
> Some bugs fixed.

Please explain. You are terrible at documenting your code.
Comment 50 Thomas Andersen 2007-10-07 23:13:25 UTC
Is there any way we can break this patch into smaller parts and review/commit the separately? I'd love to get this stuff into the game but committing it all at once is not a good idea. Not just because of the reviewing but also for the sake of the revision history.

So - one feature pr. patch if possible please. And thank you for working on this
Comment 51 mars1 2007-10-13 13:39:10 UTC
Created attachment 97163 [details] [review]
new-iagno.patch.0

No networking, and without file open, file save and keyboard menu.
Comment 52 mars1 2007-10-13 13:49:18 UTC
Created attachment 97164 [details] [review]
new-iagno.patch.2

Networking(new protocol), without file open, file save and keyboard menu.

If you don't want to use the new protocol, please return back server.c, and
server.h to current files. There are no problem to use new ggz-network.c and
ggz-network.h on the current protocol. But the current protocol has some bugs.
I think it's better to use the new protocol. It's upper compatible  with the 
current protocol.
Comment 53 mars1 2007-11-04 03:39:07 UTC
Created attachment 98502 [details] [review]
new-iagno.patch.2

I made some little changes.

 1. I changed some strings to _() from N_().
 2. I changed ggz_network_mode to be included in the #ifdef GGZ_CLIENT parts.
 3. I changed random select number. Iagno became a bit stronger.
Comment 54 Andreas Røsdal 2007-11-06 23:06:01 UTC
I'm still able to reproduce many crashes with the patch applied.
The patch is still not ready for inclusion, and is generally of bad quality...
Comment 55 mars1 2007-11-07 11:14:19 UTC
Thank you Andreas.
I want some more detail report of your crashes.
Comment 56 Thomas Andersen 2007-11-07 11:47:57 UTC
To try to get into a more constructive process I suggest we focus on the "new-iagno.patch.0" patch. While it is a lot smaller than the "new-iagno.patch.2" patch it's still a whooping 4000 lines.

In comment #51 you write what the patch does not include. Is this compared to the list in comment #42? If so can we break it up into even smaller parts? It's a lot easier to both review and test a single feature at a time.

Some of the feature descriptions you give are less than obvious. If possible could you write a short reasoning for each? What problem with the current behavior is addressed and how. Some of these things might need some discussion and advise from usability team.

You've obviously already put in a great deal of work on this so let's take the last few steps to get this code in. Thanks :)
Comment 57 mars1 2007-11-11 04:29:04 UTC
Created attachment 98903 [details] [review]
new-iagno.patch.0

This patch is only essential parts of new iagno.
Comment 58 mars1 2008-02-11 01:41:13 UTC
Created attachment 104885 [details] [review]
new-iagno.patch.3

Current protocol doesn't support sync, so if an error occurred
(for a example invalid move), iagno hang up.
Comment 59 Thomas Andersen 2008-02-11 07:25:51 UTC
Hi

We are too late to include this in the current cycle but we really should get this into 2.23. The problem is that the patch is already way too big to include at once. There is also no description of what the patch exactly does. I'm looking forward to geting most of the features mentioned in this bug into iagno but I need to know what the essential parts cover. Could you make a list of that? I would make it so much easier to review the patch that way. 

Again I'd like to say that small patches that introduce just a single feature is far more likely to get included than huge patches with lots of new things. So if there is anything here that can be split into its own patch that would be great.

Thanks for working on this!
Comment 60 mars1 2008-02-12 13:05:49 UTC
Created attachment 105040 [details] [review]
new-iagno.patch.0

Support
 Menu
  Game       Settings       Help
   New game   Preferences    Help
   Quit                      About

 Preferences
   Computer Level
   Use Fast move
   Tile set
   Background Color
    
 1. Resizeable Window
 2. Window size and position are saved.
 3. New iagno is stronger and faster than KReversi.

Not Support
 Menu
  Game           View
   Network game  Full screen
   Hint           Keyboard
   Head 
   Back
   Forward
   Last
   File save
   File open

 Preferences
  Enable sound
  Flip final results
  Show valid squares
  Show last move mark
  Show toolbar
  Show timer

Bugs report (rev.7364)

 1. Iagno doesn't show menu.
 2. Iagno doesn't show network dialog.
 3. Iagno doesn't expose when expose event occurred.
 4. All network game crash when disconnect with server.
     They show "Bad XML from server".
 5. When I win the server, Gnect show "Network error", and crash.
Comment 61 mars1 2008-02-18 11:59:04 UTC
Created attachment 105486 [details] [review]
current-iagno.patch

Current iagno patch.
(Comment #60 bug 1, 2, 3)

Bug 4 are fixed now, it happens on only local server.
Bug 5 happens when leave network is clicked on gnect.
Comment 62 mars1 2008-02-24 04:12:36 UTC
Created attachment 105849 [details]
Screenshot
Comment 63 mars1 2008-02-24 04:14:27 UTC
Created attachment 105850 [details] [review]
new-iagno.patch.3

New iagno patch.3
 This has Comment #42 all features

Changed
1. On network mode, player list and chat were removed from Game menu,
   and appended to bottom of window. Because player list and
   chat dialog remain after the player left from network game.
2. On network mode, the player can use Head, Back, Forward and
   Last menu too.
3. Actions were changed to one array from some variables.
4. Options were changed to one array from some variables.
5. On othello.c, heuristic values were changed, iagno became
   a bit stronger.
Comment 64 mars1 2008-03-16 03:19:31 UTC
Created attachment 107370 [details] [review]
new-iagno.patch.3

New-iagno.patch.3

Changed
appearance
1. A counter were appended.

Inside
1. GtkWidget were changed to one array from some variables.
2. Options were changed to enum from one array.
3. states were changed to enum.
4. flags were changed to enum.
5. Some variables were changed to some struct.
6. Some functions names were changed.
7. gui_redraw_board were changed to use flip_pixmaps.
8. on_open_activate and on_save_activate were changed to use 
   one create_file_dialog.
9. Some comments were appended.
10. Program size became a bit smaller.
11. Maybe the program became easy to read.

( math1@nifty.com were my old e-mail address.
  Please see iagno ChangeLog 2006-01-05)
Comment 65 mars1 2008-06-11 15:22:53 UTC
Created attachment 112546 [details] [review]
new-iagno.patch.3

Bug fixed
When a player is waiting for an opponent to join the game,
even if he clicked a square, this version doesn't send that move to server.

My system is Fedora-8 and ggz-0.0.14.1.
I couldn't compile ggz-server on Fedora-9.
Comment 66 Jason Clinton 2008-06-19 18:16:59 UTC
I think I can chew this work in to tiny pieces using git's interactive add system since the author won't do it. It's going to take weeks of work, though. So I'm going to mark it for work that I want to do this summer. I'm going to do it in a separate branch called MARS_NEW_IAGNO.

Mars, I would really rather than you do the work. I would love to teach you the Gnome development process and get you SVN access so you can work directly on your own private branch. Are you interested in this?
Comment 67 Andreas Røsdal 2008-06-19 18:43:16 UTC
> I think I can chew this work in to tiny pieces using git's interactive
> add system since the author won't do it. It's going to take weeks 
> of work, though.

I think it's disappointing that the contributor doesn't follow the advice
of the gnome-games maintainers. In previous open-source projects that I've
been involved in, particularly Freeciv, not listening to the maintainers 
would be an automatic reason for rejecting the patches from that contributor.
If he doesn't want to follow feedback and guidelines for simple things like
coding style or do patches in a certain way, then it's very unlikely that 
the contributor will be willing to do more demanding tasks, such as fixing critical bugs in the code he's submitted, or bother writing documentation,
or bother to properly test the patch before it is committed etc. 
So I would strongly suggest simply rejecting the patches from mars1,
because he isn't following the feedback that he has been given.
Comment 68 Jason Clinton 2008-06-19 19:00:41 UTC
I mostly agree but I do want to give Mars the opportunity to set things right if the reason he's been unresponsive is a language barrier issue.

Some of the stuff I see in this patch is worth incorporating piece-meal even if the entire body of work is rejected.
Comment 69 Christian Persch 2009-01-10 18:06:18 UTC
Setting patch statuses based on comment 11.
Comment 70 Jason Clinton 2009-02-22 00:30:46 UTC
Please reopen, Mars, if you decide you have time to work on this.