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;
58 int in_hand;//Draw the tile in the hand, or elsewhere on the board?
61 #define DECK_MAX_TILES 104
64 tile_t tiles[DECK_MAX_TILES];
68 #define TILE_GROUP_MAX_TILES DECK_MAX_TILES
70 typedef struct tile_group {
71 tile_t tiles[TILE_GROUP_MAX_TILES];
75 #define BOARD_MAX_TILE_GROUPS DECK_MAX_TILES
77 typedef struct board {
78 tile_group_t groups[BOARD_MAX_TILE_GROUPS];
82 typedef struct player {
86 typedef struct selection_box {
87 int x1, x2, y1, y2, visible;
90 #define GAME_MAX_PLAYERS 4
91 #define GAME_WINDOW_DEFAULT_WIDTH 800
92 #define GAME_WINDOW_DEFAULT_HEIGHT 600
94 typedef struct state {
95 player_t players[GAME_MAX_PLAYERS];
100 typedef struct game {
101 player_t players[GAME_MAX_PLAYERS];
105 selection_box_t selection_box;
107 RsvgHandle *blanktile;
108 RsvgHandle *selectedtile;
109 RsvgHandle *ownedtile;
112 tile_t *current_tile;
117 int click_x, click_y;
118 int release_x, release_y; /*Currently unused*/
121 static void selection_box_init(selection_box_t *box)
130 static void selection_box_draw(selection_box_t *box, cairo_t *cr)
132 cairo_rectangle (cr, box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1);
133 cairo_set_source_rgba(cr, 0.0, 0.1, 0.2, 0.5);
137 static void tile_init (tile_t *tile, color_t color, int number)
140 tile->number = number;
148 static void tile_set_x_y (tile_t *tile, int x, int y)
154 static void tile_print(tile_t tile)
156 printf("%6s %2d\n", colors[tile.color], tile.number + 1);
159 static void tile_draw(game_t *game, tile_t *tile, cairo_t *cr, GdkRegion *region)
161 char number_string[3];
163 GdkRectangle rectangle;
165 rectangle.x = tile->x - 1;
166 rectangle.y = tile->y - 1;
167 rectangle.width = TILE_WIDTH + 2;
168 rectangle.height = TILE_HEIGHT + 2;
169 if (gdk_region_rect_in (region, &rectangle) == GDK_OVERLAP_RECTANGLE_OUT)
172 len = snprintf (number_string, 3, "%d", tile->number + 1);
173 if (len < 0 || len >= 3)
174 FATAL_ERROR ("snprintf failed");
177 cairo_translate(cr, tile->x, tile->y);
180 rsvg_handle_render_cairo (game->selectedtile, cr);
182 rsvg_handle_render_cairo (game->ownedtile, cr);
184 rsvg_handle_render_cairo (game->blanktile, cr);
186 if (tile->color == BLACK)
187 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
188 if (tile->color == BLUE)
189 cairo_set_source_rgb (cr, 0.0, 0.0, 1.0);
190 if (tile->color == RED)
191 cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
192 if (tile->color == YELLOW)
193 cairo_set_source_rgb (cr, 1.0, .843, 0.0);
194 if (tile->number + 1 > 9)
195 cairo_move_to (cr, 1, 25);
197 cairo_move_to (cr, 10, 25);
198 cairo_set_font_size(cr, 25);
199 cairo_show_text (cr, number_string);
204 static void tile_group_init(tile_group_t *tile_group)
206 tile_group->num_tiles = 0;
209 static void board_init(board_t *board)
212 board->num_groups = 0;
214 for (i = 0; i <= BOARD_MAX_TILE_GROUPS; ++i)
216 tile_group_init(&board->groups[i]);
220 static void player_init(player_t *player)
222 tile_group_init(&player->hand);
226 /* If tile_one < tile_two, then return value will be negative
227 if they are equal, 0 will be returned,
228 if tile_one > tile_two, then return value will be positive */
229 static int tile_compare(const void *one, const void *two)
231 const tile_t *tile_one = one;
232 const tile_t *tile_two = two;
233 return tile_one->number - tile_two->number; //Sort lowest to highest
236 static int int_compare(const void *vx, const void *vy)
238 const int *x = vx, *y = vy;
239 return *y - *x; //Sort highest to lowest
243 static int tile_in_box(game_t *game, tile_t *tile)
249 static int tile_group_is_run_one(tile_group_t *tile_group)
252 qsort (&tile_group->tiles[0], tile_group->num_tiles,
253 sizeof (tile_t), tile_compare);
255 if (tile_group->num_tiles > 13 || tile_group->num_tiles < 3)
257 printf("fail run - invalid num tiles; ");
260 for (i = 0; i < tile_group->num_tiles - 1; ++i)
262 if(tile_group->tiles[i].color != tile_group->tiles[i + 1].color)
264 printf("fail run - colors don't match; ");
267 if( tile_group->tiles[i].number != tile_group->tiles[i + 1].number -1 &&
268 i+1 != tile_group->num_tiles)
270 printf("fail run - invalid number sequence; ");
278 static int tile_group_is_run_two(tile_group_t *tile_group)
281 int lowest = 14, highest = 0;
284 /* By definition, a run must have at least 3 tiles. Also, it's
285 * impossible for any group of tiles with more than 13 tiles to be
286 * a run, (there are only 13 unique numbers so a group with more
287 * than 13 tiles must have some duplicates).
289 if (tile_group->num_tiles < 3 || tile_group->num_tiles > 13)
294 /* Loop through all tiles in the group, ensuring that they are all
295 * the same color and finding the highest and lowest number in the
297 run_color = tile_group->tiles[0].color;
299 for (i = 0; i < tile_group->num_tiles; i++)
301 if (tile_group->tiles[i].color != run_color)
303 if (tile_group->tiles[i].number > highest)
305 highest = tile_group->tiles[i].number;
307 if (tile_group->tiles[i].number < lowest)
309 lowest = tile_group->tiles[i].number;
313 /* For a run, the difference between the highest and lowest tiles
314 * will always be one less than the number of tiles in the
315 * group. If not then we know it's not a run.
317 if (highest - lowest != tile_group->num_tiles - 1)
322 /* XXX: There's a bug here. We're guessing that at this point
323 * anything we're looking at must be a run. This would be correct
324 * if there were no duplicate tiles, but since there are
325 * duplicates this us quite broken. For example consider two
326 * sequences of entirely red tiles:
328 * This is a run: 1, 2, 3, 4
329 * But this is not: 1, 3, 4, 4
331 * As currently written, this function will consider both of these
332 * groups to be a run. One possible fix is to throw away the
333 * highest - lowest heuristic and instead simply sort the tiles up
334 * front and ensure the difference between each adjacent pair is
340 static int tile_group_is_set(tile_group_t *tile_group)
343 color_t seen_color[4];
344 for (i = 0; i < 4; i++)
347 if (tile_group->num_tiles > 4 || tile_group->num_tiles < 3)
349 printf("fail set - invalid num tiles; ");
352 for (i = 0; i <= tile_group->num_tiles - 1; ++i)
354 if (tile_group->tiles[i].number != tile_group->tiles[i + 1].number &&
355 i+1 != tile_group->num_tiles)
357 printf("fail set - numbers don't match; ");
360 seen_color[tile_group->tiles[i].color] += 1;
362 for (i = 0; i < 4; i++)
364 if (seen_color[i] > 1)
366 printf("fail set - repeat color; ");
373 static gboolean board_valid(board_t *board)
376 gboolean valid = TRUE;
377 for (i = 0; i < board->num_groups; ++i)
379 if (!(tile_group_is_run_one(&board->groups[i])) &&
380 !(tile_group_is_set(&board->groups[i])))
388 static void deck_deal(game_t *game, deck_t *deck)
394 printf ("How many players(1-4) should I deal in? ");
395 game->num_players = getchar();
396 if (game->num_players == EOF)
398 printf ("\nGoodbye.\n");
402 game->num_players -= '0';
404 for (i = 0; i < game->num_players; ++i)
406 for (j = 0; j < 14; ++j)
408 rand_tile = ((deck->num_tiles + 1.0) * rand()) / (RAND_MAX + 1.0);
409 temp = deck->tiles[rand_tile];
410 deck->tiles[rand_tile] = deck->tiles[deck->num_tiles - 1];
411 game->players[i].hand.tiles[j] = temp;
412 game->players[i].hand.tiles[j].owned = 1;
413 deck->num_tiles -= 1;
414 game->players[i].hand.num_tiles += 1;
417 printf ("Game dealt for %d player(s)\n", game->num_players);
420 static void deck_init(deck_t *deck)
424 for (h = 0; h <= 1; ++h)
426 for (i = 0; i <= 3; ++i)
428 for (j = 0; j <= 12; ++j)
430 tile_init (&deck->tiles[deck->num_tiles++], i, j);
431 printf ("There are %d tiles in the deck\n", deck->num_tiles);
437 static void deck_shuffle(deck_t *deck)
442 for (last = deck->num_tiles; last > 0; --last)
444 rand_tile = ((last + 1.0) * rand()) / (RAND_MAX + 1.0);
445 temp = deck->tiles[rand_tile];
446 deck->tiles[rand_tile] = deck->tiles[last - 1];
447 deck->tiles[last - 1] = temp;
451 static void deck_print(deck_t *deck)
454 for (h = 0; h < 2; ++h)
456 for (i = 0; i < 4; ++i)
458 for (j = 0; j < 13; ++j)
460 tile_print(deck->tiles[j + (i * 13) + (h * 52)]);
464 printf ("There are %d tiles in the deck\n" , deck->num_tiles);
467 static void deck_spread(deck_t *deck)
470 for (i = 0; i < 8; i++)
472 for (j = 0; j < 13; j++)
474 deck->tiles[j + (i * 13)].x = j * 50;
475 deck->tiles[j + (i * 13)].y = i * 60;
480 static void deck_draw(game_t *game, cairo_t *cr, GdkRegion *region)
483 for (i = 0; i < game->deck.num_tiles; i++)
485 tile_draw(game, &game->deck.tiles[i], cr, region);
489 static void board_draw(game_t *game, cairo_t *cr, GdkRegion *region)
492 for (i = 0; i < game->board.num_groups; i++)
494 for (j = 0; j < game->board.groups[i].num_tiles; j++)
496 tile_draw(game, &game->board.groups[i].tiles[j], cr, region);
497 //tile_print(game->board.groups[i].tiles[j]);
502 static void board_print(game_t *game)
505 printf("\tBegin board print\n");
506 for (i = 0; i < game->board.num_groups; i++)
508 printf("\tBegin group %d\n", i);
509 for (j = 0; j < game->board.groups[i].num_tiles; j++)
511 tile_print(game->board.groups[i].tiles[j]);
513 printf("\tEnd group %d\n", i);
517 static void hand_print(game_t *game, int player)
520 for (i = 0; i < game->players[player].hand.num_tiles; i++)
522 tile_print(game->players[player].hand.tiles[i]);
526 static void hand_draw(game_t *game, int player, cairo_t *cr, GdkRegion *region, GtkWidget *widget)
529 int width = widget->allocation.width;
530 // int width = GAME_WINDOW_DEFAULT_WIDTH;
531 int height = widget->allocation.height;
532 // int height = GAME_WINDOW_DEFAULT_HEIGHT;
533 int num_tiles = game->players[player].hand.num_tiles;
534 for (i = 0; i < num_tiles; i++)
536 if (game->players[player].hand.tiles[i].in_hand)
537 tile_set_x_y(&game->players[player].hand.tiles[i],
538 ((width/num_tiles)) * i, (height - TILE_HEIGHT - 6) );
540 for (i = 0; i < game->players[player].hand.num_tiles; i++)
542 // if (game->players[player].hand.tiles[i].in_hand)
543 tile_draw(game, &game->players[player].hand.tiles[i], cr, region);
547 static void save_state(game_t *game)
549 game->state.board = game->board;
550 game->state.deck = game->deck;
552 for (i=0; i < game->num_players; i++)
553 game->state.players[i] = game->players[i];
556 static void restore_state(game_t *game)
558 game->board = game->state.board;
559 game->deck = game->state.deck;
561 for (i=0; i < game->num_players; i++)
562 game->players[i] = game->state.players[i];
565 static void game_init(game_t *game)
568 GError *error = NULL;
570 game->num_players = 0;
572 for (i = 0; i < GAME_MAX_PLAYERS; ++i)
574 player_init(&game->players[i]);
575 game->num_players += 1;
577 game->current_player = 0;
579 selection_box_init(&game->selection_box);
580 board_init(&game->board);
581 deck_init(&game->deck);
582 deck_shuffle(&game->deck);
584 game->selectedtile = rsvg_handle_new_from_file ("tiles/selected_tile.svg", &error);
586 FATAL_ERROR (error->message);
588 game->ownedtile = rsvg_handle_new_from_file ("tiles/owned_tile.svg", &error);
590 FATAL_ERROR (error->message);
592 game->blanktile = rsvg_handle_new_from_file ("tiles/blank_tile.svg", &error);
594 FATAL_ERROR (error->message);
596 // game->current_tile = game->deck.num_tiles - 1;
597 game->current_tile = &game->deck.tiles[0];
598 game->select_mode = 1;
599 game->drag_group_mode = 0;
601 game->diff_x = game->diff_y = 0;
604 static gboolean on_expose_event (GtkWidget *widget, GdkEventExpose *event, game_t *game)
608 cr = gdk_cairo_create (widget->window);
610 deck_draw(game, cr, event->region);
611 board_draw(game, cr, event->region);
613 if (game->selection_box.visible)
614 selection_box_draw(&game->selection_box, cr);
616 hand_draw(game, game->current_player, cr, event->region, widget);
617 //hand_draw(game, 0, cr, event->region);
624 static gboolean on_configure_event (GtkWidget *widget, GdkEventConfigure *event, game_t *game)
628 cr = gdk_cairo_create (event->window);
630 hand_draw(game, game->current_player, cr, event->window, widget);
631 // gtk_widget_queue_draw(widget);
634 static gboolean on_key_press_event (GtkWidget *widget, GdkEventKey *event, game_t *game)
636 player_t *player = &game->players[game->current_player];
638 cr = gdk_cairo_create (widget->window);
639 printf ("You pressed key %d\n", event->keyval);
641 if (event->keyval == 100) //HIT "d"
643 //Draw(take) top tile from deck and put in hand
644 if (game->deck.num_tiles > 0)
646 tile_t top_tile = game->deck.tiles[game->deck.num_tiles-1];
647 game->deck.num_tiles--;
648 player->hand.tiles[player->hand.num_tiles] = top_tile;
649 player->hand.tiles[player->hand.num_tiles].owned=1;
650 player->hand.num_tiles++;
651 gtk_widget_queue_draw(widget);
654 else if (event->keyval == 115) //HIT "s"
656 else if (event->keyval == 65293) //HIT ENTER
659 printf ("\tEnd of player %d's turn\n", game->current_player+1);
660 if (game->current_player == game->num_players-1)
661 game->current_player = 0;
663 game->current_player += 1;
664 gtk_widget_queue_draw(widget);
666 else if (event->keyval == 65307) //HIT ESCAPE
669 printf ("\tChanges Reverted\n");
670 gtk_widget_queue_draw(widget);
672 else if (event->keyval == 65474) //HIT "F5"
674 gtk_widget_queue_draw(widget);
676 else if (event->keyval == 65505 || event->keyval == 65506)
677 game->drag_group_mode = 1;
681 static gboolean on_button_press_event (GtkWidget *widget, GdkEventButton *event, game_t *game)
683 int i, tile_x, tile_y;
685 player_t *curr_player = &game->players[game->current_player];
687 /*Handle tiles in player's hand */
688 for (i = 0; i < curr_player->hand.num_tiles; i++)
690 curr_tile = &curr_player->hand.tiles[i];
691 if (curr_tile->selected)
693 curr_tile->selected = 0;
694 gtk_widget_queue_draw_area (widget, curr_tile->x - 1, curr_tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
696 tile_x = curr_player->hand.tiles[i].x;
697 tile_y = curr_player->hand.tiles[i].y;
698 if (event->x >= tile_x && event->x <= (tile_x + TILE_WIDTH) &&
699 event->y >= tile_y && event->y <= (tile_y + TILE_HEIGHT) )
701 game->select_mode = 0;
702 game->current_tile = curr_tile;
703 curr_tile->in_hand = 0;
704 if (!curr_tile->selected)
705 curr_tile->selected = 1;
707 curr_tile->selected = 0;
708 gtk_widget_queue_draw_area (widget, curr_tile->x - 1, curr_tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
709 game->diff_x = event->x - tile_x;
710 game->diff_y = event->y - tile_y;
714 /*Handle tiles in deck */
715 for (i = 0; i < game->deck.num_tiles; i++)
717 curr_tile = &game->deck.tiles[i];
718 if (curr_tile->selected)
720 curr_tile->selected = 0;
721 gtk_widget_queue_draw_area (widget, curr_tile->x - 1, curr_tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
724 tile_x = game->deck.tiles[i].x;
725 tile_y = game->deck.tiles[i].y;
726 if (event->x >= tile_x && event->x <= (tile_x + TILE_WIDTH) &&
727 event->y >= tile_y && event->y <= (tile_y + TILE_HEIGHT) )
729 game->select_mode = 0;
731 // game->current_tile = i;
732 game->current_tile = curr_tile;
734 //delete_this? curr_tile = &game->deck.tiles[game->current_tile];
735 if (!curr_tile->selected)
736 curr_tile->selected = 1;
738 curr_tile->selected = 0;
739 gtk_widget_queue_draw_area (widget, curr_tile->x - 1, curr_tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
741 game->diff_x = event->x - tile_x;
742 game->diff_y = event->y - tile_y;
745 if (game->select_mode)
747 // game->deck.tiles[game->current_tile].selected = 0;
748 game->current_tile->selected = 0;
749 gtk_widget_queue_draw_area (widget, curr_tile->x - 1, curr_tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
751 game->selection_box.visible = 1;
752 /*These next two lines appear to be dead
753 game->click_x = event->x;
754 game->click_y = event->y;*/
756 game->selection_box.x1 = event->x;
757 game->selection_box.x2 = event->x;
758 game->selection_box.y1 = event->y;
759 game->selection_box.y2 = event->y;
764 static gboolean on_button_release_event (GtkWidget *widget, GdkEventButton *event, game_t *game)
766 if (game->select_mode)
768 game->select_mode = 0;
769 selection_box_t *box;
770 box = &game->selection_box;
772 int x_min = MIN(box->x1, box->x2);
773 int x_max = MAX(box->x1, box->x2);
774 int y_min = MIN(box->y1, box->y2);
775 int y_max = MAX(box->y1, box->y2);
776 int width = abs(box->x2 - box->x1);
777 int height = abs(box->y2 - box->y1);
780 gtk_widget_queue_draw_area (widget, x_min, y_min, width, height);
785 int i, tile_x, tile_y, tile_x2, tile_y2;
786 int tiles_to_remove[game->deck.num_tiles];
787 for (i = 0; i < game->deck.num_tiles; i++)
789 tile_x = game->deck.tiles[i].x;
790 tile_y = game->deck.tiles[i].y;
791 tile_x2 = tile_x + TILE_WIDTH;
792 tile_y2 = tile_y + TILE_HEIGHT;
793 if (/*If top-left corner*/
794 (tile_x >= x_min && tile_x <= x_max &&
795 tile_y >= y_min && tile_y <= y_max) ||
796 /*or bottom-right corner*/
797 (tile_x2 >= x_min && tile_x2 <= x_max &&
798 tile_y2 >= y_min && tile_y2 <= y_max) ||
799 /*or bottom-left corner*/
800 (tile_x >= x_min && tile_x <= x_max &&
801 tile_y2 >= y_min && tile_y2 <= y_max) ||
802 /*or top-right corner*/
803 (tile_x2 >= x_min && tile_x2 <= x_max &&
804 tile_y >= y_min && tile_y <= y_max) ||
806 (y_min >= tile_y && y_min <= tile_y2 &&
807 x_min <= tile_x && x_max >= tile_x) ||
809 (x_min >= tile_x && x_min <= tile_x2 &&
810 y_min <= tile_y && y_max >= tile_y) ||
812 (y_min >= tile_y && y_min <= tile_y2 &&
813 x_min >= tile_x && x_min <= tile_x2) ||
814 /*or bottom edge of tile selected*/
815 (x_min >= tile_x && x_min <= tile_x2 &&
816 y_min >= tile_y && y_min <= tile_y) )
818 tiles_to_remove[group.num_tiles] = i;
820 group.tiles[group.num_tiles] = game->deck.tiles[i];
824 printf("is run %d\n", tile_group_is_run_one(&group) );
825 printf("is set %d\n", tile_group_is_set(&group) );
827 qsort (tiles_to_remove, group.num_tiles, sizeof (int), int_compare);
829 for (i = 0; i < group.num_tiles; i++)
831 tile_print(group.tiles[i]);
832 gtk_widget_queue_draw_area (widget, group.tiles[i].x - 1,
833 group.tiles[i].y - 1, TILE_WIDTH + 1,
836 group.tiles[i].x = x_min + (i * (TILE_WIDTH));
837 group.tiles[i].y = y_min;
839 gtk_widget_queue_draw_area (widget, group.tiles[i].x - 1,
840 group.tiles[i].y - 1, TILE_WIDTH + 1,
843 //Remove tile from deck
844 if (tiles_to_remove[i] != game->deck.num_tiles - 1)
845 game->deck.tiles[tiles_to_remove[i]] = game->deck.tiles[game->deck.num_tiles-1];
846 game->deck.num_tiles--;
849 if (group.num_tiles > 0)
851 game->board.groups[game->board.num_groups] = group;
852 game->board.num_groups++;
855 printf("\nBut is the board valid?\t\t%s\n", board_valid(&game->board) ? "yes" : "no");
857 game->select_mode = 1;
862 static gboolean on_button_motion_event (GtkWidget *widget, GdkEventMotion *event,
863 game_t *game, cairo_t *cr)
865 if (game->select_mode)
867 selection_box_t *box;
868 box = &game->selection_box;
871 int x_min = MIN(box->x1, box->x2);
872 int x_max = MAX(box->x1, box->x2);
873 int y_min = MIN(box->y1, box->y2);
874 int y_max = MAX(box->y1, box->y2);
875 int width = abs(box->x2 - box->x1);
876 int height = abs(box->y2 - box->y1);
878 gtk_widget_queue_draw_area ( widget, x_min, y_min, width, height );
883 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) );
885 int i, tile_x, tile_y, tile_x2, tile_y2;
887 for (i = 0; i < game->deck.num_tiles; i++)
889 curr_tile = &game->deck.tiles[i];
891 tile_x = game->deck.tiles[i].x;
892 tile_y = game->deck.tiles[i].y;
893 tile_x2 = tile_x + TILE_WIDTH;
894 tile_y2 = tile_y + TILE_HEIGHT;
895 if (/*If top-left corner*/
896 (tile_x >= x_min && tile_x <= x_max &&
897 tile_y >= y_min && tile_y <= y_max) ||
898 /*or bottom-right corner*/
899 (tile_x2 >= x_min && tile_x2 <= x_max &&
900 tile_y2 >= y_min && tile_y2 <= y_max) ||
901 /*or bottom-left corner*/
902 (tile_x >= x_min && tile_x <= x_max &&
903 tile_y2 >= y_min && tile_y2 <= y_max) ||
904 /*or top-right corner*/
905 (tile_x2 >= x_min && tile_x2 <= x_max &&
906 tile_y >= y_min && tile_y <= y_max) ||
908 (y_min >= tile_y && y_min <= tile_y2 &&
909 x_min <= tile_x && x_max >= tile_x) ||
911 (x_min >= tile_x && x_min <= tile_x2 &&
912 y_min <= tile_y && y_max >= tile_y) ||
914 (y_min >= tile_y && y_min <= tile_y2 &&
915 x_min >= tile_x && x_min <= tile_x2) ||
916 /*or bottom edge of tile selected*/
917 (x_min >= tile_x && x_min <= tile_x2 &&
918 y_min >= tile_y && y_min <= tile_y) )
920 curr_tile->selected = 1;
921 gtk_widget_queue_draw_area (widget, curr_tile->x - 1, curr_tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
926 if (curr_tile->selected)
928 curr_tile->selected = 0;
929 gtk_widget_queue_draw_area (widget, curr_tile->x - 1, curr_tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
936 if (game->drag_group_mode)
942 // tile = &game->deck.tiles[game->current_tile];
943 tile = game->current_tile;
945 /* First, invalidate the region where the tile currently is. */
946 gtk_widget_queue_draw_area (widget, tile->x - 1, tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
948 /* Then, move the tile */
949 tile->x = event->x - game->diff_x;
950 tile->y = event->y - game->diff_y;
952 /* Finally, invalidate the region where the tile is now. */
953 gtk_widget_queue_draw_area (widget, tile->x - 1, tile->y - 1, TILE_WIDTH + 1, TILE_HEIGHT + 2);
958 int main(int argc, char *argv[])
965 gtk_init (&argc, &argv);
968 deck_print(&game.deck);
969 deck_spread(&game.deck);
970 deck_deal(&game, &game.deck);
972 game.state.board = game.board;
973 game.state.deck = game.deck;
974 //game->state.players = game.players;
976 //hand_print(&game, 0); //With Zero being passed, will print hand for player 1(players[0])
977 //deck_print(&game.deck);
979 /* Create a new window */
980 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
981 gtk_window_set_default_size (GTK_WINDOW (window),
982 GAME_WINDOW_DEFAULT_WIDTH,
983 GAME_WINDOW_DEFAULT_HEIGHT);
985 gtk_widget_set_events (window,
988 GDK_BUTTON_MOTION_MASK |
989 GDK_BUTTON_PRESS_MASK |
990 GDK_BUTTON_RELEASE_MASK);
992 g_signal_connect (G_OBJECT (window), "delete_event",
993 G_CALLBACK (gtk_main_quit), NULL);
994 g_signal_connect (G_OBJECT (window), "expose_event",
995 G_CALLBACK (on_expose_event), &game);
996 // g_signal_connect (G_OBJECT (window), "configure_event",
997 // G_CALLBACK (on_configure_event), &game);
998 g_signal_connect (G_OBJECT (window), "key_press_event",
999 G_CALLBACK (on_key_press_event), &game);
1000 g_signal_connect (G_OBJECT (window), "button_press_event",
1001 G_CALLBACK (on_button_press_event), &game);
1002 g_signal_connect (G_OBJECT (window), "button_release_event",
1003 G_CALLBACK (on_button_release_event), &game);
1004 g_signal_connect (G_OBJECT (window), "motion_notify_event",
1005 G_CALLBACK (on_button_motion_event), &game);
1008 gtk_widget_show_all (window);