]> git.cworth.org Git - grrobot/blobdiff - src/grrobot.c
Added keybindings. Can now play a board from a file without any server.
[grrobot] / src / grrobot.c
index 209c599d9fc1db6a3f5a31fd10ca996d985cbff1..a56932d5cdd23b5462908fb07970a481cf4284b5 100644 (file)
@@ -33,6 +33,7 @@
 #include <string.h>
 
 #include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
 
 #include "grr_board_view.h"
 #include "grr_util.h"
@@ -43,7 +44,7 @@ typedef struct grr_game {
     rr_board_t *board;
 
     GtkWidget *window;
-    GtkWidget *board_view;
+    grr_board_view_t *board_view;
     GtkWidget *command_entry;
 
     GtkTextBuffer *message_buffer;
@@ -85,38 +86,47 @@ main (int argc, char **argv)
     
     args_parse (&args, argc, argv);
 
-    game.client = rr_client_create (args.host, args.port, args.user);
-    if (game.client == NULL) {
-       fprintf (stderr, "Failed connecting to %s:%s as %s\n",
-                args.host, args.port, args.user);
-       return 1;
-    }
-
-    if (args.watch) {
-       status = rr_client_watch (game.client, args.game);
-       if (status == RR_STATUS_NO_GAME) {
-           fprintf (stderr, "No game %s to watch\n", args.game);
+    if (args.file) {
+       game.board = rr_board_create_from_file (args.file);
+       if (game.board == NULL) {
+           fprintf (stderr, "Failed to parse board from %s\n", args.file);
+           return 1;
        }
+       game.client = NULL;
     } else {
-       status = rr_client_join (game.client, args.game);
-       if (status == RR_STATUS_NO_GAME) {
-           status = rr_client_new (game.client, args.game);
+       game.client = rr_client_create (args.host, args.port, args.user);
+       if (game.client == NULL) {
+           fprintf (stderr, "Failed connecting to %s:%s as %s\n",
+                    args.host, args.port, args.user);
+           return 1;
        }
-    }
 
-    game.board = rr_board_create (16, 16);
-    game.msg_id = 0;
-    game.last_move_msg_id = 0;
-    game.last_move_robot = RR_ROBOT_NONE;
+       if (args.watch) {
+           status = rr_client_watch (game.client, args.game);
+           if (status == RR_STATUS_NO_GAME) {
+               fprintf (stderr, "No game %s to watch\n", args.game);
+           }
+       } else {
+           status = rr_client_join (game.client, args.game);
+           if (status == RR_STATUS_NO_GAME) {
+               status = rr_client_new (game.client, args.game);
+           }
+       }
 
-    source = grr_game_notices_source_new (&game);
-    g_source_set_priority (source, GDK_PRIORITY_EVENTS);
-    g_source_attach (source, NULL);
-    g_source_unref (source);
+       game.board = rr_board_create (16, 16);
+       game.msg_id = 0;
+       game.last_move_msg_id = 0;
+       game.last_move_robot = RR_ROBOT_NONE;
 
-    rr_client_show (game.client, &diagram);
-    rr_board_parse (game.board, diagram);
-    free (diagram);
+       source = grr_game_notices_source_new (&game);
+       g_source_set_priority (source, GDK_PRIORITY_EVENTS);
+       g_source_attach (source, NULL);
+       g_source_unref (source);
+
+       rr_client_show (game.client, &diagram);
+       rr_board_parse (game.board, diagram);
+       free (diagram);
+    }
 
     return grr_game_start_gui (&game);
 }
@@ -229,6 +239,10 @@ grr_game_read_notices (grr_game_t *game)
                             notice->u.message.username,
                             notice->u.message.text);
            break;
+       case RR_NOTICE_BOARD:
+           rr_board_parse (board, notice->u.string);
+           gtk_widget_queue_draw (GTK_WIDGET (game->window));
+           break;
        case RR_NOTICE_GAMESTATE:
            grr_game_printf (game, "\nGame state changed to: %s.",
                             rr_gamestate_str (notice->u.gamestate));
@@ -239,16 +253,8 @@ grr_game_read_notices (grr_game_t *game)
            gtk_widget_queue_draw (GTK_WIDGET (game->window));
            break;
        case RR_NOTICE_GAMEOVER:
-       {
-           char *diagram;
            grr_game_printf (game, "\nGame over. New game will begin now.");
-           /* XXX: Can drop this when the BOARD NOTICE is added in the server */
-           rr_client_show (game->client, &diagram);
-           rr_board_parse (board, diagram);
-           free (diagram);
-           gtk_widget_queue_draw (GTK_WIDGET (game->window));
-       }
-       break;
+           break;
        case RR_NOTICE_JOIN:
            grr_game_printf (game, "\nUser %s has joined the game.",
                             notice->u.string);
@@ -316,15 +322,87 @@ grr_game_read_notices (grr_game_t *game)
                             notice->u.number);
            break;
        case RR_NOTICE_POSITION:
-           rr_board_position_robot (board, notice->u.position.robot,
-                                    notice->u.position.x, notice->u.position.y);
+           rr_board_add_robot (board, notice->u.position.robot,
+                               notice->u.position.x, notice->u.position.y);
            gtk_widget_queue_draw (GTK_WIDGET (game->window));
            break;
