]> git.cworth.org Git - loa/commitdiff
Add drawing of pieces (along with loa-board board-management code from loudgame)
authorCarl Worth <cworth@cworth.org>
Sun, 24 Feb 2008 01:41:07 +0000 (17:41 -0800)
committerCarl Worth <cworth@cworth.org>
Sun, 24 Feb 2008 01:41:07 +0000 (17:41 -0800)
Makefile
loa-board.c [new file with mode: 0644]
loa-board.h [new file with mode: 0644]
loa.c

index 06aeffec92c75ed79ce42c8a68efbc67368a6eb4..9022ed97af0d4c0c28e25bbbedfedcc0069f5625 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ all: $(ALL)
 %.o: %.c
        $(CC) $(CFLAGS) $(MYCFLAGS) -c -o $@ -c $<
 
 %.o: %.c
        $(CC) $(CFLAGS) $(MYCFLAGS) -c -o $@ -c $<
 
-%: %.o
+loa: loa.o loa-board.o
        $(CC) $(LDLAGS) $(MYLDFLAGS) -o $@ $^
 
 Makefile.dep: *.c
        $(CC) $(LDLAGS) $(MYLDFLAGS) -o $@ $^
 
 Makefile.dep: *.c
diff --git a/loa-board.c b/loa-board.c
new file mode 100644 (file)
index 0000000..5eb9cc5
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2008 Carl Worth
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see http://www.gnu.org/licenses/ .
+ *
+ * Author: Carl Worth <cworth@cworth.org>
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <glib.h>
+
+#include "loa-board.h"
+
+/* Given an (x,y) position on the board, return the index of the array
+ * used to count pieces in diagonal rows running from upper-left to
+ * lower-right, (like a grave accent: à or like a backslash: \).
+ *
+ * This is the array to look into when a move occurs with dx and dy of
+ * the same sign. */
+static int
+_grave_index (int x, int y)
+{
+    return x - y + LOA_BOARD_SIZE - 1;
+}
+
+/* Given an (x,y) position on the board, return the index of the array
+ * used to count pieces in diagonal rows running from lower-left to
+ * upper-right, (like an acute accent: á or like a forward slash: /).
+ *
+ * This is the array to look into when a move occurs with dx and dy of
+ * opposite sign, (one positive, one negative). */
+static int
+_acute_index (int x, int y)
+{
+    return x + y;
+}
+
+static void
+loa_board_add_piece (loa_board_t *board, int x, int y, loa_cell_t cell)
+{
+    assert (cell == LOA_CELL_BLACK || cell == LOA_CELL_WHITE);
+    assert (board->cells[x][y] == LOA_CELL_EMPTY);
+
+    board->col_pieces[x]++;
+    board->row_pieces[y]++;
+    board->diag_grave_pieces[_grave_index (x, y)]++;
+    board->diag_acute_pieces[_acute_index (x, y)]++;
+
+    board->num_pieces[cell]++;
+
+    board->cells[x][y] = cell;
+}
+
+static loa_cell_t
+loa_board_remove_piece (loa_board_t *board, int x, int y)
+{
+    loa_cell_t cell;
+
+    cell = board->cells[x][y];
+
+    if (cell == LOA_CELL_EMPTY)
+       return LOA_CELL_EMPTY;
+
+    board->col_pieces[x]--;
+    board->row_pieces[y]--;
+    board->diag_grave_pieces[_grave_index (x, y)]--;
+    board->diag_acute_pieces[_acute_index (x, y)]--;
+
+    board->num_pieces[cell]--;
+
+    board->cells[x][y] = LOA_CELL_EMPTY;
+
+    return cell;
+}
+
+void
+loa_board_init (loa_board_t *board)
+{
+    int i, x, y;
+
+    for (x = 0; x < LOA_BOARD_SIZE; x++)
+       for (y = 0; y < LOA_BOARD_SIZE; y++)
+           board->cells[x][y] = LOA_CELL_EMPTY;
+
+    board->num_pieces[LOA_CELL_BLACK] = 0;
+    board->num_pieces[LOA_CELL_WHITE] = 0;
+
+    for (i = 0; i < LOA_BOARD_SIZE; i++) {
+       board->row_pieces[i] = 0;
+       board->col_pieces[i] = 0;
+    }
+
+    for (i = 0; i < LOA_DIAG_ARRAY_SIZE; i++) {
+       board->diag_grave_pieces[i] = 0;
+       board->diag_acute_pieces[i] = 0;
+    }
+
+    for (i = 1; i < LOA_BOARD_SIZE - 1; i++) {
+       loa_board_add_piece (board, i, 0, LOA_CELL_BLACK);
+       loa_board_add_piece (board, i, LOA_BOARD_SIZE - 1, LOA_CELL_BLACK);
+       loa_board_add_piece (board, 0, i, LOA_CELL_WHITE);
+       loa_board_add_piece (board, LOA_BOARD_SIZE - 1, i, LOA_CELL_WHITE);
+    }
+
+    board->player = LOA_PLAYER_BLACK;
+}
+
+static int
+loa_board_group_size_recursive (loa_board_t *board, int x, int y,
+                               loa_cell_t cell,
+                               uint64_t *visited)
+{
+    uint64_t bit;
+
+    if (x < 0 || y < 0)
+       return 0;
+
+    if (x >= LOA_BOARD_SIZE || y >= LOA_BOARD_SIZE)
+       return 0;
+
+    bit = 1ll << (x * LOA_BOARD_SIZE + y);
+    if (*visited & bit)
+       return 0;
+
+    *visited |= bit;
+
+    if (board->cells[x][y] != cell)
+       return 0;
+
+    return 1 +
+       loa_board_group_size_recursive (board, x-1, y-1, cell, visited) +
+       loa_board_group_size_recursive (board, x-1, y  , cell, visited) +
+       loa_board_group_size_recursive (board, x-1, y+1, cell, visited) +
+       loa_board_group_size_recursive (board, x  , y-1, cell, visited) +
+       loa_board_group_size_recursive (board, x  , y  , cell, visited) +
+       loa_board_group_size_recursive (board, x  , y+1, cell, visited) +
+       loa_board_group_size_recursive (board, x+1, y-1, cell, visited) +
+       loa_board_group_size_recursive (board, x+1, y  , cell, visited) +
+       loa_board_group_size_recursive (board, x+1, y+1, cell, visited);
+}
+
+static int
+loa_board_group_size (loa_board_t *board, int x, int y)
+{
+    uint64_t visited = 0ll;
+    loa_cell_t cell = board->cells[x][y];
+
+    return loa_board_group_size_recursive (board, x, y, cell, &visited);
+}
+
+int
+loa_board_is_won (loa_board_t *board, int x, int y)
+{
+    loa_cell_t cell = board->cells[x][y];
+
+    if (cell == LOA_CELL_EMPTY)
+       return 0;
+
+    if (loa_board_group_size (board, x, y) == board->num_pieces[cell])
+       return 1;
+
+    return 0;
+}
+
+static loa_bool_t
+loa_board_move_legal (loa_board_t *board,
+                     int x1, int y1,
+                     int x2, int y2,
+                     char **error)
+{
+    int x, y;
+    int dx, dy;
+    int step_x, step_y;
+
+    if (x1 < 0 || y1 < 0 || x1 >= LOA_BOARD_SIZE || y1 >= LOA_BOARD_SIZE) {
+       *error = "Invalid coordinates (not on board)";
+       return FALSE;
+    }
+
+
+    if (board->cells[x1][y1] == LOA_CELL_EMPTY) {
+       *error = "There is no piece there to move";
+       return FALSE;
+    }
+
+    if (board->cells[x1][y1] != board->player) {
+       *error = "You cannot move your opponent's piece";
+       return FALSE;
+    }
+
+    if (board->cells[x2][y2] == board->cells[x1][y1]) {
+       *error = "You cannot capture your own piece";
+       return FALSE;
+    }
+
+    dx = x2 - x1;
+    dy = y2 - y1;
+
+    /* Here's the meat of Lines of Action legaility: Does the distance
+     * moved exactly match the number of pieces (of either color) in
+     * the row, column, or diagonal of the movement. */
+    if (dx == 0) { 
+       /* Column */
+       if (abs (dy) != board->col_pieces[x1]) {
+           *error = "The move distance does not match the number of pieces in that column";
+           return FALSE;
+       }
+    } else if (dy == 0) {
+       /* Row */
+       if (abs (dx) != board->row_pieces[y1]) {
+           *error = "The move distance does not match the number of pieces in that row";
+           return FALSE;
+       }
+    } else {
+       if (abs (dx) != abs (dy)) {
+           *error = "That move is not in a row, column, or diagonal";
+           return FALSE;
+       }
+       /* Diagonal */
+       if ((dx > 0) == (dy > 0)) {
+           if (abs (dx) != board->diag_grave_pieces[_grave_index (x1, y1)]) {
+               *error = "The move distance does not match the number of pieces in that diagonal";
+               return FALSE;
+           }
+       } else {
+           if (abs (dx) != board->diag_acute_pieces[_acute_index (x1, y1)]) {
+               *error = "The move distance does not match the number of pieces in that diagonal";
+               return FALSE;
+           }
+       }
+    }
+
+    /* Finally, we have to ensure that no opponent pieces are being
+     * jumped. */
+    step_x = dx ? ((dx < 0) ? -1 : +1) : 0;
+    step_y = dy ? ((dy < 0) ? -1 : +1) : 0;
+    for (x = x1 + step_x, y = y1 + step_y;
+        x != x2 || y != y2;
+        x += step_x, y += step_y)
+    {
+       if (board->cells[x][y] != LOA_CELL_EMPTY &&
+           board->cells[x][y] != board->cells[x1][y1])
+       {
+           *error = "You cannot jump an opponent's piece";
+           return FALSE;
+       }
+    }
+
+    return TRUE;
+}
+
+static void
+loa_board_next_player (loa_board_t *board)
+{
+    if (board->player == LOA_PLAYER_BLACK)
+       board->player = LOA_PLAYER_WHITE;
+    else
+       board->player = LOA_PLAYER_BLACK;
+}
+
+/* XXX: Should check for a legal move for the current player and
+ * return FALSE in that case, (that is, it should be illegal to pass
+ * if there's a legal move available). */
+int
+loa_board_pass (loa_board_t *board)
+{
+    loa_board_next_player (board);
+
+    return TRUE;
+}
+
+int
+loa_board_move (loa_board_t *board,
+               int x1, int y1,
+               int x2, int y2,
+               char **error)
+{
+    loa_cell_t cell;
+
+    if (! loa_board_move_legal (board, x1, y1, x2, y2, error))
+       return FALSE;
+
+    cell = loa_board_remove_piece (board, x1, y1);
+    loa_board_remove_piece (board, x2, y2);
+    loa_board_add_piece (board, x2, y2, cell);
+
+    loa_board_next_player (board);
+
+    return TRUE;
+}
+
+/* A few different ideas for displaying boards:
+ *
+ * 8│ │●│●│●│●│●│●│ |      8| |*|*|*|*|*|*| |
+ * 7│○│ │ │ │ │ │ │○|      7|o| | | | | | |o|
+ * 6│○│ │ │ │ │ │ │○|      6|o| | | | | | |o|
+ * 5│○│ │ │ │ │ │ │○|      5|o| | | | | | |o|
+ * 4│○│ │ │ │ │ │ │○|      4|o| | | | | | |o|
+ * 3│○│ │ │ │ │ │ │○|      3|o| | | | | | |o|
+ * 2│○│ │ │ │ │ │ │○|      2|o| | | | | | |o|
+ * 1│ │●│●│●│●│●│●│ |      1| |*|*|*|*|*|*| |
+ *   A B C D E F G H     A B C D E F G H
+ *
+ *  ┌───┬───┬───┬───┬───┬───┬───┬───┐          ------------------------------- 
+ * 8│   │ ● │ ● │ ● │ ● │ ● │ ● │   │    8|   | * | * | * | * | * | * |   |
+ *  ├───┼───┼───┼───┼───┼───┼───┼───┤         |---+---+---+---+---+---+---+---|
+ * 7│ ○ │   │   │   │   │   │   │ ○ │    7| o |   |   |   |   |   |   | o |
+ *  ├───┼───┼───┼───┼───┼───┼───┼───┤         |---+---+---+---+---+---+---+---|
+ * 6│ ○ │   │   │   │   │   │   │ ○ │    6| o |   |   |   |   |   |   | o |
+ *  ├───┼───┼───┼───┼───┼───┼───┼───┤         |---+---+---+---+---+---+---+---|
+ * 5│ ○ │   │   │   │   │   │   │ ○ │    5| o |   |   |   |   |   |   | o |
+ *  ├───┼───┼───┼───┼───┼───┼───┼───┤         |---+---+---+---+---+---+---+---|
+ * 4│ ○ │   │   │   │   │   │   │ ○ │    4| o |   |   |   |   |   |   | o |
+ *  ├───┼───┼───┼───┼───┼───┼───┼───┤         |---+---+---+---+---+---+---+---|
+ * 3│ ○ │   │   │   │   │   │   │ ○ │    3| o |   |   |   |   |   |   | o |
+ *  ├───┼───┼───┼───┼───┼───┼───┼───┤         |---+---+---+---+---+---+---+---|
+ * 2│ ○ │   │   │   │   │   │   │ ○ │    2| o |   |   |   |   |   |   | o |
+ *  ├───┼───┼───┼───┼───┼───┼───┼───┤         |---+---+---+---+---+---+---+---|
+ * 1│   │ ● │ ● │ ● │ ● │ ● │ ● │   │    1|   | * | * | * | * | * | * |   |
+ *  └───┴───┴───┴───┴───┴───┴───┴───┘          ------------------------------- 
+ *    A   B   C   D   E   F   G   H       A   B   C   D   E   F   G   H
+ */
+char *
+loa_board_to_string (loa_board_t *board)
+{
+    int x, y;
+    /* In order of BLACK, WHITE, EMPTY */
+    const char* cell_strings[] = {"●","○"," "};
+    const char   board_header[] = "┌───┬───┬───┬───┬───┬───┬───┬───┐";
+    const char     row_header[] = "│ ";
+    const char cell_separator[] =    " │ ";
+    const char     row_footer[] =                                " │";
+    const char  row_separator[] = "├───┼───┼───┼───┼───┼───┼───┼───┤";
+    const char   board_footer[] = "└───┴───┴───┴───┴───┴───┴───┴───┘";
+    char *board_string = g_strdup ("");
+
+#define APPEND(str) do {                                       \
+    char *_new = g_strconcat (board_string, (str), NULL);      \
+    free (board_string);                                       \
+    board_string = _new;                                       \
+} while (0)
+
+#define APPENDF(format, ...) do {                              \
+    char *str = g_strdup_printf (format, ## __VA_ARGS__);      \
+    APPEND (str);                                              \
+    free (str);                                                        \
+} while (0)
+
+    APPENDF (" %s\n", board_header);
+    for (y = 0; y < LOA_BOARD_SIZE; y++) {
+       APPENDF ("%d%s", LOA_BOARD_SIZE - y, row_header);
+       for (x = 0; x < LOA_BOARD_SIZE; x++) {
+           APPENDF ("%s", cell_strings[board->cells[x][y]]);
+           if (x != LOA_BOARD_SIZE - 1)
+               APPENDF ("%s", cell_separator);
+       }
+       APPENDF ("%s\n", row_footer);
+       if (y != LOA_BOARD_SIZE -1)
+           APPENDF (" %s\n", row_separator);
+    }
+    APPENDF (" %s\n", board_footer);
+
+    APPENDF ("   ");
+    for (x = 0; x < LOA_BOARD_SIZE; x++) {
+       APPENDF ("%c", 'A' + x);
+       if (x != LOA_BOARD_SIZE - 1)
+           APPENDF ("   ");
+    }
+    APPENDF ("\n");
+
+    return board_string;
+}
diff --git a/loa-board.h b/loa-board.h
new file mode 100644 (file)
index 0000000..4532e01
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2008 Carl Worth
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see http://www.gnu.org/licenses/ .
+ *
+ * Author: Carl Worth <cworth@cworth.org>
+ */
+
+#ifndef LOA_BOARD_H
+#define LOA_BOARD_H
+
+typedef int loa_bool_t;
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE  1
+#endif
+
+typedef enum {
+    LOA_PLAYER_BLACK,
+    LOA_PLAYER_WHITE
+} loa_player_t;
+
+typedef enum {
+    LOA_CELL_BLACK = LOA_PLAYER_BLACK,
+    LOA_CELL_WHITE = LOA_PLAYER_WHITE,
+    LOA_CELL_EMPTY
+} loa_cell_t;
+
+/* The implementation of board_group_size depends on the square of
+ * BOARD_SIZE being less than or equal to 64. */
+#define LOA_BOARD_SIZE 8
+#define LOA_DIAG_ARRAY_SIZE (2 * LOA_BOARD_SIZE - 1)
+
+typedef struct {
+    loa_cell_t cells[LOA_BOARD_SIZE][LOA_BOARD_SIZE];
+
+    /* Number of black and white pieces */
+    int num_pieces[2];
+
+    /* Number of pieces (of either color) in each row, column, and
+     * diagonal. */
+    int row_pieces[LOA_BOARD_SIZE];
+    int col_pieces[LOA_BOARD_SIZE];
+    int diag_grave_pieces[LOA_DIAG_ARRAY_SIZE];
+    int diag_acute_pieces[LOA_DIAG_ARRAY_SIZE];
+
+    loa_player_t player;
+} loa_board_t;
+
+/* Initialize a board for a new game of Lines of Action. The 12 pieces
+ * for black and white will be put in their initial places and black
+ * will be set as the current player. */
+void
+loa_board_init (loa_board_t *board);
+
+/* Does the square at (x,y) belong to a winning group? That is, is
+ * there a piece at (x,y) that is 8-way connected to all pieces on the
+ * board of the same color. */
+int
+loa_board_is_won (loa_board_t *board, int x, int y);
+
+/* Move a piece from (x1,y1) to (x2,y2) where (0,0) is at the
+ * upper-left corner of the board. Returns TRUE if the move is legal
+ * and is performed. If the move is not legal this function returns
+ * FALSE, no change will be performed on the board, and *error will be
+ * set to a string describing why the move is illegal.*/
+int
+loa_board_move (loa_board_t *board,
+               int x1, int y1,
+               int x2, int y2,
+               char **error);
+
+/* Execute a 'pass'---changing the player-to-move from the current
+ * player to the opponent. Returns TRUE if the pass is executed.  Will
+ * eventually return FALSE if the current player has a legal move that
+ * could be made, but this is not yet implemented.
+ */
+int
+loa_board_pass (loa_board_t *board);
+
+/* Allocate a new string showing the state of the current board.
+ * When finsihed, the called should free() the resulting value.
+ */
+char *
+loa_board_to_string (loa_board_t *board);
+
+#endif
diff --git a/loa.c b/loa.c
index 48b5b045c3fdf76e4418a03e773eb4157581fd3e..49b4f16ff63dd2cfc30b5ba2cfa8135a55a8ce2b 100644 (file)
--- a/loa.c
+++ b/loa.c
@@ -20,6 +20,8 @@
 #include <gtk/gtk.h>
 #include <math.h>
 
 #include <gtk/gtk.h>
 #include <math.h>
 
