Import upstream Source
[gamazons.git] / src / board.c-bak
blob0f47f0666973997f032207dce989f152a1b406e4
1 #include <time.h>
2 #include <assert.h>
3 #include <gnome.h>
5 #include "amazons.h"
6 #include "board.h"
7 #include "callbacks.h"
9 /* local Prototypes */
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();
20 /* Globals */
21 extern Board *board;
22 extern struct options options;
23 extern struct game_states states;
24 extern int ok;
25 extern time_t start;
26 extern GtkWidget *main_window;
27 extern int new_game;
28 Square legal_moves[100];
29 int state_hash;
31 static Board_State bstate;
34 void init_game_board(GtkWidget *GamazonsMain)
36    int i,j;
37    char color[256];
38    GtkWidget *w = (GtkWidget *) lookup_widget(GamazonsMain, BOARD_NAME);
39    GtkWidget *force_button, *undo_button;
40    GtkTextView *view;
41    GtkTextBuffer *buffer;
42    static int first_run = TRUE;
43    
44    if (w == NULL)
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(),
51                NULL));
52    
53    gnome_canvas_set_scroll_region(board->canvas, 0.0, 0.0,
54            400.0,
55            400.0);
58    /* initialize pieces */
59    for (i=0; i<BOARD_SIZE; i++)
60      {
61       for (j=0; j<BOARD_SIZE; j++)
62         {
63          board->squares[i][j] = NOTHING;
64         }
65      }
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);
95    //Initialize buttons
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);
100    
101    draw_board();
102    if (first_run)
103      {
104       first_run = FALSE;
105       bstate_set_just_finished(START_GAME);
106      }
111 void fill_a_square(GnomeCanvasGroup *group,
112         double x1, double y1, double x2, double y2, char *color)
114    /* draw a box*/
115    gnome_canvas_item_new(group,
116            gnome_canvas_rect_get_type(),
117            "x1", x1,
118            "y1", y1,
119            "x2", x2,
120            "y2", y2,
121            "outline_color", "black",
122            "fill_color", color,
123            "width_pixels", (double)THICKNESS,
124            NULL, NULL);
128 static void get_square_color(int square, char *color)
130    if ((square % 2) == 0)
131       strcpy(color, SQUARE_COLOR_1);
132    else
133       strcpy(color, SQUARE_COLOR_2);
137 static void draw_grid()
139    int x,y;
141    for (x=0; x<=10; x++)
142      {
143       for (y=0; y<=10; y++)
144         {
145          //draw horiz
146          draw_a_line(board->root, //gnome_canvas_root(board->canvas),
147                  0, y*CELL_SIZE, BOARD_SIZE*CELL_SIZE, y*CELL_SIZE, "black");
149          //draw vert
150          draw_a_line(board->root, //gnome_canvas_root(board->canvas),
151                  x*CELL_SIZE, 0, x*CELL_SIZE, BOARD_SIZE*CELL_SIZE, "black");
152         }
153      }
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;
171    /* draw the line */
172    gnome_canvas_item_new(group,
173            gnome_canvas_line_get_type(),
174            "points", points,
175            "fill_color", color,
176            "width_units", (double)THICKNESS,
177            NULL);
179    /* free the points array */
180    gnome_canvas_points_free(points);
183 void draw_board()
185    int i,j,k;
186    int black_i = 0;
187    GdkPixbuf *white_pb, *black_pb;
188    GdkPixbuf *white_sq, *grey_sq, *arrow_sq;
189    char color[256];
190    GnomeCanvasItem *image;
191    GnomeCanvasGroup *root = GNOME_CANVAS_GROUP(gnome_canvas_root (GNOME_CANVAS (board->canvas)));
192    static int first_game = 1;
193    
196    /* Find images */
197    white_pb = gdk_pixbuf_new_from_file(options.images.white_piece, NULL);
198    if (white_pb == NULL)
199      {
200       fprintf(stderr, "Cannot find white piece image: %s\n", options.images.white_piece);
201       exit(1);
202      }
204    black_pb = gdk_pixbuf_new_from_file(options.images.black_piece, NULL);
205    if (black_pb == NULL)
206      {
207       fprintf(stderr, "Cannot find black piece image: %s\n", options.images.black_piece);
208       exit(1);
209      }
211    white_sq = gdk_pixbuf_new_from_file(options.images.white_sq, NULL);
212    if (white_sq == NULL)
213      {
214       fprintf(stderr, "Cannot find white square image: %s\n", options.images.white_sq);
215       exit(1);
216      }
218    grey_sq = gdk_pixbuf_new_from_file(options.images.grey_sq, NULL);
219    if (grey_sq == NULL)
220      {
221       fprintf(stderr, "Cannot find grey square image: %s\n", options.images.grey_sq);
222       exit(1);
223      }
224    arrow_sq = gdk_pixbuf_new_from_file(options.images.arrow_sq, NULL);
225    if (arrow_sq == NULL)
226      {
227       fprintf(stderr, "Cannot find arrow square image: %s\n", options.images.arrow_sq);
228       exit(1);
229      }
233    /* fill alternate squares */
234    for(j=0;j<BOARD_SIZE;j++) 
235      {
236       for(i=0;i<BOARD_SIZE;i++) 
237         {
238          board->square_items[j*10+i] = NULL;
239          if ((i + j) % 2)
240            {
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,
246                     "pixbuf", grey_sq,
247                     NULL);
248            }
249          else
250            {
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,
256                     "pixbuf", white_sq,
257                     NULL);
258            }
262          //Place the queen images on the board in the right order
263          if (board->squares[j][i] == WHITE)
264            {
265 #ifdef DEBUG
266             printf("Square %c%c contains a white queen\n",i+'a',10-j+'0');
267 #endif
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,
273                     "pixbuf", white_pb,
274                     NULL);
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[]
277             for (k=0; k<4; k++)
278               {
279                if(j*10 +i == board->square_to_wh_queen_map[k])
280                  {
281                   board->white_queens[k] = image;
282 #ifdef DEBUG
283                   printf("registering queen %d\n", k);
284 #endif
285                   break;
286                  }
287               }
289 #ifdef DEBUG
290             printf("connecting signal to queen\n");
291 #endif
292             gtk_signal_connect(GTK_OBJECT(image), "event",
293                     GTK_SIGNAL_FUNC(board_press_cb), NULL);
294            }
295          else if (board->squares[j][i] == BLACK)
296            {
297 #ifdef DEBUG
298             printf("Square %c%c contains a black queen\n",i+'a',10-j+'0');
299 #endif
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,
305                     "pixbuf", black_pb,
306                     NULL);
307             for (k=0; k<4; k++)
308               {
309                if(j*10 +i == board->square_to_bl_queen_map[k])
310                  {
311                   board->black_queens[k] = image;
312 #ifdef DEBUG
313                   printf("registering queen %d\n", k);
314 #endif
315                   break;
316                  }
317               }
319 #ifdef DEBUG
320             printf("connecting signal to queen\n");
321 #endif
322             gtk_signal_connect(GTK_OBJECT(image), "event",
323                     GTK_SIGNAL_FUNC(board_press_cb), NULL);
324            }
325          else if (board->squares[j][i] == ARROW)
326            {
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,
332                     "pixbuf", arrow_sq,
333                     NULL);
334            }
335             
337         }
338      }
340    if (options.images.grid == TRUE)
341       draw_grid();
343    /*
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,
349            "pixbuf", white_pb,
350            NULL);
351            */
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)
368    Square from;
369    int x_square;
370    int y_square;
372    /*
373    x -= (BOARD_BORDER - CELL_PAD);
374    y -= (BOARD_BORDER - CELL_PAD);
375    */
377    if (x < 0)
378       x = 0.0;
379    else if (x > ((BOARD_SIZE-1) * CELL_SIZE))
380       x = (BOARD_SIZE-1) * CELL_SIZE;
381    if (y < 0)
382       y = 0.0;
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;
389 #ifdef DEBUG
390    printf("x coord = %f   y coord = %f\n", x, y);
391    printf("x coord = %d   y coord = %d\n", x_square, y_square);
392 #endif
394    from = x_square + y_square * 10;
396    return from;
399 void clear_square (GnomeCanvasItem **square)
401    gnome_canvas_item_set (*square, "outline_color", NULL, NULL);
402    *square = NULL;
405 /*==============================================================================
406  * try_move
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
410  * FALSE
411  */
412 int try_move (Board *board, GnomeCanvasItem *item)
414    double Lx, Uy, Rx, By;
415    double to_Lx, to_Uy;
416    int x, y;
417    int inc = 1;
418    int i,j;
420    to_Lx = get_x_from_square(board->to);
421    to_Uy = get_y_from_square(board->to);
422       
423 #ifdef DEBUG
424    printf("We want the queen at coords %f, %f\n", to_Lx, to_Uy);
425 #endif
426    gnome_canvas_item_get_bounds(item, &Lx, &Uy, &Rx, &By);
427 #ifdef DEBUG
428    printf("The queen is at coords %f, %f\n", Lx, Uy);
429 #endif
430    while (Lx != to_Lx || Uy != to_Uy)
431      {
432       bstate_set_moving_piece(TRUE);
433       if (Lx < to_Lx)
434          x = inc;
435       else if (Lx > to_Lx)
436          x = -inc;
437       else
438          x = 0;
440       if (Uy < to_Uy)
441          y = inc;
442       else if (Uy > to_Uy)
443          y = -inc;
444       else
445          y = 0;
448       gnome_canvas_item_move (item, (double)x, (double)y);
449       gnome_canvas_item_raise_to_top (item);
451       //update the board
452       while (gtk_events_pending())
453          gtk_main_iteration();
455       if (bstate_get_quit_game())
456          exit(0);
458       if (bstate_get_stop_moving())
459         {
460          bstate_set_stop_moving(FALSE);
461          return FALSE;
462         }
463       gnome_canvas_item_get_bounds(item, &Lx, &Uy, &Rx, &By);
464      }
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);
470 #ifdef DEBUG
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);
473 #endif
474    return TRUE;
478 double get_x_from_square(int sq)
480    double x;
482    x = (double) ((sq % 10) * CELL_SIZE+QUEEN_OFFSET);
484    return x;
488 double get_y_from_square(int sq)
490    double y;
492    y = (double) ((sq / 10) * CELL_SIZE+QUEEN_OFFSET);
494    return y;
499 int get_x_int_from_square(int sq)
501    return(sq % 10);
504 int get_y_int_from_square(int sq)
506    return(sq / 10);
509 int get_grid_num_from_square(int sq)
511    return(10 - sq/10);
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)
526    return(9 - eng_y);
529 int board_x_to_engine_x(int brd_x)
531    return(brd_x);
534 int board_y_to_engine_y(int brd_y)
536    return(9 - brd_y);
539 int get_square_from_engine(int x, int y)
541    return((9 - y) * 10 + x);
545 void fire_arrow(Square sq)
547    int x,y;
548    GdkPixbuf *arrow_sq;
549    GnomeCanvasItem *image;
550    GnomeCanvasGroup *root = GNOME_CANVAS_GROUP(gnome_canvas_root (GNOME_CANVAS (board->canvas)));
552    x = sq % 10;
553    y = sq / 10;
555    board->squares[y][x] = ARROW;
557    arrow_sq = gdk_pixbuf_new_from_file(options.images.arrow_sq, NULL);
558    if (arrow_sq == NULL)
559      {
560       fprintf(stderr, "Cannot find arrow image: %s\n", options.images.arrow_sq);
561       exit(1);
562      }
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,
569            "pixbuf", arrow_sq,
570            NULL);
574 void square_contains(Square sq)
576    int row, col;
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);
589    else
590       printf("Whoa, I don't know _what_ is on square %d\n", sq);
594 /*==============================================================================
595  * move_ai
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.
606  */
607 int move_ai()
609    state *s = states.s[states.current_state];
610    move temp;
611    move movelist[3000];
612    int ai = FALSE;
613    int current_hash;
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.
628    /*
629    moving_ai = TRUE;
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);
634    */
639    //quit this function if a 'New Game' option was selected since this
640    //function was started.
641    if (bstate_get_new_game())
642      {
643       bstate_set_new_game(FALSE);
644       return FALSE;
645      }
647    //gnome_canvas_item_request_update(board->canvas);
648    /*
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)))
651      {
652       what_next = WAIT_FOR_AI;
653       update_status_bar();
654      */
655       ok = 1;
656       ai = TRUE;
657       start = time(NULL);
658       temp = isearch(s, NOTHINK);
659       if (s->winner) //XXX does this if statement do any good?  I thot winner was handled elsewhere
660          return FALSE;
661       makemove(s,temp);
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)
668          return FALSE;
670    if (bstate_get_new_game())
671      {
672       bstate_set_new_game(FALSE);
673       return FALSE;
674      }
676    if (bstate_get_quit_game())
677       exit(0);
680       //register move on graphical board
681       if (move_piece(temp))
682         {
683          print_move_in_text_window(&temp);
684          dup_state(s, states.s[++(states.current_state)]);
685         }
686       else
687          return FALSE;
688       /*
689      }
690    else
691      {
692 #ifdef DEBUG
693       printf("the AI doesn't move next:\n");
694 #endif
695      }
696      */
698    /*
699    if (s->turn == WHITE_PLAYER)
700       what_next = MOVE_WHITE_QUEEN;
701    if (s->turn == BLACK_PLAYER)
702       what_next = MOVE_BLACK_QUEEN;
703    update_status_bar();
704    */
705    bstate_set_just_finished(WAIT_FOR_AI);
706       
708 #ifdef DEBUG
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 );
714 #endif
716    if (game_over(movelist))
717      {
718       //XXX should I set ai = FALSE?
719       ai = FALSE;
720       return (ai);
721      }
724    /*
725    gtk_widget_set_sensitive (auto_button, TRUE);
726    gtk_widget_set_sensitive (force_button, FALSE);
727    moving_ai = FALSE;
728    */
729    return ai;
732 /*==============================================================================
733  * move_piece
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.
739  */
740 int move_piece(move m)
742    GnomeCanvasItem *item;
743    int from_row, from_col;
744    int to_row, to_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
751    //piece.
752    if (states.s[states.current_state]->turn == WHITE_PLAYER)
753      {
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]);
756       
757       board->squares[to_row][to_col] = BLACK;
758 #ifdef DEBUG
759       printf("Moving black queen\n");
760 #endif
761       item = board->black_queens[m.queen];
762       board->square_to_bl_queen_map[m.queen] = to_row*10 +to_col;
763      }
764    else
765      {
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;
769 #ifdef DEBUG
770       printf("Moving white queen\n");
771 #endif
772       item = board->white_queens[m.queen];
773       board->square_to_wh_queen_map[m.queen] = to_row*10 +to_col;
774      }
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));
783    else 
784       return FALSE;
785 #ifdef DEBUG
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));
788    pmove(m);
789 #endif
790    return TRUE;
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.
798  */
799 void register_move_with_engine(Square arrow_sq)
801    state *s = states.s[states.current_state];
802    move m;
803    move movelist[3000];
804    int move_count;
805    int i;
806    int tocol, torow;
807    int found = FALSE;
808    char move_str[32];
809    char err_msg[256];
811    //find out the index of the queen that was just moved.  
812    //weird things will happen if it's not found.
813    for (i=0; i<4; i++)
814      {
815       if (board->selected_queen == board->white_queens[i] || 
816           board->selected_queen == board->black_queens[i])
817         {
818          found = TRUE;
819          break;
820         }
821      }
823    if (!found)
824       fprintf(stderr, "Error registering move w/ AI engine!  Game play will now be weird.\n");
826    m.queen = i;
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);
835    if (move_count == 0)
836      {
837       gnome_error_dialog("The AI engine thinks the game is over.  Please use the menu item Game->New to start a new game");
838       return;
839      }
840    if (!move_lookup(&m, movelist, move_count))
841      {
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);
846       return;
847      }
849    makemove(s, m);
850    print_move_in_text_window(&m);
854 /*==============================================================================
855  * is_queen_square
857  * Compares the given square with the information stored in board->squares[][]
858  * to see if a queen is there.
859  */
860 int is_queen_square(Square sq)
862    int row, col;
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))
869       return TRUE;
870    else
871       return FALSE;
875 /*==============================================================================
876  * gen_legal_moves
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
883  */
884 void gen_legal_moves(Square sq)
886    int arr_i = 0;
887    int i;
888    int row, col, sq_row, sq_col;
889    int scanning;
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
895    //his mind
896    legal_moves[arr_i++] = sq;
898    //get vertical moves
899    row = sq_row + 1;
900    col = sq_col;
901    while (board->squares[row][col] == NOTHING && row < 10)
902      {
903       legal_moves[arr_i++] = (row*10) + col;
904       row++;
905      }
907    row = sq_row - 1;
908    while (board->squares[row][col] == NOTHING && row >= 0)
909      {
910       legal_moves[arr_i++] = (row*10) + col;
911       row--;
912      }
914    //get horizontal moves
915    row = sq_row;
916    col = sq_col + 1;
917    while (board->squares[row][col] == NOTHING && col < 10)
918      {
919       legal_moves[arr_i++] = (row*10) + col;
920       col++;
921      }
923    col = sq_col - 1;
924    while (board->squares[row][col] == NOTHING && col >= 0)
925      {
926       legal_moves[arr_i++] = (row*10) + col;
927       col--;
928      }
930    //get forward diagonal moves
931    row = sq_row + 1;
932    col = sq_col + 1;
933    while (board->squares[row][col] == NOTHING && col < 10 && row < 10)
934      {
935       legal_moves[arr_i++] = (row*10) + col;
936       col++;
937       row++;
938      }
940    row = sq_row - 1;
941    col = sq_col - 1;
942    while (board->squares[row][col] == NOTHING && col >= 0 && row >= 0)
943      {
944       legal_moves[arr_i++] = (row*10) + col;
945       col--;
946       row--;
947      }
949    //get backward diagonal moves
950    row = sq_row + 1;
951    col = sq_col - 1;
952    while (board->squares[row][col] == NOTHING && col >= 0 && row < 10)
953      {
954       legal_moves[arr_i++] = (row*10) + col;
955       col--;
956       row++;
957      }
959    row = sq_row - 1;
960    col = sq_col + 1;
961    while (board->squares[row][col] == NOTHING && col < 10 && row >= 0)
962      {
963       legal_moves[arr_i++] = (row*10) + col;
964       col++;
965       row--;
966      }
969    legal_moves[arr_i] = 100;
970 #ifdef DEBUG
971    printf("legal move list for %d of length %d: \n", sq, arr_i);
972    i = 0;
973    while (legal_moves[i] < 100)
974       printf(" %d", legal_moves[i++]);
975    printf("\n");
976 #endif
980 /*==============================================================================
981  * is_move_legal
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.
985  */
986 int is_move_legal(Square sq)
988    int i=0;
990 #ifdef DEBUG
991    printf("checking to see if a move is legal\n");
992 #endif
993    while (legal_moves[i] < 100)
994      {
995       if (sq == legal_moves[i++])
996         {
997 #ifdef DEBUG
998          printf("%d is a legal move\n", sq);
999 #endif
1000          return TRUE;
1001         }
1002      }
1004 #ifdef DEBUG
1005    printf("Can't move to square.  Legal moves are: %d\n", sq);
1006    i=0;
1007    while (legal_moves[i] < 100)
1008       printf(" %d", legal_moves[i++]);
1009    printf("\n");
1010 #endif
1011    return FALSE;
1014 /*==============================================================================
1015  * count_queens
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.
1019  */ 
1020 void count_queens()
1022    int black=0, white=0;
1023    int i,j;
1025    for(i=0; i<10; i++)
1026      {
1027       for(j=0; j<10; j++)
1028         {
1029          if (board->squares[i][j] == WHITE)
1030             white++;
1031          if (board->squares[i][j] == BLACK)
1032             black++;
1033         }
1034      }
1035    if (black > 4) 
1036       printf("YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY Gained a black queen\n");
1037    if (white > 4)
1038       printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Gained a white queen\n");
1039    if (black < 4)
1040       printf("XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXXYXYX Lost a black queen\n");
1041    if (white < 4)
1042       printf("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ Lost a white queen\n");
1047 /*==============================================================================
1048  * free_all_memory
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.
1052  */
1053 void free_all_memory()
1055    int i;
1057    //free states
1058    for (i=0; i< states.max_state; i++)
1059       free (states.s[i]);
1061    //Oh, this is ugly!  Do I really want to do this?
1062    /*
1063    if(tt)
1064      {
1065       for (i=0; i<TT; i++)
1066         {
1067          if (tt[i])
1068             free(tt[i]);
1069         }
1070      }
1071      */
1078 /*==============================================================================
1079  * create_hash
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.
1083  */
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 /*==============================================================================
1097  * game_over
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.
1101  */
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)
1108      {
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!");
1113       else
1114          gnome_ok_dialog("Black wins!");
1116       bstate_set_just_finished(GAME_OVER);
1118       /*
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);
1123       */
1125       return TRUE;
1126      }
1127    else
1128       return FALSE;
1132 /*==============================================================================
1133  * update_status_bar
1135  * Updates the status bar based on the current value of what_next
1136  */
1137 update_status_bar()
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()) 
1145      {
1146        case FIRE_ARROW:
1147            gtk_statusbar_push(status, context_id, "Fire Arrow");
1148            break;
1149        case MOVE_BLACK_QUEEN:
1150            gtk_statusbar_push(status, context_id, "Move Black Amazon");
1151            break;
1152        case MOVE_WHITE_QUEEN:
1153            gtk_statusbar_push(status, context_id, "Move White Amazon");
1154            break;
1155        case WAIT_FOR_AI:
1156            gtk_statusbar_push(status, context_id, "AI is thinking...");
1157            break;
1158        case NEW_GAME:
1159            gtk_statusbar_push(status, context_id, "Select Game->New to start game");
1160            break;
1161        default:
1162            gtk_statusbar_push(status, context_id, "I have no idea what to do next!");
1164      }
1168 /*==============================================================================
1169  * print_board
1171  * prints out an ascii version of the board, useful for ensuring the board shows
1172  * what it should show.
1173  */
1174 void print_board()
1176    int i,j;
1178    for (i=0; i<BOARD_SIZE; i++)
1179      {
1180       for (j=0; j<BOARD_SIZE; j++)
1181         {
1182          if (board->squares[i][j] == 0)
1183             printf(" 0");
1184          if (board->squares[i][j] == 1)
1185             printf(" B");
1186          if (board->squares[i][j] == 2)
1187             printf(" W");
1188          if (board->squares[i][j] == 3)
1189             printf(" x");
1190         }
1191       printf("\n");
1192      }
1195 /*==============================================================================
1196  * destroy_board
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.
1201  */
1202 void destroy_board()
1204    int i;
1205    GtkWidget *CNVS_GAMEBOARD, *w, *scrolledwindow4, *table1;
1208 #ifdef DEBUG
1209    printf("Destroying board now\n");
1210 #endif
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(),
1216                NULL));
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
1224  */
1225 void print_move_in_text_window(move *m)
1227    GtkTextView *view; 
1228    GtkTextBuffer *buffer;
1229    GtkTextIter *iter = (GtkTextIter *) malloc(sizeof(GtkTextIter));
1230    char string_buf[32];
1231    GtkScrolledWindow *w;
1232    GtkAdjustment *adj;
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);
1240 #ifdef DEBUG
1241    printf("%s", string_buf);
1242 #endif
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);
1249    
1251    free (iter);
1254 /*==============================================================================
1255  * get_move_str
1257  * Creates a move string from a move struct
1258  */
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;
1265    int turn;
1267    //Determine which side just moved:
1268    turn = states.s[state_i]->turn^3;
1269    if (turn == WHITE_PLAYER)
1270      {
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]);
1273      }
1274    else
1275      {
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]);
1278      }
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);
1289    
1290    arrow_alpha = get_grid_alpha_from_square(arrow_sq);
1291    arrow_num = get_grid_num_from_square(arrow_sq);
1292    
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);
1297    
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
1305  * this out.
1306  */
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");
1316    switch(finished)
1317      {
1318        case FIRE_ARROW:
1319            if (bstate.turn == BLACK_PLAYER)
1320              {
1321               if (options.white_player == AI)
1322                 {
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);
1329                 }
1330               else
1331                 {
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);
1338                 }
1339               bstate.turn = WHITE_PLAYER;
1340              }
1341            else
1342              {
1343               if (options.black_player == AI)
1344                 {
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);
1351                 }
1352               else
1353                 {
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);
1360                 }
1361               bstate.turn = BLACK_PLAYER;
1362              }
1363            gtk_widget_set_sensitive (settings_menu, TRUE);
1364            break;
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);
1370            break;
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);
1376            break;
1377        case WAIT_FOR_AI:
1378            if (bstate.turn == BLACK_PLAYER)
1379              {
1380               if (options.white_player == AI)
1381                 {
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);
1388                 }
1389               else
1390                 {
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);
1397                 }
1398               bstate.turn = WHITE_PLAYER;
1399              }
1400            else
1401              {
1402               if (options.black_player == AI)
1403                 {
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);
1410                 }
1411               else
1412                 {
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);
1419                 }
1420               bstate.turn = BLACK_PLAYER;
1421              }
1422            break;
1423        case UNDO:
1424            if (bstate.turn == BLACK_PLAYER)
1425              {
1426               bstate.what_next = MOVE_BLACK_QUEEN;
1427              }
1428            else
1429              {
1430               bstate.what_next = MOVE_WHITE_QUEEN;
1431              }
1432            gtk_widget_set_sensitive (settings_menu, TRUE);
1433            gtk_widget_set_sensitive (undo_button, FALSE);
1434            gtk_widget_set_sensitive (auto_button, TRUE);
1435            break;
1436        case AUTO_FINISH:
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);
1441            break;
1442        case FORCE_MOVE:
1443            gtk_widget_set_sensitive (force_button, FALSE);
1444            break;
1445        case START_GAME:
1446            if (options.white_player == AI)
1447              {
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);
1452              }
1453            else
1454              {
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);
1459              }
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;
1469            break;
1470        case NEW_GAME:
1471            if (bstate.moving_ai) //in the middle of an AI move
1472               bstate.new_game = TRUE;
1473            else
1474               bstate.new_game = FALSE;
1476            if (bstate.moving_piece)
1477               bstate.stop_moving = TRUE;
1479            if (options.white_player == AI)
1480              {
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);
1486              }
1487            else
1488              {
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);
1494              }
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;
1502            break;
1504        case LOAD_GAME:
1505            break;
1506        case GAME_OVER:
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;
1512            break;
1514        case QUIT_GAME:
1515            bstate.quit_game = TRUE;
1516            break;
1517        default:
1518            bstate.what_next = CONFUSED;
1519      }
1520    update_status_bar();
1521 #ifdef DEBUG
1522    print_bstate();
1523 #endif
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)
1535    switch(next)
1536      {
1537        case FIRE_ARROW:
1538            bstate.what_next = FIRE_ARROW;
1539            break;
1540        case MOVE_BLACK_QUEEN:
1541            if (options.black_player == AI)
1542               bstate.what_next = WAIT_FOR_AI;
1543            else
1544               bstate.what_next = MOVE_BLACK_QUEEN;
1545            bstate.turn = BLACK_PLAYER;
1546            break;
1547        case MOVE_WHITE_QUEEN:
1548            if (options.white_player == AI)
1549               bstate.what_next = WAIT_FOR_AI;
1550            else
1551               bstate.what_next = MOVE_WHITE_QUEEN;
1552            bstate.turn = WHITE_PLAYER;
1553            break;
1554        case WAIT_FOR_AI:
1555            bstate.what_next = WAIT_FOR_AI;
1556            break;
1557        default:
1558            bstate.what_next = CONFUSED;
1559      }
1560    update_status_bar();
1562  */
1564 /*==============================================================================
1565  * bstate_get_what_next
1567  * This is the method for code throughout the program to find out what input
1568  * is expected next.
1569  */
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
1579  * a given square.
1580  */
1581 void bstate_set_move_from(Square from)
1583    bstate.from = from;
1586 /*==============================================================================
1587  * bstate_set_move_from
1589  * This lets the internal board state know that a queen has just been moved to
1590  * a given square.
1591  */
1592 void bstate_set_move_to(Square to)
1594    bstate.to = to;
1597 /*==============================================================================
1598  * bstate_get_move_from
1600  * This lets the internal board state know that a queen has just been moved from
1601  * a given square.
1602  */
1603 Square bstate_get_move_from()
1605    return bstate.from;
1608 /*==============================================================================
1609  * bstate_get_move_from
1611  * This lets the internal board state know that a queen has just been moved to
1612  * a given square.
1613  */
1614 Square bstate_get_move_to()
1616    return bstate.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()
1649    return bstate.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)
1670       return;
1671    
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;
1696 void print_bstate()
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)
1708    char *buffer=NULL;
1709    size_t buf_size = 30;
1711    printf("History contents:\n");
1712    while (getline(&buffer, &buf_size, history_fd) != -1)
1713      {
1714       if (buffer != NULL)
1715          printf("%s", buffer);
1716       free(buffer);
1717       buffer = NULL;
1718      }
1719    
1721    return TRUE;