]> git.cworth.org Git - grrobot/commitdiff
* src/grrobot.c (grr_game_read_notices): Exit cleanly: need to
authorCarl Worth <cworth@theworths.org>
Tue, 11 Nov 2003 15:51:53 +0000 (15:51 +0000)
committerCarl Worth <cworth@theworths.org>
Tue, 11 Nov 2003 15:51:53 +0000 (15:51 +0000)
        return control to Gtk+ so that gtk_main_quit has a chance to do
        its job.
        (grr_game_read_notices): Track changes in grr_board_view timer
        API.
        (grr_game_key_press_callback): Eliminate bid_entry text box and
        bid button. Instead, a bare number in the message_entry will
        result in a bid.
        (grr_game_key_press_callback): Change several keybindings to
        require a control modifier: C-N=Next turn, C-P=Pass, C-Z=Zap timer
        and C-RGBY for robot selection. Now, no keybindings should
        interfere with simple text messages.
        (grr_game_pass): "Pass" button now issues "abandon" instead of
        "revoke" when not in show mode.
        (grr_game_next): "Next Turn" button now only issues turn never
        "abandon", so there's no longer a problem when two users both hit
        the "Next Turn" button.

        * src/grr_board_view.c (grr_board_view_decrement_timer): Make the
        "Zap timer" feature animate the fast clock rather than just
        snapping.
        (grr_board_view_start_timer):
        (grr_board_view_stop_timer):
        (grr_board_view_set_timer): Cleaner timer API: set, start, and
        stop.

ChangeLog
src/grr_board_view.c
src/grr_board_view.h
src/grrobot.c

index 4836baae18dee582f960c41a723acf388f259996..1cd8b52c229725364bdb8e1da1db3e03f5f199ae 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2003-11-11  Carl Worth  <cworth@isi.edu>
+
+       * src/grrobot.c (grr_game_read_notices): Exit cleanly: need to
+       return control to Gtk+ so that gtk_main_quit has a chance to do
+       its job.
+       (grr_game_read_notices): Track changes in grr_board_view timer
+       API.
+       (grr_game_key_press_callback): Eliminate bid_entry text box and
+       bid button. Instead, a bare number in the message_entry will
+       result in a bid.
+       (grr_game_key_press_callback): Change several keybindings to
+       require a control modifier: C-N=Next turn, C-P=Pass, C-Z=Zap timer
+       and C-RGBY for robot selection. Now, no keybindings should
+       interfere with simple text messages.
+       (grr_game_pass): "Pass" button now issues "abandon" instead of
+       "revoke" when not in show mode.
+       (grr_game_next): "Next Turn" button now only issues "turn" never
+       "abandon", so there's no longer a problem when two users both hit
+       the "Next Turn" button.
+
+       * src/grr_board_view.c (grr_board_view_decrement_timer): Make the
+       "Zap timer" feature animate the fast clock rather than just
+       snapping.
+       (grr_board_view_start_timer):
+       (grr_board_view_stop_timer):
+       (grr_board_view_set_timer): Cleaner timer API: set, start, and
+       stop.
+
 2003-11-10  Carl Worth  <cworth@isi.edu>
 
        * src/grrobot.c (grr_game_read_notices): Call new board_view timer
index 8d85988f0cb2c414a19b94bded0d72b11454bec9..6a184419eb2254ace5420815701ec6e1f90ad2ea 100644 (file)
@@ -134,6 +134,7 @@ grr_board_view_init (grr_board_view_t *view)
     view->time = 60.0;
     view->drift_correct = 0.0;
     view->timer = 0;
+    view->zap_time = 0.0;
 
     view->cell_width = 0;
     view->cell_height = 0;
@@ -696,7 +697,7 @@ grr_board_view_mark_damage (grr_board_view_t *view, int i, int j)
     gtk_widget_queue_draw_area (GTK_WIDGET (view), x, y, view->cell_width, view->cell_height);
 }
 
-#define TIMER_INTERVAL_MS 100
+#define TIMER_INTERVAL_MS 100.0
 
 static void
 grr_board_view_refresh_timer (grr_board_view_t *view)
@@ -721,19 +722,29 @@ grr_board_view_decrement_timer (void *widget)
     view->time -= TIMER_INTERVAL_MS / 1000.0;
     view->time += view->drift_correct;
 
+    if (view->zap_time) {
+       view->time -= view->zap_time;
+       view->zap_time += 1.0;
+    }
+
     grr_board_view_refresh_timer (view);
 
+    if (view->time < 0) {
+       grr_board_view_stop_timer (view);
+       return FALSE;
+    }
+
     return TRUE;
 }
 
 void
