10 /* local Prototypes */
13 static void fill_a_square(GnomeCanvasGroup
*group
,
14 double x1
, double y1
, double x2
, double y2
, char *color
);
15 static void get_square_color(int square
, char *color
);
16 static void draw_a_line(GnomeCanvasGroup
*group
,
17 int x1
, int y1
, int x2
, int y2
, char *color
);
18 static void draw_grid();
23 extern struct options options
;
24 extern struct game_states states
;
27 extern GtkWidget
*main_window
;
28 Square legal_moves
[100];
32 void init_game_board(GtkWidget
*GamazonsMain
)
36 GtkWidget
*w
= (GtkWidget
*) lookup_widget(GamazonsMain
, BOARD_NAME
);
37 GtkWidget
*force_button
, *undo_button
;
39 GtkTextBuffer
*buffer
;
40 GtkWidget
*speed
, *delay
;
41 static int first_run
= TRUE
;
44 printf("Couldn't find board!!!!!!!!\n");
46 board
= (Board
*) malloc(sizeof(Board
));
47 board
->canvas
= GNOME_CANVAS(w
);
48 board
->root
= GNOME_CANVAS_GROUP(gnome_canvas_item_new(gnome_canvas_root(board
->canvas
),
49 gnome_canvas_group_get_type(),
52 gnome_canvas_set_scroll_region(board
->canvas
, 0.0, 0.0,
57 /* initialize pieces */
58 for (i
=0; i
<BOARD_SIZE
; i
++)
60 for (j
=0; j
<BOARD_SIZE
; j
++)
62 board
->squares
[i
][j
] = NOTHING
;
65 gtk_signal_connect(GTK_OBJECT(board
->canvas
), "event",
66 GTK_SIGNAL_FUNC(arrow_fire_cb
), NULL
);
68 //Place amazon queens on the board
69 board
->squares
[9][3] = WHITE
;
70 board
->squares
[9][6] = WHITE
;
71 board
->squares
[6][0] = WHITE
;
72 board
->squares
[6][9] = WHITE
;
74 board
->squares
[0][3] = BLACK
;
75 board
->squares
[0][6] = BLACK
;
76 board
->squares
[3][0] = BLACK
;
77 board
->squares
[3][9] = BLACK
;
79 board
->square_to_wh_queen_map
[0] = 96;
80 board
->square_to_wh_queen_map
[1] = 93;
81 board
->square_to_wh_queen_map
[2] = 60;
82 board
->square_to_wh_queen_map
[3] = 69;
84 board
->square_to_bl_queen_map
[0] = 3;
85 board
->square_to_bl_queen_map
[1] = 6;
86 board
->square_to_bl_queen_map
[2] = 30;
87 board
->square_to_bl_queen_map
[3] = 39;
89 //Set up move history window
90 view
= (GtkTextView
*) lookup_widget(main_window
, "textview1");
91 buffer
= gtk_text_buffer_new(NULL
);
92 gtk_text_view_set_buffer(view
, buffer
);
95 force_button
= (GtkWidget
*)lookup_widget(main_window
, "BT_FORCEMOVE");
96 gtk_widget_set_sensitive (force_button
, FALSE
);
97 undo_button
= (GtkWidget
*)lookup_widget(main_window
, "BT_UNDO");
98 gtk_widget_set_sensitive (undo_button
, FALSE
);
105 delay
= (GtkWidget
*)lookup_widget(main_window
, "ReplayDelaySpinner");
106 gtk_spin_button_set_value((GtkSpinButton
*)delay
, options
.replay_delay
);
107 speed
= (GtkWidget
*)lookup_widget(main_window
, "MovementSpeedSpinner");
108 gtk_spin_button_set_value((GtkSpinButton
*)speed
, options
.movement_speed
);
111 bstate_set_just_finished(START_GAME
);
117 void fill_a_square(GnomeCanvasGroup
*group
,
118 double x1
, double y1
, double x2
, double y2
, char *color
)
121 gnome_canvas_item_new(group
,
122 gnome_canvas_rect_get_type(),
127 "outline_color", "black",
129 "width_pixels", (double)THICKNESS
,
134 static void get_square_color(int square
, char *color
)
136 if ((square
% 2) == 0)
137 strcpy(color
, SQUARE_COLOR_1
);
139 strcpy(color
, SQUARE_COLOR_2
);
143 static void draw_grid()
147 for (x
=0; x
<=10; x
++)
149 for (y
=0; y
<=10; y
++)
152 draw_a_line(board
->root
, //gnome_canvas_root(board->canvas),
153 0, y
*CELL_SIZE
, BOARD_SIZE
*CELL_SIZE
, y
*CELL_SIZE
, "black");
156 draw_a_line(board
->root
, //gnome_canvas_root(board->canvas),
157 x
*CELL_SIZE
, 0, x
*CELL_SIZE
, BOARD_SIZE
*CELL_SIZE
, "black");
164 static void draw_a_line(GnomeCanvasGroup
*group
,
165 int x1
, int y1
, int x2
, int y2
, char *color
)
167 GnomeCanvasPoints
*points
;
169 /* allocate a new points array */
170 points
= gnome_canvas_points_new (2);
172 /* fill out the points */
173 points
->coords
[0] = x1
;
174 points
->coords
[1] = y1
;
175 points
->coords
[2] = x2
;
176 points
->coords
[3] = y2
;
178 gnome_canvas_item_new(group
,
179 gnome_canvas_line_get_type(),
182 "width_units", (double)THICKNESS
,
185 /* free the points array */
186 gnome_canvas_points_free(points
);
193 GdkPixbuf
*white_pb
, *black_pb
;
194 GdkPixbuf
*white_sq
, *grey_sq
, *arrow_sq
;
196 GnomeCanvasItem
*image
;
197 GnomeCanvasGroup
*root
= GNOME_CANVAS_GROUP(gnome_canvas_root (GNOME_CANVAS (board
->canvas
)));
198 static int first_game
= 1;
203 white_pb
= gdk_pixbuf_new_from_file(options
.images
.white_piece
, NULL
);
204 if (white_pb
== NULL
)
206 fprintf(stderr
, "Cannot find white piece image: %s\n", options
.images
.white_piece
);
210 black_pb
= gdk_pixbuf_new_from_file(options
.images
.black_piece
, NULL
);
211 if (black_pb
== NULL
)
213 fprintf(stderr
, "Cannot find black piece image: %s\n", options
.images
.black_piece
);
217 white_sq
= gdk_pixbuf_new_from_file(options
.images
.white_sq
, NULL
);
218 if (white_sq
== NULL
)
220 fprintf(stderr
, "Cannot find white square image: %s\n", options
.images
.white_sq
);
224 grey_sq
= gdk_pixbuf_new_from_file(options
.images
.grey_sq
, NULL
);
227 fprintf(stderr
, "Cannot find grey square image: %s\n", options
.images
.grey_sq
);
230 arrow_sq
= gdk_pixbuf_new_from_file(options
.images
.arrow_sq
, NULL
);
231 if (arrow_sq
== NULL
)
233 fprintf(stderr
, "Cannot find arrow square image: %s\n", options
.images
.arrow_sq
);
239 /* fill alternate squares */
240 for(j
=0;j
<BOARD_SIZE
;j
++)
242 for(i
=0;i
<BOARD_SIZE
;i
++)
244 board
->square_items
[j
*10+i
] = NULL
;
247 board
->square_items
[j
*10+i
] = gnome_canvas_item_new (board
->root
,
248 gnome_canvas_pixbuf_get_type (),
249 "x", i
*CELL_SIZE
+QUEEN_OFFSET
, "y", j
*CELL_SIZE
+QUEEN_OFFSET
,
250 "width", CELL_SIZE
, "height", CELL_SIZE
,
251 "width_set", TRUE
, "height_set", TRUE
,
257 board
->square_items
[j
*10+i
] = gnome_canvas_item_new (board
->root
,
258 gnome_canvas_pixbuf_get_type (),
259 "x", i
*CELL_SIZE
+QUEEN_OFFSET
, "y", j
*CELL_SIZE
+QUEEN_OFFSET
,
260 "width", CELL_SIZE
, "height", CELL_SIZE
,
261 "width_set", TRUE
, "height_set", TRUE
,
268 //Place the queen images on the board in the right order
269 if (board
->squares
[j
][i
] == WHITE
)
272 printf("Square %c%c contains a white queen\n",i
+'a',10-j
+'0');
274 image
= gnome_canvas_item_new (board
->root
,
275 gnome_canvas_pixbuf_get_type (),
276 "x", i
*CELL_SIZE
+QUEEN_OFFSET
, "y", j
*CELL_SIZE
+QUEEN_OFFSET
,
277 "width", CELL_SIZE
, "height", CELL_SIZE
,
278 "width_set", TRUE
, "height_set", TRUE
,
281 //We need to do some funky checking to make sure board->white_queens[] matches
282 //up exactly with state->white_q_x[], state->white_q_y[]
285 if(j
*10 +i
== board
->square_to_wh_queen_map
[k
])
287 board
->white_queens
[k
] = image
;
289 printf("registering queen %d\n", k
);
296 printf("connecting signal to queen\n");
298 gtk_signal_connect(GTK_OBJECT(image
), "event",
299 GTK_SIGNAL_FUNC(board_press_cb
), NULL
);
301 else if (board
->squares
[j
][i
] == BLACK
)
304 printf("Square %c%c contains a black queen\n",i
+'a',10-j
+'0');
306 image
= gnome_canvas_item_new (board
->root
,
307 gnome_canvas_pixbuf_get_type (),
308 "x", i
*CELL_SIZE
+QUEEN_OFFSET
, "y", j
*CELL_SIZE
+QUEEN_OFFSET
,
309 "width", CELL_SIZE
, "height", CELL_SIZE
,
310 "width_set", TRUE
, "height_set", TRUE
,
315 if(j
*10 +i
== board
->square_to_bl_queen_map
[k
])
317 board
->black_queens
[k
] = image
;
319 printf("registering queen %d\n", k
);
326 printf("connecting signal to queen\n");
328 gtk_signal_connect(GTK_OBJECT(image
), "event",
329 GTK_SIGNAL_FUNC(board_press_cb
), NULL
);
331 else if (board
->squares
[j
][i
] == ARROW
)
333 image
= gnome_canvas_item_new (board
->root
,
334 gnome_canvas_pixbuf_get_type (),
335 "x", i
*CELL_SIZE
+QUEEN_OFFSET
, "y", j
*CELL_SIZE
+QUEEN_OFFSET
,
336 "width", CELL_SIZE
, "height", CELL_SIZE
,
337 "width_set", TRUE
, "height_set", TRUE
,
346 if (options
.images
.grid
== TRUE
)
350 image = gnome_canvas_item_new (root,
351 gnome_canvas_pixbuf_get_type (),
352 "x", 10.0, "y", 10.0,
353 "width", 40.0, "height", 40.0,
354 "width_set", TRUE, "height_set", TRUE,
360 gtk_widget_show_now(main_window
);
361 gtk_widget_queue_draw ((GtkWidget
*) board
->canvas
);
362 gtk_widget_show_now((GtkWidget
*) board
->canvas
);
367 void mark_square (GnomeCanvasItem
*square
)
369 gnome_canvas_item_set (square
, "outline_color", "red", NULL
);
372 Square
get_square (double x
, double y
)
379 x -= (BOARD_BORDER - CELL_PAD);
380 y -= (BOARD_BORDER - CELL_PAD);
385 else if (x
> ((BOARD_SIZE
-1) * CELL_SIZE
))
386 x
= (BOARD_SIZE
-1) * CELL_SIZE
;
389 else if (y
> ((BOARD_SIZE
-1) * CELL_SIZE
))
390 y
= (BOARD_SIZE
-1) * CELL_SIZE
;
392 x_square
= x
/ CELL_SIZE
;
393 y_square
= y
/ CELL_SIZE
;
396 printf("x coord = %f y coord = %f\n", x
, y
);
397 printf("x coord = %d y coord = %d\n", x_square
, y_square
);
400 from
= x_square
+ y_square
* 10;
405 void clear_square (GnomeCanvasItem
**square
)
407 gnome_canvas_item_set (*square
, "outline_color", NULL
, NULL
);
411 /*==============================================================================
414 * This moves the given piece to the given square. This is a very tricky function
415 * because the user can do many things to upset the state of the board while a
416 * piece is sliding, so various checks must take place throughout the movement
417 * process to make sure the board still exists as it thinks it does.
419 * The piece can also move at different speeds. Originally, it moved one pixel at
420 * a time, but it now gets its value from the MovementSpeedSpinner widget. This
421 * makes it so the pieces can move at acceptable speeds on slower computers, but
422 * adds more complexity in trying to calculate the distance a piece should move.
424 void move_piece_to(Square to
, GnomeCanvasItem
*item
)
426 double Lx
, Uy
, Rx
, By
;
431 GtkWidget
*speed
= (GtkWidget
*)lookup_widget(main_window
, "MovementSpeedSpinner");
432 int inc
= gtk_spin_button_get_value_as_int((GtkSpinButton
*)speed
);
435 game_life
= bstate_get_game_life();
436 to_Lx
= get_x_from_square(to
);
437 to_Uy
= get_y_from_square(to
);
440 printf("We want the queen at coords %f, %f\n", to_Lx
, to_Uy
);
442 gnome_canvas_item_get_bounds(item
, &Lx
, &Uy
, &Rx
, &By
);
444 printf("The queen is at coords %f, %f\n", Lx
, Uy
);
446 if (bstate_get_dont_slide())
448 gnome_canvas_item_get_bounds(item
, &Lx
, &Uy
, &Rx
, &By
);
449 gnome_canvas_item_move (item
,
450 get_x_from_square(to
) - Lx
,
451 get_y_from_square(to
) - Uy
);
452 gnome_canvas_item_raise_to_top (item
);
456 while (Lx
!= to_Lx
|| Uy
!= to_Uy
)
460 printf("Lx = %g; to_Lx = %g; Uy = %g; to_Uy = %g\n", Lx
, to_Lx
, Uy
, to_Uy
);
462 bstate_set_moving_piece(TRUE
);
463 if ((int)Lx
== (int)to_Lx
)
465 else if (Lx
< to_Lx
&& (to_Lx
- Lx
) >= inc
)
467 else if (Lx
< to_Lx
&& (to_Lx
- Lx
) <= inc
)
469 else if (Lx
> to_Lx
&& (Lx
- to_Lx
) >= inc
)
471 else if (Lx
> to_Lx
&& (Lx
- to_Lx
) <= inc
)
474 if ((int)Uy
== (int)to_Uy
)
476 else if (Uy
< to_Uy
&& (to_Uy
- Uy
) >= inc
)
478 else if (Uy
< to_Uy
&& (to_Uy
- Uy
) <= inc
)
480 else if (Uy
> to_Uy
&& (Uy
- to_Uy
) >= inc
)
482 else if (Uy
> to_Uy
&& (Uy
- to_Uy
) <= inc
)
487 printf("x = %d, y = %d\n", x
, y
);
490 if (bstate_get_game_life() != game_life
)
492 bstate_set_moving_piece(FALSE
);
495 gnome_canvas_item_move (item
, (double)x
, (double)y
);
496 gnome_canvas_item_raise_to_top (item
);
499 while (gtk_events_pending())
500 gtk_main_iteration();
502 if (bstate_get_quit_game())
504 if (bstate_get_game_life() != game_life
)
506 bstate_set_moving_piece(FALSE
);
509 gnome_canvas_item_get_bounds(item
, &Lx
, &Uy
, &Rx
, &By
);
513 if (bstate_get_game_life() != game_life
)
515 bstate_set_moving_piece(FALSE
);
518 gnome_canvas_item_raise_to_top (item
);
519 bstate_set_moving_piece(FALSE
);
520 //see where it landed
521 gnome_canvas_item_get_bounds(item
, &Lx
, &Uy
, &Rx
, &By
);
523 printf("The queen landed at coords %f, %f\n", Lx
, Uy
);
524 printf("this time the queen is on square %d\n", to
);
531 double get_x_from_square(int sq
)
535 x
= (double) ((sq
% 10) * CELL_SIZE
+QUEEN_OFFSET
);
541 double get_y_from_square(int sq
)
545 y
= (double) ((sq
/ 10) * CELL_SIZE
+QUEEN_OFFSET
);
552 int get_x_int_from_square(int sq
)
557 int get_y_int_from_square(int sq
)
562 int get_grid_num_from_square(int sq
)
567 char get_grid_alpha_from_square(int sq
)
569 return('a' + sq
% 10);
572 int engine_x_to_board_x(int eng_x
)
574 return(eng_x
);//hey, these are the same, no conversion necessary
577 int engine_y_to_board_y(int eng_y
)
582 int board_x_to_engine_x(int brd_x
)
587 int board_y_to_engine_y(int brd_y
)
592 int get_square_from_engine(int x
, int y
)
594 return((9 - y
) * 10 + x
);
598 void fire_arrow(Square sq
)
602 GnomeCanvasItem
*image
;
603 GnomeCanvasGroup
*root
= GNOME_CANVAS_GROUP(gnome_canvas_root (GNOME_CANVAS (board
->canvas
)));
608 board
->squares
[y
][x
] = ARROW
;
610 arrow_sq
= gdk_pixbuf_new_from_file(options
.images
.arrow_sq
, NULL
);
611 if (arrow_sq
== NULL
)
613 fprintf(stderr
, "Cannot find arrow image: %s\n", options
.images
.arrow_sq
);
617 image
= gnome_canvas_item_new (board
->root
,
618 gnome_canvas_pixbuf_get_type (),
619 "x", x
*CELL_SIZE
+QUEEN_OFFSET
, "y", y
*CELL_SIZE
+QUEEN_OFFSET
,
620 "width", CELL_SIZE
, "height", CELL_SIZE
,
621 "width_set", TRUE
, "height_set", TRUE
,
627 void square_contains(Square sq
)
631 col
= get_x_int_from_square(sq
);
632 row
= get_y_int_from_square(sq
);
634 if (board
->squares
[row
][col
] == NOTHING
)
635 printf("Nothing is found at square %d\n", sq
);
636 else if (board
->squares
[row
][col
] == WHITE
)
637 printf("A White Queen is found at square %d\n", sq
);
638 else if (board
->squares
[row
][col
] == BLACK
)
639 printf("A Black Queen is found at square %d\n", sq
);
640 else if (board
->squares
[row
][col
] == ARROW
)
641 printf("An arrow is found at square %d\n", sq
);
643 printf("Whoa, I don't know _what_ is on square %d\n", sq
);
647 /*==============================================================================
650 * Checks to see if an AI oppenent is next to move. If it is, it starts the
651 * move process, and checks for a win afterwards. If not, it just checks for
652 * the win. Returns TRUE if an AI opponent moves next. False if human.
654 * NOTE: If you have 2 AI players, this function would just keep thinking and
655 * never let the board update or respond. So there are several checks to see
656 * if any new events occured that should be handled, or critical changes have
657 * been made (like starting a new game, etc..). If something critical has changed
658 * the function will exit after learning about it.
662 state
*s
= states
.s
[states
.current_state
];
666 int game_life
= bstate_get_game_life();
667 //GtkWidget *auto_button, *force_button;
669 current_hash
= state_hash
= create_hash(s
);
671 //quit this function if a 'New Game' option was selected since this
672 //function was started.
674 if (bstate_get_new_game())
676 bstate_set_new_game(FALSE);
683 temp
= isearch(s
, NOTHINK
);
684 if (s
->winner
) //XXX does this if statement do any good? I thot winner was handled elsewhere
688 //update the board before drawing the new move
689 //the program would segfault if you closed it while it was thinking
690 while (gtk_events_pending())
691 gtk_main_iteration();
692 if (current_hash
!= state_hash
)
696 if (bstate_get_new_game())
698 bstate_set_new_game(FALSE);
703 if (bstate_get_quit_game())
706 if (bstate_get_game_life() != game_life
)
710 //register move on graphical board
712 if (bstate_get_game_life() != game_life
)
714 print_move_in_text_window(&temp
);
715 dup_state(s
, states
.s
[++(states
.current_state
)]);
716 bstate_set_just_finished(WAIT_FOR_AI
);
720 if (options
.white_player
== AI
)
721 printf("White is AI\n");
722 if (options
.black_player
== AI
)
723 printf("Black is AI\n");
724 printf("Turn is %d\n", states
.s
[states
.current_state
]->turn
);
729 //XXX should I set ai = FALSE?
737 /*==============================================================================
740 * Takes a move struct generated by the engine, and extracts the necessary info
741 * to update the GUI data structs and have the GUI reflect the move.
743 void move_piece(move m
)
745 GnomeCanvasItem
*item
;
746 int from_row
, from_col
;
748 int game_life
= bstate_get_game_life();
750 bstate_set_move_to(get_square_from_engine(m
.tocol
, m
.torow
));
751 to_col
= get_x_int_from_square(bstate_get_move_to());
752 to_row
= get_y_int_from_square(bstate_get_move_to());
753 //Note: by the time the state gets here, it's signaled the other player's turn
754 //so if it says it's white's turn, black just moved and we need to move black's
756 if (states
.s
[states
.current_state
]->turn
== WHITE_PLAYER
)
758 bstate_set_move_from(get_square_from_engine(states
.s
[states
.current_state
-1]->black_q_x
[m
.queen
],
759 states
.s
[states
.current_state
-1]->black_q_y
[m
.queen
]));
761 board
->squares
[to_row
][to_col
] = BLACK
;
763 printf("Moving black queen\n");
765 item
= board
->black_queens
[m
.queen
];
766 board
->square_to_bl_queen_map
[m
.queen
] = to_row
*10 +to_col
;
770 bstate_set_move_from(get_square_from_engine(states
.s
[states
.current_state
-1]->white_q_x
[m
.queen
],
771 states
.s
[states
.current_state
-1]->white_q_y
[m
.queen
]));
772 board
->squares
[to_row
][to_col
] = WHITE
;
774 printf("Moving white queen\n");
776 item
= board
->white_queens
[m
.queen
];
777 board
->square_to_wh_queen_map
[m
.queen
] = to_row
*10 +to_col
;
781 from_col
= get_x_int_from_square(bstate_get_move_from());
782 from_row
= get_y_int_from_square(bstate_get_move_from());
783 board
->squares
[from_row
][from_col
] = NOTHING
;
785 move_piece_to(bstate_get_move_to(), item
);
787 printf("Engine coords for arrow: %d, %d\n", m
.wallcol
, m
.wallrow
);
789 if (game_life
!= bstate_get_game_life())
791 fire_arrow(get_square_from_engine(m
.wallcol
, m
.wallrow
));
793 printf("fired arrow to square %d\n", get_square_from_engine(m
.wallcol
, m
.wallrow
));
798 /*==============================================================================
799 * register_move_with_engine
801 * Fills out a move struct with the human's move and calls makemove() to update
802 * the state struct, so the AI engine knows what happened.
804 void register_move_with_engine(Square arrow_sq
)
806 state
*s
= states
.s
[states
.current_state
];
816 //find out the index of the queen that was just moved.
817 //weird things will happen if it's not found.
820 if (board
->selected_queen
== board
->white_queens
[i
] ||
821 board
->selected_queen
== board
->black_queens
[i
])
829 fprintf(stderr
, "Error registering move w/ AI engine! Game play will now be weird.\n");
832 m
.torow
= board_y_to_engine_y(get_y_int_from_square(bstate_get_move_to()));
833 m
.tocol
= board_x_to_engine_x(get_x_int_from_square(bstate_get_move_to()));
835 m
.wallrow
= board_y_to_engine_y(get_y_int_from_square(arrow_sq
));
836 m
.wallcol
= board_x_to_engine_x(get_x_int_from_square(arrow_sq
));
838 //make sure it's a valid move
839 move_count
= children(s
, movelist
);
842 gnome_error_dialog("The AI engine thinks the game is over. Please use the menu item Game->New to start a new game");
845 if (!move_lookup(&m
, movelist
, move_count
))
847 get_move_str(&m
, move_str
);
848 strcpy(err_msg
, "You've hit a bug. The following illegal move was just attempted: ");
849 strcat(err_msg
, move_str
);
850 gnome_error_dialog(err_msg
);
855 print_move_in_text_window(&m
);
859 /*==============================================================================
862 * Compares the given square with the information stored in board->squares[][]
863 * to see if a queen is there.
865 int is_queen_square(Square sq
)
869 col
= get_x_int_from_square(sq
);
870 row
= get_y_int_from_square(sq
);
872 if ((board
->squares
[row
][col
] == BLACK
) ||
873 (board
->squares
[row
][col
] == WHITE
))
880 /*==============================================================================
883 * Given a square, this generates an array of all legal moves that can be made
884 * from it. This works for both queen movement, as well as firing an arrow,
885 * since both move the same way.
887 * The array terminator is 100
889 void gen_legal_moves(Square sq
)
893 int row
, col
, sq_row
, sq_col
;
896 sq_col
= get_x_int_from_square(sq
);
897 sq_row
= get_y_int_from_square(sq
);
899 //make sure the player can drop the piece on the same square if he changes
901 legal_moves
[arr_i
++] = sq
;
906 while (board
->squares
[row
][col
] == NOTHING
&& row
< 10)
908 legal_moves
[arr_i
++] = (row
*10) + col
;
913 while (board
->squares
[row
][col
] == NOTHING
&& row
>= 0)
915 legal_moves
[arr_i
++] = (row
*10) + col
;
919 //get horizontal moves
922 while (board
->squares
[row
][col
] == NOTHING
&& col
< 10)
924 legal_moves
[arr_i
++] = (row
*10) + col
;
929 while (board
->squares
[row
][col
] == NOTHING
&& col
>= 0)
931 legal_moves
[arr_i
++] = (row
*10) + col
;
935 //get forward diagonal moves
938 while (board
->squares
[row
][col
] == NOTHING
&& col
< 10 && row
< 10)
940 legal_moves
[arr_i
++] = (row
*10) + col
;
947 while (board
->squares
[row
][col
] == NOTHING
&& col
>= 0 && row
>= 0)
949 legal_moves
[arr_i
++] = (row
*10) + col
;
954 //get backward diagonal moves
957 while (board
->squares
[row
][col
] == NOTHING
&& col
>= 0 && row
< 10)
959 legal_moves
[arr_i
++] = (row
*10) + col
;
966 while (board
->squares
[row
][col
] == NOTHING
&& col
< 10 && row
>= 0)
968 legal_moves
[arr_i
++] = (row
*10) + col
;
974 legal_moves
[arr_i
] = 100;
976 printf("legal move list for %d of length %d: \n", sq
, arr_i
);
978 while (legal_moves
[i
] < 100)
979 printf(" %d", legal_moves
[i
++]);
985 /*==============================================================================
988 * Looks up the given square in the current legal_moves array. If it doesn't
989 * exist, it's not a legal move and returns FALSE. Returns TRUE if it is there.
991 int is_move_legal(Square sq
)
996 printf("checking to see if a move is legal\n");
998 while (legal_moves
[i
] < 100)
1000 if (sq
== legal_moves
[i
++])
1003 printf("%d is a legal move\n", sq
);
1010 printf("Can't move to square. Legal moves are: %d\n", sq
);
1012 while (legal_moves
[i
] < 100)
1013 printf(" %d", legal_moves
[i
++]);
1019 /*==============================================================================
1022 * DEBUG - counts the number of queens on the GUI representation and prints
1023 * out a bunch of XXXX's whenever there are not 4 of both kinds.
1027 int black
=0, white
=0;
1034 if (board
->squares
[i
][j
] == WHITE
)
1036 if (board
->squares
[i
][j
] == BLACK
)
1041 printf("YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY Gained a black queen\n");
1043 printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Gained a white queen\n");
1045 printf("XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXXYXYX Lost a black queen\n");
1047 printf("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ Lost a white queen\n");
1052 /*==============================================================================
1055 * When a new game is started, we want to free all the memory we've allocated
1056 * so we can start all over without leaking all the memory.
1058 void free_all_memory()
1063 for (i
=0; i
< states
.max_state
; i
++)
1066 //Oh, this is ugly! Do I really want to do this?
1070 for (i=0; i<TT; i++)
1083 /*==============================================================================
1086 * Creates a hash value for the current state. On the GUI side it's used to
1087 * see if the state has changed recently.
1089 int create_hash(state
*s
)
1092 ull board_u
, board_l
;
1094 board_u
= s
->white_bd
[1] | s
->black_bd
[1] | s
->blocks_bd
[1];
1095 board_l
= s
->white_bd
[0] | s
->black_bd
[0] | s
->blocks_bd
[0];
1097 return( (board_u
^ board_l
) % TT
);
1101 /*==============================================================================
1104 * Checks to see if the game is over and generates a pop-up stating who the
1105 * winner is. Returns TRUE if the game is over.
1109 state
*s
= states
.s
[states
.current_state
];
1110 move movelist
[3000];
1111 // GtkWidget *auto_button, *force_button;
1113 if (children(s
, movelist
) == 0)
1115 //printf("player %d wins!\n", s->turn^3);
1116 s
->winner
= s
->turn
^3;
1117 if (s
->winner
== BLACK
)
1118 gnome_ok_dialog("White wins!");
1120 gnome_ok_dialog("Black wins!");
1122 bstate_set_just_finished(GAME_OVER
);
1125 auto_button = (GtkWidget *) lookup_widget(main_window, "BT_AUTOFINISH");
1126 force_button = (GtkWidget *) lookup_widget(main_window, "BT_FORCEMOVE");
1127 gtk_widget_set_sensitive (auto_button, FALSE);
1128 gtk_widget_set_sensitive (force_button, FALSE);
1138 /*==============================================================================
1141 * Updates the status bar based on the current value of what_next
1145 GtkStatusbar
*status
= (GtkStatusbar
*) lookup_widget(main_window
, "statusbar1");
1146 guint context_id
= bstate_get_what_next();
1148 gtk_statusbar_pop(status
, context_id
);
1150 //printf("Updating status bar for state %d\n", bstate_get_what_next());
1151 switch (bstate_get_what_next())
1154 gtk_statusbar_push(status
, context_id
, "Fire Arrow");
1156 case MOVE_BLACK_QUEEN
:
1157 gtk_statusbar_push(status
, context_id
, "Move Black Amazon");
1159 case MOVE_WHITE_QUEEN
:
1160 gtk_statusbar_push(status
, context_id
, "Move White Amazon");
1163 gtk_statusbar_push(status
, context_id
, "AI is thinking...");
1166 gtk_statusbar_push(status
, context_id
, "Select Game->New to start game");
1169 gtk_statusbar_push(status
, context_id
, "Replaying a game...");
1173 gtk_statusbar_push(status
, context_id
, "I have no idea what to do next!");
1179 /*==============================================================================
1182 * prints out an ascii version of the board, useful for ensuring the board shows
1183 * what it should show.
1189 for (i
=0; i
<BOARD_SIZE
; i
++)
1191 for (j
=0; j
<BOARD_SIZE
; j
++)
1193 if (board
->squares
[i
][j
] == 0)
1195 if (board
->squares
[i
][j
] == 1)
1197 if (board
->squares
[i
][j
] == 2)
1199 if (board
->squares
[i
][j
] == 3)
1206 /*==============================================================================
1209 * Destroys the main board canvas group which contains all the square and piece
1210 * images, and takes them with it. Once done, it creates a new group that
1211 * draw_board() can take advantage of.
1213 void destroy_board()
1216 GtkWidget
*CNVS_GAMEBOARD
, *w
, *scrolledwindow4
, *table1
;
1220 printf("Destroying board now\n");
1224 gtk_object_destroy(GTK_OBJECT(board
->root
));
1225 board
->root
= GNOME_CANVAS_GROUP(gnome_canvas_item_new(gnome_canvas_root(board
->canvas
),
1226 gnome_canvas_group_get_type(),
1230 /*==============================================================================
1231 * print_move_in_text_window
1233 * Prints the given move in official amazon notation. The move struct doesn't
1234 * contain 'from' information, so that must be retrieved from the previous state
1236 void print_move_in_text_window(move
*m
)
1239 GtkTextBuffer
*buffer
;
1240 GtkTextIter
*iter
= (GtkTextIter
*) malloc(sizeof(GtkTextIter
));
1241 char string_buf
[32];
1242 GtkScrolledWindow
*w
;
1245 view
= (GtkTextView
*) lookup_widget(main_window
, "textview1");
1246 buffer
= gtk_text_view_get_buffer (view
);
1247 gtk_text_buffer_get_end_iter(buffer
, iter
);
1249 get_move_str(m
, string_buf
);
1252 printf("%s", string_buf
);
1254 gtk_text_buffer_insert(buffer
, iter
, string_buf
, -1);
1256 w
= (GtkScrolledWindow
*) lookup_widget(main_window
, "scrolledwindow6");
1257 adj
= gtk_scrolled_window_get_vadjustment(w
);
1258 gtk_adjustment_set_value(adj
, adj
->upper
);
1259 gtk_scrolled_window_set_vadjustment(w
, adj
);
1265 /*==============================================================================
1268 * Creates a move string from a move struct
1270 void get_move_str(move
*m
, char move_str
[])
1272 Square to_sq
, from_sq
, arrow_sq
;
1273 int to_num
, from_num
, arrow_num
;
1274 char to_alpha
, from_alpha
, arrow_alpha
;
1275 int state_i
= states
.current_state
;
1278 //Determine which side just moved:
1279 turn
= states
.s
[state_i
]->turn
^3;
1280 if (turn
== WHITE_PLAYER
)
1282 from_sq
= get_square_from_engine(states
.s
[state_i
-1]->white_q_x
[m
->queen
],
1283 states
.s
[state_i
-1]->white_q_y
[m
->queen
]);
1287 from_sq
= get_square_from_engine(states
.s
[state_i
-1]->black_q_x
[m
->queen
],
1288 states
.s
[state_i
-1]->black_q_y
[m
->queen
]);
1290 to_sq
= get_square_from_engine(m
->tocol
, m
->torow
);
1291 arrow_sq
= get_square_from_engine(m
->wallcol
, m
->wallrow
);
1295 from_alpha
= get_grid_alpha_from_square(from_sq
);
1296 from_num
= get_grid_num_from_square(from_sq
);
1298 to_alpha
= get_grid_alpha_from_square(to_sq
);
1299 to_num
= get_grid_num_from_square(to_sq
);
1301 arrow_alpha
= get_grid_alpha_from_square(arrow_sq
);
1302 arrow_num
= get_grid_num_from_square(arrow_sq
);
1304 sprintf(move_str
, "%d. %c%d-%c%d, %c%d\n", state_i
, from_alpha
, from_num
,
1305 to_alpha
, to_num
, arrow_alpha
, arrow_num
);
1308 /*==============================================================================
1311 * This generates a move struct from a move string of the format 1. a4-a6, b6
1312 * If the string is not in a valid format, the return value will be FALSE to
1313 * inform the calling routine that the returned move struct does not contain
1314 * valid information. If everything goes well, TRUE will be returned.
1316 int get_move_from_str(move
*m
, char move_str
[])
1319 int from_row
, from_col
;
1321 int arrow_row
, arrow_col
;
1325 //Ignore move number
1326 while (move_str
[i
++] != ' ')
1330 fprintf(stderr
, "Space is in wrong place: %d\n", i
);
1331 return FALSE
; //Ack! this can't be right!
1334 from_col
= move_str
[i
++] - 'a';
1335 from_row
= move_str
[i
++] - '1';
1336 if (move_str
[i
] == '0')
1342 if (move_str
[i
++] != '-')
1344 fprintf(stderr
, "Expected a hyphen at index %d\n", i
);
1345 return FALSE
; //Ack!! I expected a '-' here, this is not a valid move string
1348 to_col
= move_str
[i
++] - 'a';
1349 to_row
= move_str
[i
++] - '1';
1350 if (move_str
[i
] == '0')
1356 if (move_str
[i
++] != ',')
1358 fprintf(stderr
, "Expected a comma at index %d\n", i
);
1359 return FALSE
; //Ack!! I expected a ',' here, this is not a valid move string
1361 if (move_str
[i
++] != ' ')
1363 fprintf(stderr
, "Expected a space at index %d\n", i
);
1364 return FALSE
; //Ack!! I expected a ' ' here, this is not a valid move string
1367 arrow_col
= move_str
[i
++] - 'a';
1368 arrow_row
= move_str
[i
++] - '1';
1369 if (move_str
[i
++] == '0')
1372 //Find the index to the appropriate queen
1373 queen_sq
= get_square_from_engine(from_col
, from_row
);
1376 if (queen_sq
== board
->square_to_wh_queen_map
[j
])
1379 //printf("found move for white queen\n");
1381 if (queen_sq
== board
->square_to_bl_queen_map
[j
])
1384 //printf("found move for black queen\n");
1389 fprintf(stderr
, "Couldn't find a queen at square %d\n", queen_sq
);
1390 return FALSE
; //Couldn't find queen index!
1396 m
->wallcol
= arrow_col
;
1397 m
->wallrow
= arrow_row
;
1404 int read_in_moves(FILE *history_fd
)
1407 size_t buf_size
= 30;
1411 int replay_mode
= bstate_get_replay_mode();
1412 int replay_delay
= 0;
1413 int game_life
= bstate_get_game_life();
1418 delay
= (GtkWidget
*)lookup_widget(main_window
, "ReplayDelaySpinner");
1422 bstate_set_dont_slide(TRUE
);
1424 //printf("History contents:\n");
1425 while (getline(&buffer
, &buf_size
, history_fd
) != -1)
1427 if (replay_mode
&& !bstate_get_replay_mode()) //If not in replay mode anymore, drop out
1429 s
= states
.s
[states
.current_state
];
1432 printf("%s", buffer);
1434 if (get_move_from_str(&m
, buffer
))
1436 makemove(s
,m
); //register w/ engine
1437 move_piece(m
); //register w/ board
1438 if (game_life
!= bstate_get_game_life())
1440 print_move_in_text_window(&m
);
1441 dup_state(s
, states
.s
[++(states
.current_state
)]);
1445 fprintf(stderr
, "Move string is invalid\n");
1446 bstate_set_dont_slide(FALSE
);
1452 if (replay_mode
) //Delay for appropriate amount of time
1454 replay_delay
= gtk_spin_button_get_value_as_int((GtkSpinButton
*)delay
);
1456 if (game_life
!= bstate_get_game_life())
1462 bstate_set_dont_slide(FALSE
);
1467 void rest(int duration
)
1469 time_t start
= time(NULL
);
1470 time_t end
= start
+ duration
;
1472 while (time(NULL
) < end
)
1475 while (gtk_events_pending())
1476 gtk_main_iteration();