/* game.c generated by valac 0.56.0, the Vala compiler
 * generated from game.vala, do not modify */

/*
 * Copyright (C) 2010-2013 Robert Ancell
 *
 * 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 2 of the License, or (at your option) any later
 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
 * license.
 */

#include <glib-object.h>
#include <glib.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

#if !defined(VALA_EXTERN)
#if defined(_MSC_VER)
#define VALA_EXTERN __declspec(dllexport) extern
#elif __GNUC__ >= 4
#define VALA_EXTERN __attribute__((visibility("default"))) extern
#else
#define VALA_EXTERN extern
#endif
#endif

#define TYPE_TILE (tile_get_type ())
#define TILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TILE, Tile))
#define TILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_TILE, TileClass))
#define IS_TILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_TILE))
#define IS_TILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_TILE))
#define TILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_TILE, TileClass))

typedef struct _Tile Tile;
typedef struct _TileClass TileClass;
typedef struct _TilePrivate TilePrivate;
enum  {
	TILE_0_PROPERTY,
	TILE_CLOSED_PROPERTY,
	TILE_GRID_X_PROPERTY,
	TILE_GRID_Y_PROPERTY,
	TILE_COLOR_PROPERTY,
	TILE_VISITED_PROPERTY,
	TILE_NUM_PROPERTIES
};
static GParamSpec* tile_properties[TILE_NUM_PROPERTIES];
enum  {
	TILE_MOVE_SIGNAL,
	TILE_CLOSE_SIGNAL,
	TILE_NUM_SIGNALS
};
static guint tile_signals[TILE_NUM_SIGNALS] = {0};

#define TYPE_GAME (game_get_type ())
#define GAME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_GAME, Game))
#define GAME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_GAME, GameClass))
#define IS_GAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_GAME))
#define IS_GAME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_GAME))
#define GAME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_GAME, GameClass))

typedef struct _Game Game;
typedef struct _GameClass GameClass;
typedef struct _GamePrivate GamePrivate;

#define GAME_TYPE_HISTORY_ENTRY (game_history_entry_get_type ())
#define GAME_HISTORY_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAME_TYPE_HISTORY_ENTRY, GameHistoryEntry))
#define GAME_HISTORY_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAME_TYPE_HISTORY_ENTRY, GameHistoryEntryClass))
#define GAME_IS_HISTORY_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAME_TYPE_HISTORY_ENTRY))
#define GAME_IS_HISTORY_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAME_TYPE_HISTORY_ENTRY))
#define GAME_HISTORY_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAME_TYPE_HISTORY_ENTRY, GameHistoryEntryClass))

typedef struct _GameHistoryEntry GameHistoryEntry;
typedef struct _GameHistoryEntryClass GameHistoryEntryClass;
enum  {
	GAME_0_PROPERTY,
	GAME_SCORE_PROPERTY,
	GAME_COLOR_NUM_PROPERTY,
	GAME_ROWS_PROPERTY,
	GAME_COLUMNS_PROPERTY,
	GAME_CAN_UNDO_PROPERTY,
	GAME_CAN_REDO_PROPERTY,
	GAME_NUM_PROPERTIES
};
static GParamSpec* game_properties[GAME_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_variant_unref0(var) ((var == NULL) ? NULL : (var = (g_variant_unref (var), NULL)))
#define _g_variant_iter_free0(var) ((var == NULL) ? NULL : (var = (g_variant_iter_free (var), NULL)))
typedef struct _Block1Data Block1Data;
#define _g_variant_builder_unref0(var) ((var == NULL) ? NULL : (var = (g_variant_builder_unref (var), NULL)))
#define _g_variant_type_free0(var) ((var == NULL) ? NULL : (var = (g_variant_type_free (var), NULL)))

#define GAME_TYPE_POINT (game_point_get_type ())
#define GAME_POINT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAME_TYPE_POINT, GamePoint))
#define GAME_POINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAME_TYPE_POINT, GamePointClass))
#define GAME_IS_POINT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAME_TYPE_POINT))
#define GAME_IS_POINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAME_TYPE_POINT))
#define GAME_POINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAME_TYPE_POINT, GamePointClass))

typedef struct _GamePoint GamePoint;
typedef struct _GamePointClass GamePointClass;
typedef struct _GameHistoryEntryPrivate GameHistoryEntryPrivate;
typedef struct _GamePointPrivate GamePointPrivate;
enum  {
	GAME_POINT_0_PROPERTY,
	GAME_POINT_X_PROPERTY,
	GAME_POINT_Y_PROPERTY,
	GAME_POINT_NUM_PROPERTIES
};
static GParamSpec* game_point_properties[GAME_POINT_NUM_PROPERTIES];
enum  {
	GAME_HISTORY_ENTRY_0_PROPERTY,
	GAME_HISTORY_ENTRY_CLICK_PROPERTY,
	GAME_HISTORY_ENTRY_COLOR_PROPERTY,
	GAME_HISTORY_ENTRY_NUM_PROPERTIES
};
static GParamSpec* game_history_entry_properties[GAME_HISTORY_ENTRY_NUM_PROPERTIES];
enum  {
	GAME_UPDATE_SCORE_SIGNAL,
	GAME_COMPLETE_SIGNAL,
	GAME_STARTED_SIGNAL,
	GAME_UNDONE_SIGNAL,
	GAME_NUM_SIGNALS
};
static guint game_signals[GAME_NUM_SIGNALS] = {0};

struct _Tile {
	GObject parent_instance;
	TilePrivate * priv;
};

struct _TileClass {
	GObjectClass parent_class;
};

struct _TilePrivate {
	gboolean _closed;
	guint8 _grid_x;
	guint8 _grid_y;
	guint8 _color;
	gboolean _visited;
};

struct _Game {
	GObject parent_instance;
	GamePrivate * priv;
};

struct _GameClass {
	GObjectClass parent_class;
};

struct _GamePrivate {
	Tile** current_board;
	gint current_board_length1;
	gint current_board_length2;
	gboolean is_started;
	guint _score;
	guint8 _color_num;
	guint8 _rows;
	guint8 _columns;
	guint8* initial_board;
	gint initial_board_length1;
	gint initial_board_length2;
	gboolean _can_undo;
	gboolean _can_redo;
	guint16 history_length;
	guint16 history_index;
	GList* reversed_history;
};

struct _Block1Data {
	int _ref_count_;
	Game* self;
	GVariantBuilder* builder;
};

struct _GameHistoryEntry {
	GObject parent_instance;
	GameHistoryEntryPrivate * priv;
	GList* removed_tiles;
	guint8* removed_columns;
	gint removed_columns_length1;
	gint _removed_columns_size_;
};

struct _GameHistoryEntryClass {
	GObjectClass parent_class;
};

struct _GamePoint {
	GObject parent_instance;
	GamePointPrivate * priv;
};

struct _GamePointClass {
	GObjectClass parent_class;
};

struct _GamePointPrivate {
	guint8 _x;
	guint8 _y;
};

struct _GameHistoryEntryPrivate {
	GamePoint* _click;
	guint8 _color;
};

static gint Tile_private_offset;
static gpointer tile_parent_class = NULL;
static gint Game_private_offset;
static gpointer game_parent_class = NULL;
static gint GamePoint_private_offset;
static gpointer game_point_parent_class = NULL;
static gint GameHistoryEntry_private_offset;
static gpointer game_history_entry_parent_class = NULL;

VALA_EXTERN GType tile_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (Tile, g_object_unref)
VALA_EXTERN Tile* tile_new (guint8 x,
                guint8 y,
                guint8 c);
VALA_EXTERN Tile* tile_construct (GType object_type,
                      guint8 x,
                      guint8 y,
                      guint8 c);
VALA_EXTERN void tile_update_position (Tile* self,
                           guint8 new_x,
                           guint8 new_y);
VALA_EXTERN gboolean tile_get_closed (Tile* self);
VALA_EXTERN guint8 tile_get_grid_x (Tile* self);
VALA_EXTERN guint8 tile_get_grid_y (Tile* self);
VALA_EXTERN void tile_set_grid_x (Tile* self,
                      guint8 value);
VALA_EXTERN void tile_set_grid_y (Tile* self,
                      guint8 value);
static void tile_set_closed (Tile* self,
                      gboolean value);
VALA_EXTERN guint8 tile_get_color (Tile* self);
static void tile_set_color (Tile* self,
                     guint8 value);
VALA_EXTERN gboolean tile_get_visited (Tile* self);
static void tile_set_visited (Tile* self,
                       gboolean value);
static void g_cclosure_user_marshal_VOID__UCHAR_UCHAR_UCHAR_UCHAR (GClosure * closure,
                                                            GValue * return_value,
                                                            guint n_param_values,
                                                            const GValue * param_values,
                                                            gpointer invocation_hint,
                                                            gpointer marshal_data);
static void g_cclosure_user_marshal_VOID__UCHAR_UCHAR (GClosure * closure,
                                                GValue * return_value,
                                                guint n_param_values,
                                                const GValue * param_values,
                                                gpointer invocation_hint,
                                                gpointer marshal_data);
static void tile_finalize (GObject * obj);
static GType tile_get_type_once (void);
static void _vala_tile_get_property (GObject * object,
                              guint property_id,
                              GValue * value,
                              GParamSpec * pspec);
static void _vala_tile_set_property (GObject * object,
                              guint property_id,
                              const GValue * value,
                              GParamSpec * pspec);
VALA_EXTERN GType game_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (Game, g_object_unref)
static GType game_history_entry_get_type (void) G_GNUC_CONST  G_GNUC_UNUSED ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GameHistoryEntry, g_object_unref)
static void _g_object_unref0_ (gpointer var);
static inline void _g_list_free__g_object_unref0_ (GList* self);
VALA_EXTERN Game* game_new (guint8 rows,
                guint8 columns,
                guint8 color_num,
                GVariant* saved_game);
VALA_EXTERN Game* game_construct (GType object_type,
                      guint8 rows,
                      guint8 columns,
                      guint8 color_num,
                      GVariant* saved_game);
static inline gboolean game_load_saved_game (Game* self,
                               GVariant* variant);
static inline void game_create_new_game (Game* self);
VALA_EXTERN guint8 game_get_rows (Game* self);
VALA_EXTERN guint8 game_get_columns (Game* self);
static gboolean game_bad_colors_number (guint8** initial_board,
                                 gint* initial_board_length1,
                                 gint* initial_board_length2,
                                 guint8 color_num);
VALA_EXTERN guint8 game_get_color_num (Game* self);
static gboolean game_unclickable_board (guint8** initial_board,
                                 gint* initial_board_length1,
                                 gint* initial_board_length2);
static void game_populate_new_game (guint8** initial_board,
                             gint* initial_board_length1,
                             gint* initial_board_length2,
                             guint8 color_num);
static GList* _game_connected_tiles_real (Tile* given_tile,
                                   Tile*** current_board,
                                   gint* current_board_length1,
                                   gint* current_board_length2);
VALA_EXTERN GList* game_connected_tiles (Game* self,
                             Tile* given_tile);
static GList* _game_connected_tiles (Tile* given_tile,
                              Tile*** current_board,
                              gint* current_board_length1,
                              gint* current_board_length2);
VALA_EXTERN Tile* game_get_tile (Game* self,
                     guint8 x,
                     guint8 y);
VALA_EXTERN void game_remove_connected_tiles (Game* self,
                                  Tile* given_tile);
static void game_remove_connected_tiles_real (Game* self,
                                       Tile* given_tile,
                                       gboolean skip_history);
static void _game_remove_connected_tiles (Game* self,
                                   Tile* given_tile,
                                   Tile*** current_board,
                                   gint* current_board_length1,
                                   gint* current_board_length2,
                                   gboolean skip_history);
static gboolean game_has_completed (Tile*** current_board,
                             gint* current_board_length1,
                             gint* current_board_length2);
static gboolean game_has_won (Tile*** current_board,
                       gint* current_board_length1,
                       gint* current_board_length2);
static void game_increment_score (Game* self,
                           gint variation);
static inline void game_increment_score_from_tiles (Game* self,
                                      guint16 n_tiles);
static inline void game_add_history_entry (Game* self,
                             guint8 x,
                             guint8 y,
                             guint8 color,
                             GList* cl,
                             guint8* removed_columns,
                             gint removed_columns_length1);
static inline void game_decrement_score_from_tiles (Game* self,
                                      guint16 n_tiles);
static inline gint game_get_score_from_tiles (Game* self,
                                guint16 n_tiles);
VALA_EXTERN guint game_get_score (Game* self);
static void game_set_score (Game* self,
                     guint value);
static inline void game_clear_history (Game* self);
static void game_undo_real (Game* self,
                     Tile*** current_board,
                     gint* current_board_length1,
                     gint* current_board_length2);
static Tile** _vala_array_dup1 (Tile** self,
                         gssize length);
static guint8* _vala_array_dup2 (guint8* self,
                          gssize length);
VALA_EXTERN GVariant* game_get_saved_game (Game* self);
static Block1Data* block1_data_ref (Block1Data* _data1_);
static void block1_data_unref (void * _userdata_);
static void __lambda5_ (Block1Data* _data1_,
                 GameHistoryEntry* data);
static GType game_point_get_type (void) G_GNUC_CONST  G_GNUC_UNUSED ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GamePoint, g_object_unref)
static GamePoint* game_history_entry_get_click (GameHistoryEntry* self);
static guint8 game_point_get_x (GamePoint* self);
static guint8 game_point_get_y (GamePoint* self);
static void ___lambda5__gfunc (gconstpointer data,
                        gpointer self);
static void game_set_can_undo (Game* self,
                        gboolean value);
static void game_set_can_redo (Game* self,
                        gboolean value);
static GameHistoryEntry* game_history_entry_new (guint8 x,
                                          guint8 y,
                                          guint8 color,
                                          GList* cl,
                                          guint8* removed_columns,
                                          gint removed_columns_length1);
static GameHistoryEntry* game_history_entry_construct (GType object_type,
                                                guint8 x,
                                                guint8 y,
                                                guint8 color,
                                                GList* cl,
                                                guint8* removed_columns,
                                                gint removed_columns_length1);
VALA_EXTERN void game_undo (Game* self);
VALA_EXTERN gboolean game_get_can_undo (Game* self);
static inline void game_undo_move (Game* self,
                     GameHistoryEntry* history_entry,
                     Tile*** current_board,
                     gint* current_board_length1,
                     gint* current_board_length2);
static guint8 game_history_entry_get_color (GameHistoryEntry* self);
VALA_EXTERN void game_redo (Game* self);
VALA_EXTERN gboolean game_get_can_redo (Game* self);
static inline void game_redo_move (Game* self,
                     GameHistoryEntry* history_entry);
VALA_EXTERN void game_set_color_num (Game* self,
                         guint8 value);
static void game_set_rows (Game* self,
                    guint8 value);
static void game_set_columns (Game* self,
                       guint8 value);
static GamePoint* game_point_new (guint8 x,
                           guint8 y);
static GamePoint* game_point_construct (GType object_type,
                                 guint8 x,
                                 guint8 y);
static void game_point_set_x (GamePoint* self,
                       guint8 value);
static void game_point_set_y (GamePoint* self,
                       guint8 value);
static void game_point_finalize (GObject * obj);
static GType game_point_get_type_once (void);
static void _vala_game_point_get_property (GObject * object,
                                    guint property_id,
                                    GValue * value,
                                    GParamSpec * pspec);
static void _vala_game_point_set_property (GObject * object,
                                    guint property_id,
                                    const GValue * value,
                                    GParamSpec * pspec);
static guint8* _vala_array_dup3 (guint8* self,
                          gssize length);
static gint __lambda4_ (GamePoint* tile_1,
                 GamePoint* tile_2);
static gint ___lambda4__gcompare_func (gconstpointer a,
                                gconstpointer b);
static void game_history_entry_set_click (GameHistoryEntry* self,
                                   GamePoint* value);
static void game_history_entry_set_color (GameHistoryEntry* self,
                                   guint8 value);
static void game_history_entry_finalize (GObject * obj);
static GType game_history_entry_get_type_once (void);
static void _vala_game_history_entry_get_property (GObject * object,
                                            guint property_id,
                                            GValue * value,
                                            GParamSpec * pspec);
static void _vala_game_history_entry_set_property (GObject * object,
                                            guint property_id,
                                            const GValue * value,
                                            GParamSpec * pspec);
static void game_finalize (GObject * obj);
static GType game_get_type_once (void);
static void _vala_game_get_property (GObject * object,
                              guint property_id,
                              GValue * value,
                              GParamSpec * pspec);
static void _vala_game_set_property (GObject * object,
                              guint property_id,
                              const GValue * value,
                              GParamSpec * pspec);
static void _vala_array_destroy (gpointer array,
                          gssize array_length,
                          GDestroyNotify destroy_func);
static void _vala_array_free (gpointer array,
                       gssize array_length,
                       GDestroyNotify destroy_func);
