]> git.cworth.org Git - rrsolve/blobdiff - src/rrsolve.c
Small cleanups.
[rrsolve] / src / rrsolve.c
index 80f17b1c2987b103ad1940afad5d375880259b5c..5e92cbb94a5edb16cbb996e96e9ee7fbf6ed0b1d 100644 (file)
 
 #include "rrsolve.h"
 
-#define HOST "localhost"
-#define PORT "5252"
-#define USER "rrsolve"
-#define GAME "game"
-
 /* Tuning this can reduce excess reallocs */
 #define RRS_BRANCHING_FACTOR_ESTIMATE 10
 
 #define RRS_STATE_SET_ROBOT(s, ri, x, y) ((s) |= (((y) << ((ri)<<3)) | ((x) << (((ri)<<3) + 4))))
 #define RRS_STATE_GET_ROBOT(s, ri, x, y) { (y) = ((s) >> ((ri)<<3)) & 0xf; (x) = ((s) >> (((ri)<<3) + 4)) & 0xf; }
 
+static void
+handle_events (rr_client_t *client);
+
 static rrs_state_t
 rrs_state_get_from_board (rr_board_t *board);
 
@@ -77,49 +75,171 @@ main (int argc, char *argv[])
     args_t args;
     rr_status_t status;
     rr_client_t *client;
-    rr_board_t *board;
-    rrs_solution_t solution;
-    char *diagram;
 
     args_parse (&args, argc, argv);
 
-    client = rr_client_create (args.host, args.port, args.user);
-    if (client == NULL) {
-       fprintf (stderr, "Failed connecting to %s:%s as %s\n",
-                args.host, args.port, args.user);
-       return 1;
-    }
+    if (args.files) {
+       int i;
+       rr_board_t *board;
+       rrs_solution_t solution;
 
-    status = rr_client_join (client, GAME);
-    if (status == RR_STATUS_NO_GAME)
-       status = rr_client_new (client, GAME);
-    if (status) {
-       fprintf (stderr, "Error joining or creating game: %s\n", rr_status_str (status));
-       return 1;
-    }
+       for (i = 0; args.files[i]; i++) {
+           board = rr_board_create_from_file (args.files[i]);
+           if (board == NULL) {
+               fprintf (stderr, "Failed to parse board in %s\n", args.files[i]);
+               continue;
+           }
+           rrs_solution_init (&solution);
+           solve_board (board, &solution);
+           rrs_solution_print (&solution);
+           rrs_solution_fini (&solution);
+           rr_board_destroy (board);
+       }
+    } else {
+       client = rr_client_create (args.host, args.port, args.user);
+       if (client == NULL) {
+           fprintf (stderr, "Failed connecting to %s:%s as %s\n",
+                    args.host, args.port, args.user);
+           return 1;
+       }
+
+       status = rr_client_join (client, args.game);
+       if (status == RR_STATUS_NO_GAME)
+           status = rr_client_new (client, args.game);
+       if (status) {
+           fprintf (stderr, "Error joining or creating game: %s\n", rr_status_str (status));
+           return 1;
+       }
+
+       handle_events (client);
 
-    status = rr_client_show (client, &diagram);
-    if (status) {
-       fprintf (stderr, "Error in rr_client_new: %s\n", rr_status_str (status));
-       return 1;
+       rr_client_destroy (client);
     }
-    board = rr_board_create_from_str (diagram);
 
-    puts (rr_board_to_str (board));
+    return 0;
+}
 
-    rrs_solution_init (&solution);
-    solve_board (board, &solution);
-    printf ("Solution (%d moves):", solution.num_moves);
-    rrs_solution_print (&solution);
-    rrs_solution_fini (&solution);
+static void
+handle_events (rr_client_t *client)
+{
+    int i;
+    rr_status_t status;
+    rr_notice_t *notice;
+    rrs_solution_t solution;
+    rr_board_t *board;
+    char *diagram;
+    struct timespec move_delay = { 1, 200000000l };
+
+    /* XXX: This block of code can go away when add a NOTICE BOARD
+       for new users joining a game. */
+    {
+       status = rr_client_show (client, &diagram);
+       if (status) {
+           fprintf (stderr, "Error in rr_client_show: %s\n", rr_status_str (status));
+           goto DONE;
+       }
+       board = rr_board_create_from_str (diagram);
+       free (diagram);
+    }
 
-    free (diagram);
+    /* XXX: This block of code can go away when we add a NOTICE TURN
+       for new users joining a game in progress. */
+    {
+       rrs_solution_init (&solution);
+       solve_board (board, &solution);
+       rr_client_bid (client, solution.num_moves);
+       rr_client_nobid (client);
+    }
 
-    rr_board_destroy (board);
+    while (1) {
+       status = rr_client_next_notice (client, &notice);
+       if (status) {
+           if (status == RR_STATUS_EOF)
+               fprintf (stderr, "Server has disconnected. Exiting.\n");
+           else
+               fprintf (stderr, "ERROR during rr_client_next_notice: %s\n",
+                        rr_status_str (status));
+           return;
+       }
+       if (!notice) {
+           fprintf (stderr, "No notice during rr_client_next_notice\n");
+           continue;
+       }
 
-    rr_client_destroy (client);
+       switch  (notice->type) {
+       case RR_NOTICE_BOARD:
+           rr_board_parse (board, notice->u.string);
+           break;
+       case RR_NOTICE_TURN:
+           rr_board_set_goal_target (board, notice->u.target);
+           rrs_solution_init (&solution);
+           solve_board (board, &solution);
+           rr_client_bid (client, solution.num_moves);
+           rr_client_nobid (client);
+           break;
+       case RR_NOTICE_ACTIVATE:
+           for (i = 0; i < solution.num_moves; i++) {
+               status = rr_client_move (client,
+                                        solution.move[i].robot,
+                                        solution.move[i].dir);
+               if (status) {
+                   rr_client_message (client, "Drat, looks like I was wrong.");
+                   rr_client_pass (client);
+                   break;
+               }
+               nanosleep (&move_delay, NULL);
+           }
+           rrs_solution_fini (&solution);
+           break;
+       case RR_NOTICE_ABANDON:
+           rr_client_abandon (client);
+           break;
+       case RR_NOTICE_NOBID:
+           rr_client_nobid (client);
+           break;
+       case RR_NOTICE_POSITION:
+           rr_board_add_robot (board,
+                               notice->u.position.robot,
+                               notice->u.position.x,
+                               notice->u.position.y);
+           break;
+       case RR_NOTICE_GAMESTATE:
+           if (notice->u.gamestate == RR_GAMESTATE_DONE
+               || notice->u.gamestate == RR_GAMESTATE_SHOW) {
+               if (solution.num_moves) {
+                   printf ("My solution (%d moves):", solution.num_moves);
+                   rrs_solution_print (&solution);
+               }
+           }
+           break;
+       case RR_NOTICE_GAMEOVER:
+       case RR_NOTICE_GAME:
+       case RR_NOTICE_USER:
+       case RR_NOTICE_JOIN:
+       case RR_NOTICE_QUIT:
+       case RR_NOTICE_DISPOSE:
+       case RR_NOTICE_MESSAGE:
+       case RR_NOTICE_WATCH:
+       case RR_NOTICE_PART:
+       case RR_NOTICE_BID:
+       case RR_NOTICE_REVOKE:
+       case RR_NOTICE_TIMER:
+       case RR_NOTICE_ACTIVE:
+       case RR_NOTICE_MOVE:
+       case RR_NOTICE_UNDO:
+       case RR_NOTICE_RESET:
+       case RR_NOTICE_SCORE:
+           /* Ignore these notices */
+           break;
+       }
+       free (notice);
+    }
 
-    return 0;
+  DONE:
+    if (notice)
+       free (notice);
+    if (board)
+       rr_board_destroy (board);
 }
 
 static void
