]> git.cworth.org Git - grrobot/blob - src/grrobot.c
Initial revision
[grrobot] / src / grrobot.c
1 /* grrobot - Ricochet Robot using GTK+ and Xr
2  *
3  * Copyright © 2003 Carl Worth
4  *
5  * Permission to use, copy, modify, distribute, and sell this software
6  * and its documentation for any purpose is hereby granted without
7  * fee, provided that the above copyright notice appear in all copies
8  * and that both that copyright notice and this permission notice
9  * appear in supporting documentation, and that the name of Carl Worth
10  * not be used in advertising or publicity pertaining to distribution
11  * of the software without specific, written prior permission.
12  * Carl Worth makes no representations about the suitability of this
13  * software for any purpose.  It is provided "as is" without express
14  * or implied warranty.
15  * 
16  * CARL WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
18  * NO EVENT SHALL CARL WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
20  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
21  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23  *
24  * Author: Carl Worth <carl@theworths.org>
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <gtk/gtk.h>
34
35 #include "grr_board_view.h"
36 #include "args.h"
37
38 typedef struct grr_game {
39     rr_client_t *client;
40     rr_board_t *board;
41
42     GtkWidget *window;
43     GtkWidget *board_view;
44     GtkTextBuffer *message_buffer;
45     GtkWidget *message_view;
46     GtkWidget *command_entry;
47 } grr_game_t;
48
49 static int
50 do_gui (grr_game_t *game);
51
52 void
53 game_callback (gpointer data,
54                gint fd,
55                GdkInputCondition condition);
56
57 int 
58 main (int argc, char **argv)
59 {
60     args_t args;
61     rr_status_t status;
62     grr_game_t game;
63
64     char *diagram;
65
66     gtk_init (&argc, &argv);
67     
68     args_parse (&args, argc, argv);
69
70     game.client = rr_client_create (args.host, args.port, args.user);
71     if (game.client == NULL) {
72         fprintf (stderr, "Failed connecting to %s:%s as %s\n",
73                  args.host, args.port, args.user);
74         return 1;
75     }
76
77     status = rr_client_join (game.client, args.game);
78     if (status == RR_STATUS_NO_GAME) {
79         status = rr_client_new (game.client, args.game);
80     }
81
82     game.board = rr_board_create (16, 16);
83
84     gdk_input_add (rr_client_fd (game.client),
85                    GDK_INPUT_READ,
86                    game_callback,
87                    &game);
88
89     rr_client_show (game.client, &diagram);
90     rr_board_parse (game.board, diagram);
91     free (diagram);
92
93     return do_gui (&game);
94 }
95
96 void
97 game_callback (gpointer data,
98                gint fd,
99                GdkInputCondition condition)
100 {
101     grr_game_t *game = data;
102     rr_board_t *board = game->board;
103     rr_status_t status;
104     char **notice_s;
105     rr_notice_t *notice;
106
107     while (rr_client_notice_pending (game->client)) {
108         status = rr_client_next_notice (game->client, &notice_s);
109         if (status) {
110             fprintf (stderr, "Error during rr_client_notice: %s\n",
111                      rr_status_str (status));
112             gtk_exit (1);
113             return;
114         }
115         notice = rr_client_parse_notice (game->client, notice_s);
116         switch (notice->type) {
117         case RR_NOTICE_USER:
118         case RR_NOTICE_QUIT:
119         case RR_NOTICE_GAME:
120         case RR_NOTICE_DISPOSE:
121         case RR_NOTICE_MESSAGE:
122         case RR_NOTICE_GAMESTATE:
123         case RR_NOTICE_TURN:
124         case RR_NOTICE_JOIN:
125         case RR_NOTICE_WATCH:
126         case RR_NOTICE_PART:
127         case RR_NOTICE_BID:
128         case RR_NOTICE_REVOKE:
129         case RR_NOTICE_TIMER:
130         case RR_NOTICE_ABANDON:
131         case RR_NOTICE_NOBID:
132         case RR_NOTICE_ACTIVE:
133         case RR_NOTICE_MOVE:
134         case RR_NOTICE_UNDO:
135         case RR_NOTICE_RESET:
136         case RR_NOTICE_SCORE:
137         case RR_NOTICE_ACTIVATE:
138             /* Ignore these requests */
139             break;
140         case RR_NOTICE_POSITION:
141             rr_board_position (board, notice->u.position.robot,
142                                notice->u.position.x, notice->u.position.y);
143             gtk_widget_queue_draw (GTK_WIDGET (game->window));
144             break;
145         }
146         free (notice);
147     }
148 }
149
150 void
151 command_callback (GtkWidget *widget,
152                   grr_game_t *game)
153 {
154     const gchar *entry_text;
155     char **response;
156
157     entry_text = gtk_entry_get_text (GTK_ENTRY (widget));
158     rr_client_request (game->client, entry_text, &response);
159     gtk_entry_set_text (GTK_ENTRY (widget), "");
160     gtk_text_buffer_insert_at_cursor (game->message_buffer, entry_text, -1);
161
162 /* XXX: Huh? Why is this triggering valgrind?
163     free (response);
164 */
165
166 }
167
168 static int
169 do_gui (grr_game_t *game)
170 {
171     GtkWidget *board_frame;
172     GtkWidget *vpaned;
173     GtkWidget *sw;
174     GtkWidget *vbox;
175     GtkWidget *window;
176     GtkWidget *message_view;
177     GtkWidget *command_entry;
178
179     game->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
180     window = game->window;
181
182     gtk_window_set_title (GTK_WINDOW (window), "Ricochet Robot");
183     gtk_window_set_default_size (GTK_WINDOW (window), 512, 512);
184     
185     g_signal_connect (G_OBJECT (window), "destroy",
186                       G_CALLBACK (exit), NULL);
187     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
188
189     vpaned = gtk_vpaned_new ();
190     gtk_container_set_border_width (GTK_CONTAINER (vpaned), 5);
191     gtk_container_add (GTK_CONTAINER (window), vpaned);
192     {
193         board_frame = gtk_aspect_frame_new (NULL, 0.5, 0.5, 1.0, FALSE);
194         gtk_paned_pack1 (GTK_PANED (vpaned), board_frame, TRUE, TRUE);
195         {
196             game->board_view = grr_board_view_new (game->board);
197
198             gtk_container_add (GTK_CONTAINER (board_frame), game->board_view);
199             gtk_widget_show (game->board_view);
200         }
201         gtk_widget_show (board_frame);
202
203         vbox = gtk_vbox_new (FALSE, 1);
204         gtk_paned_pack2 (GTK_PANED (vpaned), vbox, FALSE, TRUE);
205         {
206             sw = gtk_scrolled_window_new (NULL, NULL);
207             gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
208                                             GTK_POLICY_NEVER,
209                                             GTK_POLICY_AUTOMATIC);
210             gtk_container_add (GTK_CONTAINER (vbox), sw);
211             gtk_widget_show (sw);
212
213             game->message_buffer = gtk_text_buffer_new (NULL);
214             game->message_view = gtk_text_view_new_with_buffer (game->message_buffer);
215             message_view = game->message_view;
216             gtk_text_view_set_editable (GTK_TEXT_VIEW (message_view), FALSE);
217             gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (message_view), FALSE);
218             gtk_container_add (GTK_CONTAINER (sw), message_view);
219             gtk_widget_show (message_view);
220
221             game->command_entry = gtk_entry_new ();
222             command_entry = game->command_entry;
223             gtk_container_add (GTK_CONTAINER (vbox), command_entry);
224             gtk_widget_show (command_entry);
225             g_signal_connect (G_OBJECT (command_entry), "activate",
226                               G_CALLBACK (command_callback),
227                               (gpointer) game);
228         }
229         gtk_widget_show (vbox);
230     }
231     gtk_widget_show (vpaned);
232
233     gtk_widget_show (window);
234     
235     gtk_main ();
236     
237     return 0;
238 }