From: Carl Worth Date: Tue, 11 Nov 2003 15:51:53 +0000 (+0000) Subject: * src/grrobot.c (grr_game_read_notices): Exit cleanly: need to X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=94802efc6fe8481ba43c379b57a038d6d415ce4d;p=grrobot * 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. --- diff --git a/ChangeLog b/ChangeLog index 4836baa..1cd8b52 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2003-11-11 Carl Worth + + * 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 * src/grrobot.c (grr_game_read_notices): Call new board_view timer diff --git a/src/grr_board_view.c b/src/grr_board_view.c index 8d85988..6a18441 100644 --- a/src/grr_board_view.c +++ b/src/grr_board_view.c @@ -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); } + diff --git a/src/grr_board_view.h b/src/grr_board_view.h index 92cf981..948d8a4 100644 --- a/src/grr_board_view.h +++ b/src/grr_board_view.h @@ -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, diff --git a/src/grrobot.c b/src/grrobot.c index 8df5b98..386a163 100644 --- a/src/grrobot.c +++ b/src/grrobot.c @@ -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);