+#include "loa-board.h"
+
 #define BOARD_SIZE 8
 
 typedef struct {
 #define BOARD_SIZE 8
 
 typedef struct {
@@ -30,6 +32,11 @@ typedef struct {
     int cell_size;
 } layout_t;
 
     int cell_size;
 } layout_t;
 
+typedef struct {
+    layout_t layout;
+    loa_board_t board;
+} loa_game_t;
+
 static gboolean
 on_delete_event_quit (GtkWidget  *widget,
                      GdkEvent   *event,
 static gboolean
 on_delete_event_quit (GtkWidget  *widget,
                      GdkEvent   *event,
@@ -42,13 +49,19 @@ on_delete_event_quit (GtkWidget  *widget,
     return FALSE;
 }
 
     return FALSE;
 }
 
+/* Something like buff */
+#define LIGHT_SQUARE_COLOR 0.89, 0.70, 0.40
+/* Something like mahogany */
+#define DARK_SQUARE_COLOR  0.26, 0.02, 0.01
+
 static gboolean
 on_expose_event_draw (GtkWidget                *widget,
                      GdkEventExpose    *event,
                      gpointer           user_data)
 {
 static gboolean
 on_expose_event_draw (GtkWidget                *widget,
                      GdkEventExpose    *event,
                      gpointer           user_data)
 {
+    loa_game_t *game = user_data;
+    layout_t *layout = &game->layout;
     cairo_t *cr;
     cairo_t *cr;
-    layout_t *layout = user_data;
     int x, y;
 
     if (layout->width != widget->allocation.width ||
     int x, y;
 
     if (layout->width != widget->allocation.width ||
@@ -74,14 +87,34 @@ on_expose_event_draw (GtkWidget             *widget,
 
     for (y = 0; y < BOARD_SIZE; y++) {
        for (x = 0; x < BOARD_SIZE; x++) {
 
     for (y = 0; y < BOARD_SIZE; y++) {
        for (x = 0; x < BOARD_SIZE; x++) {
+           loa_cell_t cell;
+           cairo_save (cr);
+           cairo_translate(cr, x * layout->cell_size, y * layout->cell_size);
            if ((x + y) % 2 == 0)
            if ((x + y) % 2 == 0)
-               cairo_set_source_rgb (cr, 0.89, 0.70, 0.40);
+               cairo_set_source_rgb (cr, LIGHT_SQUARE_COLOR);
            else
            else
-               cairo_set_source_rgb (cr, 0.26, 0.02, 0.01);
-           cairo_rectangle (cr,
-                            x * layout->cell_size, y * layout->cell_size,
-                            layout->cell_size, layout->cell_size);
+               cairo_set_source_rgb (cr, DARK_SQUARE_COLOR);
+           cairo_rectangle (cr, 0, 0, layout->cell_size, layout->cell_size);
            cairo_fill (cr);
            cairo_fill (cr);
+           cell = game->board.cells[x][y];
+           if (cell != LOA_CELL_EMPTY) {
+               cairo_arc (cr,
+                          layout->cell_size / 2.0, layout->cell_size / 2.0,
+                          layout->cell_size / 2.5,
+                          0, 2 * M_PI);
+               if (cell == LOA_CELL_BLACK)
+                   cairo_set_source_rgb (cr, 0, 0, 0); /* black */
+               else
+                   cairo_set_source_rgb (cr, 1, 1, 1); /* white */
+               cairo_fill_preserve (cr);
+               cairo_set_line_width (cr, 2.0);
+               if (cell == LOA_CELL_BLACK)
+                   cairo_set_source_rgb (cr, LIGHT_SQUARE_COLOR);
+               else
+                   cairo_set_source_rgb (cr, DARK_SQUARE_COLOR);
+               cairo_stroke (cr);
+           }
+           cairo_restore (cr);
        }
     }
 
        }
     }
 
@@ -90,15 +123,23 @@ on_expose_event_draw (GtkWidget            *widget,
     return TRUE;
 }
 
     return TRUE;
 }
 
+static void
+loa_game_init (loa_game_t *game)
+{
+    game->layout.width = 0;
+    game->layout.height = 0;
+
+    loa_board_init (&game->board);
+}
+
 int
 main (int argc, char *argv[])
 {
     GtkWidget *window;
     GtkWidget *drawing_area;
 int
 main (int argc, char *argv[])
 {
     GtkWidget *window;
     GtkWidget *drawing_area;
-    layout_t layout;
+    loa_game_t game;
 
 
-    layout.width = 0;
-    layout.height = 0;
+    loa_game_init (&game);
 
     gtk_init (&argc, &argv);
 
 
     gtk_init (&argc, &argv);
 
@@ -114,7 +155,7 @@ main (int argc, char *argv[])
     gtk_container_add (GTK_CONTAINER (window), drawing_area);
 
     g_signal_connect (drawing_area, "expose-event",  
     gtk_container_add (GTK_CONTAINER (window), drawing_area);
 
     g_signal_connect (drawing_area, "expose-event",  
-                     G_CALLBACK (on_expose_event_draw), &layout);
+                     G_CALLBACK (on_expose_event_draw), &game);
 
     gtk_widget_show_all (window);
     
 
     gtk_widget_show_all (window);