static void _vala_array_move (gpointer array,
                       gsize element_size,
                       gssize src,
                       gssize dest,
                       gssize length);
static inline gpointer _vala_memdup2 (gconstpointer mem,
                        gsize byte_size);

static inline gpointer
tile_get_instance_private (Tile* self)
{
	return G_STRUCT_MEMBER_P (self, Tile_private_offset);
}

Tile*
tile_construct (GType object_type,
                guint8 x,
                guint8 y,
                guint8 c)
{
	Tile * self = NULL;
	self = (Tile*) g_object_new (object_type, "grid-x", x, "grid-y", y, "color", c, NULL);
	return self;
}

Tile*
tile_new (guint8 x,
          guint8 y,
          guint8 c)
{
	return tile_construct (TYPE_TILE, x, y, c);
}

void
tile_update_position (Tile* self,
                      guint8 new_x,
                      guint8 new_y)
{
	gboolean _tmp0_;
	gboolean _tmp1_;
	guint8 old_x = 0U;
	guint8 _tmp2_;
	guint8 old_y = 0U;
	guint8 _tmp3_;
	gboolean _tmp4_ = FALSE;
	g_return_if_fail (self != NULL);
	_tmp0_ = tile_get_closed (self);
	_tmp1_ = _tmp0_;
	if (_tmp1_) {
		return;
	}
	_tmp2_ = self->priv->_grid_x;
	old_x = _tmp2_;
	_tmp3_ = self->priv->_grid_y;
	old_y = _tmp3_;
	if (new_x != old_x) {
		_tmp4_ = TRUE;
	} else {
		_tmp4_ = new_y != old_y;
	}
	if (_tmp4_) {
		gboolean _tmp5_;
		gboolean _tmp6_;
		tile_set_grid_x (self, new_x);
		tile_set_grid_y (self, new_y);
		_tmp5_ = tile_get_closed (self);
		_tmp6_ = _tmp5_;
		if (!_tmp6_) {
			g_signal_emit (self, tile_signals[TILE_MOVE_SIGNAL], 0, old_x, old_y, new_x, new_y);
		}
	}
}

gboolean
tile_get_closed (Tile* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = self->priv->_closed;
	return result;
}

static void
tile_set_closed (Tile* self,
                 gboolean value)
{
	g_return_if_fail (self != NULL);
	self->priv->_closed = value;
	if (self->priv->_closed) {
		guint8 _tmp0_;
		guint8 _tmp1_;
		_tmp0_ = self->priv->_grid_x;
		_tmp1_ = self->priv->_grid_y;
		g_signal_emit (self, tile_signals[TILE_CLOSE_SIGNAL], 0, _tmp0_, _tmp1_);
	}
	g_object_notify_by_pspec ((GObject *) self, tile_properties[TILE_CLOSED_PROPERTY]);
}

guint8
tile_get_grid_x (Tile* self)
{
	guint8 result;
	g_return_val_if_fail (self != NULL, 0U);
	result = self->priv->_grid_x;
	return result;
}

void
tile_set_grid_x (Tile* self,
                 guint8 value)
{
	guint8 old_value;
	g_return_if_fail (self != NULL);
	old_value = tile_get_grid_x (self);
	if (old_value != value) {
		self->priv->_grid_x = value;
		g_object_notify_by_pspec ((GObject *) self, tile_properties[TILE_GRID_X_PROPERTY]);
	}
}

guint8
tile_get_grid_y (Tile* self)
{
	guint8 result;
	g_return_val_if_fail (self != NULL, 0U);
	result = self->priv->_grid_y;
	return result;
}

void
tile_set_grid_y (Tile* self,
                 guint8 value)
{
	guint8 old_value;
	g_return_if_fail (self != NULL);
	old_value = tile_get_grid_y (self);
	if (old_value != value) {
		self->priv->_grid_y = value;
		g_object_notify_by_pspec ((GObject *) self, tile_properties[TILE_GRID_Y_PROPERTY]);
	}
}

guint8
tile_get_color (Tile* self)
{
	guint8 result;
	g_return_val_if_fail (self != NULL, 0U);
	result = self->priv->_color;
	return result;
}

static void
tile_set_color (Tile* self,
                guint8 value)
{
	guint8 old_value;
	g_return_if_fail (self != NULL);
	old_value = tile_get_color (self);
	if (old_value != value) {
		self->priv->_color = value;
		g_object_notify_by_pspec ((GObject *) self, tile_properties[TILE_COLOR_PROPERTY]);
	}
}

gboolean
tile_get_visited (Tile* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = self->priv->_visited;
	return result;
}

static void
tile_set_visited (Tile* self,
                  gboolean value)
{
	gboolean old_value;
	g_return_if_fail (self != NULL);
	old_value = tile_get_visited (self);
	if (old_value != value) {
		self->priv->_visited = value;
		g_object_notify_by_pspec ((GObject *) self, tile_properties[TILE_VISITED_PROPERTY]);
	}
}

static void
g_cclosure_user_marshal_VOID__UCHAR_UCHAR_UCHAR_UCHAR (GClosure * closure,
                                                       GValue * return_value,
                                                       guint n_param_values,
                                                       const GValue * param_values,
                                                       gpointer invocation_hint,
                                                       gpointer marshal_data)
{
	typedef void (*GMarshalFunc_VOID__UCHAR_UCHAR_UCHAR_UCHAR) (gpointer data1, guint8 arg_1, guint8 arg_2, guint8 arg_3, guint8 arg_4, gpointer data2);
	register GMarshalFunc_VOID__UCHAR_UCHAR_UCHAR_UCHAR callback;
	register GCClosure * cc;
	register gpointer data1;
	register gpointer data2;
	cc = (GCClosure *) closure;
	g_return_if_fail (n_param_values == 5);
	if (G_CCLOSURE_SWAP_DATA (closure)) {
		data1 = closure->data;
		data2 = param_values->data[0].v_pointer;
	} else {
		data1 = param_values->data[0].v_pointer;
		data2 = closure->data;
	}
	callback = (GMarshalFunc_VOID__UCHAR_UCHAR_UCHAR_UCHAR) (marshal_data ? marshal_data : cc->callback);
	callback (data1, g_value_get_uchar (param_values + 1), g_value_get_uchar (param_values + 2), g_value_get_uchar (param_values + 3), g_value_get_uchar (param_values + 4), data2);
}

static void
g_cclosure_user_marshal_VOID__UCHAR_UCHAR (GClosure * closure,
                                           GValue * return_value,
                                           guint n_param_values,
                                           const GValue * param_values,
                                           gpointer invocation_hint,
                                           gpointer marshal_data)
{
	typedef void (*GMarshalFunc_VOID__UCHAR_UCHAR) (gpointer data1, guint8 arg_1, guint8 arg_2, gpointer data2);
	register GMarshalFunc_VOID__UCHAR_UCHAR callback;
	register GCClosure * cc;
	register gpointer data1;
	register gpointer data2;
	cc = (GCClosure *) closure;
	g_return_if_fail (n_param_values == 3);
	if (G_CCLOSURE_SWAP_DATA (closure)) {
		data1 = closure->data;
		data2 = param_values->data[0].v_pointer;
	} else {
		data1 = param_values->data[0].v_pointer;
		data2 = closure->data;
	}
	callback = (GMarshalFunc_VOID__UCHAR_UCHAR) (marshal_data ? marshal_data : cc->callback);
	callback (data1, g_value_get_uchar (param_values + 1), g_value_get_uchar (param_values + 2), data2);
}