@@ -136,7 +256,7 @@ rrs_solution_print (rrs_solution_t *solution)
            printf (", %s", rr_direction_str (move->dir));
        else
            printf ("\n Move #%d: %s %s",
-                   i, rr_robot_str (move->robot), rr_direction_str (move->dir));
+                   i+1, rr_robot_str (move->robot), rr_direction_str (move->dir));
        last_robot = move->robot;
     }
     printf ("\n");
@@ -165,11 +285,13 @@ rrs_state_set_board (rrs_state_t state, rr_board_t *board)
     int i;
     int x, y;
 
+    for (i=0; i < RR_NUM_ROBOTS; i++)
+       rr_board_remove_robot (board, rr_robot_from_idx (i));
+
     for (i=0; i < RR_NUM_ROBOTS; i++) {
        RRS_STATE_GET_ROBOT (state, i, x, y);
-       rr_board_position_robot (board, rr_robot_from_idx (i), x, y);
+       rr_board_add_robot (board, rr_robot_from_idx (i), x, y);
     }
-
 }
 
 static rr_status_t
@@ -185,6 +307,9 @@ solve_board (rr_board_t *board, rrs_solution_t *solution)
        printf ("Board is solved to begin with.\n");
        return RR_STATUS_SUCCESS;
     }
+
+    printf ("Now trying to solve:");
+    puts (rr_board_to_str (board));
     
     gettimeofday (&tv_start, NULL);
 
@@ -291,8 +416,10 @@ trace_solution (rr_board_t *board,
     rr_status_t status;
     int i, j;
     rrs_state_buf_t *buf;
-    rr_robot_t robot;
-    rr_direction_t dir;
+    int found_move = 0;
+    rr_robot_t robot, robot_found, last_robot_found = RR_ROBOT_NONE;
+    rr_direction_t dir, dir_found;
+    rrs_state_t state_found;
 
     for (i = moves-1; i >= 0; i--) {
        buf = states[i];
@@ -303,18 +430,27 @@ trace_solution (rr_board_t *board,
                status = rr_board_move (board, robot, dir);
                if (status == RR_STATUS_SUCCESS) {
                    if (rrs_state_get_from_board (board) == solution_state) {
-                       rrs_solution_prepend (solution, robot, dir);
-                       solution_state = buf->state[j];
-                       goto NEXT_MOVE;
+                       found_move = 1;
+                       robot_found = robot;
+                       dir_found = dir;
+                       state_found = buf->state[j];
+                       if (robot_found == last_robot_found)
+                           goto NEXT_MOVE;
+                       else
+                           last_robot_found = robot_found;
                    }
                }
            }
        }
-       fprintf (stderr, "ERROR: Failed to trace solution backwards to 0x%x at move %d\n",
-                solution_state, i+1);
-       break;
       NEXT_MOVE:
-       ;
+       if (found_move) {
+           rrs_solution_prepend (solution, robot_found, dir_found);
+           solution_state = state_found;
+       } else {
+           fprintf (stderr, "ERROR: Failed to trace solution backwards to 0x%x at move %d\n",
+                    solution_state, i+1);
+           break;
+       }
     }
 }
 
@@ -407,6 +543,9 @@ rrs_find_new_states (rr_board_t *board,
        state = initial->state[i];
 
        rrs_state_set_board (state, board);
+
+       if (state == 0x611a4350)
+           printf ("I'm within one move now\n");
        for (ri = 0; ri < RR_NUM_ROBOTS; ri++) {
            robot = rr_robot_from_idx (ri);
            for (dir = RR_DIRECTION_NORTH; dir <= RR_DIRECTION_EAST; dir++) {