}
}
-GtkWidget*
+grr_board_view_t *
grr_board_view_new (rr_board_t *board)
{
grr_board_view_t *view;
grr_board_view_update (view);
- return GTK_WIDGET (view);
+ return view;
}
void
view->client = client;
}
+void
+grr_board_view_set_active_robot (grr_board_view_t *view, rr_robot_t robot)
+{
+ g_return_if_fail (view != NULL);
+
+ view->active_robot = robot;
+}
+
+void
+grr_board_view_move_active (grr_board_view_t *view, rr_direction_t dir)
+{
+ if (view->client) {
+ rr_client_move (view->client, view->active_robot, dir);
+ } else {
+ rr_board_move (view->board, view->active_robot, dir);
+ gtk_widget_queue_draw (GTK_WIDGET (view));
+ }
+}
+
+void
+grr_board_view_undo (grr_board_view_t *view)
+{
+ if (view->client) {
+ rr_client_undo (view->client);
+ } else {
+ rr_board_undo (view->board);
+ gtk_widget_queue_draw (GTK_WIDGET (view));
+ }
+}
+
static void
grr_board_view_destroy (GtkObject *object)
{
}
/* Draw goal target in center of board */
- XrSave (xrs);
- {
+ /* XXX: Not a perfect heuristic. Should check for the vacant box too. */
+ if (view->board_width == 16 && view->board_height == 16) {
+ XrSave (xrs);
XrTranslate (xrs,
(view->board_width / 2 - 1) * view->cell_width,
(view->board_height / 2 - 1) * view->cell_height);
grr_board_view_draw_cell (view, xrs, goal_target, goal_target,
view->cell_width * 2, view->cell_height * 2);
+ XrRestore (xrs);
}
- XrRestore (xrs);
/* Draw walls */
for (j=0; j < view->board_height; j++) {
*grid_y = (pointer_y - view->board_pad_y) / view->cell_height;
}
-
static gint
grr_board_view_button_press (GtkWidget *widget,
- GdkEventButton *event)
+ GdkEventButton *event)
{
grr_board_view_t *view;
rr_cell_t cell;
gtk_grab_add (widget);
view->button = event->button;
- view->drag_robot = RR_CELL_GET_ROBOT (cell);
+ grr_board_view_set_active_robot (view, RR_CELL_GET_ROBOT (cell));
grr_board_view_update_mouse (view, event->x, event->y);
}
grr_board_view_pointer_coords_to_grid (view, event->x, event->y, &x, &y);
- rr_board_find_robot (view->board, view->drag_robot, &robot_x, &robot_y);
+ rr_board_find_robot (view->board, view->active_robot, &robot_x, &robot_y);
dx = x - robot_x;
dy = y - robot_y;
if (dx == 0 && dy == 0)
dir = RR_DIRECTION_SOUTH;
else
dir = RR_DIRECTION_NORTH;
-
- if (view->client)
- rr_client_move (view->client, view->drag_robot, dir);
- return FALSE;
+ grr_board_view_move_active (view, dir);
+
+ return FALSE;
}
static gint
g_return_if_fail (view != NULL);
g_return_if_fail (GRR_IS_BOARD_VIEW (view));
- /* XXX: Should draw a robot here */
+ /* XXX: Perhaps should draw a robot here */
}
static void
#include <string.h>
#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
#include "grr_board_view.h"
#include "grr_util.h"
rr_board_t *board;
GtkWidget *window;
- GtkWidget *board_view;
+ grr_board_view_t *board_view;
GtkWidget *command_entry;
GtkTextBuffer *message_buffer;
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);
}
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));
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);
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)
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);
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);
}
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 ();