12 static void fill_a_square(GnomeCanvasGroup *group,
13 double x1, double y1, double x2, double y2, char *color);
14 static void get_square_color(int square, char *color);
15 static void draw_a_line(GnomeCanvasGroup *group,
16 int x1, int y1, int x2, int y2, char *color);
17 static void draw_grid();
22 extern struct options options;
23 extern struct game_states states;
26 extern GtkWidget *main_window;
28 Square legal_moves[100];
31 static Board_State bstate;
34 void init_game_board(GtkWidget *GamazonsMain)
38 GtkWidget *w = (GtkWidget *) lookup_widget(GamazonsMain, BOARD_NAME);
39 GtkWidget *force_button, *undo_button;
41 GtkTextBuffer *buffer;
42 static int first_run = TRUE;
45 printf("Couldn't find board!!!!!!!!\n");
47 board = (Board *) malloc(sizeof(Board));
48 board->canvas = GNOME_CANVAS(w);
49 board->root = GNOME_CANVAS_GROUP(gnome_canvas_item_new(gnome_canvas_root(board->canvas),
50 gnome_canvas_group_get_type(),
53 gnome_canvas_set_scroll_region(board->canvas, 0.0, 0.0,
58 /* initialize pieces */
59 for (i=0; i<BOARD_SIZE; i++)
61 for (j=0; j<BOARD_SIZE; j++)
63 board->squares[i][j] = NOTHING;
66 gtk_signal_connect(GTK_OBJECT(board->canvas), "event",
67 GTK_SIGNAL_FUNC(arrow_fire_cb), NULL);
69 //Place amazon queens on the board
70 board->squares[9][3] = WHITE;
71 board->squares[9][6] = WHITE;
72 board->squares[6][0] = WHITE;
73 board->squares[6][9] = WHITE;
75 board->squares[0][3] = BLACK;
76 board->squares[0][6] = BLACK;
77 board->squares[3][0] = BLACK;
78 board->squares[3][9] = BLACK;
80 board->square_to_wh_queen_map[0] = 96;
81 board->square_to_wh_queen_map[1] = 93;
82 board->square_to_wh_queen_map[2] = 60;
83 board->square_to_wh_queen_map[3] = 69;
85 board->square_to_bl_queen_map[0] = 3;
86 board->square_to_bl_queen_map[1] = 6;
87 board->square_to_bl_queen_map[2] = 30;
88 board->square_to_bl_queen_map[3] = 39;
90 //Set up move history window
91 view = (GtkTextView *) lookup_widget(main_window, "textview1");
92 buffer = gtk_text_buffer_new(NULL);
93 gtk_text_view_set_buffer(view, buffer);
96 force_button = (GtkWidget *)lookup_widget(main_window, "BT_FORCEMOVE");
97 gtk_widget_set_sensitive (force_button, FALSE);
98 undo_button = (GtkWidget *)lookup_widget(main_window, "BT_UNDO");
99 gtk_widget_set_sensitive (undo_button, FALSE);
105 bstate_set_just_finished(START_GAME);
111 void fill_a_square(GnomeCanvasGroup *group,
112 double x1, double y1, double x2, double y2, char *color)
115 gnome_canvas_item_new(group,
116 gnome_canvas_rect_get_type(),
121 "outline_color", "black",
123 "width_pixels", (double)THICKNESS,
128 static void get_square_color(int square, char *color)
130 if ((square % 2) == 0)
131 strcpy(color, SQUARE_COLOR_1);
133 strcpy(color, SQUARE_COLOR_2);
137 static void draw_grid()
141 for (x=0; x<=10; x++)
143 for (y=0; y<=10; y++)
146 draw_a_line(board->root, //gnome_canvas_root(board->canvas),
147 0, y*CELL_SIZE, BOARD_SIZE*CELL_SIZE, y*CELL_SIZE, "black");
150 draw_a_line(board->root, //gnome_canvas_root(board->canvas),
151 x*CELL_SIZE, 0, x*CELL_SIZE, BOARD_SIZE*CELL_SIZE, "black");
158 static void draw_a_line(GnomeCanvasGroup *group,
159 int x1, int y1, int x2, int y2, char *color)
161 GnomeCanvasPoints *points;
163 /* allocate a new points array */
164 points = gnome_canvas_points_new (2);
166 /* fill out the points */
167 points->coords[0] = x1;
168 points->coords[1] = y1;
169 points->coords[2] = x2;
170 points->coords[3] = y2;
172 gnome_canvas_item_new(group,
173 gnome_canvas_line_get_type(),
176 "width_units", (double)THICKNESS,
179 /* free the points array */
180 gnome_canvas_points_free(points);
187 GdkPixbuf *white_pb, *black_pb;
188 GdkPixbuf *white_sq, *grey_sq, *arrow_sq;
190 GnomeCanvasItem *image;
191 GnomeCanvasGroup *root = GNOME_CANVAS_GROUP(gnome_canvas_root (GNOME_CANVAS (board->canvas)));
192 static int first_game = 1;
197 white_pb = gdk_pixbuf_new_from_file(options.images.white_piece, NULL);
198 if (white_pb == NULL)
200 fprintf(stderr, "Cannot find white piece image: %s\n", options.images.white_piece);
204 black_pb = gdk_pixbuf_new_from_file(options.images.black_piece, NULL);
205 if (black_pb == NULL)
207 fprintf(stderr, "Cannot find black piece image: %s\n", options.images.black_piece);
211 white_sq = gdk_pixbuf_new_from_file(options.images.white_sq, NULL);
212 if (white_sq == NULL)
214 fprintf(stderr, "Cannot find white square image: %s\n", options.images.white_sq);
218 grey_sq = gdk_pixbuf_new_from_file(options.images.grey_sq, NULL);
221 fprintf(stderr, "Cannot find grey square image: %s\n", options.images.grey_sq);
224 arrow_sq = gdk_pixbuf_new_from_file(options.images.arrow_sq, NULL);
225 if (arrow_sq == NULL)
227 fprintf(stderr, "Cannot find arrow square image: %s\n", options.images.arrow_sq);
233 /* fill alternate squares */
234 for(j=0;j<BOARD_SIZE;j++)
236 for(i=0;i<BOARD_SIZE;i++)
238 board->square_items[j*10+i] = NULL;
241 board->square_items[j*10+i] = gnome_canvas_item_new (board->root,
242 gnome_canvas_pixbuf_get_type (),
243 "x", i*CELL_SIZE+QUEEN_OFFSET, "y", j*CELL_SIZE+QUEEN_OFFSET,
244 "width", CELL_SIZE, "height", CELL_SIZE,
245 "width_set", TRUE, "height_set", TRUE,
251 board->square_items[j*10+i] = gnome_canvas_item_new (board->root,
252 gnome_canvas_pixbuf_get_type (),
253 "x", i*CELL_SIZE+QUEEN_OFFSET, "y", j*CELL_SIZE+QUEEN_OFFSET,
254 "width", CELL_SIZE, "height", CELL_SIZE,
255 "width_set", TRUE, "height_set", TRUE,
262 //Place the queen images on the board in the right order
263 if (board->squares[j][i] == WHITE)
266 printf("Square %c%c contains a white queen\n",i+'a',10-j+'0');
268 image = gnome_canvas_item_new (board->root,
269 gnome_canvas_pixbuf_get_type (),
270 "x", i*CELL_SIZE+QUEEN_OFFSET, "y", j*CELL_SIZE+QUEEN_OFFSET,
271 "width", CELL_SIZE, "height", CELL_SIZE,
272 "width_set", TRUE, "height_set", TRUE,
275 //We need to do some funky checking to make sure board->white_queens[] matches
276 //up exactly with state->white_q_x[], state->white_q_y[]
279 if(j*10 +i == board->square_to_wh_queen_map[k])
281 board->white_queens[k] = image;
283 printf("registering queen %d\n", k);
290 printf("connecting signal to queen\n");
292 gtk_signal_connect(GTK_OBJECT(image), "event",
293 GTK_SIGNAL_FUNC(board_press_cb), NULL);
295 else if (board->squares[j][i] == BLACK)
298 printf("Square %c%c contains a black queen\n",i+'a',10-j+'0');
300 image = gnome_canvas_item_new (board->root,
301 gnome_canvas_pixbuf_get_type (),
302 "x", i*CELL_SIZE+QUEEN_OFFSET, "y", j*CELL_SIZE+QUEEN_OFFSET,
303 "width", CELL_SIZE, "height", CELL_SIZE,
304 "width_set", TRUE, "height_set", TRUE,
309 if(j*10 +i == board->square_to_bl_queen_map[k])
311 board->black_queens[k] = image;
313 printf("registering queen %d\n", k);
320 printf("connecting signal to queen\n");
322 gtk_signal_connect(GTK_OBJECT(image), "event",
323 GTK_SIGNAL_FUNC(board_press_cb), NULL);
325 else if (board->squares[j][i] == ARROW)
327 image = gnome_canvas_item_new (board->root,
328 gnome_canvas_pixbuf_get_type (),
329 "x", i*CELL_SIZE+QUEEN_OFFSET, "y", j*CELL_SIZE+QUEEN_OFFSET,
330 "width", CELL_SIZE, "height", CELL_SIZE,
331 "width_set", TRUE, "height_set", TRUE,
340 if (options.images.grid == TRUE)
344 image = gnome_canvas_item_new (root,
345 gnome_canvas_pixbuf_get_type (),
346 "x", 10.0, "y", 10.0,
347 "width", 40.0, "height", 40.0,
348 "width_set", TRUE, "height_set", TRUE,
354 gtk_widget_show_now(main_window);
355 gtk_widget_queue_draw ((GtkWidget *) board->canvas);
356 gtk_widget_show_now((GtkWidget *) board->canvas);
361 void mark_square (GnomeCanvasItem *square)
363 gnome_canvas_item_set (square, "outline_color", "red", NULL);
366 Square get_square (double x, double y)
373 x -= (BOARD_BORDER - CELL_PAD);
374 y -= (BOARD_BORDER - CELL_PAD);
379 else if (x > ((BOARD_SIZE-1) * CELL_SIZE))
380 x = (BOARD_SIZE-1) * CELL_SIZE;
383 else if (y > ((BOARD_SIZE-1) * CELL_SIZE))
384 y = (BOARD_SIZE-1) * CELL_SIZE;
386 x_square = x / CELL_SIZE;
387 y_square = y / CELL_SIZE;
390 printf("x coord = %f y coord = %f\n", x, y);
391 printf("x coord = %d y coord = %d\n", x_square, y_square);
394 from = x_square + y_square * 10;
399 void clear_square (GnomeCanvasItem **square)
401 gnome_canvas_item_set (*square, "outline_color", NULL, NULL);
405 /*==============================================================================
408 * Attempts to move a piece from one square to the next. If the piece successfully
409 * arrives to its destination, it returns TRUE. If the move is aborted, returns
412 int try_move (Board *board, GnomeCanvasItem *item)
414 double Lx, Uy, Rx, By;
420 to_Lx = get_x_from_square(board->to);
421 to_Uy = get_y_from_square(board->to);
424 printf("We want the queen at coords %f, %f\n", to_Lx, to_Uy);
426 gnome_canvas_item_get_bounds(item, &Lx, &Uy, &Rx, &By);
428 printf("The queen is at coords %f, %f\n", Lx, Uy);
430 while (Lx != to_Lx || Uy != to_Uy)
432 bstate_set_moving_piece(TRUE);
448 gnome_canvas_item_move (item, (double)x, (double)y);
449 gnome_canvas_item_raise_to_top (item);
452 while (gtk_events_pending())
453 gtk_main_iteration();
455 if (bstate_get_quit_game())
458 if (bstate_get_stop_moving())
460 bstate_set_stop_moving(FALSE);
463 gnome_canvas_item_get_bounds(item, &Lx, &Uy, &Rx, &By);
466 gnome_canvas_item_raise_to_top (item);
467 bstate_set_moving_piece(FALSE);
468 //see where it landed
469 gnome_canvas_item_get_bounds(item, &Lx, &Uy, &Rx, &By);
471 printf("The queen landed at coords %f, %f\n", Lx, Uy);
472 printf("this time the queen is on square %d\n", board->to);
478 double get_x_from_square(int sq)
482 x = (double) ((sq % 10) * CELL_SIZE+QUEEN_OFFSET);
488 double get_y_from_square(int sq)
492 y = (double) ((sq / 10) * CELL_SIZE+QUEEN_OFFSET);
499 int get_x_int_from_square(int sq)
504 int get_y_int_from_square(int sq)
509 int get_grid_num_from_square(int sq)
514 char get_grid_alpha_from_square(int sq)
516 return('a' + sq % 10);
519 int engine_x_to_board_x(int eng_x)
521 return(eng_x);//hey, these are the same, no conversion necessary
524 int engine_y_to_board_y(int eng_y)
529 int board_x_to_engine_x(int brd_x)
534 int board_y_to_engine_y(int brd_y)
539 int get_square_from_engine(int x, int y)
541 return((9 - y) * 10 + x);
545 void fire_arrow(Square sq)
549 GnomeCanvasItem *image;
550 GnomeCanvasGroup *root = GNOME_CANVAS_GROUP(gnome_canvas_root (GNOME_CANVAS (board->canvas)));
555 board->squares[y][x] = ARROW;
557 arrow_sq = gdk_pixbuf_new_from_file(options.images.arrow_sq, NULL);
558 if (arrow_sq == NULL)
560 fprintf(stderr, "Cannot find arrow image: %s\n", options.images.arrow_sq);
564 image = gnome_canvas_item_new (board->root,
565 gnome_canvas_pixbuf_get_type (),
566 "x", x*CELL_SIZE+QUEEN_OFFSET, "y", y*CELL_SIZE+QUEEN_OFFSET,
567 "width", CELL_SIZE, "height", CELL_SIZE,
568 "width_set", TRUE, "height_set", TRUE,
574 void square_contains(Square sq)
578 col = get_x_int_from_square(sq);
579 row = get_y_int_from_square(sq);
581 if (board->squares[row][col] == NOTHING)
582 printf("Nothing is found at square %d\n", sq);
583 else if (board->squares[row][col] == WHITE)
584 printf("A White Queen is found at square %d\n", sq);
585 else if (board->squares[row][col] == BLACK)
586 printf("A Black Queen is found at square %d\n", sq);
587 else if (board->squares[row][col] == ARROW)
588 printf("An arrow is found at square %d\n", sq);
590 printf("Whoa, I don't know _what_ is on square %d\n", sq);
594 /*==============================================================================
597 * Checks to see if an AI oppenent is next to move. If it is, it starts the
598 * move process, and checks for a win afterwards. If not, it just checks for
599 * the win. Returns TRUE if an AI opponent moves next. False if human.
601 * NOTE: If you have 2 AI players, this function would just keep thinking and
602 * never let the board update or respond. So there are several checks to see
603 * if any new events occured that should be handled, or critical changes have
604 * been made (like starting a new game, etc..). If something critical has changed
605 * the function will exit after learning about it.
609 state *s = states.s[states.current_state];
614 //GtkWidget *auto_button, *force_button;
616 current_hash = state_hash = create_hash(s);
618 //It's sometimes necessary to know if we're in the middle of a move, because
619 //if an event causes another move to start and that event is processed and then
620 //this function finishes, it leaves the board in an unstable result
622 //XXX This should call a function to disable certain event handling instead of
623 //just having a silly global variable. For instance, it could gray out the
624 //Auto Finish button so the user knows it's not going to do anything when he
625 //presses it. Perhaps the 'Force Move' button should be greyed out until the AI
626 //is thinking, or since Force Move & Auto Finish are mutually exclusive, it would
627 //be cool to have the button switch labels depending on the state of the game.
630 auto_button = (GtkWidget *) lookup_widget(main_window, "BT_AUTOFINISH");
631 force_button = (GtkWidget *) lookup_widget(main_window, "BT_FORCEMOVE");
632 gtk_widget_set_sensitive (auto_button, FALSE);
633 gtk_widget_set_sensitive (force_button, TRUE);
639 //quit this function if a 'New Game' option was selected since this
640 //function was started.
641 if (bstate_get_new_game())
643 bstate_set_new_game(FALSE);
647 //gnome_canvas_item_request_update(board->canvas);
649 if (((states.s[states.current_state]->turn == WHITE_PLAYER) && (options.white_player == AI)) ||
650 ((states.s[states.current_state]->turn == BLACK_PLAYER) && (options.black_player == AI)))
652 what_next = WAIT_FOR_AI;
658 temp = isearch(s, NOTHINK);
659 if (s->winner) //XXX does this if statement do any good? I thot winner was handled elsewhere
663 //update the board before drawing the new move
664 //the program would segfault if you closed it while it was thinking
665 while (gtk_events_pending())
666 gtk_main_iteration();
667 if (current_hash != state_hash)
670 if (bstate_get_new_game())
672 bstate_set_new_game(FALSE);
676 if (bstate_get_quit_game())
680 //register move on graphical board
681 if (move_piece(temp))
683 print_move_in_text_window(&temp);
684 dup_state(s, states.s[++(states.current_state)]);
693 printf("the AI doesn't move next:\n");
699 if (s->turn == WHITE_PLAYER)
700 what_next = MOVE_WHITE_QUEEN;
701 if (s->turn == BLACK_PLAYER)
702 what_next = MOVE_BLACK_QUEEN;
705 bstate_set_just_finished(WAIT_FOR_AI);
709 if (options.white_player == AI)
710 printf("White is AI\n");
711 if (options.black_player == AI)
712 printf("Black is AI\n");
713 printf("Turn is %d\n", states.s[states.current_state]->turn );
716 if (game_over(movelist))
718 //XXX should I set ai = FALSE?
725 gtk_widget_set_sensitive (auto_button, TRUE);
726 gtk_widget_set_sensitive (force_button, FALSE);
732 /*==============================================================================
735 * Takes a move struct generated by the engine, and extracts the necessary info
736 * to update the GUI data structs and have the GUI reflect the move.
738 * Returns FALSE if the move failed or aborted, TRUE if successful.
740 int move_piece(move m)
742 GnomeCanvasItem *item;
743 int from_row, from_col;
746 board->to = get_square_from_engine(m.tocol, m.torow);
747 to_col = get_x_int_from_square(board->to);
748 to_row = get_y_int_from_square(board->to);
749 //Note: by the time the state gets here, it's signaled the other player's turn
750 //so if it says it's white's turn, black just moved and we need to move black's
752 if (states.s[states.current_state]->turn == WHITE_PLAYER)
754 board->from = get_square_from_engine(states.s[states.current_state -1]->black_q_x[m.queen],
755 states.s[states.current_state -1]->black_q_y[m.queen]);
757 board->squares[to_row][to_col] = BLACK;
759 printf("Moving black queen\n");
761 item = board->black_queens[m.queen];
762 board->square_to_bl_queen_map[m.queen] = to_row*10 +to_col;
766 board->from = get_square_from_engine(states.s[states.current_state -1]->white_q_x[m.queen],
767 states.s[states.current_state -1]->white_q_y[m.queen]);
768 board->squares[to_row][to_col] = WHITE;
770 printf("Moving white queen\n");
772 item = board->white_queens[m.queen];
773 board->square_to_wh_queen_map[m.queen] = to_row*10 +to_col;
777 from_col = get_x_int_from_square(board->from);
778 from_row = get_y_int_from_square(board->from);
779 board->squares[from_row][from_col] = NOTHING;
781 if (try_move(board, item))
782 fire_arrow(get_square_from_engine(m.wallcol, m.wallrow));
786 printf("Engine coords for arrow: %d, %d\n", m.wallcol, m.wallrow);
787 printf("fired arrow to square %d\n", get_square_from_engine(m.wallcol, m.wallrow));
793 /*==============================================================================
794 * register_move_with_engine
796 * Fills out a move struct with the human's move and calls makemove() to update
797 * the state struct, so the AI engine knows what happened.
799 void register_move_with_engine(Square arrow_sq)
801 state *s = states.s[states.current_state];
811 //find out the index of the queen that was just moved.
812 //weird things will happen if it's not found.
815 if (board->selected_queen == board->white_queens[i] ||
816 board->selected_queen == board->black_queens[i])
824 fprintf(stderr, "Error registering move w/ AI engine! Game play will now be weird.\n");
827 m.torow = board_y_to_engine_y(get_y_int_from_square(board->to));
828 m.tocol = board_x_to_engine_x(get_x_int_from_square(board->to));
830 m.wallrow = board_y_to_engine_y(get_y_int_from_square(arrow_sq));
831 m.wallcol = board_x_to_engine_x(get_x_int_from_square(arrow_sq));
833 //make sure it's a valid move
834 move_count = children(s, movelist);
837 gnome_error_dialog("The AI engine thinks the game is over. Please use the menu item Game->New to start a new game");
840 if (!move_lookup(&m, movelist, move_count))
842 get_move_str(&m, move_str);
843 strcpy(err_msg, "You've hit a bug. The following illegal move was just attempted: ");
844 strcat(err_msg, move_str);
845 gnome_error_dialog(err_msg);
850 print_move_in_text_window(&m);
854 /*==============================================================================
857 * Compares the given square with the information stored in board->squares[][]
858 * to see if a queen is there.
860 int is_queen_square(Square sq)
864 col = get_x_int_from_square(sq);
865 row = get_y_int_from_square(sq);
867 if ((board->squares[row][col] == BLACK) ||
868 (board->squares[row][col] == WHITE))
875 /*==============================================================================
878 * Given a square, this generates an array of all legal moves that can be made
879 * from it. This works for both queen movement, as well as firing an arrow,
880 * since both move the same way.
882 * The array terminator is 100
884 void gen_legal_moves(Square sq)
888 int row, col, sq_row, sq_col;
891 sq_col = get_x_int_from_square(sq);
892 sq_row = get_y_int_from_square(sq);
894 //make sure the player can drop the piece on the same square if he changes
896 legal_moves[arr_i++] = sq;
901 while (board->squares[row][col] == NOTHING && row < 10)
903 legal_moves[arr_i++] = (row*10) + col;
908 while (board->squares[row][col] == NOTHING && row >= 0)
910 legal_moves[arr_i++] = (row*10) + col;
914 //get horizontal moves
917 while (board->squares[row][col] == NOTHING && col < 10)
919 legal_moves[arr_i++] = (row*10) + col;
924 while (board->squares[row][col] == NOTHING && col >= 0)
926 legal_moves[arr_i++] = (row*10) + col;
930 //get forward diagonal moves
933 while (board->squares[row][col] == NOTHING && col < 10 && row < 10)
935 legal_moves[arr_i++] = (row*10) + col;
942 while (board->squares[row][col] == NOTHING && col >= 0 && row >= 0)
944 legal_moves[arr_i++] = (row*10) + col;
949 //get backward diagonal moves
952 while (board->squares[row][col] == NOTHING && col >= 0 && row < 10)
954 legal_moves[arr_i++] = (row*10) + col;
961 while (board->squares[row][col] == NOTHING && col < 10 && row >= 0)
963 legal_moves[arr_i++] = (row*10) + col;
969 legal_moves[arr_i] = 100;
971 printf("legal move list for %d of length %d: \n", sq, arr_i);
973 while (legal_moves[i] < 100)
974 printf(" %d", legal_moves[i++]);
980 /*==============================================================================
983 * Looks up the given square in the current legal_moves array. If it doesn't
984 * exist, it's not a legal move and returns FALSE. Returns TRUE if it is there.
986 int is_move_legal(Square sq)
991 printf("checking to see if a move is legal\n");
993 while (legal_moves[i] < 100)
995 if (sq == legal_moves[i++])
998 printf("%d is a legal move\n", sq);
1005 printf("Can't move to square. Legal moves are: %d\n", sq);
1007 while (legal_moves[i] < 100)
1008 printf(" %d", legal_moves[i++]);
1014 /*==============================================================================
1017 * DEBUG - counts the number of queens on the GUI representation and prints
1018 * out a bunch of XXXX's whenever there are not 4 of both kinds.
1022 int black=0, white=0;
1029 if (board->squares[i][j] == WHITE)
1031 if (board->squares[i][j] == BLACK)
1036 printf("YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY Gained a black queen\n");
1038 printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Gained a white queen\n");
1040 printf("XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXXYXYX Lost a black queen\n");
1042 printf("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ Lost a white queen\n");
1047 /*==============================================================================
1050 * When a new game is started, we want to free all the memory we've allocated
1051 * so we can start all over without leaking all the memory.
1053 void free_all_memory()
1058 for (i=0; i< states.max_state; i++)
1061 //Oh, this is ugly! Do I really want to do this?
1065 for (i=0; i<TT; i++)
1078 /*==============================================================================
1081 * Creates a hash value for the current state. On the GUI side it's used to
1082 * see if the state has changed recently.
1084 int create_hash(state *s)
1087 ull board_u, board_l;
1089 board_u = s->white_bd[1] | s->black_bd[1] | s->blocks_bd[1];
1090 board_l = s->white_bd[0] | s->black_bd[0] | s->blocks_bd[0];
1092 return( (board_u ^ board_l) % TT);
1096 /*==============================================================================
1099 * Checks to see if the game is over and generates a pop-up stating who the
1100 * winner is. Returns TRUE if the game is over.
1102 int game_over(move *movelist)
1104 state *s = states.s[states.current_state];
1105 // GtkWidget *auto_button, *force_button;
1107 if (children(s, movelist) == 0)
1109 //printf("player %d wins!\n", s->turn^3);
1110 s->winner = s->turn^3;
1111 if (s->winner == BLACK)
1112 gnome_ok_dialog("White wins!");
1114 gnome_ok_dialog("Black wins!");
1116 bstate_set_just_finished(GAME_OVER);
1119 auto_button = (GtkWidget *) lookup_widget(main_window, "BT_AUTOFINISH");
1120 force_button = (GtkWidget *) lookup_widget(main_window, "BT_FORCEMOVE");
1121 gtk_widget_set_sensitive (auto_button, FALSE);
1122 gtk_widget_set_sensitive (force_button, FALSE);
1132 /*==============================================================================
1135 * Updates the status bar based on the current value of what_next
1139 GtkStatusbar *status = (GtkStatusbar *) lookup_widget(main_window, "statusbar1");
1140 guint context_id = bstate_get_what_next();
1142 gtk_statusbar_pop(status, context_id);
1144 switch (bstate_get_what_next())
1147 gtk_statusbar_push(status, context_id, "Fire Arrow");
1149 case MOVE_BLACK_QUEEN:
1150 gtk_statusbar_push(status, context_id, "Move Black Amazon");
1152 case MOVE_WHITE_QUEEN:
1153 gtk_statusbar_push(status, context_id, "Move White Amazon");
1156 gtk_statusbar_push(status, context_id, "AI is thinking...");
1159 gtk_statusbar_push(status, context_id, "Select Game->New to start game");
1162 gtk_statusbar_push(status, context_id, "I have no idea what to do next!");
1168 /*==============================================================================
1171 * prints out an ascii version of the board, useful for ensuring the board shows
1172 * what it should show.
1178 for (i=0; i<BOARD_SIZE; i++)
1180 for (j=0; j<BOARD_SIZE; j++)
1182 if (board->squares[i][j] == 0)
1184 if (board->squares[i][j] == 1)
1186 if (board->squares[i][j] == 2)
1188 if (board->squares[i][j] == 3)
1195 /*==============================================================================
1198 * Destroys the main board canvas group which contains all the square and piece
1199 * images, and takes them with it. Once done, it creates a new group that
1200 * draw_board() can take advantage of.
1202 void destroy_board()
1205 GtkWidget *CNVS_GAMEBOARD, *w, *scrolledwindow4, *table1;
1209 printf("Destroying board now\n");
1213 gtk_object_destroy(GTK_OBJECT(board->root));
1214 board->root = GNOME_CANVAS_GROUP(gnome_canvas_item_new(gnome_canvas_root(board->canvas),
1215 gnome_canvas_group_get_type(),
1219 /*==============================================================================
1220 * print_move_in_text_window
1222 * Prints the given move in official amazon notation. The move struct doesn't
1223 * contain 'from' information, so that must be retrieved from the previous state
1225 void print_move_in_text_window(move *m)
1228 GtkTextBuffer *buffer;
1229 GtkTextIter *iter = (GtkTextIter *) malloc(sizeof(GtkTextIter));
1230 char string_buf[32];
1231 GtkScrolledWindow *w;
1234 view = (GtkTextView *) lookup_widget(main_window, "textview1");
1235 buffer = gtk_text_view_get_buffer (view);
1236 gtk_text_buffer_get_end_iter(buffer, iter);
1238 get_move_str(m, string_buf);
1241 printf("%s", string_buf);
1243 gtk_text_buffer_insert(buffer, iter, string_buf, -1);
1245 w = (GtkScrolledWindow *) lookup_widget(main_window, "scrolledwindow6");
1246 adj = gtk_scrolled_window_get_vadjustment(w);
1247 gtk_adjustment_set_value(adj, adj->upper);
1248 gtk_scrolled_window_set_vadjustment(w, adj);
1254 /*==============================================================================
1257 * Creates a move string from a move struct
1259 void get_move_str(move *m, char move_str[])
1261 Square to_sq, from_sq, arrow_sq;
1262 int to_num, from_num, arrow_num;
1263 char to_alpha, from_alpha, arrow_alpha;
1264 int state_i = states.current_state;
1267 //Determine which side just moved:
1268 turn = states.s[state_i]->turn^3;
1269 if (turn == WHITE_PLAYER)
1271 from_sq = get_square_from_engine(states.s[state_i-1]->white_q_x[m->queen],
1272 states.s[state_i-1]->white_q_y[m->queen]);
1276 from_sq = get_square_from_engine(states.s[state_i-1]->black_q_x[m->queen],
1277 states.s[state_i-1]->black_q_y[m->queen]);
1279 to_sq = get_square_from_engine(m->tocol, m->torow);
1280 arrow_sq = get_square_from_engine(m->wallcol, m->wallrow);
1284 from_alpha = get_grid_alpha_from_square(from_sq);
1285 from_num = get_grid_num_from_square(from_sq);
1287 to_alpha = get_grid_alpha_from_square(to_sq);
1288 to_num = get_grid_num_from_square(to_sq);
1290 arrow_alpha = get_grid_alpha_from_square(arrow_sq);
1291 arrow_num = get_grid_num_from_square(arrow_sq);
1293 sprintf(move_str, "%d. %c%d-%c%d, %c%d\n", state_i, from_alpha, from_num,
1294 to_alpha, to_num, arrow_alpha, arrow_num);
1299 /*==============================================================================
1300 * bstate_set_just_finished
1302 * tells the internal state machine what state was just finished. It then
1303 * figures out from that what the next state should be. This is designed to
1304 * eliminate the redundant code scattered all around that tries to figure
1307 int bstate_set_just_finished(int finished)
1309 GtkWidget *auto_button, *force_button, *undo_button, *settings_menu;
1311 auto_button = (GtkWidget *) lookup_widget(main_window, "BT_AUTOFINISH");
1312 force_button = (GtkWidget *) lookup_widget(main_window, "BT_FORCEMOVE");
1313 undo_button = (GtkWidget *) lookup_widget(main_window, "BT_UNDO");
1314 settings_menu = (GtkWidget *) lookup_widget(main_window, "Settings");
1319 if (bstate.turn == BLACK_PLAYER)
1321 if (options.white_player == AI)
1323 bstate.what_next = WAIT_FOR_AI;
1324 bstate.moving_ai = TRUE;
1326 gtk_widget_set_sensitive (undo_button, FALSE);
1327 gtk_widget_set_sensitive (auto_button, FALSE);
1328 gtk_widget_set_sensitive (force_button, TRUE);
1332 bstate.what_next = MOVE_WHITE_QUEEN;
1333 bstate.moving_ai = FALSE;
1335 gtk_widget_set_sensitive (undo_button, FALSE);
1336 gtk_widget_set_sensitive (auto_button, TRUE);
1337 gtk_widget_set_sensitive (force_button, FALSE);
1339 bstate.turn = WHITE_PLAYER;
1343 if (options.black_player == AI)
1345 bstate.what_next = WAIT_FOR_AI;
1346 bstate.moving_ai = TRUE;
1348 gtk_widget_set_sensitive (undo_button, FALSE);
1349 gtk_widget_set_sensitive (auto_button, FALSE);
1350 gtk_widget_set_sensitive (force_button, TRUE);
1354 bstate.what_next = MOVE_BLACK_QUEEN;
1355 bstate.moving_ai = FALSE;
1357 gtk_widget_set_sensitive (undo_button, FALSE);
1358 gtk_widget_set_sensitive (auto_button, TRUE);
1359 gtk_widget_set_sensitive (force_button, FALSE);
1361 bstate.turn = BLACK_PLAYER;
1363 gtk_widget_set_sensitive (settings_menu, TRUE);
1365 case MOVE_BLACK_QUEEN:
1366 bstate.what_next = FIRE_ARROW;
1367 gtk_widget_set_sensitive (undo_button, TRUE);
1368 gtk_widget_set_sensitive (auto_button, FALSE);
1369 gtk_widget_set_sensitive (settings_menu, FALSE);
1371 case MOVE_WHITE_QUEEN:
1372 bstate.what_next = FIRE_ARROW;
1373 gtk_widget_set_sensitive (undo_button, TRUE);
1374 gtk_widget_set_sensitive (auto_button, FALSE);
1375 gtk_widget_set_sensitive (settings_menu, FALSE);
1378 if (bstate.turn == BLACK_PLAYER)
1380 if (options.white_player == AI)
1382 bstate.what_next = WAIT_FOR_AI;
1383 bstate.moving_ai = TRUE;
1385 gtk_widget_set_sensitive (undo_button, FALSE);
1386 gtk_widget_set_sensitive (auto_button, FALSE);
1387 gtk_widget_set_sensitive (force_button, TRUE);
1391 bstate.what_next = MOVE_WHITE_QUEEN;
1392 bstate.moving_ai = FALSE;
1394 gtk_widget_set_sensitive (undo_button, FALSE);
1395 gtk_widget_set_sensitive (auto_button, TRUE);
1396 gtk_widget_set_sensitive (force_button, FALSE);
1398 bstate.turn = WHITE_PLAYER;
1402 if (options.black_player == AI)
1404 bstate.what_next = WAIT_FOR_AI;
1405 bstate.moving_ai = TRUE;
1407 gtk_widget_set_sensitive (undo_button, FALSE);
1408 gtk_widget_set_sensitive (auto_button, FALSE);
1409 gtk_widget_set_sensitive (force_button, TRUE);
1413 bstate.what_next = MOVE_BLACK_QUEEN;
1414 bstate.moving_ai = FALSE;
1416 gtk_widget_set_sensitive (undo_button, FALSE);
1417 gtk_widget_set_sensitive (auto_button, TRUE);
1418 gtk_widget_set_sensitive (force_button, FALSE);
1420 bstate.turn = BLACK_PLAYER;
1424 if (bstate.turn == BLACK_PLAYER)
1426 bstate.what_next = MOVE_BLACK_QUEEN;
1430 bstate.what_next = MOVE_WHITE_QUEEN;
1432 gtk_widget_set_sensitive (settings_menu, TRUE);
1433 gtk_widget_set_sensitive (undo_button, FALSE);
1434 gtk_widget_set_sensitive (auto_button, TRUE);
1437 bstate.what_next = WAIT_FOR_AI;
1438 gtk_widget_set_sensitive (settings_menu, FALSE);
1439 gtk_widget_set_sensitive (undo_button, FALSE);
1440 gtk_widget_set_sensitive (auto_button, FALSE);
1443 gtk_widget_set_sensitive (force_button, FALSE);
1446 if (options.white_player == AI)
1448 bstate.what_next = NEW_GAME;
1449 gtk_widget_set_sensitive (undo_button, FALSE);
1450 gtk_widget_set_sensitive (auto_button, FALSE);
1451 gtk_widget_set_sensitive (force_button, FALSE);
1455 bstate.what_next = MOVE_WHITE_QUEEN;
1456 gtk_widget_set_sensitive (undo_button, FALSE);
1457 gtk_widget_set_sensitive (auto_button, TRUE);
1458 gtk_widget_set_sensitive (force_button, FALSE);
1460 gtk_widget_set_sensitive (settings_menu, TRUE);
1461 bstate.turn = WHITE_PLAYER;
1462 bstate.from = INVALID_SQUARE_VALUE;
1463 bstate.to = INVALID_SQUARE_VALUE;
1464 bstate.last_arrow = INVALID_SQUARE_VALUE;
1465 bstate.moving_ai = FALSE;
1466 bstate.open_dialog = FALSE;
1467 bstate.new_game = FALSE;
1468 bstate.quit_game = FALSE;
1471 if (bstate.moving_ai) //in the middle of an AI move
1472 bstate.new_game = TRUE;
1474 bstate.new_game = FALSE;
1476 if (bstate.moving_piece)
1477 bstate.stop_moving = TRUE;
1479 if (options.white_player == AI)
1481 bstate.what_next = WAIT_FOR_AI;
1482 bstate.moving_ai = TRUE;
1483 gtk_widget_set_sensitive (undo_button, FALSE);
1484 gtk_widget_set_sensitive (auto_button, FALSE);
1485 gtk_widget_set_sensitive (force_button, TRUE);
1489 bstate.what_next = MOVE_WHITE_QUEEN;
1490 bstate.moving_ai = FALSE;
1491 gtk_widget_set_sensitive (undo_button, FALSE);
1492 gtk_widget_set_sensitive (auto_button, TRUE);
1493 gtk_widget_set_sensitive (force_button, FALSE);
1495 gtk_widget_set_sensitive (settings_menu, TRUE);
1496 bstate.turn = WHITE_PLAYER;
1497 bstate.from = INVALID_SQUARE_VALUE;
1498 bstate.to = INVALID_SQUARE_VALUE;
1499 bstate.last_arrow = INVALID_SQUARE_VALUE;
1500 bstate.quit_game = FALSE;
1507 gtk_widget_set_sensitive (undo_button, FALSE);
1508 gtk_widget_set_sensitive (auto_button, FALSE);
1509 gtk_widget_set_sensitive (force_button, FALSE);
1510 gtk_widget_set_sensitive (settings_menu, TRUE);
1511 bstate.what_next = NEW_GAME;
1515 bstate.quit_game = TRUE;
1518 bstate.what_next = CONFUSED;
1520 update_status_bar();
1524 return bstate.what_next;
1528 /*==============================================================================
1529 * bstate_store_what_next
1531 * This initializes the internal board state machine. Use of this is discouraged
1532 * and should instead use bstate_set_just_finished.
1533 void bstate_store_what_next(int next)
1538 bstate.what_next = FIRE_ARROW;
1540 case MOVE_BLACK_QUEEN:
1541 if (options.black_player == AI)
1542 bstate.what_next = WAIT_FOR_AI;
1544 bstate.what_next = MOVE_BLACK_QUEEN;
1545 bstate.turn = BLACK_PLAYER;
1547 case MOVE_WHITE_QUEEN:
1548 if (options.white_player == AI)
1549 bstate.what_next = WAIT_FOR_AI;
1551 bstate.what_next = MOVE_WHITE_QUEEN;
1552 bstate.turn = WHITE_PLAYER;
1555 bstate.what_next = WAIT_FOR_AI;
1558 bstate.what_next = CONFUSED;
1560 update_status_bar();
1564 /*==============================================================================
1565 * bstate_get_what_next
1567 * This is the method for code throughout the program to find out what input
1570 int bstate_get_what_next()
1572 return bstate.what_next;
1575 /*==============================================================================
1576 * bstate_set_move_from
1578 * This lets the internal board state know that a queen has just been moved from
1581 void bstate_set_move_from(Square from)
1586 /*==============================================================================
1587 * bstate_set_move_from
1589 * This lets the internal board state know that a queen has just been moved to
1592 void bstate_set_move_to(Square to)
1597 /*==============================================================================
1598 * bstate_get_move_from
1600 * This lets the internal board state know that a queen has just been moved from
1603 Square bstate_get_move_from()
1608 /*==============================================================================
1609 * bstate_get_move_from
1611 * This lets the internal board state know that a queen has just been moved to
1614 Square bstate_get_move_to()
1619 int bstate_get_moving_ai()
1621 return bstate.moving_ai;
1624 void bstate_set_moving_ai(int moving)
1626 bstate.moving_ai = moving;
1629 int bstate_get_new_game()
1631 return bstate.new_game;
1633 void bstate_set_new_game(int new_game)
1635 bstate.new_game = new_game;
1638 void bstate_set_moving_piece(int moving)
1640 bstate.moving_piece = moving;
1642 int bstate_get_moving_piece()
1644 return bstate.moving_piece;
1647 int bstate_get_turn()
1652 int bstate_get_open_dialog()
1654 return bstate.open_dialog;
1657 void bstate_set_open_dialog(int dialog)
1659 bstate.open_dialog = dialog;
1662 void bstate_update_player_settings()
1664 if (bstate.turn == WHITE_PLAYER && options.white_player == HUMAN)
1665 bstate.what_next = MOVE_WHITE_QUEEN;
1666 if (bstate.turn == BLACK_PLAYER && options.black_player == HUMAN)
1667 bstate.what_next = MOVE_BLACK_QUEEN;
1669 if (bstate.what_next == NEW_GAME)
1672 if (bstate.turn == WHITE_PLAYER && options.white_player == AI)
1673 bstate.what_next = WAIT_FOR_AI;
1674 if (bstate.turn == BLACK_PLAYER && options.black_player == AI)
1675 bstate.what_next = WAIT_FOR_AI;
1676 update_status_bar();
1680 int bstate_get_quit_game()
1682 return bstate.quit_game;
1685 int bstate_get_stop_moving()
1687 return bstate.stop_moving;
1690 void bstate_set_stop_moving(int stop_moving)
1692 bstate.stop_moving = stop_moving;
1698 printf("turn = %d\n", bstate.turn);
1699 printf("what_next = %d\n", bstate.what_next);
1700 printf("moving_ai = %d\n", bstate.moving_ai);
1701 printf("new_game = %d\n", bstate.new_game);
1706 int read_in_moves(FILE *history_fd)
1709 size_t buf_size = 30;
1711 printf("History contents:\n");
1712 while (getline(&buffer, &buf_size, history_fd) != -1)
1715 printf("%s", buffer);