GNOME Bugzilla – Bug 350069
iagno new version-2
Last modified: 2006-08-05 15:25:48 UTC
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/network.c gnome-games-2.14.1/iagno/network.c --- gnome-games-2.14.1.org/iagno/network.c 2006-08-05 15:32:11.000000000 +0900 +++ gnome-games-2.14.1/iagno/network.c 2006-08-05 16:17:27.000000000 +0900 @@ -1,5 +1,5 @@ /* - * Network.c - network code for iagno. + * network.c - network code for iagno. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,21 +29,25 @@ #include <netinet/in.h> #include <errno.h> #include <netdb.h> -#include "othello.h" + #include "gnothello.h" +#include "othello.h" #include "games-network.h" #include "games-network-dialog.h" #include "network.h" -char *game_server = "localhost"; +char *game_server = "localhost"; char *game_port = "26478"; -static void game_handle_input (NetworkGame *ng, char *buf); +extern gint t_black_computer_level; +extern gint t_white_computer_level; + +static void game_handle_input (NetworkGame * ng, char *buf); void network_start (void) { - games_network_start(); + games_network_start (); } void @@ -58,18 +62,15 @@ return (get_network_status () == CONNECTED); } -int +gboolean game_move (guint x, guint y, guint me) { static char msgbuf[256]; gnome_triggers_do ("", NULL, "gnothello", "flip-piece", NULL); - snprintf (msgbuf, sizeof (msgbuf), "move %u %u %u\n", x, y, me); - - games_send_gamedata(msgbuf); - - return move (x, y, me); + games_send_gamedata (msgbuf); + return move (x, y); } int @@ -89,70 +90,86 @@ } -static void +static void game_handle_input (NetworkGame *ng, char *buf) { char *args; args = strchr (buf, ' '); - if (args) { + if (args) + { *args = '\0'; args++; } - if (!strcmp (buf, "set_peer")) { + if (!strcmp (buf, "set_peer")) + { int me; - - if (ng->mycolor) { + + if (ng->mycolor) + { network_set_status (ng, DISCONNECTED, _("Invalid move attempted")); return; } - + if (!args || sscanf (args, "%d", &me) != 1 - || (me != WHITE_TURN && me != BLACK_TURN)) { - network_set_status (ng, DISCONNECTED, _("Invalid game data (set_peer)")); + || (me != WHITE_TURN && me != BLACK_TURN)) + { + network_set_status (ng, DISCONNECTED, + _("Invalid game data (set_peer)")); return; } - white_level_cb (NULL, "0"); - black_level_cb (NULL, "0"); - + + t_black_computer_level = 0; + t_white_computer_level = 0; + apply_changes (); + save_properties (); + ng->mycolor = me; network_gui_message (_("Peer introduction complete")); - } else if (! strcmp (buf, "move")) { + } + else if (!strcmp (buf, "move")) + { int x, y, me; - if (!args || sscanf(args, "%d %d %d", &x, &y, &me) != 3 - || !me || me != (32-ng->mycolor) - || x >= 8 || y >= 8) { + if (!args || sscanf (args, "%d %d %d", &x, &y, &me) != 3 + || me != OTHER_PLAYER (ng->mycolor) + || x > 8 || x < 1 || y > 8 || y < 1) + { network_set_status (ng, DISCONNECTED, _("Invalid game data (move)")); return; } - move (x, y, me); - } else if (!strcmp(buf, "new_game")) { + move (x, y); + } + else if (!strcmp (buf, "new_game")) + { - if (!ng->sent_newgame) { + if (!ng->sent_newgame) + { g_string_append_printf (ng->outbuf, "new_game %s \n", player_name); - } else { - network_gui_connected(); + } + else + { + network_gui_connected (); network_gui_message (_("New game ready to be started")); - network_gui_add_player(args); + network_gui_add_player (args); } ng->sent_newgame = 0; whose_turn = BLACK_TURN; - } else if (!strcmp(buf, "start_game")) { + } + else if (!strcmp (buf, "start_game")) + { network_gui_message (_("New game started")); - - if (!ng->sent_startgame) { - g_string_append_printf (ng->outbuf, "start_game\n"); - } + + if (!ng->sent_startgame) + g_string_append_printf (ng->outbuf, "start_game\n"); ng->sent_startgame = 0; - + init_new_game (); - network_gui_close(); + network_gui_close (); } } - diff -uNr gnome-games-2.14.1.org/iagno/network.h gnome-games-2.14.1/iagno/network.h --- gnome-games-2.14.1.org/iagno/network.h 2006-08-05 15:32:11.000000000 +0900 +++ gnome-games-2.14.1/iagno/network.h 2006-08-05 15:32:35.000000000 +0900 @@ -1,11 +1,8 @@ #ifndef NETWORK_H #define NETWORK_H -#define BLACK_TURN 1 -#define WHITE_TURN 31 - extern char *game_server; -extern gint game_move (guint, guint, guint); +extern gboolean game_move (guint, guint, guint); extern int network_allow (void); extern void network_new (GtkWidget *parent_window); extern void network_start (void); @@ -13,4 +10,3 @@ extern gboolean is_network_running (void); #endif - diff -uNr gnome-games-2.14.1.org/iagno/othello.c gnome-games-2.14.1/iagno/othello.c --- gnome-games-2.14.1.org/iagno/othello.c 2006-08-05 15:32:11.000000000 +0900 +++ gnome-games-2.14.1/iagno/othello.c 2006-08-05 16:01:32.000000000 +0900 @@ -1,8 +1,5 @@ -/* -*- mode:C; indent-tabs-mode:t; tab-width:4; c-basic-offset:8; -*- */ - /* - * othello.c - Othello support routines for iagno - * written by Ian Peters <itp@gnu.org> + * othello.c * * 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 @@ -24,700 +21,572 @@ #include <config.h> #include <gnome.h> #include <string.h> -#include <games-clock.h> -#include "othello.h" #include "gnothello.h" +#include "othello.h" -#define PERFECT 17 -#define VICTORY 19 -#define BEST 56 -#define MAX_DEPTH 7 - -#define BLANK 0 -#define OUTSIDE 128 -#define UL -11 -#define UU -10 -#define UR -9 -#define LL -1 -#define RR +1 -#define DL +9 -#define DD +10 -#define DR +11 -#define NDIRS 8 - -gint8 squares[64] = {44,45,54,55,23,26,73,76, - 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}; - -static const gint heuristic[100] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 65, -3, 6, 4, 4, 6, -3, 65, 0, - 0, -3,-29, 3, 1, 1, 3,-29, -3, 0, - 0, 6, 3, 5, 3, 3, 5, 3, 6, 0, - 0, 4, 1, 3, 1, 1, 3, 1, 4, 0, - 0, 4, 1, 3, 1, 1, 3, 1, 4, 0, - 0, 6, 3, 5, 3, 3, 5, 3, 6, 0, - 0, -3,-29, 3, 1, 1, 3,-29, -3, 0, - 0, 65, -3, 6, 4, 4, 6, -3, 65, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +guint squares[64] = { + 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 +}; + +static const gint heuristic[100] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,115,-23, 6, 4, 4, 6,-23,115, 0, + 0,-23,-51, 3, 2, 2, 3,-51,-23, 0, + 0, 6, 3, 5, 3, 3, 5, 3, 6, 0, + 0, 4, 2, 3, 1, 1, 3, 2, 4, 0, + 0, 4, 2, 3, 1, 1, 3, 2, 4, 0, + 0, 6, 3, 5, 3, 3, 5, 3, 6, 0, + 0,-23,-51, 3, 2, 2, 3,-51,-23, 0, + 0,115,-23, 6, 4, 4, 6,-23,115, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; static const gint dirs[] = { UL, UU, UR, LL, RR, DL, DD, DR }; -guint flip_final_id = 0; -gint flip_final; - -gint8 board0[100]; -/* This array can probably be a lot smaller (< 600). However, I am absolutely - * certain that it cannot be more than 1200. So 1200 is what we use. */ -gint8 history[1200]; -gint hpointer; +guint board0[100]; +/* This array can probably be a lot smaller (< 300). */ +guint history[600]; +guint hpointer; gint vsquares[280][2]; -gint vpointer; -gint s_kind; +guint vpointer; +guint s_kind; +guint bcount; +guint wcount; GRand *rgen; -extern guint black_computer_level; -extern guint white_computer_level; - -extern gint animate; -extern gint animate_stagger; +guint move_count; +guint whose_turn; extern guint game_in_progress; + extern gint8 pixmaps[8][8]; extern gint8 board[8][8]; -extern gint8 move_count; -extern guint whose_turn; -extern gint bcount; -extern gint wcount; - -extern guint tiles_to_flip; /* Initialization of data */ void -init ( void ) +init (void) { - gint i,j; - gint x; + guint i, j, ji; - rgen = g_rand_new (); + rgen = g_rand_new (); - x = 0; - for( j = 0; j < 10; j++ ) - for( i = 0; i < 10; i++ ) - { - if ( j == 0 || j ==9 ) board0[x] = OUTSIDE; - else if ( i == 0 || i == 9 ) board0[x] = OUTSIDE; - else board0[x] = BLANK; - x++; - } - - board0[ 44 ] = WHITE_TURN; - board0[ 45 ] = BLACK_TURN; - board0[ 54 ] = BLACK_TURN; - board0[ 55 ] = WHITE_TURN; - - hpointer = 0; - vpointer = 0; + ji = 0; + for (j = 0; j < 10; j++) + for (i = 0; i < 10; i++) + { + if (j == 0 || j == 9) + board0[ji] = OUTSIDE; + else if (i == 0 || i == 9) + board0[ji] = OUTSIDE; + else + board0[ji] = BLANK; + ji++; + } + + board0[44] = WHITE_TURN; + board0[45] = BLACK_TURN; + board0[54] = BLACK_TURN; + board0[55] = WHITE_TURN; + + hpointer = 0; + vpointer = 0; + move_count = 4; + whose_turn = BLACK_TURN; + bcount = 2; + wcount = 2; } /* Copy data from board0 to board */ void -board_copy ( void ) +copy_board (void) +{ + guint i, j; + + for (j = 0; j < 8; j++) + for (i = 0; i < 8; i++) + board[i][j] = (gint8) board0[(j + 1) * 10 + i + 1]; +} + +void +copy_pixmaps (void) { - gint i,j; + guint i, j; - for ( j = 0; j < 8; j++ ) - for ( i = 0; i < 8; i++ ) - board[ i ][ j ] = board0[ ( j + 1 ) * 10 + i + 1 ]; + for (j = 0; j < 8; j++) + for (i = 0; i < 8; i++) + pixmaps[i][j] = board[i][j]; } /* Check the validity of the move in a given direction. */ -static -gint -is_valid0 (gint xy, gint dir, gint who) +static gboolean +is_valid0 (guint xy, gint dir, guint who) { - gint tmp; - gint8 not_me; + guint tmp, not_me; - not_me = OTHER_PLAYER (who); + not_me = OTHER_PLAYER (who); - /* To be valid, the next counter should not be the current player ... */ - tmp = xy + dir; - if ( board0[tmp] != not_me ) - return FALSE; + /* To be valid, the next counter should not be the current player ... */ + tmp = xy + dir; + if (board0[tmp] != not_me) + return FALSE; - /* ... but eventually we must find a counter that is. */ - do { tmp += dir; } while ( board0[tmp] == not_me ); + /* ... but eventually we must find a counter that is. */ + do + { + tmp += dir; + } + while (board0[tmp] == not_me); - return board0[tmp] == who; + return board0[tmp] == who; } /* Check if a given (empty) square can provide a valid move */ -static -gint -is_valid (gint xy, gint who) +static gboolean +is_valid (guint xy, guint who) { - int i; + guint i; - for (i=0; i<NDIRS; i++) - if ( is_valid0( xy, dirs[i], who ) ) return( TRUE ); + for (i = 0; i < NDIRS; i++) + if (is_valid0 (xy, dirs[i], who)) + return (TRUE); - return FALSE; + return FALSE; } /* Check whether the supplied move is a valid one. */ -gint -is_valid_move (guint x, guint y, guint who) { - gint xy; +gboolean +is_valid_move (guint x, guint y, guint who) +{ + guint xy; - xy = ( y + 1 ) * 10 + x + 1; - if ( board0[ xy ] != BLANK ) - return FALSE; + xy = y * 10 + x; + if (board0[xy] != BLANK) + return FALSE; - return is_valid (xy, who); + return is_valid (xy, who); } -static -void -move_board0 (gint xy, gint dir) +static void +move_board0 (guint xy, gint dir) { - gint8 tmp; - guint not_me; + guint tmp; + guint not_me; - not_me = OTHER_PLAYER (whose_turn); - tmp = xy + dir; - if ( board0[ tmp ] != not_me ) - return; - /* Find the extent of the move in direction dir. */ - do { tmp += dir; } while ( board0[ tmp ] == not_me ); - if ( board0[tmp] != whose_turn ) - return; - - /* Now walk back to where we started flipping pieces over. */ + not_me = OTHER_PLAYER (whose_turn); + tmp = xy + dir; + if (board0[tmp] != not_me) + return; + /* Find the extent of the move in direction dir. */ + do + { + tmp += dir; + } + while (board0[tmp] == not_me); + if (board0[tmp] != whose_turn) + return; + + /* Now walk back to where we started flipping pieces over. */ + tmp -= dir; + while (tmp != xy) + { + board0[tmp] = whose_turn; /* Flip pieces */ + history[hpointer++] = tmp; /* Record history */ tmp -= dir; - while ( tmp != xy ) - { - board0[tmp] = whose_turn; /* Flip pieces */ - history[ hpointer++ ] = tmp; /* Record history */ - tmp -= dir; - } + } } /* reverse some pieces */ void -move_board (gint xy) +move_board (guint xy) { - gint tmp, count; - int i; - - count = hpointer; - - for (i=0; i<NDIRS; i++) - move_board0( xy, dirs[i] ); - - board0[xy] = whose_turn; - count = hpointer-count; - history[ hpointer++ ] = count; /* make history */ - history[ hpointer++ ] = whose_turn; - - if ( whose_turn == WHITE_TURN ) - { - wcount += count+1; - bcount -= count; - } - else - { - bcount += count+1; - wcount -= count; - } - tmp = squares[move_count]; - squares[move_count++] = xy; - if ( tmp != xy) - { - count = move_count; - while ( squares[count] != xy ) count++; - squares[count] = tmp; - } - whose_turn = OTHER_PLAYER (whose_turn); -} + guint tmp, i; + tmp = hpointer; -gint -move (guint x, guint y, guint me) -{ - gint tmp; - - tmp = (gint)( ( y + 1 ) * 10 + x + 1 ); - if ( board0[ tmp ] != BLANK ) - return FALSE; - if ( !is_valid( tmp, whose_turn ) ) - return FALSE; - move_board( tmp ); - board_copy(); - - pixmaps[ x ][ y ] = (gint8)me; - gui_draw_pixmap( me, x, y ); - - if ( whose_turn == BLACK_TURN ) - { - gui_message(_("Dark's move")); - } - else if ( whose_turn == WHITE_TURN ) - { - gui_message(_("Light's move")); - } - - gui_status(); - - tiles_to_flip = 1; - check_valid_moves(); - check_computer_players(); + for (i = 0; i < NDIRS; i++) + move_board0 (xy, dirs[i]); - return FALSE; + board0[xy] = whose_turn; + tmp = hpointer - tmp; + history[hpointer++] = tmp; /* history[t1,t2,,,tn, n,who] */ + history[hpointer++] = whose_turn; + if (whose_turn == WHITE_TURN) + { + wcount += tmp + 1; + bcount -= tmp; + } + else + { + bcount += tmp + 1; + wcount -= tmp; + } + tmp = squares[move_count]; /* squares[0,1,2,3.,,move_count,,,62,63] */ + squares[move_count++] = xy; /* [-already puted-|-yet blank--] */ + if (tmp != xy) /* sort squares */ + { + i = move_count; + while (squares[i] != xy) + i++; + squares[i] = tmp; + } + whose_turn = OTHER_PLAYER (whose_turn); } /* Back to before board0 */ void -undo ( void ) +back (void) { - gint8 not_me, count; + guint count, not_me; - whose_turn = history[ --hpointer ]; /* history[t1,t2,,,tn, n,who] */ - count = history[ --hpointer ]; + whose_turn = history[--hpointer]; /* history[t1,t2,,,tn, n,who] */ + count = history[--hpointer]; - if ( whose_turn == WHITE_TURN ) - { - wcount -= count+1; - bcount += count; - } - else - { - bcount -= count+1; - wcount += count; - } - - board0[ squares[ --move_count ]] = BLANK; /* decrease move_count */ - - not_me = OTHER_PLAYER (whose_turn); - while ( count > 0 ) - { - board0[ history[ --hpointer ] ] = not_me; - count--; - } + if (whose_turn == WHITE_TURN) + { + wcount -= count + 1; + bcount += count; + } + else + { + bcount -= count + 1; + wcount += count; + } + + board0[squares[--move_count]] = BLANK; /* decrease move_count */ + + not_me = OTHER_PLAYER (whose_turn); + while (count > 0) + { + board0[history[--hpointer]] = not_me; + count--; + } } /* Sort vsquares by small order */ -static -void -sort (gint l, gint r) -{ - gint i, j, v, w, x; - - i = l; j = r; - x = vsquares[ ( l + r ) / 2 ][ 1 ]; - do - { - while ( vsquares[ i ][ 1 ] < x ) i++; - while ( x < vsquares[ j ][ 1 ] ) j--; - if ( i < j ) - { - v = vsquares[ i ][ 0 ]; - w = vsquares[ i ][ 1 ]; - vsquares[ i ][ 0 ] = vsquares[ j ][ 0 ]; - vsquares[ i ][ 1 ] = vsquares[ j ][ 1 ]; - vsquares[ j ][ 0 ] = v; - vsquares[ j ][ 1 ] = w; - } - if ( i <= j ) - { - i++; - j--; - } - } while ( i <= j ); - - if ( l < j ) sort( l, j ); - if ( i < r ) sort( i, r ); -} - -static -gint -eval_heuristic( void ) +static void +sort (guint l, guint r) { - gint8 i, xy; - gint count = 0; + guint i, j; + gint v, w, x; - for ( i = 0; i < move_count; i++ ) - { - xy = squares[ i ]; - count = ( board0[ xy ] == whose_turn ) ? - count + heuristic[ xy ] : count - heuristic[ xy ]; - } + i = l; + j = r; + x = vsquares[(l + r) / 2][1]; + do + { + while (vsquares[i][1] < x) + i++; + while (x < vsquares[j][1]) + j--; + if (i < j) + { + v = vsquares[i][0]; + w = vsquares[i][1]; + vsquares[i][0] = vsquares[j][0]; + vsquares[i][1] = vsquares[j][1]; + vsquares[j][0] = v; + vsquares[j][1] = w; + } + if (i <= j) + { + i++; + j--; + } + } + while (i <= j); + + if (l < j) + sort (l, j); + if (i < r) + sort (i, r); +} + +static gint +eval_heuristic (void) +{ + guint i, xy; + gint count = 0; + + for (i = 0; i < move_count; i++) + { + xy = squares[i]; + if (board0[xy] == whose_turn) + count += heuristic[xy]; + else + count -= heuristic[xy]; + } - return count; + return count; } -static gint -mobility( void ) +mobility (guint who) { - gint8 i, xy; - gint count = 0; + guint i, xy; + gint count = 0; - for ( i = move_count; i < 64; i++ ) - { - xy = squares[ i ]; - if ( is_valid( xy, whose_turn ) ) count++; - } + for (i = move_count; i < 64; i++) + { + xy = squares[i]; + if (is_valid (xy, who)) + count++; + } - return count; + return count; } -static -gint -around0(gint xy) +static gint +around0 (guint xy) { - gint count = 0; - int i; + guint i; + gint count = 0; - for (i=0; i<NDIRS; i++) - if ( board0[ xy + dirs[i] ] == BLANK ) count--; + for (i = 0; i < NDIRS; i++) + if (board0[xy + dirs[i]] == BLANK) + count--; - if ( !count ) count = 2; + if (!count) + count = 2; - return count; + return count; } -static -gint -around( void ) +static gint +around (void) { - gint8 i, xy; - gint count = 0; + guint i, xy; + gint count = 0; - for ( i = 0 ; i < move_count; i++ ) - { - xy = squares[ i ]; - count = ( board0[ xy ] == whose_turn ) ? - count + around0( (gint) xy ) : count - around0( (gint) xy ); - } + for (i = 0; i < move_count; i++) + { + xy = squares[i]; + if (board0[xy] == whose_turn) + count += around0 (xy); + else + count -= around0 (xy); + } - return count; + return count; } -/* Evaluate the board */ -static -gint -b_evaluation( void ) +/* Best evaluation */ +static gint +b_evaluation (void) { - gint score1, score2, score3; - - score1 = mobility(); - whose_turn = OTHER_PLAYER (whose_turn); - score1 -= mobility(); - whose_turn = OTHER_PLAYER (whose_turn); - - score2 = around(); - score3 = eval_heuristic(); + gint score1, score2, score3; - return score1 + score2 + score3; + score1 = mobility (whose_turn); + score1 -= mobility (OTHER_PLAYER (whose_turn)); + score2 = around (); + score3 = eval_heuristic (); + return score1 * 2 + score2 + score3 / 2; } /* Victory evaluation */ -static -gint -v_evaluation( void ) +static gint +v_evaluation (void) { - gint aa; + gint aa; - aa = wcount - bcount; - if ( whose_turn == BLACK_TURN ) aa = -aa; + aa = wcount - bcount; + if (whose_turn == BLACK_TURN) + aa = -aa; - if ( aa > 0 ) return 1; /* win */ - if ( aa < 0 ) return -1; /* lose */ - return 0; /* draw */ + if (aa > 0) + return 1; /* win */ + if (aa < 0) + return -1; /* lose */ + return 0; /* draw */ } -static -gint -p_evaluation( void ) +/* Perfect evaluation */ +static gint +p_evaluation (void) { - - if ( whose_turn == WHITE_TURN ) - return wcount - bcount; - - return bcount - wcount; + if (whose_turn == WHITE_TURN) + return wcount - bcount; + return bcount - wcount; } -static -gint -w_evaluation( void ) +/* Win evaluation under best search */ +static gint +w_evaluation (void) { - gint aa; - - if ( !bcount || !wcount ) - { - if ( whose_turn == WHITE_TURN && !bcount ) return 10000; - if ( whose_turn == BLACK_TURN && !wcount ) return 10000; - return -10000; - } - - aa = wcount - bcount; - if ( whose_turn == BLACK_TURN ) aa = -aa; - - if ( aa > 0 ) return aa + 100; - if ( aa < 0 ) return aa - 100; - return( 0 ); -} + gint aa; -/* alpha-beta search */ -static -gint -search(gint n, gint a, gint b) -{ - gint aa, bb, xy, i, j; - - if ( !n ) - { - switch (s_kind) - { - case PERFECT: - return( p_evaluation() ); - case VICTORY: - return( v_evaluation() ); - default: - return( b_evaluation() ); - } - } - - aa = a; - - j = vpointer; - for ( i = (gint)move_count ; i < 64 ; i++ ) - { /* entry valid squares */ - xy = (gint)squares[ i ]; - if ( is_valid( xy, whose_turn ) ) - { - vsquares[ ++j ][ 0 ] = xy; - move_board( xy ); - vsquares[ j ][ 1 ] = mobility(); - undo(); - } - } - - if ( j == vpointer ) /* pass ? */ - { - whose_turn = ( whose_turn == WHITE_TURN ) ? BLACK_TURN : WHITE_TURN; - if ( !mobility() ) - { - whose_turn = OTHER_PLAYER (whose_turn); - - switch ( s_kind ) - { - case PERFECT: return( p_evaluation() ); - case VICTORY: return( v_evaluation() ); - default: return( w_evaluation() ); - } - } - aa = -search( n, -b, -aa ); - whose_turn = OTHER_PLAYER (whose_turn); - vsquares[ j ][ 0 ] = 0; /* mark pass */ - return aa; - } - - sort( vpointer + 1, j ); - - i = vpointer; /* save old vpointer */ - vpointer = j + 1; /* new vpointer */ - - j = i + 1; - while ( aa < b && j < vpointer ) - { - xy = vsquares[ j ][ 0 ]; - move_board( xy ); - bb = -search( n - 1, -b, -aa ); /* evaluate this square */ - undo(); - if ( aa < bb ) - { - aa = bb; - vsquares[ i ][ 0 ] = xy; /* save this square */ - } - j++; - } - vpointer = i; /* pop vpointer */ - return aa; -} + aa = wcount - bcount; + if (whose_turn == BLACK_TURN) + aa = -aa; -static -void -random_select( void ) -{ - gint xy, i, j; + if (!bcount || !wcount) + { + if (aa > 0) + return aa + 10000; + return aa - 10000; + } - vsquares[ 0 ][ 0 ] = 0; - j = 0; - for ( i = move_count ; i < 64 ; i++ ) - { - xy = squares[ i ]; - if ( is_valid( xy, whose_turn ) ) - vsquares[ j++ ][ 0 ] = xy; - } - if ( j ) - { - i = g_rand_int_range (rgen, 0, j); - vsquares[ 0 ][ 0 ] = vsquares[ i ][ 0 ]; - } + if (aa > 0) + return aa + 1000; + if (aa < 0) + return aa - 1000; + return 0; } -static +/* alpha-beta search */ gint -computer_move (gint level) +search (guint n, gint a, gint b) { - gint nn, aa, kind, best_xy; + guint i, j, xy; + gint aa, bb; - vsquares[ 0 ][ 0 ] = -1; - nn = 64 - move_count; - if ( nn > BEST ) random_select(); - else - { - if ( nn <= PERFECT - level ) - { kind = PERFECT; aa = 127; } - if ( PERFECT - level < nn && nn <= VICTORY - level ) - { kind = VICTORY; aa = 2; } - if ( VICTORY - level < nn && nn <= BEST ) - { kind = BEST; aa = 32767; nn = MAX_DEPTH - level; } - s_kind = kind; - vsquares[ 0 ][ 1 ] = search( nn, -aa, aa ); - } - - best_xy = vsquares[ 0 ][ 0 ]; - - if ( best_xy == -1 ) /* If I can't win, then search the best again. */ - { - s_kind = BEST; - vsquares[ 0 ][ 1 ] = search( MAX_DEPTH - level, -32767, 32767 ); - best_xy = vsquares[ 0 ][ 0 ]; - } + if (!n) /* end ? */ + { + switch (s_kind) + { + case PERFECT: + return (p_evaluation ()); + case VICTORY: + return (v_evaluation ()); + default: + return (b_evaluation ()); + } + } + + aa = a; + + j = vpointer; /* entry valid squares */ + for (i = move_count; i < 64; i++) + { + xy = squares[i]; + if (is_valid (xy, whose_turn)) + { + vsquares[++j][0] = xy; + move_board (xy); + vsquares[j][1] = mobility (whose_turn); /* simple evaluation */ + back (); + } + } - if ( best_xy ) - move ( best_xy % 10 - 1, best_xy / 10 - 1, whose_turn ); + if (j == vpointer) /* pass ? */ + { + whose_turn = OTHER_PLAYER (whose_turn); + if (!mobility (whose_turn)) /* end ? */ + { + whose_turn = OTHER_PLAYER (whose_turn); - return FALSE; -} + switch (s_kind) + { + case PERFECT: + return p_evaluation (); + case VICTORY: + return v_evaluation (); + default: + return w_evaluation (); + } + } -gint -computer_move_1 (guint me) -{ - return computer_move( 6 ); -} + aa = -search (n, -b, -aa); + whose_turn = OTHER_PLAYER (whose_turn); + vsquares[j][0] = 0; /* mark pass */ + return aa; + } -gint -computer_move_2 (guint me) -{ - return computer_move( 4 ); -} + sort (vpointer + 1, j); /* sort vsquares */ -gint -computer_move_3 (guint me) -{ - return computer_move( 2 ); -} + i = vpointer; /* save vpointer */ + vpointer = j + 1; /* new vpointer */ -gint -computer_move_4 (guint me) -{ - return computer_move( 0 ); + j = i + 1; + while (aa < b && j < vpointer) /* evaluate squares */ + { + xy = vsquares[j][0]; + move_board (xy); + bb = -search (n - 1, -b, -aa); + back (); + if (aa < bb) + { + aa = bb; + vsquares[i][0] = xy; /* save this square */ + } + j++; + } + vpointer = i; /* pop vpointer */ + return aa; +} + +/* for first 6 turns */ +static void +random_select (void) +{ + guint i, j, xy; + + vsquares[0][0] = 0; + j = 0; + for (i = move_count; i < 64; i++) + { + xy = squares[i]; + if (is_valid (xy, whose_turn)) + vsquares[j++][0] = xy; + } + if (j > 1) + { + i = g_rand_int_range (rgen, 0, j); + if (heuristic[vsquares[i][0]] < 0) /* If the square is critical */ + i = g_rand_int_range (rgen, 0, j); /* then select once more. */ + vsquares[0][0] = vsquares[i][0]; + } } gboolean -flip_final_results (gpointer data) +computer_move (guint level) { - guint i; - guint white_pieces; - guint black_pieces; - guint adder = 0; - - white_pieces = wcount; - black_pieces = bcount; - - i = 0; - for ( ; i < black_pieces; i++ ) - { - board[i % 8][i / 8] = BLACK_TURN; - if ( pixmaps[i % 8][i / 8] < 1 ) - pixmaps[i % 8][i / 8] = WHITE_TURN; - if ( pixmaps[i % 8][i / 8] == WHITE_TURN ) - { - pixmaps[i % 8][i / 8] += adder; - if (animate_stagger) adder++; - } - } - for ( ; i < 64 - white_pieces; i++ ) - { - board[i % 8][i / 8] = 0; - pixmaps[i % 8][i / 8] = 100; - } - for ( ; i < 64; i++ ) - { - board[i % 8][i / 8] = WHITE_TURN; - if ( pixmaps[i % 8][i / 8] == 0 ) - pixmaps[i % 8][i / 8] = BLACK_TURN; - if ( pixmaps[i % 8][i / 8] == BLACK_TURN ) - { - pixmaps[i % 8][i / 8] -= adder; - if ( animate_stagger ) adder++; - } - } - - tiles_to_flip = 1; - - return FALSE; -} - -gint -check_valid_moves (void) -{ - guint white_moves = 0; - guint black_moves = 0; - - if ( !game_in_progress ) - return TRUE; - if ( mobility() ) - return TRUE; - - whose_turn = OTHER_PLAYER (whose_turn); + guint depth, nn, kind; + gint aa, best_xy; + + vsquares[0][0] = -1; + depth = clamp_int ((level * 2 - CS), 1, MAX_DEPTH); + nn = 64 - move_count; + if (nn > BEST) + random_select (); + else + { + if (nn <= PERFECT - MAX_DEPTH + depth) + { + kind = PERFECT; + aa = 127; + } + if (PERFECT - MAX_DEPTH + depth < nn && nn <= VICTORY - MAX_DEPTH + depth) + { + kind = VICTORY; + aa = 2; + } + if (VICTORY - MAX_DEPTH + depth < nn && nn <= BEST) + { + kind = BEST; + aa = 32767; + nn = depth; + } + s_kind = kind; + vsquares[0][1] = search (nn, -aa, aa); + } + + best_xy = vsquares[0][0]; + if (best_xy == -1) /* If I can't win, then search the best again. */ + { + s_kind = BEST; + vsquares[0][1] = search (depth, -32767, 32767); + best_xy = vsquares[0][0]; + } - if ( !mobility() ) - { - white_moves = wcount; - black_moves = bcount; - if ( white_moves > black_moves ) - gui_message (_("Light player wins!")); - if ( black_moves > white_moves ) - gui_message (_("Dark player wins!")); - if ( white_moves == black_moves ) - gui_message (_("The game was a draw.")); - whose_turn = 0; - game_in_progress = 0; - if ( flip_final ) - flip_final_id = g_timeout_add (100, flip_final_results, NULL); - return TRUE; - } - - if ( whose_turn == BLACK_TURN ) - { - gui_message(_("Light must pass, Dark's move")); - return TRUE; - } - - if ( whose_turn == WHITE_TURN ) - { - gui_message(_("Dark must pass, Light's move")); - return TRUE; - } + if (game_in_progress && best_xy) /* not pass ? */ + return move (best_xy % 10, best_xy / 10); - return TRUE; + return FALSE; } diff -uNr gnome-games-2.14.1.org/iagno/othello.h gnome-games-2.14.1/iagno/othello.h --- gnome-games-2.14.1.org/iagno/othello.h 2006-08-05 15:32:11.000000000 +0900 +++ gnome-games-2.14.1/iagno/othello.h 2006-08-05 15:32:35.000000000 +0900 @@ -1,6 +1,5 @@ /* - * othello.h - Header for othello.c - * written by Ian Peters <itp@gnu.org> + * othello.h * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,17 +21,14 @@ #ifndef _OTHELLO_H_ #define _OTHELLO_H_ -gint is_valid_move (guint, guint, guint); -gint move (guint, guint, guint); -void move_board (gint); -gboolean flip_final_results (gpointer data); -gint check_valid_moves (void); -gint computer_move_1 (guint); -gint computer_move_2 (guint); -gint computer_move_3 (guint); -gint computer_move_4 (guint); void init (void); -void board_copy (void); -void undo (void); +void copy_board (void); +void copy_pixmaps (void); +gboolean is_valid_move (guint x, guint y, guint who); +void move_board (guint xy); +void back (void); +gint mobility (guint who); +gint search (guint n, gint a, gint b); +gboolean computer_move (guint level); #endif
Please attach patches instead. *** This bug has been marked as a duplicate of 350068 ***