-grr_board_view_start_timer (grr_board_view_t *view, double time)
+grr_board_view_set_timer (grr_board_view_t *view, double time)
 {
     /* XXX: It would be good to adjust the clock for latency somewhere... */
-    /* Correct any drift within the next 10 seconds, or half the
-       remaining time --- whichever is less. */
     if (view->timer) {
        double correction_time;
+       /* Correct any drift within the next 10 seconds, or half the
+          remaining time --- whichever is less. */
        if (time >= 20.0)
            correction_time = 10.0;
        else
@@ -741,11 +752,20 @@ grr_board_view_start_timer (grr_board_view_t *view, double time)
        view->drift_correct = (time - view->time) / (correction_time * TIMER_INTERVAL_MS);
     } else {
        view->time = time;
-
-       view->timer = gtk_timeout_add (TIMER_INTERVAL_MS, grr_board_view_decrement_timer, view);
+       view->drift_correct = 0.0;
+       view->zap_time = 0.0;
     }
 }
 
+void
+grr_board_view_start_timer (grr_board_view_t *view)
+{
+    if (view->timer)
+       return;
+
+    view->timer = gtk_timeout_add (TIMER_INTERVAL_MS, grr_board_view_decrement_timer, view);
+}
+
 void
 grr_board_view_stop_timer (grr_board_view_t *view)
 {
@@ -755,15 +775,17 @@ grr_board_view_stop_timer (grr_board_view_t *view)
     gtk_timeout_remove (view->timer);
     view->timer = 0;
     view->time = 0.0;
+    view->drift_correct = 0.0;
+    view->zap_time = 0.0;
 
     grr_board_view_refresh_timer (view);
 }
 
 void
-grr_board_view_reset_timer (grr_board_view_t *view)
+grr_board_view_zap_timer (grr_board_view_t *view)
 {
-    grr_board_view_stop_timer (view);
+    view->zap_time = 4;
 
-    view->time = 60.0;
-    view->drift_correct = 0.0;
+    grr_board_view_refresh_timer (view);
 }
+
index 92cf981fc0cf1bbc55c5df2e9f15eda293ee731f..948d8a4928aa7866105b611451be22947079cc74 100644 (file)
@@ -68,6 +68,7 @@ struct grr_board_view
     guint8 button;
     
     double time;
+    double zap_time;
     double drift_correct;
     guint timer;
 
@@ -106,13 +107,16 @@ void
 grr_board_view_mark_damage (grr_board_view_t *view, int i, int j);
 
 void
-grr_board_view_start_timer (grr_board_view_t *view, double time);
+grr_board_view_set_timer (grr_board_view_t *view, double time);
+
+void
+grr_board_view_start_timer (grr_board_view_t *view);
 
 void
 grr_board_view_stop_timer (grr_board_view_t *view);
 
 void
