5 #include <librsvg/rsvg.h>
6 #include <librsvg/rsvg-cairo.h>
9 * TILE_NUMBER_X_OFFSET = 3
11 * || TILE_NUMBER_WIDTH = 34
13 * || | TILE_WIDTH = 40
16 * +-----+ - TILE_NUMBER_Y_OFFSET = 3 -
19 * || || TILE_NUMBER_HEIGHT = 24 |
21 * | _ | _ |-TILE_HEIGHT = 50
23 * || || TILE_SUN_HEIGHT = 20 |
25 * | | TILE_SUN_Y_OFFSET = 3 |
27 * || | TILE_SUN_WIDTH = 20
29 * || TILE_SUN_X_OFFSET = 10
32 #define TILE_HEIGHT 50
34 #define TILE_NUMBER_X_OFFSET 3
35 #define TILE_NUMBER_Y_OFFSET 3
36 #define TILE_NUMBER_WIDTH 34
37 #define TILE_NUMBER_HEIGHT 24
39 #define TILE_SUN_X_OFFSET 10
40 #define TILE_SUN_Y_OFFSET 3
41 #define TILE_SUN_WIDTH 20
42 #define TILE_SUN_HEIGHT 20
44 #define FATAL_ERROR(msg) \
45 do { fprintf (stderr, "Error: %s\n", msg); exit (1); } while (0)
47 char *colors[] = {"Black", "Blue", "Red", "Yellow"};
49 typedef enum {BLACK, BLUE, RED, YELLOW} color_t;
60 #define DECK_MAX_TILES 104
63 tile_t tiles[DECK_MAX_TILES];
67 #define TILE_GROUP_MAX_TILES DECK_MAX_TILES
69 typedef struct tile_group {
70 tile_t tiles[TILE_GROUP_MAX_TILES];
74 #define BOARD_MAX_TILE_GROUPS (DECK_MAX_TILES / 3)
76 typedef struct board {
77 tile_group_t groups[BOARD_MAX_TILE_GROUPS];
81 typedef struct player {
85 typedef struct selection_box {
86 int x1, x2, y1, y2, visible;
89 #define GAME_MAX_PLAYERS 4
90 #define GAME_WINDOW_DEFAULT_WIDTH 800
91 #define GAME_WINDOW_DEFAULT_HEIGHT 600
93 typedef struct state {
94 player_t players[GAME_MAX_PLAYERS];
100 player_t players[GAME_MAX_PLAYERS];
104 selection_box_t selection_box;
106 RsvgHandle *blanktile;
107 RsvgHandle *selectedtile;
108 RsvgHandle *ownedtile;
111 tile_t *current_tile;
116 int click_x, click_y;
117 int release_x, release_y; /*Currently unused*/
120 static void selection_box_init(selection_box_t *box)
129 static void selection_box_draw(selection_box_t *box, cairo_t *cr)
131 cairo_rectangle (cr, box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1);
132 cairo_set_source_rgba(cr, 0.0, 0.1, 0.2, 0.5);
136 static void tile_init (tile_t *tile, color_t color, int number)
139 tile->number = number;
146 static void tile_set_x_y (tile_t *tile, int x, int y)
152 static void tile_print(tile_t tile)
154 printf("%6s %2d\n", colors[tile.color], tile.number + 1);
157 static void tile_draw(game_t *game, tile_t *tile, cairo_t *cr, GdkRegion *region)
159 char number_string[3];
161 GdkRectangle rectangle;
163 rectangle.x = tile->x - 1;
164 rectangle.y = tile->y - 1;
165 rectangle.width = TILE_WIDTH + 2;
166 rectangle.height = TILE_HEIGHT + 2;
167 if (gdk_region_rect_in (region, &rectangle) == GDK_OVERLAP_RECTANGLE_OUT)
170 len = snprintf (number_string, 3, "%d", tile->number + 1);
171 if (len < 0 || len >= 3)
172 FATAL_ERROR ("snprintf failed");
175 cairo_translate(cr, tile->x, tile->y);
178 rsvg_handle_render_cairo (game->selectedtile, cr);
180 rsvg_handle_render_cairo (game->ownedtile, cr);
182 rsvg_handle_render_cairo (game->blanktile, cr);
184 if (tile->color == BLACK)
185 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
186 if (tile->color == BLUE)
187 cairo_set_source_rgb (cr, 0.0, 0.0, 1.0);
188 if (tile->color == RED)
189 cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
190 if (tile->color == YELLOW)
191 cairo_set_source_rgb (cr, 1.0, .843, 0.0);
192 if (tile->number + 1 > 9)
193 cairo_move_to (cr, 1, 25);
195 cairo_move_to (cr, 10, 25);
196 cairo_set_font_size(cr, 25);
197 cairo_show_text (cr, number_string);
202 static void tile_group_init(tile_group_t *tile_group)
204 tile_group->num_tiles = 0;
207 static void board_init(board_t *board)
210 board->num_groups = 0;
212 for (i = 0; i <= BOARD_MAX_TILE_GROUPS; ++i)
214 tile_group_init(&board->groups[i]);
218 static void player_init(player_t *player)
220 tile_group_init(&player->hand);
224 /* If tile_one < tile_two, then return value will be negative
225 if they are equal, 0 will be returned,
226 if tile_one > tile_two, then return value will be positive */
227 static int tile_compare(const void *one, const void *two)
229 const tile_t *tile_one = one;
230 const tile_t *tile_two = two;
231 return tile_one->number - tile_two->number; //Sort lowest to highest
234 static int int_compare(const void *vx, const void *vy)
236 const int *x = vx, *y = vy;
237 return *y - *x; //Sort highest to lowest
241 static int tile_in_box(game_t *game, tile_t *tile)
247 static int tile_group_is_run_one(tile_group_t *tile_group)
250 qsort (&tile_group->tiles[0], tile_group->num_tiles,
251 sizeof (tile_t), tile_compare);
253 if (tile_group->num_tiles > 13 || tile_group->num_tiles < 3)
255 printf("fail run - invalid num tiles; ");
258 for (i = 0; i < tile_group->num_tiles - 1; ++i)
260 if(tile_group->tiles[i].color != tile_group->tiles[i + 1].color)
262 printf("fail run - colors don't match; ");
265 if( tile_group->tiles[i].number != tile_group->tiles[i + 1].number -1 &&
266 i+1 != tile_group->num_tiles)
268 printf("fail run - invalid number sequence; ");
276 static int tile_group_is_run_two(tile_group_t *tile_group)
279 int lowest = 14, highest = 0;
282 /* By definition, a run must have at least 3 tiles. Also, it's
283 * impossible for any group of tiles with more than 13 tiles to be
284 * a run, (there are only 13 unique numbers so a group with more
285 * than 13 tiles must have some duplicates).
287 if (tile_group->num_tiles < 3 || tile_group->num_tiles > 13)
292 /* Loop through all tiles in the group, ensuring that they are all
293 * the same color and finding the highest and lowest number in the
295 run_color = tile_group->tiles[0].color;
297 for (i = 0; i < tile_group->num_tiles; i++)
299 if (tile_group->tiles[i].color != run_color)
301 if (tile_group->tiles[i].number > highest)
303 highest = tile_group->tiles[i].number;
305 if (tile_group->tiles[i].number < lowest)
307 lowest = tile_group->tiles[i].number;
311 /* For a run, the difference between the highest and lowest tiles
312 * will always be one less than the number of tiles in the
313 * group. If not then we know it's not a run.
315 if (highest - lowest != tile_group->num_tiles - 1)
320 /* XXX: There's a bug here. We're guessing that at this point
321 * anything we're looking at must be a run. This would be correct
322 * if there were no duplicate tiles, but since there are
323 * duplicates this us quite broken. For example consider two
324 * sequences of entirely red tiles:
326 * This is a run: 1, 2, 3, 4
327 * But this is not: 1, 3, 4, 4
329 * As currently written, this function will consider both of these
330 * groups to be a run. One possible fix is to throw away the
331 * highest - lowest heuristic and instead simply sort the tiles up
332 * front and ensure the difference between each adjacent pair is
338 static int tile_group_is_set(tile_group_t *tile_group)
341 color_t seen_color[4];
342 for (i = 0; i < 4; i++)
345 if (tile_group->num_tiles > 4 || tile_group->num_tiles < 3)
347 printf("fail set - invalid num tiles; ");
350 for (i = 0; i <= tile_group->num_tiles - 1; ++i)
352 if (tile_group->tiles[i].number != tile_group->tiles[i + 1].number &&
353 i+1 != tile_group->num_tiles)
355 printf("fail set - numbers don't match; ");
358 seen_color[tile_group->tiles[i].color] += 1;
360 for (i = 0; i < 4; i++)
362 if (seen_color[i] > 1)
364 printf("fail set - repeat color; ");
371 static gboolean board_valid(board_t *board)
374 gboolean valid = TRUE;
375 for (i = 0; i < board->num_groups; ++i)
377 if (!(tile_group_is_run_one(&board->groups[i])) &&
378 !(tile_group_is_set(&board->groups[i])))
386 static void deck_deal(game_t *game, deck_t *deck)
392 printf ("How many players(1-4) should I deal in? ");
393 game->num_players = getchar();
394 if (game->num_players == EOF)
396 printf ("\nGoodbye.\n");
400 game->num_players -= '0';
402 for (i = 0; i < game->num_players; ++i)
404 for (j = 0; j < 14; ++j)
406 rand_tile = ((deck->num_tiles + 1.0) * rand()) / (RAND_MAX + 1.0);
407 temp = deck->tiles[rand_tile];
408 deck->tiles[rand_tile] = deck->tiles[deck->num_tiles - 1];
409 game->players[i].hand.tiles[j] = temp;
410 game->players[i].hand.tiles[j].owned = 1;
411 deck->num_tiles -= 1;
412 game->players[i].hand.num_tiles += 1;
415 printf ("Game dealt for %d player(s)\n", game->num_players);
418 static void deck_init(deck_t *deck)
422 for (h = 0; h <= 1; ++h)
424 for (i = 0; i <= 3; ++i)
426 for (j = 0; j <= 12; ++j)
428 tile_init (&deck->tiles[deck->num_tiles++], i, j);
429 printf ("There are %d tiles in the deck\n", deck->num_tiles);
435 static void deck_shuffle(deck_t *deck)
440 for (last = deck->num_tiles; last > 0; --last)
442 rand_tile = ((last + 1.0) * rand()) / (RAND_MAX + 1.0);
443 temp = deck->tiles[rand_tile];
444 deck->tiles[rand_tile] = deck->tiles[last - 1];
445 deck->tiles[last - 1] = temp;
449 static void deck_print(deck_t *deck)
452 for (h = 0; h < 2; ++h)
454 for (i = 0; i < 4; ++i)
456 for (j = 0; j < 13; ++j)
458 tile_print(deck->tiles[j + (i * 13) + (h * 52)]);
462 printf ("There are %d tiles in the deck\n" , deck->num_tiles);
465 static void deck_spread(deck_t *deck)
468 for (i = 0; i < 8; i++)
470 for (j = 0; j < 13; j++)
472 deck->tiles[j + (i * 13)].x = j * 50;
473 deck->tiles[j + (i * 13)].y = i * 60;
478 static void deck_draw(game_t *game, cairo_t *cr, GdkRegion *region)
481 for (i = 0; i < game->deck.num_tiles; i++)
483 tile_draw(game, &game->deck.tiles[i], cr, region);
487 static void board_draw(game_t *game, cairo_t *cr, GdkRegion *region)
490 for (i = 0; i < game->board.num_groups; i++)
492 for (j = 0; j < game->board.groups[i].num_tiles; j++)
494 tile_draw(game, &game->board.groups[i].tiles[j], cr, region);
495 //tile_print(game->board.groups[i].tiles[j]);
500 static void board_print(game_t *game)
503 printf("\tBegin board print\n");
504 for (i = 0; i < game->board.num_groups; i++)
506 printf("\tBegin group %d\n", i);
507 for (j = 0; j < game->board.groups[i].num_tiles; j++)
509 tile_print(game->board.groups[i].tiles[j]);
511 printf("\tEnd group %d\n", i);
515 static void hand_print(game_t *game, int player)
518 for (i = 0; i < game->players[player].hand.num_tiles; i++)
520 tile_print(game->players[player].hand.tiles[i]);
524 static void hand_draw(game_t *game, int player, cairo_t *cr, GdkRegion *region, GtkWidget *widget)
527 int width = widget->allocation.width;
528 // int width = GAME_WINDOW_DEFAULT_WIDTH;
529 int height = widget->allocation.height;
530 // int height = GAME_WINDOW_DEFAULT_HEIGHT;
531 int num_tiles = game->players[player].hand.num_tiles;
532 for (i = 0; i < num_tiles; i++)
534 tile_set_x_y(&game->players[player].hand.tiles[i],
535 ((width/num_tiles)) * i, (height - TILE_HEIGHT - 6) );
537 for (i = 0; i < game->players[player].hand.num_tiles; i++)
539 tile_draw(game, &game->players[player].hand.tiles[i], cr, region);
543 static void save_state(game_t *game)
545 game->state.board = game->board;
546 game->state.deck = game->deck;
547 //game->state.players = game->players;
550 static void restore_state(game_t *game)
552 game->board = game->state.board;
553 game->deck = game->state.deck;
554 //game->players = game->state.players;
557 static void game_init(game_t *game)
560 GError *error = NULL;
562 game->num_players = 0;
564 for (i = 0; i < GAME_MAX_PLAYERS; ++i)
566 player_init(&game->players[i]);
567 game->num_players += 1;
569 game->current_player = 0;
571 selection_box_init(&game->selection_box);
572 board_init(&game->board);
573 deck_init(&game->deck);
574 deck_shuffle(&game->deck);
576 game->selectedtile = rsvg_handle_new_from_file ("tiles/selected_tile.svg", &error);
578 FATAL_ERROR (error->message);
580 game->ownedtile = rsvg_handle_new_from_file ("tiles/owned_tile.svg", &error);
582 FATAL_ERROR (error->message);
584 game->blanktile = rsvg_handle_new_from_file ("tiles/blank_tile.svg", &error);
586 FATAL_ERROR (error->message);
588 // game->current_tile = game->deck.num_tiles - 1;
589 game->current_tile = &game->deck.tiles[0];
590 game->select_mode = 1;
591 game->drag_group_mode = 0;
593 game->diff_x = game->diff_y = 0;
596 static gboolean on_expose_event (GtkWidget *widget, GdkEventExpose *event, game_t *game)
600 cr = gdk_cairo_create (widget->window);
602 deck_draw(game, cr, event->region);
603 board_draw(game, cr, event->region);
605 if (game->selection_box.visible)
606 selection_box_draw(&game->selection_box, cr);
608 hand_draw(game, game->current_player, cr, event->region, widget);
609 //hand_draw(game, 0, cr, event->region);
616 static gboolean on_configure_event (GtkWidget *widget, GdkEventConfigure *event, game_t *game)
620 cr = gdk_cairo_create (event->window);
622 hand_draw(game, game->current_player, cr, event->window, widget);
623 // gtk_widget_queue_draw(widget);
626 static gboolean on_key_press_event (GtkWidget *widget, GdkEventKey *event, game_t *game)
628 player_t *player = &game->players[game->current_player];
630 cr = gdk_cairo_create (widget->window);
631 printf ("You pressed key %d\n", event->keyval);
633 if (event->keyval == 100) //HIT "d"
635 //Draw(take) top tile from deck and put in hand
636 if (game->deck.num_tiles > 0)
638 tile_t top_tile = game->deck.tiles[game->deck.num_tiles-1];
639 game->deck.num_tiles--;
640 player->hand.tiles[player->hand.num_tiles] = top_tile;
641 player->hand.tiles[player->hand.num_tiles].owned=1;
642 player->hand.num_tiles++;
643 gtk_widget_queue_draw(widget);
646 else if (event->keyval == 65293) //HIT ENTER
649 printf ("\tEnd of player %d's turn\n", game->current_player+1);
650 if (game->current_player == game->num_players-1)
651 game->current_player = 0;
653 game->current_player += 1;
654 gtk_widget_queue_draw(widget);
656 else if (event->keyval == 65307) //HIT ESCAPE
659 printf ("\tChanges Reverted\n");
660 gtk_widget_queue_draw(widget);
662 else if (event->keyval == 65474) //HIT "F5"
664 gtk_widget_queue_draw(widget);
666 else if (event->keyval == 65505 || event->keyval == 65506)
667 game->drag_group_mode = 1;
671 static gboolean on_button_press_event (GtkWidget *widget, GdkEventButton *event, game_t *game)
673 int i, tile_x, tile_y;
675 player_t *curr_player = &game->players[0];
677 /*Handle tiles in player's hand */
678 for (i = 0; i < curr_player->hand.num_tiles; i++)
680 curr_tile = &curr_player->hand.tiles[i];
681 if (curr_tile->selected)
683 curr_tile->selected = 0;
684 gtk_widget_queue_draw_area (widget, curr_tile->x - 1, curr_tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
686 tile_x = curr_player->hand.tiles[i].x;
687 tile_y = curr_player->hand.tiles[i].y;
688 if (event->x >= tile_x && event->x <= (tile_x + TILE_WIDTH) &&
689 event->y >= tile_y && event->y <= (tile_y + TILE_HEIGHT) )
691 game->select_mode = 0;
692 game->current_tile = curr_tile;
693 if (!curr_tile->selected)
694 curr_tile->selected = 1;
696 curr_tile->selected = 0;
697 gtk_widget_queue_draw_area (widget, curr_tile->x - 1, curr_tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
698 game->diff_x = event->x - tile_x;
699 game->diff_y = event->y - tile_y;
703 /*Handle tiles in deck */
704 for (i = 0; i < game->deck.num_tiles; i++)
706 curr_tile = &game->deck.tiles[i];
707 if (curr_tile->selected)
709 curr_tile->selected = 0;
710 gtk_widget_queue_draw_area (widget, curr_tile->x - 1, curr_tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
713 tile_x = game->deck.tiles[i].x;
714 tile_y = game->deck.tiles[i].y;
715 if (event->x >= tile_x && event->x <= (tile_x + TILE_WIDTH) &&
716 event->y >= tile_y && event->y <= (tile_y + TILE_HEIGHT) )
718 game->select_mode = 0;
720 // game->current_tile = i;
721 game->current_tile = curr_tile;
723 //delete_this? curr_tile = &game->deck.tiles[game->current_tile];
724 if (!curr_tile->selected)
725 curr_tile->selected = 1;
727 curr_tile->selected = 0;
728 gtk_widget_queue_draw_area (widget, curr_tile->x - 1, curr_tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
730 game->diff_x = event->x - tile_x;
731 game->diff_y = event->y - tile_y;
734 if (game->select_mode)
736 // game->deck.tiles[game->current_tile].selected = 0;
737 game->current_tile->selected = 0;
738 gtk_widget_queue_draw_area (widget, curr_tile->x - 1, curr_tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
740 game->selection_box.visible = 1;
741 /*These next two lines appear to be dead
742 game->click_x = event->x;
743 game->click_y = event->y;*/
745 game->selection_box.x1 = event->x;
746 game->selection_box.x2 = event->x;
747 game->selection_box.y1 = event->y;
748 game->selection_box.y2 = event->y;
753 static gboolean on_button_release_event (GtkWidget *widget, GdkEventButton *event, game_t *game)
755 if (game->select_mode)
757 game->select_mode = 0;
758 selection_box_t *box;
759 box = &game->selection_box;
761 int x_min = MIN(box->x1, box->x2);
762 int x_max = MAX(box->x1, box->x2);
763 int y_min = MIN(box->y1, box->y2);
764 int y_max = MAX(box->y1, box->y2);
765 int width = abs(box->x2 - box->x1);
766 int height = abs(box->y2 - box->y1);
769 gtk_widget_queue_draw_area (widget, x_min, y_min, width, height);
774 int i, tile_x, tile_y, tile_x2, tile_y2;
775 int tiles_to_remove[game->deck.num_tiles];
776 for (i = 0; i < game->deck.num_tiles; i++)
778 tile_x = game->deck.tiles[i].x;
779 tile_y = game->deck.tiles[i].y;
780 tile_x2 = tile_x + TILE_WIDTH;
781 tile_y2 = tile_y + TILE_HEIGHT;
782 if (/*If top-left corner*/
783 (tile_x >= x_min && tile_x <= x_max &&
784 tile_y >= y_min && tile_y <= y_max) ||
785 /*or bottom-right corner*/
786 (tile_x2 >= x_min && tile_x2 <= x_max &&
787 tile_y2 >= y_min && tile_y2 <= y_max) ||
788 /*or bottom-left corner*/
789 (tile_x >= x_min && tile_x <= x_max &&
790 tile_y2 >= y_min && tile_y2 <= y_max) ||
791 /*or top-right corner*/
792 (tile_x2 >= x_min && tile_x2 <= x_max &&
793 tile_y >= y_min && tile_y <= y_max) ||
795 (y_min >= tile_y && y_min <= tile_y2 &&
796 x_min <= tile_x && x_max >= tile_x) ||
798 (x_min >= tile_x && x_min <= tile_x2 &&
799 y_min <= tile_y && y_max >= tile_y) ||
801 (y_min >= tile_y && y_min <= tile_y2 &&
802 x_min >= tile_x && x_min <= tile_x2) ||
803 /*or bottom edge of tile selected*/
804 (x_min >= tile_x && x_min <= tile_x2 &&
805 y_min >= tile_y && y_min <= tile_y) )
807 tiles_to_remove[group.num_tiles] = i;
809 group.tiles[group.num_tiles] = game->deck.tiles[i];
813 printf("is run %d\n", tile_group_is_run_one(&group) );
814 printf("is set %d\n", tile_group_is_set(&group) );
816 qsort (tiles_to_remove, group.num_tiles, sizeof (int), int_compare);
818 for (i = 0; i < group.num_tiles; i++)
820 tile_print(group.tiles[i]);
821 gtk_widget_queue_draw_area (widget, group.tiles[i].x - 1,
822 group.tiles[i].y - 1, TILE_WIDTH + 1,
825 group.tiles[i].x = x_min + (i * (TILE_WIDTH));
826 group.tiles[i].y = y_min;
828 gtk_widget_queue_draw_area (widget, group.tiles[i].x - 1,
829 group.tiles[i].y - 1, TILE_WIDTH + 1,
832 //Remove tile from deck
833 if (tiles_to_remove[i] != game->deck.num_tiles - 1)
834 game->deck.tiles[tiles_to_remove[i]] = game->deck.tiles[game->deck.num_tiles-1];
835 game->deck.num_tiles--;
838 if (group.num_tiles > 0)
840 game->board.groups[game->board.num_groups] = group;
841 game->board.num_groups++;
844 printf("\nBut is the board valid?\t\t%s\n", board_valid(&game->board) ? "yes" : "no");
846 game->select_mode = 1;
851 static gboolean on_button_motion_event (GtkWidget *widget, GdkEventMotion *event,
852 game_t *game, cairo_t *cr)
854 if (game->select_mode)
856 selection_box_t *box;
857 box = &game->selection_box;
860 int x_min = MIN(box->x1, box->x2);
861 int x_max = MAX(box->x1, box->x2);
862 int y_min = MIN(box->y1, box->y2);
863 int y_max = MAX(box->y1, box->y2);
864 int width = abs(box->x2 - box->x1);
865 int height = abs(box->y2 - box->y1);
867 gtk_widget_queue_draw_area ( widget, x_min, y_min, width, height );
872 gtk_widget_queue_draw_area ( widget, MIN(box->x1, box->x2), MIN(box->y1, box->y2), abs(box->x2 - box->x1), abs(box->y2 - box->y1) );
874 int i, tile_x, tile_y, tile_x2, tile_y2;
876 for (i = 0; i < game->deck.num_tiles; i++)
878 curr_tile = &game->deck.tiles[i];
880 tile_x = game->deck.tiles[i].x;
881 tile_y = game->deck.tiles[i].y;
882 tile_x2 = tile_x + TILE_WIDTH;
883 tile_y2 = tile_y + TILE_HEIGHT;
884 if (/*If top-left corner*/
885 (tile_x >= x_min && tile_x <= x_max &&
886 tile_y >= y_min && tile_y <= y_max) ||
887 /*or bottom-right corner*/
888 (tile_x2 >= x_min && tile_x2 <= x_max &&
889 tile_y2 >= y_min && tile_y2 <= y_max) ||
890 /*or bottom-left corner*/
891 (tile_x >= x_min && tile_x <= x_max &&
892 tile_y2 >= y_min && tile_y2 <= y_max) ||
893 /*or top-right corner*/
894 (tile_x2 >= x_min && tile_x2 <= x_max &&
895 tile_y >= y_min && tile_y <= y_max) ||
897 (y_min >= tile_y && y_min <= tile_y2 &&
898 x_min <= tile_x && x_max >= tile_x) ||
900 (x_min >= tile_x && x_min <= tile_x2 &&
901 y_min <= tile_y && y_max >= tile_y) ||
903 (y_min >= tile_y && y_min <= tile_y2 &&
904 x_min >= tile_x && x_min <= tile_x2) ||
905 /*or bottom edge of tile selected*/
906 (x_min >= tile_x && x_min <= tile_x2 &&
907 y_min >= tile_y && y_min <= tile_y) )
909 curr_tile->selected = 1;
910 gtk_widget_queue_draw_area (widget, curr_tile->x - 1, curr_tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
915 if (curr_tile->selected)
917 curr_tile->selected = 0;
918 gtk_widget_queue_draw_area (widget, curr_tile->x - 1, curr_tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
925 if (game->drag_group_mode)
931 // tile = &game->deck.tiles[game->current_tile];
932 tile = game->current_tile;
934 /* First, invalidate the region where the tile currently is. */
935 gtk_widget_queue_draw_area (widget, tile->x - 1, tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
937 /* Then, move the tile */
938 tile->x = event->x - game->diff_x;
939 tile->y = event->y - game->diff_y;
941 /* Finally, invalidate the region where the tile is now. */
942 gtk_widget_queue_draw_area (widget, tile->x - 1, tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
947 int main(int argc, char *argv[])
954 gtk_init (&argc, &argv);
957 deck_print(&game.deck);
958 deck_spread(&game.deck);
959 deck_deal(&game, &game.deck);
961 game.state.board = game.board;
962 game.state.deck = game.deck;
963 //game->state.players = game.players;
965 //hand_print(&game, 0); //With Zero being passed, will print hand for player 1(players[0])
966 //deck_print(&game.deck);
968 /* Create a new window */
969 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
970 gtk_window_set_default_size (GTK_WINDOW (window),
971 GAME_WINDOW_DEFAULT_WIDTH,
972 GAME_WINDOW_DEFAULT_HEIGHT);
974 gtk_widget_set_events (window,
977 GDK_BUTTON_MOTION_MASK |
978 GDK_BUTTON_PRESS_MASK |
979 GDK_BUTTON_RELEASE_MASK);
981 g_signal_connect (G_OBJECT (window), "delete_event",
982 G_CALLBACK (gtk_main_quit), NULL);
983 g_signal_connect (G_OBJECT (window), "expose_event",
984 G_CALLBACK (on_expose_event), &game);
985 // g_signal_connect (G_OBJECT (window), "configure_event",
986 // G_CALLBACK (on_configure_event), &game);
987 g_signal_connect (G_OBJECT (window), "key_press_event",
988 G_CALLBACK (on_key_press_event), &game);
989 g_signal_connect (G_OBJECT (window), "button_press_event",
990 G_CALLBACK (on_button_press_event), &game);
991 g_signal_connect (G_OBJECT (window), "button_release_event",
992 G_CALLBACK (on_button_release_event), &game);
993 g_signal_connect (G_OBJECT (window), "motion_notify_event",
994 G_CALLBACK (on_button_motion_event), &game);
997 gtk_widget_show_all (window);