+       default:
+           fprintf (stderr, "Unknown notice: %d\n", notice->type);
+           break;
        }
        free (notice);
     }
 }
 
+static gboolean
+grr_game_key_press_callback (GtkWidget *widget,
+                            GdkEventKey *event,
+                            grr_game_t *game)
+{
+    if (GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (game->command_entry))) {
+       if (event->keyval == GDK_Escape) {
+           gtk_entry_set_text (GTK_ENTRY (game->command_entry), "");
+           gtk_widget_grab_focus (GTK_WIDGET (game->message_view));
+
+           return TRUE;
+       } else {
+           return FALSE;
+       }
+    }
+
+    switch (event->keyval) {
+    case GDK_B:
+    case GDK_b:
+       grr_board_view_set_active_robot (game->board_view, RR_ROBOT_BLUE);
+       break;
+    case GDK_G:
+    case GDK_g:
+       grr_board_view_set_active_robot (game->board_view, RR_ROBOT_GREEN);
+       break;
+    case GDK_R:
+    case GDK_r:
+       grr_board_view_set_active_robot (game->board_view, RR_ROBOT_RED);
+       break;
+    case GDK_Y:
+    case GDK_y:
+       grr_board_view_set_active_robot (game->board_view, RR_ROBOT_YELLOW);
+       break;
+    case GDK_Up:
+       grr_board_view_move_active (game->board_view, RR_DIRECTION_NORTH);
+       break;
+    case GDK_Right:
+       grr_board_view_move_active (game->board_view, RR_DIRECTION_EAST);
+       break;
+    case GDK_Down:
+       grr_board_view_move_active (game->board_view, RR_DIRECTION_SOUTH);
+       break;
+    case GDK_Left:
+       grr_board_view_move_active (game->board_view, RR_DIRECTION_WEST);
+       break;
+    case GDK_BackSpace:
+       grr_board_view_undo (game->board_view);
+       break;
+    case GDK_space:
+    case GDK_slash:
+       gtk_widget_grab_focus (GTK_WIDGET (game->command_entry));
+       if (event->keyval == GDK_slash) {
+           int pos = -1;
+           gtk_editable_insert_text (GTK_EDITABLE (game->command_entry),
+                                     "/", 1, &pos);
+           gtk_editable_set_position (GTK_EDITABLE (game->command_entry), -1);
+       }
+       break;
+    case GDK_Q:
+    case GDK_q:
+       if (event->state & GDK_CONTROL_MASK) {
+           gtk_exit (0);
+       }
+       break;
+    }
+
+    return TRUE;
+}
+
 static void
 grr_game_entry_callback (GtkWidget *widget,
                         grr_game_t *game)
@@ -336,18 +414,25 @@ grr_game_entry_callback (GtkWidget *widget,
 
     entry_text = gtk_entry_get_text (GTK_ENTRY (game->command_entry));
 
-    status = rr_client_request (game->client, entry_text, &response);
-    if (status) {
-       grr_game_printf (game, "\nERROR: %s.", rr_status_str (status));
-    } else {
-       if (response[0]) {
-           grr_game_print (game, "\n");
-           for (i=0; response[i]; i++)
-               grr_game_printf (game, "%s ", response[i]);
+    if (entry_text && entry_text[0] && game->client) {
+       if (entry_text[0] == '/') {
+           status = rr_client_request (game->client, entry_text + 1, &response);
+           if (status) {
+               grr_game_printf (game, "\nERROR: %s.", rr_status_str (status));
+           } else {
+               if (response[0]) {
+                   grr_game_print (game, "\n");
+                   for (i=0; response[i]; i++)
+                       grr_game_printf (game, "%s ", response[i]);
+               }
+           }
+       } else {
+           rr_client_message (game->client, entry_text);
        }
     }
 
     gtk_entry_set_text (GTK_ENTRY (game->command_entry), "");
+    gtk_widget_grab_focus (GTK_WIDGET (game->message_view));
 
 /* XXX: Huh? Why is this triggering valgrind?
     free (response);
@@ -452,8 +537,8 @@ grr_game_start_gui (grr_game_t *game)
            board_frame = gtk_aspect_frame_new (NULL, 0.5, 0.5, 1.0, FALSE);
            gtk_paned_pack1 (GTK_PANED (vpaned), board_frame, TRUE, TRUE);
            {
-               gtk_container_add (GTK_CONTAINER (board_frame), game->board_view);
-               gtk_widget_show (game->board_view);
+               gtk_container_add (GTK_CONTAINER (board_frame), GTK_WIDGET (game->board_view));
+               gtk_widget_show (GTK_WIDGET (game->board_view));
            }
            gtk_widget_show (board_frame);
 
@@ -483,6 +568,10 @@ grr_game_start_gui (grr_game_t *game)
     }
     gtk_widget_show (vbox);
 
+    g_signal_connect (G_OBJECT (window), "key_press_event",
+                     G_CALLBACK (grr_game_key_press_callback),
+                     (gpointer) game);
+
     gtk_widget_show (window);
     
     gtk_main ();