-grr_board_view_reset_timer (grr_board_view_t *view);
+grr_board_view_zap_timer (grr_board_view_t *view);
 
 void
 grr_board_view_transform_pixel_to_cell (grr_board_view_t *view,
index 8df5b9815d9da75615c0f9ac690830007e1f2fa6..386a1637956a275586cdb1dfd502349c2729534f 100644 (file)
@@ -46,7 +46,6 @@ typedef struct grr_game {
     GtkWidget *window;
     grr_board_view_t *board_view;
     GtkWidget *message_entry;
-    GtkWidget *bid_entry;
 
     GtkTextBuffer *message_buffer;
     GtkWidget *message_view;
@@ -230,6 +229,7 @@ grr_game_read_notices (grr_game_t *game)
                fprintf (stderr, "Error during rr_client_next_notice: %s\n",
                         rr_status_str (status));
            gtk_main_quit ();
+           return;
        }
        if (!notice) {
            fprintf (stderr, "Missing notice\n");
@@ -273,7 +273,7 @@ grr_game_read_notices (grr_game_t *game)
                here. */
            game->state = RR_GAMESTATE_NEW;
 
-           grr_board_view_reset_timer (game->board_view);
+           grr_board_view_set_timer (game->board_view, 60.0);
            grr_game_print (game, "\nNew round!");
            rr_board_set_goal_target (board, notice->u.target);
            gtk_widget_queue_draw (GTK_WIDGET (game->window));
@@ -339,14 +339,15 @@ grr_game_read_notices (grr_game_t *game)
                             notice->u.number);
            break;
        case RR_NOTICE_ACTIVE:
-           grr_board_view_stop_timer (game->board_view);
+           grr_board_view_zap_timer (game->board_view);
            grr_game_printf (game, "\nUser %s now active to demonstrate solution in %d moves.",
                             notice->u.bid.username,
                             notice->u.bid.number);
            break;
        case RR_NOTICE_TIMER:
-           grr_board_view_start_timer (game->board_view,
-                                       notice->u.number);
+           grr_board_view_set_timer (game->board_view,
+                                     notice->u.number);
+           grr_board_view_start_timer (game->board_view);
            break;
        case RR_NOTICE_POSITION:
        {
@@ -372,104 +373,81 @@ grr_game_key_press_callback (GtkWidget *widget,
                             GdkEventKey *event,
                             grr_game_t *game)
 {
-    if (GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (game->message_entry))
-       || GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (game->bid_entry))
-       ) {
+    if (GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (game->message_entry))) {
        if (event->keyval == GDK_Escape) {
            gtk_entry_set_text (GTK_ENTRY (game->message_entry), "");
-           gtk_entry_set_text (GTK_ENTRY (game->bid_entry), "");
            gtk_widget_grab_focus (GTK_WIDGET (game->message_view));
-
            return TRUE;
        } else {
-           return FALSE;
+           if ((event->state & GDK_CONTROL_MASK) == 0)
+               return FALSE;
+       }
+    }
+
+    if (event->state & GDK_CONTROL_MASK) {
+       switch (event->keyval) {
+       case GDK_N:
+       case GDK_n:
+       case GDK_T:
+       case GDK_t:
+           grr_game_next (game);
+           return TRUE;
+       case GDK_P:
+       case GDK_p:
+           grr_game_pass (game);
+           return TRUE;
+       case GDK_Z:
+       case GDK_z:
+           grr_game_zap (game);
+           return TRUE;
+       case GDK_B:
+       case GDK_b:
+           grr_board_view_set_active_robot (game->board_view, RR_ROBOT_BLUE);
+           return TRUE;
+       case GDK_G:
+       case GDK_g:
+           grr_board_view_set_active_robot (game->board_view, RR_ROBOT_GREEN);
+           return TRUE;
+       case GDK_R:
+       case GDK_r:
+           grr_board_view_set_active_robot (game->board_view, RR_ROBOT_RED);
+           return TRUE;
+       case GDK_Y:
+       case GDK_y:
+           grr_board_view_set_active_robot (game->board_view, RR_ROBOT_YELLOW);
+           return TRUE;
+       case GDK_Q:
+       case GDK_q:
+           if (event->state & GDK_CONTROL_MASK) {
+               gtk_main_quit ();
+           }
+           return TRUE;
        }
     }
 
     switch (event->keyval) {
-    case GDK_N:
-    case GDK_n:
-    case GDK_T:
-    case GDK_t:
-       grr_game_next (game);
-       break;
-    case GDK_P:
-    case GDK_p:
-       grr_game_pass (game);
-       break;
-    case GDK_Z:
-    case GDK_z:
-       grr_game_zap (game);
-       break;
-    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_BackSpace:
+       grr_board_view_undo (game->board_view);
+       return TRUE;
     case GDK_Up:
        grr_board_view_move_active (game->board_view, RR_DIRECTION_NORTH);
-       break;
+       return TRUE;
     case GDK_Right:
        grr_board_view_move_active (game->board_view, RR_DIRECTION_EAST);
-       break;
+       return TRUE;
     case GDK_Down:
        grr_board_view_move_active (game->board_view, RR_DIRECTION_SOUTH);
-       break;
+       return TRUE;
     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_0:
-    case GDK_1:
-    case GDK_2:
-    case GDK_3:
-    case GDK_4:
-    case GDK_5:
-    case GDK_6:
-    case GDK_7:
-    case GDK_8:
-    case GDK_9:
-        {
-           int pos = -1;
-           const gchar *key = gdk_keyval_name (event->keyval);
-           gtk_widget_grab_focus (GTK_WIDGET (game->bid_entry));
-           gtk_editable_insert_text (GTK_EDITABLE (game->bid_entry),
-                                     key, strlen (key), &pos);
-           gtk_editable_set_position (GTK_EDITABLE (game->bid_entry), -1);
-       }
-       break;
-    case GDK_space:
-    case GDK_slash:
-       gtk_widget_grab_focus (GTK_WIDGET (game->message_entry));
-       if (event->keyval == GDK_slash) {
-           int pos = -1;
-           gtk_editable_insert_text (GTK_EDITABLE (game->message_entry),
-                                     "/", 1, &pos);
-           gtk_editable_set_position (GTK_EDITABLE (game->message_entry), -1);
-       }
-       break;
-    case GDK_Q:
-    case GDK_q:
-       if (event->state & GDK_CONTROL_MASK) {
-           gtk_main_quit ();
-       }
-       break;
+       return TRUE;
+    case GDK_Control_L:
+    case GDK_Control_R:
+       return TRUE;
     }
 
-    return TRUE;
+    gtk_widget_grab_focus (GTK_WIDGET (game->message_entry));
+    return FALSE;
 }
 
 /* XXX: Messy, messy. I can't seem to make up my mind whether client
@@ -484,7 +462,7 @@ grr_game_pass (grr_game_t *game)
     if (game->state == RR_GAMESTATE_SHOW)
        rr_client_pass (game->client);
     else
-       rr_client_revoke (game->client);
+       rr_client_abandon (game->client);
 }
 
 static void
@@ -502,10 +480,7 @@ grr_game_next (grr_game_t *game)
     if (game->client == NULL)
        return;
 
-    if (game->state == RR_GAMESTATE_DONE)
-       rr_client_turn (game->client);
-    else
-       rr_client_abandon (game->client);
+    rr_client_turn (game->client);
 }
 
 static void
@@ -529,35 +504,6 @@ grr_game_next_callback (GtkWidget *widget,
     grr_game_next (game);
 }
 
-static void
-grr_game_bid_entry_callback (GtkWidget *widget,
-                            grr_game_t *game)
-{
-    const gchar *bid_text;
-    char *end;
-    long bid;
-
-    if (game->client == NULL)
-       return;
-
-    bid_text = gtk_entry_get_text (GTK_ENTRY (game->bid_entry));
-
-    if (bid_text && bid_text[0]) {
-       bid = strtol (bid_text, &end, 10);
-       if (*end != '\0' && ! isspace (*end)) {
-           grr_game_printf (game, "\nInvalid bid value: %s", bid_text);
-       } else {
-           if (bid == 0)
-               rr_client_revoke (game->client);
-           else
-               rr_client_bid (game->client, bid);
-       }
-    }
-    
-    gtk_entry_set_text (GTK_ENTRY (game->bid_entry), "");
-    gtk_widget_grab_focus (GTK_WIDGET (game->message_view));
-}
-
 static void
 grr_game_message_entry_callback (GtkWidget *widget,
                                 grr_game_t *game)
@@ -565,6 +511,8 @@ grr_game_message_entry_callback (GtkWidget *widget,
     rr_status_t status;
     const gchar *entry_text;
     char **response;
+    char *end;
+    long bid;
     int i;
 
     if (game->client == NULL)
@@ -573,7 +521,13 @@ grr_game_message_entry_callback (GtkWidget *widget,
     entry_text = gtk_entry_get_text (GTK_ENTRY (game->message_entry));
 
     if (entry_text && entry_text[0]) {
-       if (entry_text[0] == '/') {
+       bid = strtol (entry_text, &end, 10);
+       if (*end == '\0' || isspace (*end)) {
+           if (bid == 0)
+               rr_client_revoke (game->client);
+           else
+               rr_client_bid (game->client, bid);
+       } else  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));
@@ -663,8 +617,6 @@ grr_game_start_gui (grr_game_t *game, const char *user)
     GtkWidget *window;
     GtkWidget *message_view;
     GtkWidget *message_entry;
-    GtkWidget *bid_entry;
-    GtkWidget *bid_button;
     GtkWidget *pass_button;
     GtkWidget *zap_button;
     GtkWidget *next_button;
@@ -742,29 +694,10 @@ grr_game_start_gui (grr_game_t *game, const char *user)
                              (gpointer) game);
        }
        gtk_widget_show (hbox);
-           
+
        hbox = gtk_hbox_new (FALSE, 1);
        gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
        {
-           bid_button = gtk_button_new_with_label ("Bid:");
-           gtk_box_pack_start (GTK_BOX (hbox), bid_button,
-                               FALSE, FALSE, 1);
-           gtk_widget_show (bid_button);
-           g_signal_connect (G_OBJECT (bid_button), "clicked",
-                             G_CALLBACK (grr_game_bid_entry_callback),
-                             (gpointer) game);
-
-           game->bid_entry = gtk_entry_new ();
-           bid_entry = game->bid_entry;
-           gtk_entry_set_max_length (GTK_ENTRY (bid_entry), 3);
-           gtk_entry_set_width_chars (GTK_ENTRY (bid_entry), 4);
-           gtk_box_pack_start (GTK_BOX (hbox), bid_entry,
-                               FALSE, FALSE, 0);
-           gtk_widget_show (bid_entry);
-           g_signal_connect (G_OBJECT (bid_entry), "activate",
-                             G_CALLBACK (grr_game_bid_entry_callback),
-                             (gpointer) game);
-
            pass_button = gtk_button_new_with_label ("Pass");
            gtk_box_pack_start (GTK_BOX (hbox), pass_button,
                                FALSE, FALSE, 1);