static void
tile_class_init (TileClass * klass,
                 gpointer klass_data)
{
	tile_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &Tile_private_offset);
	G_OBJECT_CLASS (klass)->get_property = _vala_tile_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_tile_set_property;
	G_OBJECT_CLASS (klass)->finalize = tile_finalize;
	g_object_class_install_property (G_OBJECT_CLASS (klass), TILE_CLOSED_PROPERTY, tile_properties[TILE_CLOSED_PROPERTY] = g_param_spec_boolean ("closed", "closed", "closed", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), TILE_GRID_X_PROPERTY, tile_properties[TILE_GRID_X_PROPERTY] = g_param_spec_uchar ("grid-x", "grid-x", "grid-x", 0, G_MAXUINT8, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
	g_object_class_install_property (G_OBJECT_CLASS (klass), TILE_GRID_Y_PROPERTY, tile_properties[TILE_GRID_Y_PROPERTY] = g_param_spec_uchar ("grid-y", "grid-y", "grid-y", 0, G_MAXUINT8, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
	g_object_class_install_property (G_OBJECT_CLASS (klass), TILE_COLOR_PROPERTY, tile_properties[TILE_COLOR_PROPERTY] = g_param_spec_uchar ("color", "color", "color", 0, G_MAXUINT8, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
	g_object_class_install_property (G_OBJECT_CLASS (klass), TILE_VISITED_PROPERTY, tile_properties[TILE_VISITED_PROPERTY] = g_param_spec_boolean ("visited", "visited", "visited", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	tile_signals[TILE_MOVE_SIGNAL] = g_signal_new ("move", TYPE_TILE, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__UCHAR_UCHAR_UCHAR_UCHAR, G_TYPE_NONE, 4, G_TYPE_UCHAR, G_TYPE_UCHAR, G_TYPE_UCHAR, G_TYPE_UCHAR);
	tile_signals[TILE_CLOSE_SIGNAL] = g_signal_new ("close", TYPE_TILE, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__UCHAR_UCHAR, G_TYPE_NONE, 2, G_TYPE_UCHAR, G_TYPE_UCHAR);
}

static void
tile_instance_init (Tile * self,
                    gpointer klass)
{
	self->priv = tile_get_instance_private (self);
	self->priv->_closed = FALSE;
	self->priv->_visited = FALSE;
}

static void
tile_finalize (GObject * obj)
{
	Tile * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_TILE, Tile);
	G_OBJECT_CLASS (tile_parent_class)->finalize (obj);
}

/**
 *  This is the model layer of a tile.
 */
static GType
tile_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (TileClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) tile_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Tile), 0, (GInstanceInitFunc) tile_instance_init, NULL };
	GType tile_type_id;
	tile_type_id = g_type_register_static (G_TYPE_OBJECT, "Tile", &g_define_type_info, 0);
	Tile_private_offset = g_type_add_instance_private (tile_type_id, sizeof (TilePrivate));
	return tile_type_id;
}

GType
tile_get_type (void)
{
	static volatile gsize tile_type_id__once = 0;
	if (g_once_init_enter (&tile_type_id__once)) {
		GType tile_type_id;
		tile_type_id = tile_get_type_once ();
		g_once_init_leave (&tile_type_id__once, tile_type_id);
	}
	return tile_type_id__once;
}

static void
_vala_tile_get_property (GObject * object,
                         guint property_id,
                         GValue * value,
                         GParamSpec * pspec)
{
	Tile * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_TILE, Tile);
	switch (property_id) {
		case TILE_CLOSED_PROPERTY:
		g_value_set_boolean (value, tile_get_closed (self));
		break;
		case TILE_GRID_X_PROPERTY:
		g_value_set_uchar (value, tile_get_grid_x (self));
		break;
		case TILE_GRID_Y_PROPERTY:
		g_value_set_uchar (value, tile_get_grid_y (self));
		break;
		case TILE_COLOR_PROPERTY:
		g_value_set_uchar (value, tile_get_color (self));
		break;
		case TILE_VISITED_PROPERTY:
		g_value_set_boolean (value, tile_get_visited (self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_tile_set_property (GObject * object,
                         guint property_id,
                         const GValue * value,
                         GParamSpec * pspec)
{
	Tile * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_TILE, Tile);
	switch (property_id) {
		case TILE_CLOSED_PROPERTY:
		tile_set_closed (self, g_value_get_boolean (value));
		break;
		case TILE_GRID_X_PROPERTY:
		tile_set_grid_x (self, g_value_get_uchar (value));
		break;
		case TILE_GRID_Y_PROPERTY:
		tile_set_grid_y (self, g_value_get_uchar (value));
		break;
		case TILE_COLOR_PROPERTY:
		tile_set_color (self, g_value_get_uchar (value));
		break;
		case TILE_VISITED_PROPERTY:
		tile_set_visited (self, g_value_get_boolean (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static inline gpointer
game_get_instance_private (Game* self)
{
	return G_STRUCT_MEMBER_P (self, Game_private_offset);
}

static void
_g_object_unref0_ (gpointer var)
{
	(var == NULL) ? NULL : (var = (g_object_unref (var), NULL));
}

static inline void
_g_list_free__g_object_unref0_ (GList* self)
{
	g_list_free_full (self, (GDestroyNotify) _g_object_unref0_);
}

Game*
game_construct (GType object_type,
                guint8 rows,
                guint8 columns,
                guint8 color_num,
                GVariant* saved_game)
{
	Game * self = NULL;
	gboolean _tmp0_ = FALSE;
	self = (Game*) g_object_new (object_type, "rows", rows, "columns", columns, "color-num", color_num, NULL);
	if (saved_game == NULL) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = !game_load_saved_game (self, (GVariant*) saved_game);
	}
	if (_tmp0_) {
		game_create_new_game (self);
	}
	return self;
}

Game*
game_new (guint8 rows,
          guint8 columns,
          guint8 color_num,
          GVariant* saved_game)
{
	return game_construct (TYPE_GAME, rows, columns, color_num, saved_game);
}

static inline void
game_create_new_game (Game* self)
{
	guint8 _tmp0_;
	guint8 _tmp1_;
	guint8* _tmp2_;
	guint8 _tmp3_;
	guint8 _tmp4_;
	Tile** _tmp5_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->_rows;
	_tmp1_ = self->priv->_columns;
	_tmp2_ = g_new0 (guint8, _tmp0_ * _tmp1_);
	self->priv->initial_board = (g_free (self->priv->initial_board), NULL);
	self->priv->initial_board = _tmp2_;
	self->priv->initial_board_length1 = _tmp0_;
	self->priv->initial_board_length2 = _tmp1_;
	_tmp3_ = self->priv->_rows;
	_tmp4_ = self->priv->_columns;
	_tmp5_ = g_new0 (Tile*, (_tmp3_ * _tmp4_) + 1);
	self->priv->current_board = (_vala_array_free (self->priv->current_board, self->priv->current_board_length1 * self->priv->current_board_length2, (GDestroyNotify) g_object_unref), NULL);
	self->priv->current_board = _tmp5_;
	self->priv->current_board_length1 = _tmp3_;
	self->priv->current_board_length2 = _tmp4_;
	{
		gboolean _tmp6_ = FALSE;
		_tmp6_ = TRUE;
		while (TRUE) {
			guint8 _tmp12_;
			guint8 _tmp13_;
			if (!_tmp6_) {
				gboolean _tmp7_ = FALSE;
				guint8 _tmp8_;
				guint8 _tmp9_;
				gboolean _tmp10_;
				_tmp8_ = game_get_color_num (self);
				_tmp9_ = _tmp8_;
				_tmp10_ = game_bad_colors_number (&self->priv->initial_board, (gint*) (&self->priv->initial_board_length1), (gint*) (&self->priv->initial_board_length2), _tmp9_);
				if (_tmp10_) {
					_tmp7_ = TRUE;
				} else {
					gboolean _tmp11_;
					_tmp11_ = game_unclickable_board (&self->priv->initial_board, (gint*) (&self->priv->initial_board_length1), (gint*) (&self->priv->initial_board_length2));
					_tmp7_ = _tmp11_;
				}
				if (!_tmp7_) {
					break;
				}
			}
			_tmp6_ = FALSE;
			_tmp12_ = game_get_color_num (self);
			_tmp13_ = _tmp12_;
			game_populate_new_game (&self->priv->initial_board, (gint*) (&self->priv->initial_board_length1), (gint*) (&self->priv->initial_board_length2), _tmp13_);
		}
	}
	{
		guint8 x = 0U;
		x = (guint8) 0;
		{
			gboolean _tmp14_ = FALSE;
			_tmp14_ = TRUE;
			while (TRUE) {
				guint8 _tmp16_;
				if (!_tmp14_) {
					guint8 _tmp15_;
					_tmp15_ = x;
					x = _tmp15_ + 1;
				}
				_tmp14_ = FALSE;
				_tmp16_ = self->priv->_columns;
				if (!(x < _tmp16_)) {
					break;
				}
				{
					guint8 y = 0U;
					y = (guint8) 0;
					{
						gboolean _tmp17_ = FALSE;
						_tmp17_ = TRUE;
						while (TRUE) {
							guint8 _tmp19_;
							Tile** _tmp20_;
							gint _tmp20__length1;
							gint _tmp20__length2;
							guint8* _tmp21_;
							gint _tmp21__length1;
							gint _tmp21__length2;
							guint8 _tmp22_;
							Tile* _tmp23_;
							if (!_tmp17_) {
								guint8 _tmp18_;
								_tmp18_ = y;
								y = _tmp18_ + 1;
							}
							_tmp17_ = FALSE;
							_tmp19_ = self->priv->_rows;
							if (!(y < _tmp19_)) {
								break;
							}
							_tmp20_ = self->priv->current_board;
							_tmp20__length1 = self->priv->current_board_length1;
							_tmp20__length2 = self->priv->current_board_length2;
							_tmp21_ = self->priv->initial_board;
							_tmp21__length1 = self->priv->initial_board_length1;
							_tmp21__length2 = self->priv->initial_board_length2;
							_tmp22_ = _tmp21_[(y * _tmp21__length2) + x];
							_tmp23_ = tile_new (x, y, _tmp22_);
							_g_object_unref0 (_tmp20_[(y * _tmp20__length2) + x]);
							_tmp20_[(y * _tmp20__length2) + x] = _tmp23_;
						}
					}
				}
			}
		}
	}
	self->priv->is_started = FALSE;
}

static void
game_populate_new_game (guint8** initial_board,
                        gint* initial_board_length1,
                        gint* initial_board_length2,
                        guint8 color_num)
{
	guint8 rows = 0U;
	gint _tmp0_;
	guint8 columns = 0U;
	gint _tmp1_;
	_tmp0_ = *initial_board_length1;
	rows = (guint8) _tmp0_;
	_tmp1_ = *initial_board_length2;
	columns = (guint8) _tmp1_;
	{
		guint8 x = 0U;
		x = (guint8) 0;
		{
			gboolean _tmp2_ = FALSE;
			_tmp2_ = TRUE;
			while (TRUE) {
				if (!_tmp2_) {
					guint8 _tmp3_;
					_tmp3_ = x;
					x = _tmp3_ + 1;
				}
				_tmp2_ = FALSE;
				if (!(x < columns)) {
					break;
				}
				{
					guint8 y = 0U;
					y = (guint8) 0;
					{
						gboolean _tmp4_ = FALSE;
						_tmp4_ = TRUE;
						while (TRUE) {
							if (!_tmp4_) {
								guint8 _tmp5_;
								_tmp5_ = y;
								y = _tmp5_ + 1;
							}
							_tmp4_ = FALSE;
							if (!(y < rows)) {
								break;
							}
							(*initial_board)[(y * (*initial_board_length2)) + x] = (guint8) (((guint8) floor (g_random_double () * color_num)) + 1);
						}
					}
				}
			}
		}
	}
}

static gboolean
game_bad_colors_number (guint8** initial_board,
                        gint* initial_board_length1,
                        gint* initial_board_length2,
                        guint8 color_num)
{
	guint8 counter = 0U;
	guint8* colors = NULL;
	guint8* _tmp0_;
	gint colors_length1;
	gint _colors_size_;
	guint8 rows = 0U;
	gint _tmp4_;
	guint8 columns = 0U;
	gint _tmp5_;
	gboolean result;
	counter = (guint8) 0;
	_tmp0_ = g_new0 (guint8, color_num);
	colors = _tmp0_;
	colors_length1 = color_num;
	_colors_size_ = colors_length1;
	{
		guint8 x = 0U;
		x = (guint8) 0;
		{
			gboolean _tmp1_ = FALSE;
			_tmp1_ = TRUE;
			while (TRUE) {
				guint8* _tmp3_;
				gint _tmp3__length1;
				if (!_tmp1_) {
					guint8 _tmp2_;
					_tmp2_ = x;
					x = _tmp2_ + 1;
				}
				_tmp1_ = FALSE;
				if (!(x < color_num)) {
					break;
				}
				_tmp3_ = colors;
				_tmp3__length1 = colors_length1;
				_tmp3_[x] = (guint8) 0;
			}
		}
	}
	_tmp4_ = *initial_board_length1;
	rows = (guint8) _tmp4_;
	_tmp5_ = *initial_board_length2;
	columns = (guint8) _tmp5_;
	{
		guint8 x = 0U;
		x = (guint8) 0;
		{
			gboolean _tmp6_ = FALSE;
			_tmp6_ = TRUE;
			while (TRUE) {
				if (!_tmp6_) {
					guint8 _tmp7_;
					_tmp7_ = x;
					x = _tmp7_ + 1;
				}
				_tmp6_ = FALSE;
				if (!(x < columns)) {
					break;
				}
				{
					guint8 y = 0U;
					y = (guint8) 0;
					{
						gboolean _tmp8_ = FALSE;
						_tmp8_ = TRUE;
						while (TRUE) {
							guint8 color_id = 0U;
							guint8 _tmp10_;
							guint8 _tmp11_;
							guint8* _tmp12_;
							gint _tmp12__length1;
							guint8 _tmp13_;
							guint8 _tmp14_;
							guint8* _tmp15_;
							gint _tmp15__length1;
							guint8 _tmp16_;
							guint8 _tmp17_;
							if (!_tmp8_) {
								guint8 _tmp9_;
								_tmp9_ = y;
								y = _tmp9_ + 1;
							}
							_tmp8_ = FALSE;
							if (!(y < rows)) {
								break;
							}
							_tmp10_ = (*initial_board)[(y * (*initial_board_length2)) + x];
							color_id = _tmp10_;
							if (((gint) color_id) == 0) {
								g_assert_not_reached ();
							}
							_tmp11_ = color_id;
							color_id = _tmp11_ - 1;
							if (color_id >= color_num) {
								result = TRUE;
								colors = (g_free (colors), NULL);
								return result;
							}
							_tmp12_ = colors;
							_tmp12__length1 = colors_length1;
							_tmp13_ = _tmp12_[color_id];
							if (((gint) _tmp13_) >= 2) {
								continue;
							}
							_tmp14_ = counter;
							counter = _tmp14_ + 1;
							if (((gint) counter) >= (2 * color_num)) {
								result = FALSE;
								colors = (g_free (colors), NULL);
								return result;
							}
							_tmp15_ = colors;
							_tmp15__length1 = colors_length1;
							_tmp16_ = color_id;
							_tmp17_ = _tmp15_[_tmp16_];
							_tmp15_[_tmp16_] = _tmp17_ + 1;
						}
					}
				}
			}
		}
	}
	result = TRUE;
	colors = (g_free (colors), NULL);
	return result;
}

static gboolean
game_unclickable_board (guint8** initial_board,
                        gint* initial_board_length1,
                        gint* initial_board_length2)
{
	guint8 rows = 0U;
	gint _tmp0_;
	guint8 columns = 0U;
	gint _tmp1_;
	gboolean result;
	_tmp0_ = *initial_board_length1;
	rows = (guint8) _tmp0_;
	_tmp1_ = *initial_board_length2;
	columns = (guint8) _tmp1_;
	{
		guint8 x = 0U;
		x = (guint8) 1;
		{
			gboolean _tmp2_ = FALSE;
			_tmp2_ = TRUE;
			while (TRUE) {
				if (!_tmp2_) {
					guint8 _tmp3_;
					_tmp3_ = x;
					x = _tmp3_ + 1;
				}
				_tmp2_ = FALSE;
				if (!(x < columns)) {
					break;
				}
				{
					guint8 y = 0U;
					y = (guint8) 0;
					{
						gboolean _tmp4_ = FALSE;
						_tmp4_ = TRUE;
						while (TRUE) {
							guint8 _tmp6_;
							guint8 _tmp7_;
							if (!_tmp4_) {
								guint8 _tmp5_;
								_tmp5_ = y;
								y = _tmp5_ + 1;
							}
							_tmp4_ = FALSE;
							if (!(y < rows)) {
								break;
							}
							_tmp6_ = (*initial_board)[(y * (*initial_board_length2)) + x];
							_tmp7_ = (*initial_board)[(y * (*initial_board_length2)) + (x - 1)];
							if (_tmp6_ == _tmp7_) {
								result = FALSE;
								return result;
							}
						}
					}
				}
			}
		}
	}
	{
		guint8 x = 0U;
		x = (guint8) 0;
		{
			gboolean _tmp8_ = FALSE;
			_tmp8_ = TRUE;
			while (TRUE) {
				if (!_tmp8_) {
					guint8 _tmp9_;
					_tmp9_ = x;
					x = _tmp9_ + 1;
				}
				_tmp8_ = FALSE;
				if (!(x < columns)) {
					break;
				}
				{
					guint8 y = 0U;
					y = (guint8) 1;
					{
						gboolean _tmp10_ = FALSE;
						_tmp10_ = TRUE;
						while (TRUE) {
							guint8 _tmp12_;
							guint8 _tmp13_;
							if (!_tmp10_) {
								guint8 _tmp11_;
								_tmp11_ = y;
								y = _tmp11_ + 1;
							}
							_tmp10_ = FALSE;
							if (!(y < rows)) {
								break;
							}
							_tmp12_ = (*initial_board)[(y * (*initial_board_length2)) + x];
							_tmp13_ = (*initial_board)[((y - 1) * (*initial_board_length2)) + x];
							if (_tmp12_ == _tmp13_) {
								result = FALSE;
								return result;
							}
						}
					}
				}
			}
		}
	}
	result = TRUE;
	return result;
}

static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

static GList*
_game_connected_tiles_real (Tile* given_tile,
                            Tile*** current_board,
                            gint* current_board_length1,
                            gint* current_board_length2)
{
	GList* cl = NULL;
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	guint8 x = 0U;
	guint8 _tmp6_;
	guint8 _tmp7_;
	guint8 y = 0U;
	guint8 _tmp8_;
	guint8 _tmp9_;
	Tile* _tmp10_;
	Tile* tile = NULL;
	Tile* _tmp11_;
	gboolean _tmp12_ = FALSE;
	gboolean _tmp13_ = FALSE;
	gint _tmp14_;
	Tile* _tmp33_;
	gboolean _tmp34_ = FALSE;
	gboolean _tmp35_ = FALSE;
	gint _tmp36_;
	GList* result;
	cl = NULL;
	if (given_tile == NULL) {
		_tmp1_ = TRUE;
	} else {
		gboolean _tmp2_;
		gboolean _tmp3_;
		_tmp2_ = tile_get_visited (G_TYPE_CHECK_INSTANCE_CAST (given_tile, TYPE_TILE, Tile));
		_tmp3_ = _tmp2_;
		_tmp1_ = _tmp3_;
	}
	if (_tmp1_) {
		_tmp0_ = TRUE;
	} else {
		gboolean _tmp4_;
		gboolean _tmp5_;
		_tmp4_ = tile_get_closed (G_TYPE_CHECK_INSTANCE_CAST (given_tile, TYPE_TILE, Tile));
		_tmp5_ = _tmp4_;
		_tmp0_ = _tmp5_;
	}
	if (_tmp0_) {
		result = cl;
		return result;
	}
	_tmp6_ = tile_get_grid_x (G_TYPE_CHECK_INSTANCE_CAST (given_tile, TYPE_TILE, Tile));
	_tmp7_ = _tmp6_;
	x = _tmp7_;
	_tmp8_ = tile_get_grid_y (G_TYPE_CHECK_INSTANCE_CAST (given_tile, TYPE_TILE, Tile));
	_tmp9_ = _tmp8_;
	y = _tmp9_;
	tile_set_visited (G_TYPE_CHECK_INSTANCE_CAST (given_tile, TYPE_TILE, Tile), TRUE);
	_tmp10_ = _g_object_ref0 (G_TYPE_CHECK_INSTANCE_CAST (given_tile, TYPE_TILE, Tile));
	cl = g_list_append (cl, _tmp10_);
	_tmp11_ = (*current_board)[((y + 1) * (*current_board_length2)) + x];
	tile = _tmp11_;
	_tmp14_ = *current_board_length1;
	if ((y + 1) < _tmp14_) {
		Tile* _tmp15_;
		_tmp15_ = tile;
		_tmp13_ = _tmp15_ != NULL;
	} else {
		_tmp13_ = FALSE;
	}
	if (_tmp13_) {
		guint8 _tmp16_;
		guint8 _tmp17_;
		Tile* _tmp18_;
		guint8 _tmp19_;
		guint8 _tmp20_;
		_tmp16_ = tile_get_color (G_TYPE_CHECK_INSTANCE_CAST (given_tile, TYPE_TILE, Tile));
		_tmp17_ = _tmp16_;
		_tmp18_ = tile;
		_tmp19_ = tile_get_color (G_TYPE_CHECK_INSTANCE_CAST (_tmp18_, TYPE_TILE, Tile));
		_tmp20_ = _tmp19_;
		_tmp12_ = _tmp17_ == _tmp20_;
	} else {
		_tmp12_ = FALSE;
	}
	if (_tmp12_) {
		Tile* _tmp21_;
		GList* _tmp22_;
		_tmp21_ = tile;
		_tmp22_ = _game_connected_tiles_real (_tmp21_, current_board, (gint*) (current_board_length1), (gint*) (current_board_length2));
		cl = g_list_concat (cl, _tmp22_);
	}
	if (((gint) y) >= 1) {
		Tile* _tmp23_;
		gboolean _tmp24_ = FALSE;
		Tile* _tmp25_;
		_tmp23_ = (*current_board)[((y - 1) * (*current_board_length2)) + x];
		tile = _tmp23_;
		_tmp25_ = tile;
		if (_tmp25_ != NULL) {
			guint8 _tmp26_;
			guint8 _tmp27_;
			Tile* _tmp28_;
			guint8 _tmp29_;
			guint8 _tmp30_;
			_tmp26_ = tile_get_color (G_TYPE_CHECK_INSTANCE_CAST (given_tile, TYPE_TILE, Tile));
			_tmp27_ = _tmp26_;
			_tmp28_ = tile;
			_tmp29_ = tile_get_color (G_TYPE_CHECK_INSTANCE_CAST (_tmp28_, TYPE_TILE, Tile));
			_tmp30_ = _tmp29_;
			_tmp24_ = _tmp27_ == _tmp30_;
		} else {
			_tmp24_ = FALSE;
		}
		if (_tmp24_) {
			Tile* _tmp31_;
			GList* _tmp32_;
			_tmp31_ = tile;
			_tmp32_ = _game_connected_tiles_real (_tmp31_, current_board, (gint*) (current_board_length1), (gint*) (current_board_length2));
			cl = g_list_concat (cl, _tmp32_);
		}
	}
	_tmp33_ = (*current_board)[(y * (*current_board_length2)) + (x + 1)];
	tile = _tmp33_;
	_tmp36_ = *current_board_length2;
	if ((x + 1) < _tmp36_) {
		Tile* _tmp37_;
		_tmp37_ = tile;
		_tmp35_ = _tmp37_ != NULL;
	} else {
		_tmp35_ = FALSE;
	}
	if (_tmp35_) {
		guint8 _tmp38_;
		guint8 _tmp39_;
		Tile* _tmp40_;
		guint8 _tmp41_;
		guint8 _tmp42_;
		_tmp38_ = tile_get_color (G_TYPE_CHECK_INSTANCE_CAST (given_tile, TYPE_TILE, Tile));
		_tmp39_ = _tmp38_;
		_tmp40_ = tile;
		_tmp41_ = tile_get_color (G_TYPE_CHECK_INSTANCE_CAST (_tmp40_, TYPE_TILE, Tile));
		_tmp42_ = _tmp41_;
		_tmp34_ = _tmp39_ == _tmp42_;
	} else {
		_tmp34_ = FALSE;
	}
	if (_tmp34_) {
		Tile* _tmp43_;
		GList* _tmp44_;
		_tmp43_ = tile;
		_tmp44_ = _game_connected_tiles_real (_tmp43_, current_board, (gint*) (current_board_length1), (gint*) (current_board_length2));
		cl = g_list_concat (cl, _tmp44_);
	}
	if (((gint) x) >= 1) {
		Tile* _tmp45_;
		gboolean _tmp46_ = FALSE;
		Tile* _tmp47_;
		_tmp45_ = (*current_board)[(y * (*current_board_length2)) + (x - 1)];
		tile = _tmp45_;
		_tmp47_ = tile;
		if (_tmp47_ != NULL) {
			guint8 _tmp48_;
			guint8 _tmp49_;
			Tile* _tmp50_;
			guint8 _tmp51_;
			guint8 _tmp52_;
			_tmp48_ = tile_get_color (G_TYPE_CHECK_INSTANCE_CAST (given_tile, TYPE_TILE, Tile));
			_tmp49_ = _tmp48_;
			_tmp50_ = tile;
			_tmp51_ = tile_get_color (G_TYPE_CHECK_INSTANCE_CAST (_tmp50_, TYPE_TILE, Tile));
			_tmp52_ = _tmp51_;
			_tmp46_ = _tmp49_ == _tmp52_;
		} else {
			_tmp46_ = FALSE;
		}
		if (_tmp46_) {
			Tile* _tmp53_;
			GList* _tmp54_;
			_tmp53_ = tile;
			_tmp54_ = _game_connected_tiles_real (_tmp53_, current_board, (gint*) (current_board_length1), (gint*) (current_board_length2));
			cl = g_list_concat (cl, _tmp54_);
		}
	}
	result = cl;
	return result;
}

GList*
game_connected_tiles (Game* self,
                      Tile* given_tile)
{
	GList* _tmp0_;
	GList* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (given_tile != NULL, NULL);
	_tmp0_ = _game_connected_tiles (given_tile, &self->priv->current_board, (gint*) (&self->priv->current_board_length1), (gint*) (&self->priv->current_board_length2));
	result = _tmp0_;
	return result;
}

static GList*
_game_connected_tiles (Tile* given_tile,
                       Tile*** current_board,
                       gint* current_board_length1,
                       gint* current_board_length2)
{
	GList* cl = NULL;
	GList* _tmp0_;
	GList* _tmp3_;
	GList* result;
	g_return_val_if_fail (given_tile != NULL, NULL);
	_tmp0_ = _game_connected_tiles_real (given_tile, current_board, (gint*) (current_board_length1), (gint*) (current_board_length2));
	cl = _tmp0_;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint tile_collection_length2 = 0;
		gint tile_it = 0;
		tile_collection = *current_board;
		tile_collection_length1 = (*current_board_length1) * (*current_board_length2);
		for (tile_it = 0; tile_it < tile_collection_length1; tile_it = tile_it + 1) {
			Tile* tile = NULL;
			tile = tile_collection[tile_it];
			{
				Tile* _tmp1_;
				_tmp1_ = tile;
				if (_tmp1_ != NULL) {
					Tile* _tmp2_;
					_tmp2_ = tile;
					tile_set_visited (G_TYPE_CHECK_INSTANCE_CAST (_tmp2_, TYPE_TILE, Tile), FALSE);
				}
			}
		}
	}
	_tmp3_ = cl;
	if (g_list_length (_tmp3_) < ((guint) 2)) {
		result = NULL;
		(cl == NULL) ? NULL : (cl = (_g_list_free__g_object_unref0_ (cl), NULL));
		return result;
	}
	result = cl;
	return result;
}

Tile*
game_get_tile (Game* self,
               guint8 x,
               guint8 y)
{
	Tile** _tmp0_;
	gint _tmp0__length1;
	gint _tmp0__length2;
	Tile* _tmp1_;
	Tile* _tmp2_;
	Tile* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->current_board;
	_tmp0__length1 = self->priv->current_board_length1;
	_tmp0__length2 = self->priv->current_board_length2;
	_tmp1_ = _tmp0_[(y * _tmp0__length2) + x];
	_tmp2_ = _g_object_ref0 (_tmp1_);
	result = _tmp2_;
	return result;
}

void
game_remove_connected_tiles (Game* self,
                             Tile* given_tile)
{
	g_return_if_fail (self != NULL);
	g_return_if_fail (given_tile != NULL);
	game_remove_connected_tiles_real (self, given_tile, FALSE);
}

static void
game_remove_connected_tiles_real (Game* self,
                                  Tile* given_tile,
                                  gboolean skip_history)
{
	gboolean _tmp0_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (given_tile != NULL);
	_game_remove_connected_tiles (self, given_tile, &self->priv->current_board, (gint*) (&self->priv->current_board_length1), (gint*) (&self->priv->current_board_length2), skip_history);
	if (!self->priv->is_started) {
		self->priv->is_started = TRUE;
		g_signal_emit (self, game_signals[GAME_STARTED_SIGNAL], 0);
	}
	_tmp0_ = game_has_completed (&self->priv->current_board, (gint*) (&self->priv->current_board_length1), (gint*) (&self->priv->current_board_length2));
	if (_tmp0_) {
		gboolean _tmp1_;
		_tmp1_ = game_has_won (&self->priv->current_board, (gint*) (&self->priv->current_board_length1), (gint*) (&self->priv->current_board_length2));
		if (_tmp1_) {
			game_increment_score (self, 1000);
		}
		g_signal_emit (self, game_signals[GAME_COMPLETE_SIGNAL], 0);
	}
}

static void
_game_remove_connected_tiles (Game* self,
                              Tile* given_tile,
                              Tile*** current_board,
                              gint* current_board_length1,
                              gint* current_board_length2,
                              gboolean skip_history)
{
	GList* cl = NULL;
	GList* _tmp0_;
	GList* _tmp1_;
	GList* _tmp2_;
	guint8 new_x = 0U;
	guint8* removed_columns = NULL;
	guint8* _tmp4_;
	gint removed_columns_length1;
	gint _removed_columns_size_;
	GList* _tmp46_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (given_tile != NULL);
	_tmp0_ = _game_connected_tiles (given_tile, current_board, (gint*) (current_board_length1), (gint*) (current_board_length2));
	cl = _tmp0_;
	_tmp1_ = cl;
	if (g_list_length (_tmp1_) < ((guint) 2)) {
		(cl == NULL) ? NULL : (cl = (_g_list_free__g_object_unref0_ (cl), NULL));
		return;
	}
	_tmp2_ = cl;
	{
		GList* tile_collection = NULL;
		GList* tile_it = NULL;
		tile_collection = (GList*) _tmp2_;
		for (tile_it = tile_collection; tile_it != NULL; tile_it = tile_it->next) {
			Tile* tile = NULL;
			tile = (Tile*) tile_it->data;
			{
				Tile* _tmp3_;
				_tmp3_ = tile;
				tile_set_closed (_tmp3_, TRUE);
			}
		}
	}
	new_x = (guint8) 0;
	_tmp4_ = g_new0 (guint8, 0);
	removed_columns = _tmp4_;
	removed_columns_length1 = 0;
	_removed_columns_size_ = removed_columns_length1;
	{
		guint8 x = 0U;
		x = (guint8) 0;
		{
			gboolean _tmp5_ = FALSE;
			_tmp5_ = TRUE;
			while (TRUE) {
				guint8 _tmp7_;
				GList* not_closed_tiles = NULL;
				GList* closed_tiles = NULL;
				GList* _tmp20_;
				gboolean has_empty_col = FALSE;
				if (!_tmp5_) {
					guint8 _tmp6_;
					_tmp6_ = x;
					x = _tmp6_ + 1;
				}
				_tmp5_ = FALSE;
				_tmp7_ = self->priv->_columns;
				if (!(x < _tmp7_)) {
					break;
				}
				not_closed_tiles = NULL;
				closed_tiles = NULL;
				{
					guint8 y = 0U;
					y = (guint8) 0;
					{
						gboolean _tmp8_ = FALSE;
						_tmp8_ = TRUE;
						while (TRUE) {
							guint8 _tmp10_;
							Tile* tile = NULL;
							Tile* _tmp11_;
							Tile* _tmp12_;
							Tile* _tmp13_;
							gboolean _tmp14_;
							gboolean _tmp15_;
							if (!_tmp8_) {
								guint8 _tmp9_;
								_tmp9_ = y;
								y = _tmp9_ + 1;
							}
							_tmp8_ = FALSE;
							_tmp10_ = self->priv->_rows;
							if (!(y < _tmp10_)) {
								break;
							}
							_tmp11_ = (*current_board)[(y * (*current_board_length2)) + x];
							tile = _tmp11_;
							_tmp12_ = tile;
							if (_tmp12_ == NULL) {
								break;
							}
							_tmp13_ = tile;
							_tmp14_ = tile_get_closed (G_TYPE_CHECK_INSTANCE_CAST (_tmp13_, TYPE_TILE, Tile));
							_tmp15_ = _tmp14_;
							if (_tmp15_) {
								Tile* _tmp16_;
								Tile* _tmp17_;
								_tmp16_ = tile;
								_tmp17_ = _g_object_ref0 (G_TYPE_CHECK_INSTANCE_CAST (_tmp16_, TYPE_TILE, Tile));
								closed_tiles = g_list_append (closed_tiles, _tmp17_);
							} else {
								Tile* _tmp18_;
								Tile* _tmp19_;
								_tmp18_ = tile;
								_tmp19_ = _g_object_ref0 (G_TYPE_CHECK_INSTANCE_CAST (_tmp18_, TYPE_TILE, Tile));
								not_closed_tiles = g_list_append (not_closed_tiles, _tmp19_);
							}
						}
					}
				}
				_tmp20_ = closed_tiles;
				closed_tiles = NULL;
				not_closed_tiles = g_list_concat (not_closed_tiles, _tmp20_);
				{
					guint8 y = 0U;
					y = (guint8) 0;
					{
						gboolean _tmp21_ = FALSE;
						_tmp21_ = TRUE;
						while (TRUE) {
							guint8 _tmp23_;
							GList* _tmp24_;
							gconstpointer _tmp25_;
							Tile* _tmp26_;
							if (!_tmp21_) {
								guint8 _tmp22_;
								_tmp22_ = y;
								y = _tmp22_ + 1;
							}
							_tmp21_ = FALSE;
							_tmp23_ = self->priv->_rows;
							if (!(y < _tmp23_)) {
								break;
							}
							_tmp24_ = not_closed_tiles;
							_tmp25_ = g_list_nth_data (_tmp24_, (guint) y);
							_tmp26_ = _g_object_ref0 ((Tile*) _tmp25_);
							_g_object_unref0 ((*current_board)[(y * (*current_board_length2)) + new_x]);
							(*current_board)[(y * (*current_board_length2)) + new_x] = _tmp26_;
						}
					}
				}
				has_empty_col = TRUE;
				{
					guint8 y = 0U;
					y = (guint8) 0;
					{
						gboolean _tmp27_ = FALSE;
						_tmp27_ = TRUE;
						while (TRUE) {
							guint8 _tmp29_;
							Tile* tile = NULL;
							Tile* _tmp30_;
							Tile* _tmp31_;
							Tile* _tmp32_;
							gboolean _tmp33_;
							gboolean _tmp34_;
							if (!_tmp27_) {
								guint8 _tmp28_;
								_tmp28_ = y;
								y = _tmp28_ + 1;
							}
							_tmp27_ = FALSE;
							_tmp29_ = self->priv->_rows;
							if (!(y < _tmp29_)) {
								break;
							}
							_tmp30_ = (*current_board)[(y * (*current_board_length2)) + new_x];
							tile = _tmp30_;
							_tmp31_ = tile;
							if (_tmp31_ == NULL) {
								break;
							}
							_tmp32_ = tile;
							_tmp33_ = tile_get_closed (G_TYPE_CHECK_INSTANCE_CAST (_tmp32_, TYPE_TILE, Tile));
							_tmp34_ = _tmp33_;
							if (!_tmp34_) {
								Tile* _tmp35_;
								_tmp35_ = tile;
								tile_update_position (G_TYPE_CHECK_INSTANCE_CAST (_tmp35_, TYPE_TILE, Tile), new_x, y);
								has_empty_col = FALSE;
							}
						}
					}
				}
				if (!has_empty_col) {
					guint8 _tmp36_;
					_tmp36_ = new_x;
					new_x = _tmp36_ + 1;
				} else {
					gint length = 0;
					guint8* _tmp37_;
					gint _tmp37__length1;
					gint _tmp38_;
					guint8* _tmp39_;
					gint _tmp39__length1;
					_tmp37_ = removed_columns;
					_tmp37__length1 = removed_columns_length1;
					length = _tmp37__length1;
					_tmp38_ = length + 1;
					removed_columns = g_renew (guint8, removed_columns, length + 1);
					(_tmp38_ > removed_columns_length1) ? memset (removed_columns + removed_columns_length1, 0, sizeof (guint8) * (_tmp38_ - removed_columns_length1)) : NULL;
					removed_columns_length1 = _tmp38_;
					_removed_columns_size_ = _tmp38_;
					_vala_array_move (removed_columns, sizeof (guint8), 0, 1, length);
					_tmp39_ = removed_columns;
					_tmp39__length1 = removed_columns_length1;
					_tmp39_[0] = new_x;
				}
				(closed_tiles == NULL) ? NULL : (closed_tiles = (_g_list_free__g_object_unref0_ (closed_tiles), NULL));
				(not_closed_tiles == NULL) ? NULL : (not_closed_tiles = (_g_list_free__g_object_unref0_ (not_closed_tiles), NULL));
			}
		}
	}
	{
		gboolean _tmp40_ = FALSE;
		_tmp40_ = TRUE;
		while (TRUE) {
			guint8 _tmp42_;
			if (!_tmp40_) {
				guint8 _tmp41_;
				_tmp41_ = new_x;
				new_x = _tmp41_ + 1;
			}
			_tmp40_ = FALSE;
			_tmp42_ = self->priv->_columns;
			if (!(new_x < _tmp42_)) {
				break;
			}
			{
				guint8 y = 0U;
				y = (guint8) 0;
				{
					gboolean _tmp43_ = FALSE;
					_tmp43_ = TRUE;
					while (TRUE) {
						guint8 _tmp45_;
						if (!_tmp43_) {
							guint8 _tmp44_;
							_tmp44_ = y;
							y = _tmp44_ + 1;
						}
						_tmp43_ = FALSE;
						_tmp45_ = self->priv->_rows;
						if (!(y < _tmp45_)) {
							break;
						}
						_g_object_unref0 ((*current_board)[(y * (*current_board_length2)) + new_x]);
						(*current_board)[(y * (*current_board_length2)) + new_x] = NULL;
					}
				}
			}
		}
	}
	_tmp46_ = cl;
	game_increment_score_from_tiles (self, (guint16) g_list_length (_tmp46_));
	if (!skip_history) {
		guint8 _tmp47_;
		guint8 _tmp48_;
		guint8 _tmp49_;
		guint8 _tmp50_;
		guint8 _tmp51_;
		guint8 _tmp52_;
		GList* _tmp53_;
		guint8* _tmp54_;
		gint _tmp54__length1;
		_tmp47_ = tile_get_grid_x (given_tile);
		_tmp48_ = _tmp47_;
		_tmp49_ = tile_get_grid_y (given_tile);
		_tmp50_ = _tmp49_;
		_tmp51_ = tile_get_color (given_tile);
		_tmp52_ = _tmp51_;
		_tmp53_ = cl;
		_tmp54_ = removed_columns;
		_tmp54__length1 = removed_columns_length1;
		removed_columns = NULL;
		removed_columns_length1 = 0;
		game_add_history_entry (self, _tmp48_, _tmp50_, _tmp52_, _tmp53_, _tmp54_, (gint) _tmp54__length1);
	}
	removed_columns = (g_free (removed_columns), NULL);
	(cl == NULL) ? NULL : (cl = (_g_list_free__g_object_unref0_ (cl), NULL));
}

static gboolean
game_has_completed (Tile*** current_board,
                    gint* current_board_length1,
                    gint* current_board_length2)
{
	gboolean result;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint tile_collection_length2 = 0;
		gint tile_it = 0;
		tile_collection = *current_board;
		tile_collection_length1 = (*current_board_length1) * (*current_board_length2);
		for (tile_it = 0; tile_it < tile_collection_length1; tile_it = tile_it + 1) {
			Tile* tile = NULL;
			tile = tile_collection[tile_it];
			{
				gboolean _tmp0_ = FALSE;
				gboolean _tmp1_ = FALSE;
				Tile* _tmp2_;
				_tmp2_ = tile;
				if (_tmp2_ != NULL) {
					Tile* _tmp3_;
					gboolean _tmp4_;
					gboolean _tmp5_;
					_tmp3_ = tile;
					_tmp4_ = tile_get_closed (G_TYPE_CHECK_INSTANCE_CAST (_tmp3_, TYPE_TILE, Tile));
					_tmp5_ = _tmp4_;
					_tmp1_ = !_tmp5_;
				} else {
					_tmp1_ = FALSE;
				}
				if (_tmp1_) {
					Tile* _tmp6_;
					GList* _tmp7_;
					GList* _tmp8_;
					_tmp6_ = tile;
					_tmp7_ = _game_connected_tiles (G_TYPE_CHECK_INSTANCE_CAST (_tmp6_, TYPE_TILE, Tile), current_board, (gint*) (current_board_length1), (gint*) (current_board_length2));
					_tmp8_ = _tmp7_;
					_tmp0_ = g_list_length (_tmp8_) > ((guint) 1);
					(_tmp8_ == NULL) ? NULL : (_tmp8_ = (_g_list_free__g_object_unref0_ (_tmp8_), NULL));
				} else {
					_tmp0_ = FALSE;
				}
				if (_tmp0_) {
					result = FALSE;
					return result;
				}
			}
		}
	}
	result = TRUE;
	return result;
}

static gboolean
game_has_won (Tile*** current_board,
              gint* current_board_length1,
              gint* current_board_length2)
{
	gboolean result;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint tile_collection_length2 = 0;
		gint tile_it = 0;
		tile_collection = *current_board;
		tile_collection_length1 = (*current_board_length1) * (*current_board_length2);
		for (tile_it = 0; tile_it < tile_collection_length1; tile_it = tile_it + 1) {
			Tile* tile = NULL;
			tile = tile_collection[tile_it];
			{
				gboolean _tmp0_ = FALSE;
				Tile* _tmp1_;
				_tmp1_ = tile;
				if (_tmp1_ != NULL) {
					Tile* _tmp2_;
					gboolean _tmp3_;
					gboolean _tmp4_;
					_tmp2_ = tile;
					_tmp3_ = tile_get_closed (G_TYPE_CHECK_INSTANCE_CAST (_tmp2_, TYPE_TILE, Tile));
					_tmp4_ = _tmp3_;
					_tmp0_ = !_tmp4_;
				} else {
					_tmp0_ = FALSE;
				}
				if (_tmp0_) {
					result = FALSE;
					return result;
				}
			}
		}
	}
	result = TRUE;
	return result;
}

static inline void
game_decrement_score_from_tiles (Game* self,
                                 guint16 n_tiles)
{
	g_return_if_fail (self != NULL);
	game_increment_score (self, -1 * game_get_score_from_tiles (self, n_tiles));
}

static inline void
game_increment_score_from_tiles (Game* self,
                                 guint16 n_tiles)
{
	g_return_if_fail (self != NULL);
	game_increment_score (self, game_get_score_from_tiles (self, n_tiles));
}

static inline gint
game_get_score_from_tiles (Game* self,
                           guint16 n_tiles)
{
	gint _tmp0_ = 0;
	gint result;
	g_return_val_if_fail (self != NULL, 0);
	if (((gint) n_tiles) < 3) {
		_tmp0_ = 0;
	} else {
		_tmp0_ = (n_tiles - 2) * (n_tiles - 2);
	}
	result = _tmp0_;
	return result;
}

static void
game_increment_score (Game* self,
                      gint variation)
{
	guint _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->_score;
	game_set_score (self, _tmp0_ + variation);
	if (variation > 0) {
		g_signal_emit (self, game_signals[GAME_UPDATE_SCORE_SIGNAL], 0, (guint) variation);
	} else {
		g_signal_emit (self, game_signals[GAME_UPDATE_SCORE_SIGNAL], 0, (guint) 0);
	}
}

static Tile**
_vala_array_dup1 (Tile** self,
                  gssize length)
{
	if (length >= 0) {
		Tile** result;
		gssize i;
		result = g_new0 (Tile*, length + 1);
		for (i = 0; i < length; i++) {
			Tile* _tmp0_;
			_tmp0_ = _g_object_ref0 (self[i]);
			result[i] = _tmp0_;
		}
		return result;
	}
	return NULL;
}

static guint8*
_vala_array_dup2 (guint8* self,
                  gssize length)
{
	if (length > 0) {
		return _vala_memdup2 (self, length * sizeof (guint8));
	}
	return NULL;
}

static inline gboolean
game_load_saved_game (Game* self,
                      GVariant* variant)
{
	const gchar* _tmp0_;
	GVariant* child = NULL;
	GVariant* _tmp1_;
	GVariant* _tmp2_;
	GVariantIter* iter = NULL;
	GVariant* _tmp3_;
	GVariantIter* _tmp4_;
	GVariant* board_variant = NULL;
	GVariantIter* _tmp5_;
	GVariant* _tmp6_;
	GVariant* _tmp7_;
	guint16 history_index = 0U;
	GVariantIter* _tmp8_;
	guint16 _tmp9_ = 0U;
	GVariant* history_variant = NULL;
	GVariantIter* _tmp10_;
	GVariant* _tmp11_;
	GVariant* _tmp12_;
	GVariant* tmp_variant_1 = NULL;
	GVariant* _tmp13_;
	GVariant* _tmp14_;
	GVariant* _tmp15_;
	guint rows = 0U;
	GVariant* _tmp16_;
	guint columns = 0U;
	GVariant* _tmp17_;
	gboolean _tmp18_ = FALSE;
	guint8 _tmp19_;
	guint8* initial_board = NULL;
	guint8* _tmp21_;
	gint initial_board_length1;
	gint initial_board_length2;
	gboolean _tmp32_ = FALSE;
	guint8 _tmp33_;
	guint8 _tmp34_;
	gboolean _tmp35_;
	Tile** current_board = NULL;
	Tile** _tmp37_;
	gint current_board_length1;
	gint current_board_length2;
	GVariant* _tmp46_;
	GVariantIter* _tmp47_;
	GList* _tmp60_;
	gboolean _tmp63_;
	Tile** _tmp64_;
	gint _tmp64__length1;
	gint _tmp64__length2;
	Tile** _tmp65_;
	gint _tmp65__length1;
	gint _tmp65__length2;
	guint8* _tmp66_;
	gint _tmp66__length1;
	gint _tmp66__length2;
	guint8* _tmp67_;
	gint _tmp67__length1;
	gint _tmp67__length2;
	guint _tmp68_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (variant != NULL, FALSE);
	_tmp0_ = g_variant_get_type_string (variant);
	if (g_strcmp0 (_tmp0_, "m(aayqa(yy))") != 0) {
		result = FALSE;
		return result;
	}
	_tmp1_ = g_variant_get_maybe (variant);
	child = _tmp1_;
	_tmp2_ = child;
	if (_tmp2_ == NULL) {
		result = FALSE;
		_g_variant_unref0 (child);
		return result;
	}
	_tmp3_ = child;
	_tmp4_ = g_variant_iter_new ((GVariant*) _tmp3_);
	iter = _tmp4_;
	_tmp5_ = iter;
	_tmp6_ = g_variant_iter_next_value (_tmp5_);
	board_variant = _tmp6_;
	_tmp7_ = board_variant;
	if (_tmp7_ == NULL) {
		g_assert_not_reached ();
	}
	_tmp8_ = iter;
	g_variant_iter_next (_tmp8_, "q", &_tmp9_, NULL);
	history_index = _tmp9_;
	_tmp10_ = iter;
	_tmp11_ = g_variant_iter_next_value (_tmp10_);
	history_variant = _tmp11_;
	_tmp12_ = history_variant;
	if (_tmp12_ == NULL) {
		g_assert_not_reached ();
	}
	_tmp13_ = board_variant;
	_tmp14_ = g_variant_get_child_value ((GVariant*) _tmp13_, (gsize) 0);
	tmp_variant_1 = _tmp14_;
	_tmp15_ = tmp_variant_1;
	if (_tmp15_ == NULL) {
		result = FALSE;
		_g_variant_unref0 (tmp_variant_1);
		_g_variant_unref0 (history_variant);
		_g_variant_unref0 (board_variant);
		_g_variant_iter_free0 (iter);
		_g_variant_unref0 (child);
		return result;
	}
	_tmp16_ = board_variant;
	rows = (guint) g_variant_n_children ((GVariant*) _tmp16_);
	_tmp17_ = tmp_variant_1;
	columns = (guint) g_variant_n_children ((GVariant*) _tmp17_);
	_tmp19_ = self->priv->_rows;
	if (rows != ((guint) _tmp19_)) {
		_tmp18_ = TRUE;
	} else {
		guint8 _tmp20_;
		_tmp20_ = self->priv->_columns;
		_tmp18_ = columns != ((guint) _tmp20_);
	}
	if (_tmp18_) {
		result = FALSE;
		_g_variant_unref0 (tmp_variant_1);
		_g_variant_unref0 (history_variant);
		_g_variant_unref0 (board_variant);
		_g_variant_iter_free0 (iter);
		_g_variant_unref0 (child);
		return result;
	}
	_tmp21_ = g_new0 (guint8, rows * columns);
	initial_board = _tmp21_;
	initial_board_length1 = rows;
	initial_board_length2 = columns;
	{
		guint8 i = 0U;
		i = (guint8) 0;
		{
			gboolean _tmp22_ = FALSE;
			_tmp22_ = TRUE;
			while (TRUE) {
				GVariant* _tmp24_;
				GVariant* _tmp25_;
				if (!_tmp22_) {
					guint8 _tmp23_;
					_tmp23_ = i;
					i = _tmp23_ + 1;
				}
				_tmp22_ = FALSE;
				if (!(((guint) i) < rows)) {
					break;
				}
				_tmp24_ = board_variant;
				_tmp25_ = g_variant_get_child_value ((GVariant*) _tmp24_, (gsize) i);
				_g_variant_unref0 (tmp_variant_1);
				tmp_variant_1 = _tmp25_;
				{
					guint8 j = 0U;
					j = (guint8) 0;
					{
						gboolean _tmp26_ = FALSE;
						_tmp26_ = TRUE;
						while (TRUE) {
							GVariant* tmp_variant_2 = NULL;
							GVariant* _tmp28_;
							GVariant* _tmp29_;
							guint8 color = 0U;
							GVariant* _tmp30_;
							guint8* _tmp31_;
							gint _tmp31__length1;
							gint _tmp31__length2;
							if (!_tmp26_) {
								guint8 _tmp27_;
								_tmp27_ = j;
								j = _tmp27_ + 1;
							}
							_tmp26_ = FALSE;
							if (!(((guint) j) < columns)) {
								break;
							}
							_tmp28_ = tmp_variant_1;
							_tmp29_ = g_variant_get_child_value (_tmp28_, (gsize) j);
							tmp_variant_2 = _tmp29_;
							_tmp30_ = tmp_variant_2;
							color = g_variant_get_byte (_tmp30_);
							if (((gint) color) > 4) {
								result = FALSE;
								_g_variant_unref0 (tmp_variant_2);
								initial_board = (g_free (initial_board), NULL);
								_g_variant_unref0 (tmp_variant_1);
								_g_variant_unref0 (history_variant);
								_g_variant_unref0 (board_variant);
								_g_variant_iter_free0 (iter);
								_g_variant_unref0 (child);
								return result;
							}
							if (((gint) color) == 0) {
								result = FALSE;
								_g_variant_unref0 (tmp_variant_2);
								initial_board = (g_free (initial_board), NULL);
								_g_variant_unref0 (tmp_variant_1);
								_g_variant_unref0 (history_variant);
								_g_variant_unref0 (board_variant);
								_g_variant_iter_free0 (iter);
								_g_variant_unref0 (child);
								return result;
							}
							_tmp31_ = initial_board;
							_tmp31__length1 = initial_board_length1;
							_tmp31__length2 = initial_board_length2;
							_tmp31_[(((rows - i) - 1) * _tmp31__length2) + j] = color;
							_g_variant_unref0 (tmp_variant_2);
						}
					}
				}
			}
		}
	}
	_tmp33_ = game_get_color_num (self);
	_tmp34_ = _tmp33_;
	_tmp35_ = game_bad_colors_number (&initial_board, (gint*) (&initial_board_length1), (gint*) (&initial_board_length2), _tmp34_);
	if (_tmp35_) {
		_tmp32_ = TRUE;
	} else {
		gboolean _tmp36_;
		_tmp36_ = game_unclickable_board (&initial_board, (gint*) (&initial_board_length1), (gint*) (&initial_board_length2));
		_tmp32_ = _tmp36_;
	}
	if (_tmp32_) {
		result = FALSE;
		initial_board = (g_free (initial_board), NULL);
		_g_variant_unref0 (tmp_variant_1);
		_g_variant_unref0 (history_variant);
		_g_variant_unref0 (board_variant);
		_g_variant_iter_free0 (iter);
		_g_variant_unref0 (child);
		return result;
	}
	_tmp37_ = g_new0 (Tile*, (rows * columns) + 1);
	current_board = _tmp37_;
	current_board_length1 = rows;
	current_board_length2 = columns;
	{
		guint8 i = 0U;
		i = (guint8) 0;
		{
			gboolean _tmp38_ = FALSE;
			_tmp38_ = TRUE;
			while (TRUE) {
				if (!_tmp38_) {
					guint8 _tmp39_;
					_tmp39_ = i;
					i = _tmp39_ + 1;
				}
				_tmp38_ = FALSE;
				if (!(((guint) i) < rows)) {
					break;
				}
				{
					guint8 j = 0U;
					j = (guint8) 0;
					{
						gboolean _tmp40_ = FALSE;
						_tmp40_ = TRUE;
						while (TRUE) {
							Tile** _tmp42_;
							gint _tmp42__length1;
							gint _tmp42__length2;
							guint8* _tmp43_;
							gint _tmp43__length1;
							gint _tmp43__length2;
							guint8 _tmp44_;
							Tile* _tmp45_;
							if (!_tmp40_) {
								guint8 _tmp41_;
								_tmp41_ = j;
								j = _tmp41_ + 1;
							}
							_tmp40_ = FALSE;
							if (!(((guint) j) < columns)) {
								break;
							}
							_tmp42_ = current_board;
							_tmp42__length1 = current_board_length1;
							_tmp42__length2 = current_board_length2;
							_tmp43_ = initial_board;
							_tmp43__length1 = initial_board_length1;
							_tmp43__length2 = initial_board_length2;
							_tmp44_ = _tmp43_[(i * _tmp43__length2) + j];
							_tmp45_ = tile_new (j, i, _tmp44_);
							_g_object_unref0 (_tmp42_[(i * _tmp42__length2) + j]);
							_tmp42_[(i * _tmp42__length2) + j] = _tmp45_;
						}
					}
				}
			}
		}
	}
	_tmp46_ = history_variant;
	_tmp47_ = g_variant_iter_new ((GVariant*) _tmp46_);
	_g_variant_iter_free0 (iter);
	iter = _tmp47_;
	while (TRUE) {
		GVariantIter* _tmp48_;
		GVariantIter* _tmp49_;
		GVariant* _tmp50_;
		GVariant* _tmp51_;
		Tile** _tmp52_;
		gint _tmp52__length1;
		gint _tmp52__length2;
		GVariant* _tmp53_;
		GVariant* _tmp54_;
		GVariant* _tmp55_;
		GVariant* _tmp56_;
		GVariant* _tmp57_;
		GVariant* _tmp58_;
		Tile* _tmp59_;
		_tmp48_ = iter;
		if (!(_tmp48_ != NULL)) {
			break;
		}
		_tmp49_ = iter;
		_tmp50_ = g_variant_iter_next_value (_tmp49_);
		_g_variant_unref0 (tmp_variant_1);
		tmp_variant_1 = _tmp50_;
		_tmp51_ = tmp_variant_1;
		if (_tmp51_ == NULL) {
			break;
		}
		_tmp52_ = current_board;
		_tmp52__length1 = current_board_length1;
		_tmp52__length2 = current_board_length2;
		_tmp53_ = tmp_variant_1;
		_tmp54_ = g_variant_get_child_value (_tmp53_, (gsize) 1);
		_tmp55_ = _tmp54_;
		_tmp56_ = tmp_variant_1;
		_tmp57_ = g_variant_get_child_value (_tmp56_, (gsize) 0);
		_tmp58_ = _tmp57_;
		_tmp59_ = _tmp52_[(((rows - g_variant_get_byte (_tmp55_)) - 1) * _tmp52__length2) + g_variant_get_byte (_tmp58_)];
		_game_remove_connected_tiles (self, _tmp59_, &current_board, (gint*) (&current_board_length1), (gint*) (&current_board_length2), FALSE);
		_g_variant_unref0 (_tmp58_);
		_g_variant_unref0 (_tmp55_);
	}
	_tmp60_ = self->priv->reversed_history;
	if (((guint) history_index) > g_list_length (_tmp60_)) {
		game_clear_history (self);
		result = FALSE;
		current_board = (_vala_array_free (current_board, current_board_length1 * current_board_length2, (GDestroyNotify) g_object_unref), NULL);
		initial_board = (g_free (initial_board), NULL);
		_g_variant_unref0 (tmp_variant_1);
		_g_variant_unref0 (history_variant);
		_g_variant_unref0 (board_variant);
		_g_variant_iter_free0 (iter);
		_g_variant_unref0 (child);
		return result;
	}
	{
		guint16 i = 0U;
		i = history_index;
		{
			gboolean _tmp61_ = FALSE;
			_tmp61_ = TRUE;
			while (TRUE) {
				if (!_tmp61_) {
					guint16 _tmp62_;
					_tmp62_ = i;
					i = _tmp62_ - 1;
				}
				_tmp61_ = FALSE;
				if (!(((gint) i) != 0)) {
					break;
				}
				game_undo_real (self, &current_board, (gint*) (&current_board_length1), (gint*) (&current_board_length2));
			}
		}
	}
	_tmp63_ = game_has_completed (&current_board, (gint*) (&current_board_length1), (gint*) (&current_board_length2));
	if (_tmp63_) {
		game_clear_history (self);
		result = FALSE;
		current_board = (_vala_array_free (current_board, current_board_length1 * current_board_length2, (GDestroyNotify) g_object_unref), NULL);
		initial_board = (g_free (initial_board), NULL);
		_g_variant_unref0 (tmp_variant_1);
		_g_variant_unref0 (history_variant);
		_g_variant_unref0 (board_variant);
		_g_variant_iter_free0 (iter);
		_g_variant_unref0 (child);
		return result;
	}
	_tmp64_ = current_board;
	_tmp64__length1 = current_board_length1;
	_tmp64__length2 = current_board_length2;
	_tmp65_ = (_tmp64_ != NULL) ? _vala_array_dup1 (_tmp64_, _tmp64__length1 * _tmp64__length2) : _tmp64_;
	_tmp65__length1 = _tmp64__length1;
	_tmp65__length2 = _tmp64__length2;
	self->priv->current_board = (_vala_array_free (self->priv->current_board, self->priv->current_board_length1 * self->priv->current_board_length2, (GDestroyNotify) g_object_unref), NULL);
	self->priv->current_board = _tmp65_;
	self->priv->current_board_length1 = _tmp65__length1;
	self->priv->current_board_length2 = _tmp65__length2;
	_tmp66_ = initial_board;
	_tmp66__length1 = initial_board_length1;
	_tmp66__length2 = initial_board_length2;
	_tmp67_ = (_tmp66_ != NULL) ? _vala_array_dup2 (_tmp66_, _tmp66__length1 * _tmp66__length2) : _tmp66_;
	_tmp67__length1 = _tmp66__length1;
	_tmp67__length2 = _tmp66__length2;
	self->priv->initial_board = (g_free (self->priv->initial_board), NULL);
	self->priv->initial_board = _tmp67_;
	self->priv->initial_board_length1 = _tmp67__length1;
	self->priv->initial_board_length2 = _tmp67__length2;
	self->priv->history_index = history_index;
	_tmp68_ = self->priv->_score;
	g_signal_emit (self, game_signals[GAME_UPDATE_SCORE_SIGNAL], 0, _tmp68_);
	self->priv->is_started = TRUE;
	result = TRUE;
	current_board = (_vala_array_free (current_board, current_board_length1 * current_board_length2, (GDestroyNotify) g_object_unref), NULL);
	initial_board = (g_free (initial_board), NULL);
	_g_variant_unref0 (tmp_variant_1);
	_g_variant_unref0 (history_variant);
	_g_variant_unref0 (board_variant);
	_g_variant_iter_free0 (iter);
	_g_variant_unref0 (child);
	return result;
}

static Block1Data*
block1_data_ref (Block1Data* _data1_)
{
	g_atomic_int_inc (&_data1_->_ref_count_);
	return _data1_;
}

static void
block1_data_unref (void * _userdata_)
{
	Block1Data* _data1_;
	_data1_ = (Block1Data*) _userdata_;
	if (g_atomic_int_dec_and_test (&_data1_->_ref_count_)) {
		Game* self;
		self = _data1_->self;
		_g_variant_builder_unref0 (_data1_->builder);
		_g_object_unref0 (self);
		g_slice_free (Block1Data, _data1_);
	}
}

static void
__lambda5_ (Block1Data* _data1_,
            GameHistoryEntry* data)
{
	Game* self;
	GVariantBuilder* _tmp0_;
	GVariantType* _tmp1_;
	GVariantType* _tmp2_;
	GVariantBuilder* _tmp3_;
	GamePoint* _tmp4_;
	GamePoint* _tmp5_;
	guint8 _tmp6_;
	guint8 _tmp7_;
	GVariantBuilder* _tmp8_;
	guint8 _tmp9_;
	GamePoint* _tmp10_;
	GamePoint* _tmp11_;
	guint8 _tmp12_;
	guint8 _tmp13_;
	GVariantBuilder* _tmp14_;
	self = _data1_->self;
	g_return_if_fail (data != NULL);
	if (data == NULL) {
		return;
	}
	_tmp0_ = _data1_->builder;
	_tmp1_ = g_variant_type_new ("(yy)");
	_tmp2_ = _tmp1_;
	g_variant_builder_open (_tmp0_, _tmp2_);
	_g_variant_type_free0 (_tmp2_);
	_tmp3_ = _data1_->builder;
	_tmp4_ = game_history_entry_get_click (G_TYPE_CHECK_INSTANCE_CAST (data, GAME_TYPE_HISTORY_ENTRY, GameHistoryEntry));
	_tmp5_ = _tmp4_;
	_tmp6_ = game_point_get_x (_tmp5_);
	_tmp7_ = _tmp6_;
	g_variant_builder_add (_tmp3_, "y", _tmp7_, NULL);
	_tmp8_ = _data1_->builder;
	_tmp9_ = self->priv->_rows;
	_tmp10_ = game_history_entry_get_click (G_TYPE_CHECK_INSTANCE_CAST (data, GAME_TYPE_HISTORY_ENTRY, GameHistoryEntry));
	_tmp11_ = _tmp10_;
	_tmp12_ = game_point_get_y (_tmp11_);
	_tmp13_ = _tmp12_;
	g_variant_builder_add (_tmp8_, "y", (_tmp9_ - _tmp13_) - 1, NULL);
	_tmp14_ = _data1_->builder;
	g_variant_builder_close (_tmp14_);
}

static void
___lambda5__gfunc (gconstpointer data,
                   gpointer self)
{
	__lambda5_ (self, (GameHistoryEntry*) data);
}

GVariant*
game_get_saved_game (Game* self)
{
	Block1Data* _data1_;
	gboolean _tmp0_ = FALSE;
	GVariantType* _tmp3_;
	GVariantType* _tmp4_;
	GVariantBuilder* _tmp5_;
	GVariantBuilder* _tmp6_;
	GVariantBuilder* _tmp7_;
	GVariantType* _tmp8_;
	GVariantType* _tmp9_;
	GVariantType* ay_type = NULL;
	GVariantType* _tmp10_;
	GVariantBuilder* _tmp23_;
	GVariantBuilder* _tmp24_;
	GVariantBuilder* _tmp25_;
	GVariantType* _tmp26_;
	GVariantType* _tmp27_;
	GList* _tmp28_;
	GVariantBuilder* _tmp29_;
	GVariantBuilder* _tmp30_;
	GVariant* _tmp31_;
	GVariant* _tmp32_;
	GVariant* _tmp33_;
	GVariant* _tmp34_;
	GVariant* result;
	g_return_val_if_fail (self != NULL, NULL);
	_data1_ = g_slice_new0 (Block1Data);
	_data1_->_ref_count_ = 1;
	_data1_->self = g_object_ref (self);
	if (!self->priv->is_started) {
		_tmp0_ = TRUE;
	} else {
		gboolean _tmp1_;
		_tmp1_ = game_has_completed (&self->priv->current_board, (gint*) (&self->priv->current_board_length1), (gint*) (&self->priv->current_board_length2));
		_tmp0_ = _tmp1_;
	}
	if (_tmp0_) {
		GVariant* _tmp2_;
		_tmp2_ = g_variant_new ("m(aayqa(yy))", NULL, NULL);
		g_variant_ref_sink (_tmp2_);
		result = _tmp2_;
		block1_data_unref (_data1_);
		_data1_ = NULL;
		return result;
	}
	_tmp3_ = g_variant_type_new ("(aayqa(yy))");
	_tmp4_ = _tmp3_;
	_tmp5_ = g_variant_builder_new (_tmp4_);
	_tmp6_ = _tmp5_;
	_g_variant_type_free0 (_tmp4_);
	_data1_->builder = _tmp6_;
	_tmp7_ = _data1_->builder;
	_tmp8_ = g_variant_type_new ("aay");
	_tmp9_ = _tmp8_;
	g_variant_builder_open (_tmp7_, _tmp9_);
	_g_variant_type_free0 (_tmp9_);
	_tmp10_ = g_variant_type_new ("ay");
	ay_type = _tmp10_;
	{
		guint8 i = 0U;
		guint8 _tmp11_;
		_tmp11_ = self->priv->_rows;
		i = _tmp11_;
		{
			gboolean _tmp12_ = FALSE;
			_tmp12_ = TRUE;
			while (TRUE) {
				GVariantBuilder* _tmp14_;
				const GVariantType* _tmp15_;
				GVariantBuilder* _tmp22_;
				if (!_tmp12_) {
					guint8 _tmp13_;
					_tmp13_ = i;
					i = _tmp13_ - 1;
				}
				_tmp12_ = FALSE;
				if (!(((gint) i) > 0)) {
					break;
				}
				_tmp14_ = _data1_->builder;
				_tmp15_ = ay_type;
				g_variant_builder_open (_tmp14_, _tmp15_);
				{
					guint8 j = 0U;
					j = (guint8) 0;
					{
						gboolean _tmp16_ = FALSE;
						_tmp16_ = TRUE;
						while (TRUE) {
							guint8 _tmp18_;
							GVariantBuilder* _tmp19_;
							guint8* _tmp20_;
							gint _tmp20__length1;
							gint _tmp20__length2;
							guint8 _tmp21_;
							if (!_tmp16_) {
								guint8 _tmp17_;
								_tmp17_ = j;
								j = _tmp17_ + 1;
							}
							_tmp16_ = FALSE;
							_tmp18_ = self->priv->_columns;
							if (!(j < _tmp18_)) {
								break;
							}
							_tmp19_ = _data1_->builder;
							_tmp20_ = self->priv->initial_board;
							_tmp20__length1 = self->priv->initial_board_length1;
							_tmp20__length2 = self->priv->initial_board_length2;
							_tmp21_ = _tmp20_[((i - 1) * _tmp20__length2) + j];
							g_variant_builder_add (_tmp19_, "y", _tmp21_, NULL);
						}
					}
				}
				_tmp22_ = _data1_->builder;
				g_variant_builder_close (_tmp22_);
			}
		}
	}
	_tmp23_ = _data1_->builder;
	g_variant_builder_close (_tmp23_);
	_tmp24_ = _data1_->builder;
	g_variant_builder_add (_tmp24_, "q", self->priv->history_index, NULL);
	_tmp25_ = _data1_->builder;
	_tmp26_ = g_variant_type_new ("a(yy)");
	_tmp27_ = _tmp26_;
	g_variant_builder_open (_tmp25_, _tmp27_);
	_g_variant_type_free0 (_tmp27_);
	self->priv->reversed_history = g_list_reverse (self->priv->reversed_history);
	_tmp28_ = self->priv->reversed_history;
	g_list_foreach (_tmp28_, ___lambda5__gfunc, _data1_);
	self->priv->reversed_history = g_list_reverse (self->priv->reversed_history);
	_tmp29_ = _data1_->builder;
	g_variant_builder_close (_tmp29_);
	_tmp30_ = _data1_->builder;
	_tmp31_ = g_variant_builder_end (_tmp30_);
	g_variant_ref_sink (_tmp31_);
	_tmp32_ = _tmp31_;
	_tmp33_ = g_variant_new_maybe (NULL, _tmp32_);
	g_variant_ref_sink (_tmp33_);
	_tmp34_ = _tmp33_;
	_g_variant_unref0 (_tmp32_);
	result = _tmp34_;
	_g_variant_type_free0 (ay_type);
	block1_data_unref (_data1_);
	_data1_ = NULL;
	return result;
}

static inline void
game_clear_history (Game* self)
{
	g_return_if_fail (self != NULL);
	(self->priv->reversed_history == NULL) ? NULL : (self->priv->reversed_history = (_g_list_free__g_object_unref0_ (self->priv->reversed_history), NULL));
	self->priv->reversed_history = NULL;
	self->priv->history_length = (guint16) 0;
	self->priv->history_index = (guint16) 0;
	game_set_can_undo (self, FALSE);
	game_set_can_redo (self, FALSE);
}

static GList*
vala_g_list_remove_full (GList* self,
                         gconstpointer data,
                         GFreeFunc func)
{
	GList* l = NULL;
	GList* result;
	l = self;
	while (TRUE) {
		GList* _tmp0_;
		GList* _tmp1_;
		gconstpointer _tmp2_;
		_tmp0_ = l;
		if (!(_tmp0_ != NULL)) {
			break;
		}
		_tmp1_ = l;
		_tmp2_ = ((GList*) _tmp1_)->data;
		if (_tmp2_ != data) {
			GList* _tmp3_;
			GList* _tmp4_;
			_tmp3_ = l;
			_tmp4_ = ((GList*) _tmp3_)->next;
			l = _tmp4_;
		} else {
			GList* _tmp5_;
			gconstpointer _tmp6_;
			GList* _tmp7_;
			_tmp5_ = l;
			_tmp6_ = ((GList*) _tmp5_)->data;
			func (_tmp6_);
			_tmp7_ = l;
			self = g_list_delete_link (self, (GList*) _tmp7_);
			break;
		}
	}
	result = self;
	return result;
}

static inline void
game_add_history_entry (Game* self,
                        guint8 x,
                        guint8 y,
                        guint8 color,
                        GList* cl,
                        guint8* removed_columns,
                        gint removed_columns_length1)
{
	guint8* _tmp6_;
	gint _tmp6__length1;
	GameHistoryEntry* _tmp7_;
	guint16 _tmp8_;
	g_return_if_fail (self != NULL);
	while (TRUE) {
		GameHistoryEntry* history_data = NULL;
		GList* _tmp0_;
		gconstpointer _tmp1_;
		GameHistoryEntry* _tmp2_;
		GameHistoryEntry* _tmp3_;
		guint16 _tmp4_;
		guint16 _tmp5_;
		if (!(((gint) self->priv->history_index) > 0)) {
			break;
		}
		_tmp0_ = self->priv->reversed_history;
		_tmp1_ = g_list_nth_data (_tmp0_, (guint) 0);
		history_data = (GameHistoryEntry*) _tmp1_;
		_tmp2_ = history_data;
		if (_tmp2_ == NULL) {
			g_assert_not_reached ();
		}
		_tmp3_ = history_data;
		self->priv->reversed_history = vala_g_list_remove_full (self->priv->reversed_history, G_TYPE_CHECK_INSTANCE_CAST (_tmp3_, GAME_TYPE_HISTORY_ENTRY, GameHistoryEntry), _g_object_unref0_);
		_tmp4_ = self->priv->history_index;
		self->priv->history_index = _tmp4_ - 1;
		_tmp5_ = self->priv->history_length;
		self->priv->history_length = _tmp5_ - 1;
	}
	_tmp6_ = removed_columns;
	_tmp6__length1 = removed_columns_length1;
	removed_columns = NULL;
	removed_columns_length1 = 0;
	_tmp7_ = game_history_entry_new (x, y, color, cl, _tmp6_, _tmp6__length1);
	self->priv->reversed_history = g_list_prepend (self->priv->reversed_history, _tmp7_);
	_tmp8_ = self->priv->history_length;
	self->priv->history_length = _tmp8_ + 1;
	game_set_can_undo (self, TRUE);
	game_set_can_redo (self, FALSE);
	removed_columns = (g_free (removed_columns), NULL);
}

void
game_undo (Game* self)
{
	g_return_if_fail (self != NULL);
	game_undo_real (self, &self->priv->current_board, (gint*) (&self->priv->current_board_length1), (gint*) (&self->priv->current_board_length2));
}

static void
game_undo_real (Game* self,
                Tile*** current_board,
                gint* current_board_length1,
                gint* current_board_length2)
{
	gboolean _tmp0_;
	GList* history_item = NULL;
	GList* _tmp1_;
	GList* _tmp2_;
	GList* _tmp3_;
	GameHistoryEntry* history_data = NULL;
	GList* _tmp4_;
	gconstpointer _tmp5_;
	GameHistoryEntry* _tmp6_;
	GameHistoryEntry* _tmp7_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->_can_undo;
	if (!_tmp0_) {
		return;
	}
	_tmp1_ = self->priv->reversed_history;
	_tmp2_ = g_list_nth (_tmp1_, (guint) self->priv->history_index);
	history_item = _tmp2_;
	_tmp3_ = history_item;
	if (_tmp3_ == NULL) {
		g_assert_not_reached ();
	}
	_tmp4_ = history_item;
	_tmp5_ = ((GList*) _tmp4_)->data;
	history_data = (GameHistoryEntry*) _tmp5_;
	_tmp6_ = history_data;
	if (_tmp6_ == NULL) {
		g_assert_not_reached ();
	}
	_tmp7_ = history_data;
	game_undo_move (self, G_TYPE_CHECK_INSTANCE_CAST (_tmp7_, GAME_TYPE_HISTORY_ENTRY, GameHistoryEntry), current_board, (gint*) (current_board_length1), (gint*) (current_board_length2));
	if (self->priv->history_index == self->priv->history_length) {
		game_set_can_undo (self, FALSE);
	}
	game_set_can_redo (self, TRUE);
}

static inline void
game_undo_move (Game* self,
                GameHistoryEntry* history_entry,
                Tile*** current_board,
                gint* current_board_length1,
                gint* current_board_length2)
{
	gboolean _tmp0_;
	GList* _tmp1_;
	guint8* _tmp2_;
	gint _tmp2__length1;
	GList* _tmp15_;
	guint16 _tmp37_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (history_entry != NULL);
	_tmp0_ = game_has_won (current_board, (gint*) (current_board_length1), (gint*) (current_board_length2));
	if (_tmp0_) {
		game_increment_score (self, -1000);
	}
	_tmp1_ = history_entry->removed_tiles;
	game_decrement_score_from_tiles (self, (guint16) g_list_length (_tmp1_));
	_tmp2_ = history_entry->removed_columns;
	_tmp2__length1 = history_entry->removed_columns_length1;
	{
		guint8* removed_column_collection = NULL;
		gint removed_column_collection_length1 = 0;
		gint _removed_column_collection_size_ = 0;
		gint removed_column_it = 0;
		removed_column_collection = _tmp2_;
		removed_column_collection_length1 = _tmp2__length1;
		for (removed_column_it = 0; removed_column_it < removed_column_collection_length1; removed_column_it = removed_column_it + 1) {
			guint8 removed_column = 0U;
			removed_column = removed_column_collection[removed_column_it];
			{
				{
					guint8 j = 0U;
					guint8 _tmp3_;
					_tmp3_ = self->priv->_columns;
					j = (guint8) (_tmp3_ - 1);
					{
						gboolean _tmp4_ = FALSE;
						_tmp4_ = TRUE;
						while (TRUE) {
							if (!_tmp4_) {
								guint8 _tmp5_;
								_tmp5_ = j;
								j = _tmp5_ - 1;
							}
							_tmp4_ = FALSE;
							if (!(j > removed_column)) {
								break;
							}
							{
								guint8 i = 0U;
								i = (guint8) 0;
								{
									gboolean _tmp6_ = FALSE;
									_tmp6_ = TRUE;
									while (TRUE) {
										guint8 _tmp8_;
										Tile* _tmp9_;
										if (!_tmp6_) {
											guint8 _tmp7_;
											_tmp7_ = i;
											i = _tmp7_ + 1;
										}
										_tmp6_ = FALSE;
										_tmp8_ = self->priv->_rows;
										if (!(i < _tmp8_)) {
											break;
										}
										_tmp9_ = (*current_board)[(i * (*current_board_length2)) + (j - 1)];
										if (_tmp9_ != NULL) {
											Tile* _tmp10_;
											Tile* _tmp11_;
											_tmp10_ = (*current_board)[(i * (*current_board_length2)) + (j - 1)];
											(*current_board)[(i * (*current_board_length2)) + (j - 1)] = NULL;
											_g_object_unref0 ((*current_board)[(i * (*current_board_length2)) + j]);
											(*current_board)[(i * (*current_board_length2)) + j] = _tmp10_;
											_tmp11_ = (*current_board)[(i * (*current_board_length2)) + j];
											tile_update_position (G_TYPE_CHECK_INSTANCE_CAST (_tmp11_, TYPE_TILE, Tile), j, i);
										} else {
											_g_object_unref0 ((*current_board)[(i * (*current_board_length2)) + j]);
											(*current_board)[(i * (*current_board_length2)) + j] = NULL;
										}
									}
								}
							}
						}
					}
				}
				{
					guint8 i = 0U;
					i = (guint8) 0;
					{
						gboolean _tmp12_ = FALSE;
						_tmp12_ = TRUE;
						while (TRUE) {
							guint8 _tmp14_;
							if (!_tmp12_) {
								guint8 _tmp13_;
								_tmp13_ = i;
								i = _tmp13_ + 1;
							}
							_tmp12_ = FALSE;
							_tmp14_ = self->priv->_rows;
							if (!(i < _tmp14_)) {
								break;
							}
							_g_object_unref0 ((*current_board)[(i * (*current_board_length2)) + removed_column]);
							(*current_board)[(i * (*current_board_length2)) + removed_column] = NULL;
						}
					}
				}
			}
		}
	}
	_tmp15_ = history_entry->removed_tiles;
	{
		GList* removed_tile_collection = NULL;
		GList* removed_tile_it = NULL;
		removed_tile_collection = _tmp15_;
		for (removed_tile_it = removed_tile_collection; removed_tile_it != NULL; removed_tile_it = removed_tile_it->next) {
			GamePoint* removed_tile = NULL;
			removed_tile = (GamePoint*) removed_tile_it->data;
			{
				guint8 column = 0U;
				GamePoint* _tmp16_;
				guint8 _tmp17_;
				guint8 _tmp18_;
				GamePoint* _tmp28_;
				guint8 _tmp29_;
				guint8 _tmp30_;
				GamePoint* _tmp31_;
				guint8 _tmp32_;
				guint8 _tmp33_;
				guint8 _tmp34_;
				guint8 _tmp35_;
				Tile* _tmp36_;
				_tmp16_ = removed_tile;
				_tmp17_ = game_point_get_x (_tmp16_);
				_tmp18_ = _tmp17_;
				column = _tmp18_;
				{
					guint8 row = 0U;
					guint8 _tmp19_;
					_tmp19_ = self->priv->_rows;
					row = (guint8) (_tmp19_ - 1);
					{
						gboolean _tmp20_ = FALSE;
						_tmp20_ = TRUE;
						while (TRUE) {
							GamePoint* _tmp22_;
							guint8 _tmp23_;
							guint8 _tmp24_;
							Tile* _tmp25_;
							if (!_tmp20_) {
								guint8 _tmp21_;
								_tmp21_ = row;
								row = _tmp21_ - 1;
							}
							_tmp20_ = FALSE;
							_tmp22_ = removed_tile;
							_tmp23_ = game_point_get_y (_tmp22_);
							_tmp24_ = _tmp23_;
							if (!(row > _tmp24_)) {
								break;
							}
							_tmp25_ = (*current_board)[((row - 1) * (*current_board_length2)) + column];
							if (_tmp25_ != NULL) {
								Tile* _tmp26_;
								Tile* _tmp27_;
								_tmp26_ = (*current_board)[((row - 1) * (*current_board_length2)) + column];
								(*current_board)[((row - 1) * (*current_board_length2)) + column] = NULL;
								_g_object_unref0 ((*current_board)[(row * (*current_board_length2)) + column]);
								(*current_board)[(row * (*current_board_length2)) + column] = _tmp26_;
								_tmp27_ = (*current_board)[(row * (*current_board_length2)) + column];
								tile_update_position (G_TYPE_CHECK_INSTANCE_CAST (_tmp27_, TYPE_TILE, Tile), column, row);
							} else {
								_g_object_unref0 ((*current_board)[(row * (*current_board_length2)) + column]);
								(*current_board)[(row * (*current_board_length2)) + column] = NULL;
							}
							if (((gint) row) == 0) {
								break;
							}
						}
					}
				}
				_tmp28_ = removed_tile;
				_tmp29_ = game_point_get_y (_tmp28_);
				_tmp30_ = _tmp29_;
				_tmp31_ = removed_tile;
				_tmp32_ = game_point_get_y (_tmp31_);
				_tmp33_ = _tmp32_;
				_tmp34_ = game_history_entry_get_color (history_entry);
				_tmp35_ = _tmp34_;
				_tmp36_ = tile_new (column, _tmp33_, _tmp35_);
				_g_object_unref0 ((*current_board)[(_tmp30_ * (*current_board_length2)) + column]);
				(*current_board)[(_tmp30_ * (*current_board_length2)) + column] = _tmp36_;
			}
		}
	}
	_tmp37_ = self->priv->history_index;
	self->priv->history_index = _tmp37_ + 1;
	g_signal_emit (self, game_signals[GAME_UNDONE_SIGNAL], 0);
}

void
game_redo (Game* self)
{
	gboolean _tmp0_;
	GList* history_item = NULL;
	GList* _tmp1_;
	GList* _tmp2_;
	GList* _tmp3_;
	GameHistoryEntry* history_data = NULL;
	GList* _tmp4_;
	gconstpointer _tmp5_;
	GameHistoryEntry* _tmp6_;
	GameHistoryEntry* _tmp7_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->_can_redo;
	if (!_tmp0_) {
		return;
	}
	_tmp1_ = self->priv->reversed_history;
	_tmp2_ = g_list_nth (_tmp1_, (guint) (self->priv->history_index - 1));
	history_item = _tmp2_;
	_tmp3_ = history_item;
	if (_tmp3_ == NULL) {
		g_assert_not_reached ();
	}
	_tmp4_ = history_item;
	_tmp5_ = ((GList*) _tmp4_)->data;
	history_data = (GameHistoryEntry*) _tmp5_;
	_tmp6_ = history_data;
	if (_tmp6_ == NULL) {
		g_assert_not_reached ();
	}
	_tmp7_ = history_data;
	game_redo_move (self, G_TYPE_CHECK_INSTANCE_CAST (_tmp7_, GAME_TYPE_HISTORY_ENTRY, GameHistoryEntry));
	if (((gint) self->priv->history_index) == 0) {
		game_set_can_redo (self, FALSE);
	}
	game_set_can_undo (self, TRUE);
}

static inline void
game_redo_move (Game* self,
                GameHistoryEntry* history_entry)
{
	guint16 _tmp0_;
	Tile** _tmp1_;
	gint _tmp1__length1;
	gint _tmp1__length2;
	GList* _tmp2_;
	GList* _tmp3_;
	gconstpointer _tmp4_;
	guint8 _tmp5_;
	guint8 _tmp6_;
	GList* _tmp7_;
	GList* _tmp8_;
	gconstpointer _tmp9_;
	guint8 _tmp10_;
	guint8 _tmp11_;
	Tile* _tmp12_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (history_entry != NULL);
	_tmp0_ = self->priv->history_index;
	self->priv->history_index = _tmp0_ - 1;
	_tmp1_ = self->priv->current_board;
	_tmp1__length1 = self->priv->current_board_length1;
	_tmp1__length2 = self->priv->current_board_length2;
	_tmp2_ = history_entry->removed_tiles;
	_tmp3_ = g_list_first (_tmp2_);
	_tmp4_ = _tmp3_->data;
	_tmp5_ = game_point_get_y ((GamePoint*) _tmp4_);
	_tmp6_ = _tmp5_;
	_tmp7_ = history_entry->removed_tiles;
	_tmp8_ = g_list_first (_tmp7_);
	_tmp9_ = _tmp8_->data;
	_tmp10_ = game_point_get_x ((GamePoint*) _tmp9_);
	_tmp11_ = _tmp10_;
	_tmp12_ = _tmp1_[(_tmp6_ * _tmp1__length2) + _tmp11_];
	game_remove_connected_tiles_real (self, _tmp12_, TRUE);
}

guint
game_get_score (Game* self)
{
	guint result;
	g_return_val_if_fail (self != NULL, 0U);
	result = self->priv->_score;
	return result;
}

static void
game_set_score (Game* self,
                guint value)
{
	guint old_value;
	g_return_if_fail (self != NULL);
	old_value = game_get_score (self);
	if (old_value != value) {
		self->priv->_score = value;
		g_object_notify_by_pspec ((GObject *) self, game_properties[GAME_SCORE_PROPERTY]);
	}
}

guint8
game_get_color_num (Game* self)
{
	guint8 result;
	g_return_val_if_fail (self != NULL, 0U);
	result = self->priv->_color_num;
	return result;
}

void
game_set_color_num (Game* self,
                    guint8 value)
{
	gboolean _tmp0_ = FALSE;
	g_return_if_fail (self != NULL);
	if (((gint) value) < 2) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = ((gint) value) > 4;
	}
	if (_tmp0_) {
		self->priv->_color_num = (guint8) 3;
	} else {
		self->priv->_color_num = value;
	}
	g_object_notify_by_pspec ((GObject *) self, game_properties[GAME_COLOR_NUM_PROPERTY]);
}

guint8
game_get_rows (Game* self)
{
	guint8 result;
	g_return_val_if_fail (self != NULL, 0U);
	result = self->priv->_rows;
	return result;
}

static void
game_set_rows (Game* self,
               guint8 value)
{
	guint8 old_value;
	g_return_if_fail (self != NULL);
	old_value = game_get_rows (self);
	if (old_value != value) {
		self->priv->_rows = value;
		g_object_notify_by_pspec ((GObject *) self, game_properties[GAME_ROWS_PROPERTY]);
	}
}

guint8
game_get_columns (Game* self)
{
	guint8 result;
	g_return_val_if_fail (self != NULL, 0U);
	result = self->priv->_columns;
	return result;
}

static void
game_set_columns (Game* self,
                  guint8 value)
{
	guint8 old_value;
	g_return_if_fail (self != NULL);
	old_value = game_get_columns (self);
	if (old_value != value) {
		self->priv->_columns = value;
		g_object_notify_by_pspec ((GObject *) self, game_properties[GAME_COLUMNS_PROPERTY]);
	}
}

gboolean
game_get_can_undo (Game* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = self->priv->_can_undo;
	return result;
}

static void
game_set_can_undo (Game* self,
                   gboolean value)
{
	gboolean old_value;
	g_return_if_fail (self != NULL);
	old_value = game_get_can_undo (self);
	if (old_value != value) {
		self->priv->_can_undo = value;
		g_object_notify_by_pspec ((GObject *) self, game_properties[GAME_CAN_UNDO_PROPERTY]);
	}
}

gboolean
game_get_can_redo (Game* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = self->priv->_can_redo;
	return result;
}

static void
game_set_can_redo (Game* self,
                   gboolean value)
{
	gboolean old_value;
	g_return_if_fail (self != NULL);
	old_value = game_get_can_redo (self);
	if (old_value != value) {
		self->priv->_can_redo = value;
		g_object_notify_by_pspec ((GObject *) self, game_properties[GAME_CAN_REDO_PROPERTY]);
	}
}

static inline gpointer
game_point_get_instance_private (GamePoint* self)
{
	return G_STRUCT_MEMBER_P (self, GamePoint_private_offset);
}

static GamePoint*
game_point_construct (GType object_type,
                      guint8 x,
                      guint8 y)
{
	GamePoint * self = NULL;
	self = (GamePoint*) g_object_new (object_type, "x", x, "y", y, NULL);
	return self;
}

static GamePoint*
game_point_new (guint8 x,
                guint8 y)
{
	return game_point_construct (GAME_TYPE_POINT, x, y);
}

static guint8
game_point_get_x (GamePoint* self)
{
	guint8 result;
	g_return_val_if_fail (self != NULL, 0U);
	result = self->priv->_x;
	return result;
}

static void
game_point_set_x (GamePoint* self,
                  guint8 value)
{
	guint8 old_value;
	g_return_if_fail (self != NULL);
	old_value = game_point_get_x (self);
	if (old_value != value) {
		self->priv->_x = value;
		g_object_notify_by_pspec ((GObject *) self, game_point_properties[GAME_POINT_X_PROPERTY]);
	}
}

static guint8
game_point_get_y (GamePoint* self)
{
	guint8 result;
	g_return_val_if_fail (self != NULL, 0U);
	result = self->priv->_y;
	return result;
}

static void
game_point_set_y (GamePoint* self,
                  guint8 value)
{
	guint8 old_value;
	g_return_if_fail (self != NULL);
	old_value = game_point_get_y (self);
	if (old_value != value) {
		self->priv->_y = value;
		g_object_notify_by_pspec ((GObject *) self, game_point_properties[GAME_POINT_Y_PROPERTY]);
	}
}

static void
game_point_class_init (GamePointClass * klass,
                       gpointer klass_data)
{
	game_point_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &GamePoint_private_offset);
	G_OBJECT_CLASS (klass)->get_property = _vala_game_point_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_game_point_set_property;
	G_OBJECT_CLASS (klass)->finalize = game_point_finalize;
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_POINT_X_PROPERTY, game_point_properties[GAME_POINT_X_PROPERTY] = g_param_spec_uchar ("x", "x", "x", 0, G_MAXUINT8, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_POINT_Y_PROPERTY, game_point_properties[GAME_POINT_Y_PROPERTY] = g_param_spec_uchar ("y", "y", "y", 0, G_MAXUINT8, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
}

static void
game_point_instance_init (GamePoint * self,
                          gpointer klass)
{
	self->priv = game_point_get_instance_private (self);
}

static void
game_point_finalize (GObject * obj)
{
	GamePoint * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, GAME_TYPE_POINT, GamePoint);
	G_OBJECT_CLASS (game_point_parent_class)->finalize (obj);
}

static GType
game_point_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (GamePointClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) game_point_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GamePoint), 0, (GInstanceInitFunc) game_point_instance_init, NULL };
	GType game_point_type_id;
	game_point_type_id = g_type_register_static (G_TYPE_OBJECT, "GamePoint", &g_define_type_info, 0);
	GamePoint_private_offset = g_type_add_instance_private (game_point_type_id, sizeof (GamePointPrivate));
	return game_point_type_id;
}

static GType
game_point_get_type (void)
{
	static volatile gsize game_point_type_id__once = 0;
	if (g_once_init_enter (&game_point_type_id__once)) {
		GType game_point_type_id;
		game_point_type_id = game_point_get_type_once ();
		g_once_init_leave (&game_point_type_id__once, game_point_type_id);
	}
	return game_point_type_id__once;
}

static void
_vala_game_point_get_property (GObject * object,
                               guint property_id,
                               GValue * value,
                               GParamSpec * pspec)
{
	GamePoint * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, GAME_TYPE_POINT, GamePoint);
	switch (property_id) {
		case GAME_POINT_X_PROPERTY:
		g_value_set_uchar (value, game_point_get_x (self));
		break;
		case GAME_POINT_Y_PROPERTY:
		g_value_set_uchar (value, game_point_get_y (self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_game_point_set_property (GObject * object,
                               guint property_id,
                               const GValue * value,
                               GParamSpec * pspec)
{
	GamePoint * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, GAME_TYPE_POINT, GamePoint);
	switch (property_id) {
		case GAME_POINT_X_PROPERTY:
		game_point_set_x (self, g_value_get_uchar (value));
		break;
		case GAME_POINT_Y_PROPERTY:
		game_point_set_y (self, g_value_get_uchar (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static inline gpointer
game_history_entry_get_instance_private (GameHistoryEntry* self)
{
	return G_STRUCT_MEMBER_P (self, GameHistoryEntry_private_offset);
}

static guint8*
_vala_array_dup3 (guint8* self,
                  gssize length)
{
	if (length > 0) {
		return _vala_memdup2 (self, length * sizeof (guint8));
	}
	return NULL;
}

static gint
__lambda4_ (GamePoint* tile_1,
            GamePoint* tile_2)
{
	guint8 _tmp0_;
	guint8 _tmp1_;
	guint8 _tmp2_;
	guint8 _tmp3_;
	guint8 _tmp4_;
	guint8 _tmp5_;
	guint8 _tmp6_;
	guint8 _tmp7_;
	guint8 _tmp8_;
	guint8 _tmp9_;
	guint8 _tmp10_;
	guint8 _tmp11_;
	guint8 _tmp12_;
	guint8 _tmp13_;
	guint8 _tmp14_;
	guint8 _tmp15_;
	gint result;
	g_return_val_if_fail (tile_1 != NULL, 0);
	g_return_val_if_fail (tile_2 != NULL, 0);
	_tmp0_ = game_point_get_x (tile_1);
	_tmp1_ = _tmp0_;
	_tmp2_ = game_point_get_x (tile_2);
	_tmp3_ = _tmp2_;
	if (_tmp1_ < _tmp3_) {
		result = -1;
		return result;
	}
	_tmp4_ = game_point_get_x (tile_1);
	_tmp5_ = _tmp4_;
	_tmp6_ = game_point_get_x (tile_2);
	_tmp7_ = _tmp6_;
	if (_tmp5_ > _tmp7_) {
		result = 1;
		return result;
	}
	_tmp8_ = game_point_get_y (tile_1);
	_tmp9_ = _tmp8_;
	_tmp10_ = game_point_get_y (tile_2);
	_tmp11_ = _tmp10_;
	if (_tmp9_ < _tmp11_) {
		result = -1;
		return result;
	}
	_tmp12_ = game_point_get_y (tile_1);
	_tmp13_ = _tmp12_;
	_tmp14_ = game_point_get_y (tile_2);
	_tmp15_ = _tmp14_;
	if (_tmp13_ > _tmp15_) {
		result = 1;
		return result;
	}
	g_assert_not_reached ();
}

static gint
___lambda4__gcompare_func (gconstpointer a,
                           gconstpointer b)
{
	gint result;
	result = __lambda4_ ((GamePoint*) a, (GamePoint*) b);
	return result;
}

static GameHistoryEntry*
game_history_entry_construct (GType object_type,
                              guint8 x,
                              guint8 y,
                              guint8 color,
                              GList* cl,
                              guint8* removed_columns,
                              gint removed_columns_length1)
{
	GameHistoryEntry * self = NULL;
	GamePoint* _tmp0_;
	GamePoint* _tmp1_;
	guint8* _tmp2_;
	gint _tmp2__length1;
	_tmp0_ = game_point_new (x, y);
	_tmp1_ = _tmp0_;
	self = (GameHistoryEntry*) g_object_new (object_type, "click", _tmp1_, "color", color, NULL);
	_g_object_unref0 (_tmp1_);
	_tmp2_ = (removed_columns != NULL) ? _vala_array_dup3 (removed_columns, removed_columns_length1) : removed_columns;
	_tmp2__length1 = removed_columns_length1;
	self->removed_columns = (g_free (self->removed_columns), NULL);
	self->removed_columns = _tmp2_;
	self->removed_columns_length1 = _tmp2__length1;
	self->_removed_columns_size_ = self->removed_columns_length1;
	{
		GList* tile_collection = NULL;
		GList* tile_it = NULL;
		tile_collection = cl;
		for (tile_it = tile_collection; tile_it != NULL; tile_it = tile_it->next) {
			Tile* tile = NULL;
			tile = (Tile*) tile_it->data;
			{
				Tile* _tmp3_;
				guint8 _tmp4_;
				guint8 _tmp5_;
				Tile* _tmp6_;
				guint8 _tmp7_;
				guint8 _tmp8_;
				GamePoint* _tmp9_;
				_tmp3_ = tile;
				_tmp4_ = tile_get_grid_x (_tmp3_);
				_tmp5_ = _tmp4_;
				_tmp6_ = tile;
				_tmp7_ = tile_get_grid_y (_tmp6_);
				_tmp8_ = _tmp7_;
				_tmp9_ = game_point_new (_tmp5_, _tmp8_);
				self->removed_tiles = g_list_prepend (self->removed_tiles, _tmp9_);
			}
		}
	}
	self->removed_tiles = g_list_sort (self->removed_tiles, ___lambda4__gcompare_func);
	removed_columns = (g_free (removed_columns), NULL);
	return self;
}

static GameHistoryEntry*
game_history_entry_new (guint8 x,
                        guint8 y,
                        guint8 color,
                        GList* cl,
                        guint8* removed_columns,
                        gint removed_columns_length1)
{
	return game_history_entry_construct (GAME_TYPE_HISTORY_ENTRY, x, y, color, cl, removed_columns, removed_columns_length1);
}

static GamePoint*
game_history_entry_get_click (GameHistoryEntry* self)
{
	GamePoint* result;
	GamePoint* _tmp0_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->_click;
	result = _tmp0_;
	return result;
}

static void
game_history_entry_set_click (GameHistoryEntry* self,
                              GamePoint* value)
{
	GamePoint* _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = _g_object_ref0 (value);
	_g_object_unref0 (self->priv->_click);
	self->priv->_click = _tmp0_;
}

static guint8
game_history_entry_get_color (GameHistoryEntry* self)
{
	guint8 result;
	g_return_val_if_fail (self != NULL, 0U);
	result = self->priv->_color;
	return result;
}

static void
game_history_entry_set_color (GameHistoryEntry* self,
                              guint8 value)
{
	g_return_if_fail (self != NULL);
	self->priv->_color = value;
}

static void
game_history_entry_class_init (GameHistoryEntryClass * klass,
                               gpointer klass_data)
{
	game_history_entry_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &GameHistoryEntry_private_offset);
	G_OBJECT_CLASS (klass)->get_property = _vala_game_history_entry_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_game_history_entry_set_property;
	G_OBJECT_CLASS (klass)->finalize = game_history_entry_finalize;
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_HISTORY_ENTRY_CLICK_PROPERTY, game_history_entry_properties[GAME_HISTORY_ENTRY_CLICK_PROPERTY] = g_param_spec_object ("click", "click", "click", GAME_TYPE_POINT, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_HISTORY_ENTRY_COLOR_PROPERTY, game_history_entry_properties[GAME_HISTORY_ENTRY_COLOR_PROPERTY] = g_param_spec_uchar ("color", "color", "color", 0, G_MAXUINT8, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY));
}

static void
game_history_entry_instance_init (GameHistoryEntry * self,
                                  gpointer klass)
{
	self->priv = game_history_entry_get_instance_private (self);
	self->removed_tiles = NULL;
}

static void
game_history_entry_finalize (GObject * obj)
{
	GameHistoryEntry * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, GAME_TYPE_HISTORY_ENTRY, GameHistoryEntry);
	_g_object_unref0 (self->priv->_click);
	(self->removed_tiles == NULL) ? NULL : (self->removed_tiles = (_g_list_free__g_object_unref0_ (self->removed_tiles), NULL));
	self->removed_columns = (g_free (self->removed_columns), NULL);
	G_OBJECT_CLASS (game_history_entry_parent_class)->finalize (obj);
}

static GType
game_history_entry_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (GameHistoryEntryClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) game_history_entry_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GameHistoryEntry), 0, (GInstanceInitFunc) game_history_entry_instance_init, NULL };
	GType game_history_entry_type_id;
	game_history_entry_type_id = g_type_register_static (G_TYPE_OBJECT, "GameHistoryEntry", &g_define_type_info, 0);
	GameHistoryEntry_private_offset = g_type_add_instance_private (game_history_entry_type_id, sizeof (GameHistoryEntryPrivate));
	return game_history_entry_type_id;
}

static GType
game_history_entry_get_type (void)
{
	static volatile gsize game_history_entry_type_id__once = 0;
	if (g_once_init_enter (&game_history_entry_type_id__once)) {
		GType game_history_entry_type_id;
		game_history_entry_type_id = game_history_entry_get_type_once ();
		g_once_init_leave (&game_history_entry_type_id__once, game_history_entry_type_id);
	}
	return game_history_entry_type_id__once;
}

static void
_vala_game_history_entry_get_property (GObject * object,
                                       guint property_id,
                                       GValue * value,
                                       GParamSpec * pspec)
{
	GameHistoryEntry * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, GAME_TYPE_HISTORY_ENTRY, GameHistoryEntry);
	switch (property_id) {
		case GAME_HISTORY_ENTRY_CLICK_PROPERTY:
		g_value_set_object (value, game_history_entry_get_click (self));
		break;
		case GAME_HISTORY_ENTRY_COLOR_PROPERTY:
		g_value_set_uchar (value, game_history_entry_get_color (self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_game_history_entry_set_property (GObject * object,
                                       guint property_id,
                                       const GValue * value,
                                       GParamSpec * pspec)
{
	GameHistoryEntry * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, GAME_TYPE_HISTORY_ENTRY, GameHistoryEntry);
	switch (property_id) {
		case GAME_HISTORY_ENTRY_CLICK_PROPERTY:
		game_history_entry_set_click (self, g_value_get_object (value));
		break;
		case GAME_HISTORY_ENTRY_COLOR_PROPERTY:
		game_history_entry_set_color (self, g_value_get_uchar (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
game_class_init (GameClass * klass,
                 gpointer klass_data)
{
	game_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &Game_private_offset);
	G_OBJECT_CLASS (klass)->get_property = _vala_game_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_game_set_property;
	G_OBJECT_CLASS (klass)->finalize = game_finalize;
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_SCORE_PROPERTY, game_properties[GAME_SCORE_PROPERTY] = g_param_spec_uint ("score", "score", "score", 0, G_MAXUINT, (guint) 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_COLOR_NUM_PROPERTY, game_properties[GAME_COLOR_NUM_PROPERTY] = g_param_spec_uchar ("color-num", "color-num", "color-num", 0, G_MAXUINT8, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_ROWS_PROPERTY, game_properties[GAME_ROWS_PROPERTY] = g_param_spec_uchar ("rows", "rows", "rows", 0, G_MAXUINT8, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_COLUMNS_PROPERTY, game_properties[GAME_COLUMNS_PROPERTY] = g_param_spec_uchar ("columns", "columns", "columns", 0, G_MAXUINT8, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_CAN_UNDO_PROPERTY, game_properties[GAME_CAN_UNDO_PROPERTY] = g_param_spec_boolean ("can-undo", "can-undo", "can-undo", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_CAN_REDO_PROPERTY, game_properties[GAME_CAN_REDO_PROPERTY] = g_param_spec_boolean ("can-redo", "can-redo", "can-redo", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	game_signals[GAME_UPDATE_SCORE_SIGNAL] = g_signal_new ("update-score", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT);
	game_signals[GAME_COMPLETE_SIGNAL] = g_signal_new ("complete", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	game_signals[GAME_STARTED_SIGNAL] = g_signal_new ("started", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	game_signals[GAME_UNDONE_SIGNAL] = g_signal_new ("undone", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}

static void
game_instance_init (Game * self,
                    gpointer klass)
{
	self->priv = game_get_instance_private (self);
	self->priv->is_started = FALSE;
	self->priv->_score = (guint) 0;
	self->priv->_color_num = (guint8) 3;
	self->priv->_can_undo = FALSE;
	self->priv->_can_redo = FALSE;
	self->priv->history_length = (guint16) 0;
	self->priv->history_index = (guint16) 0;
	self->priv->reversed_history = NULL;
}

static void
game_finalize (GObject * obj)
{
	Game * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_GAME, Game);
	self->priv->current_board = (_vala_array_free (self->priv->current_board, self->priv->current_board_length1 * self->priv->current_board_length2, (GDestroyNotify) g_object_unref), NULL);
	self->priv->initial_board = (g_free (self->priv->initial_board), NULL);
	(self->priv->reversed_history == NULL) ? NULL : (self->priv->reversed_history = (_g_list_free__g_object_unref0_ (self->priv->reversed_history), NULL));
	G_OBJECT_CLASS (game_parent_class)->finalize (obj);
}

/**
 *  This is the model layer of the whole game. All game logic goes here. This class tries not to
 *  bring in any visual stuff to comply the separation of view-model idea.
 */
static GType
game_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (GameClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) game_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Game), 0, (GInstanceInitFunc) game_instance_init, NULL };
	GType game_type_id;
	game_type_id = g_type_register_static (G_TYPE_OBJECT, "Game", &g_define_type_info, 0);
	Game_private_offset = g_type_add_instance_private (game_type_id, sizeof (GamePrivate));
	return game_type_id;
}

GType
game_get_type (void)
{
	static volatile gsize game_type_id__once = 0;
	if (g_once_init_enter (&game_type_id__once)) {
		GType game_type_id;
		game_type_id = game_get_type_once ();
		g_once_init_leave (&game_type_id__once, game_type_id);
	}
	return game_type_id__once;
}

static void
_vala_game_get_property (GObject * object,
                         guint property_id,
                         GValue * value,
                         GParamSpec * pspec)
{
	Game * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_GAME, Game);
	switch (property_id) {
		case GAME_SCORE_PROPERTY:
		g_value_set_uint (value, game_get_score (self));
		break;
		case GAME_COLOR_NUM_PROPERTY:
		g_value_set_uchar (value, game_get_color_num (self));
		break;
		case GAME_ROWS_PROPERTY:
		g_value_set_uchar (value, game_get_rows (self));
		break;
		case GAME_COLUMNS_PROPERTY:
		g_value_set_uchar (value, game_get_columns (self));
		break;
		case GAME_CAN_UNDO_PROPERTY:
		g_value_set_boolean (value, game_get_can_undo (self));
		break;
		case GAME_CAN_REDO_PROPERTY:
		g_value_set_boolean (value, game_get_can_redo (self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_game_set_property (GObject * object,
                         guint property_id,
                         const GValue * value,
                         GParamSpec * pspec)
{
	Game * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_GAME, Game);
	switch (property_id) {
		case GAME_SCORE_PROPERTY:
		game_set_score (self, g_value_get_uint (value));
		break;
		case GAME_COLOR_NUM_PROPERTY:
		game_set_color_num (self, g_value_get_uchar (value));
		break;
		case GAME_ROWS_PROPERTY:
		game_set_rows (self, g_value_get_uchar (value));
		break;
		case GAME_COLUMNS_PROPERTY:
		game_set_columns (self, g_value_get_uchar (value));
		break;
		case GAME_CAN_UNDO_PROPERTY:
		game_set_can_undo (self, g_value_get_boolean (value));
		break;
		case GAME_CAN_REDO_PROPERTY:
		game_set_can_redo (self, g_value_get_boolean (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_array_destroy (gpointer array,
                     gssize array_length,
                     GDestroyNotify destroy_func)
{
	if ((array != NULL) && (destroy_func != NULL)) {
		gssize i;
		for (i = 0; i < array_length; i = i + 1) {
			if (((gpointer*) array)[i] != NULL) {
				destroy_func (((gpointer*) array)[i]);
			}
		}
	}
}

static void
_vala_array_free (gpointer array,
                  gssize array_length,
                  GDestroyNotify destroy_func)
{
	_vala_array_destroy (array, array_length, destroy_func);
	g_free (array);
}

static void
_vala_array_move (gpointer array,
                  gsize element_size,
                  gssize src,
                  gssize dest,
                  gssize length)
{
	memmove (((char*) array) + (dest * element_size), ((char*) array) + (src * element_size), length * element_size);
	if ((src < dest) && ((src + length) > dest)) {
		memset (((char*) array) + (src * element_size), 0, (dest - src) * element_size);
	} else if ((src > dest) && (src < (dest + length))) {
		memset (((char*) array) + ((dest + length) * element_size), 0, (src - dest) * element_size);
	} else if (src != dest) {
		memset (((char*) array) + (src * element_size), 0, length * element_size);
	}
}

static inline gpointer
_vala_memdup2 (gconstpointer mem,
               gsize byte_size)
{
	gpointer new_mem;
	if (mem && byte_size != 0) {
		new_mem = g_malloc (byte_size);
		memcpy (new_mem, mem, byte_size);
	} else {
		new_mem = NULL;
	}
	return new_mem;
}

