/* game.c generated by valac 0.30.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.h>
#include <glib-object.h>
#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>


#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;

#define TYPE_SLOT (slot_get_type ())
#define SLOT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SLOT, Slot))
#define SLOT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SLOT, SlotClass))
#define IS_SLOT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SLOT))
#define IS_SLOT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SLOT))
#define SLOT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SLOT, SlotClass))

typedef struct _Slot Slot;
typedef struct _SlotClass SlotClass;
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))

#define TYPE_MATCH (match_get_type ())
#define MATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_MATCH, Match))
#define MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_MATCH, MatchClass))
#define IS_MATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_MATCH))
#define IS_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_MATCH))
#define MATCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_MATCH, MatchClass))

typedef struct _Match Match;
typedef struct _MatchClass MatchClass;
typedef struct _MatchPrivate MatchPrivate;

#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 TYPE_MAP (map_get_type ())
#define MAP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_MAP, Map))
#define MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_MAP, MapClass))
#define IS_MAP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_MAP))
#define IS_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_MAP))
#define MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_MAP, MapClass))

typedef struct _Map Map;
typedef struct _MapClass MapClass;
#define __g_list_free__g_object_unref0_0(var) ((var == NULL) ? NULL : (var = (_g_list_free__g_object_unref0_ (var), NULL)))
#define _g_timer_destroy0(var) ((var == NULL) ? NULL : (var = (g_timer_destroy (var), NULL)))
typedef struct _MapPrivate MapPrivate;
typedef struct _SlotPrivate SlotPrivate;

struct _Tile {
	GObject parent_instance;
	TilePrivate * priv;
	gint number;
	Slot* slot;
	gboolean visible;
	gint move_number;
};

struct _TileClass {
	GObjectClass parent_class;
};

struct _Match {
	GObject parent_instance;
	MatchPrivate * priv;
	Tile* tile0;
	Tile* tile1;
};

struct _MatchClass {
	GObjectClass parent_class;
};

struct _Game {
	GObject parent_instance;
	GamePrivate * priv;
	Map* map;
	GList* tiles;
	Tile* hint_tiles[2];
	gint move_number;
	guint hint_blink_counter;
};

struct _GameClass {
	GObjectClass parent_class;
};

struct _GamePrivate {
	guint hint_timout;
	gdouble clock_elapsed;
	GTimer* clock;
	guint clock_timeout;
	gboolean _paused;
	Tile* _selected_tile;
};

struct _Map {
	GObject parent_instance;
	MapPrivate * priv;
	gchar* name;
	gchar* score_name;
	GList* slots;
};

struct _MapClass {
	GObjectClass parent_class;
};

struct _Slot {
	GObject parent_instance;
	SlotPrivate * priv;
	gint x;
	gint y;
	gint layer;
};

struct _SlotClass {
	GObjectClass parent_class;
};


static gpointer tile_parent_class = NULL;
static gpointer match_parent_class = NULL;
static gpointer game_parent_class = NULL;

GType tile_get_type (void) G_GNUC_CONST;
GType slot_get_type (void) G_GNUC_CONST;
enum  {
	TILE_DUMMY_PROPERTY,
	TILE_SET
};
Tile* tile_new (Slot* slot);
Tile* tile_construct (GType object_type, Slot* slot);
gboolean tile_matches (Tile* self, Tile* tile);
gint tile_get_set (Tile* self);
static void tile_finalize (GObject* obj);
static void _vala_tile_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec);
gint compare_tiles (Tile* a, Tile* b);
gint compare_slots (Slot* a, Slot* b);
gboolean switch_tiles (Tile* a, Tile* b);
GType match_get_type (void) G_GNUC_CONST;
enum  {
	MATCH_DUMMY_PROPERTY
};
Match* match_new (Tile* tile0, Tile* tile1);
Match* match_construct (GType object_type, Tile* tile0, Tile* tile1);
static void match_finalize (GObject* obj);
GType game_get_type (void) G_GNUC_CONST;
GType map_get_type (void) G_GNUC_CONST;
#define GAME_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_GAME, GamePrivate))
enum  {
	GAME_DUMMY_PROPERTY,
	GAME_STARTED,
	GAME_ELAPSED,
	GAME_PAUSED,
	GAME_SELECTED_TILE,
	GAME_VISIBLE_TILES,
	GAME_MOVES_LEFT,
	GAME_COMPLETE,
	GAME_CAN_MOVE,
	GAME_CAN_UNDO,
	GAME_CAN_REDO
};
static void _g_object_unref0_ (gpointer var);
static void _g_list_free__g_object_unref0_ (GList* self);
Game* game_new (Map* map);
Game* game_construct (GType object_type, Map* map);
static gint _compare_tiles_gcompare_func (gconstpointer a, gconstpointer b);
static gboolean game_shuffle (Game* self, gint* numbers, int numbers_length1, gint depth);
void game_reset (Game* self);
void game_shuffle_remaining (Game* self, gboolean redraw);
gboolean game_get_can_move (Game* self);
gint game_get_visible_tiles (Game* self);
GList* game_find_matches (Game* self, Tile* tile);
void game_redraw_all_tiles (Game* self);
static void game_reset_clock (Game* self);
void game_set_selected_tile (Game* self, Tile* value);
void game_set_hint (Game* self, Tile* tile0, Tile* tile1);
static gboolean game_hint_timeout_cb (Game* self);
static gboolean _game_hint_timeout_cb_gsource_func (gpointer self);
static void game_start_clock (Game* self);
gboolean game_tile_can_move (Game* self, Tile* tile);
gint game_number_of_movable_tiles (Game* self);
gboolean game_remove_pair (Game* self, Tile* tile0, Tile* tile1);
gboolean game_get_complete (Game* self);
static void game_stop_clock (Game* self);
static gboolean game_timeout_cb (Game* self);
static void game_continue_clock (Game* self);
static gboolean _game_timeout_cb_gsource_func (gpointer self);
void game_undo (Game* self);
gboolean game_get_can_undo (Game* self);
void game_redo (Game* self);
gboolean game_get_can_redo (Game* self);
gboolean game_get_started (Game* self);
gdouble game_get_elapsed (Game* self);
gboolean game_get_paused (Game* self);
void game_set_paused (Game* self, gboolean value);
Tile* game_get_selected_tile (Game* self);
guint game_get_moves_left (Game* self);
static void game_finalize (GObject* obj);
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, gint array_length, GDestroyNotify destroy_func);
static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func);


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


Tile* tile_construct (GType object_type, Slot* slot) {
	Tile * self = NULL;
	Slot* _tmp0_ = NULL;
	Slot* _tmp1_ = NULL;
	g_return_val_if_fail (slot != NULL, NULL);
	self = (Tile*) g_object_new (object_type, NULL);
	_tmp0_ = slot;
	_tmp1_ = _g_object_ref0 (_tmp0_);
	_g_object_unref0 (self->slot);
	self->slot = _tmp1_;
	return self;
}


Tile* tile_new (Slot* slot) {
	return tile_construct (TYPE_TILE, slot);
}


gboolean tile_matches (Tile* self, Tile* tile) {
	gboolean result = FALSE;
	Tile* _tmp0_ = NULL;
	gint _tmp1_ = 0;
	gint _tmp2_ = 0;
	gint _tmp3_ = 0;
	gint _tmp4_ = 0;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (tile != NULL, FALSE);
	_tmp0_ = tile;
	_tmp1_ = tile_get_set (_tmp0_);
	_tmp2_ = _tmp1_;
	_tmp3_ = tile_get_set (self);
	_tmp4_ = _tmp3_;
	result = _tmp2_ == _tmp4_;
	return result;
}


gint tile_get_set (Tile* self) {
	gint result;
	gint _tmp0_ = 0;
	g_return_val_if_fail (self != NULL, 0);
	_tmp0_ = self->number;
	result = _tmp0_ / 4;
	return result;
}


static void tile_class_init (TileClass * klass) {
	tile_parent_class = g_type_class_peek_parent (klass);
	G_OBJECT_CLASS (klass)->get_property = _vala_tile_get_property;
	G_OBJECT_CLASS (klass)->finalize = tile_finalize;
	g_object_class_install_property (G_OBJECT_CLASS (klass), TILE_SET, g_param_spec_int ("set", "set", "set", G_MININT, G_MAXINT, 0, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
}


static void tile_instance_init (Tile * self) {
	self->visible = TRUE;
}


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


GType tile_get_type (void) {
	static volatile gsize tile_type_id__volatile = 0;
	if (g_once_init_enter (&tile_type_id__volatile)) {
		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);
		g_once_init_leave (&tile_type_id__volatile, tile_type_id);
	}
	return tile_type_id__volatile;
}


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_SET:
		g_value_set_int (value, tile_get_set (self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}


gint compare_tiles (Tile* a, Tile* b) {
	gint result = 0;
	Tile* _tmp0_ = NULL;
	Slot* _tmp1_ = NULL;
	Tile* _tmp2_ = NULL;
	Slot* _tmp3_ = NULL;
	gint _tmp4_ = 0;
	g_return_val_if_fail (a != NULL, 0);
	g_return_val_if_fail (b != NULL, 0);
	_tmp0_ = a;
	_tmp1_ = _tmp0_->slot;
	_tmp2_ = b;
	_tmp3_ = _tmp2_->slot;
	_tmp4_ = compare_slots (_tmp1_, _tmp3_);
	result = _tmp4_;
	return result;
}


gboolean switch_tiles (Tile* a, Tile* b) {
	gboolean result = FALSE;
	gboolean _tmp0_ = FALSE;
	Tile* _tmp1_ = NULL;
	gboolean _tmp2_ = FALSE;
	g_return_val_if_fail (a != NULL, FALSE);
	g_return_val_if_fail (b != NULL, FALSE);
	_tmp1_ = a;
	_tmp2_ = _tmp1_->visible;
	if (_tmp2_) {
		Tile* _tmp3_ = NULL;
		gboolean _tmp4_ = FALSE;
		_tmp3_ = b;
		_tmp4_ = _tmp3_->visible;
		_tmp0_ = _tmp4_;
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		Slot* h = NULL;
		Tile* _tmp5_ = NULL;
		Slot* _tmp6_ = NULL;
		Slot* _tmp7_ = NULL;
		Tile* _tmp8_ = NULL;
		Tile* _tmp9_ = NULL;
		Slot* _tmp10_ = NULL;
		Slot* _tmp11_ = NULL;
		Tile* _tmp12_ = NULL;
		Slot* _tmp13_ = NULL;
		Slot* _tmp14_ = NULL;
		_tmp5_ = a;
		_tmp6_ = _tmp5_->slot;
		_tmp7_ = _g_object_ref0 (_tmp6_);
		h = _tmp7_;
		_tmp8_ = a;
		_tmp9_ = b;
		_tmp10_ = _tmp9_->slot;
		_tmp11_ = _g_object_ref0 (_tmp10_);
		_g_object_unref0 (_tmp8_->slot);
		_tmp8_->slot = _tmp11_;
		_tmp12_ = b;
		_tmp13_ = h;
		_tmp14_ = _g_object_ref0 (_tmp13_);
		_g_object_unref0 (_tmp12_->slot);
		_tmp12_->slot = _tmp14_;
		result = TRUE;
		_g_object_unref0 (h);
		return result;
	}
	result = FALSE;
	return result;
}


Match* match_construct (GType object_type, Tile* tile0, Tile* tile1) {
	Match * self = NULL;
	Tile* _tmp0_ = NULL;
	Tile* _tmp1_ = NULL;
	Tile* _tmp2_ = NULL;
	Tile* _tmp3_ = NULL;
	g_return_val_if_fail (tile0 != NULL, NULL);
	g_return_val_if_fail (tile1 != NULL, NULL);
	self = (Match*) g_object_new (object_type, NULL);
	_tmp0_ = tile0;
	_tmp1_ = _g_object_ref0 (_tmp0_);
	_g_object_unref0 (self->tile0);
	self->tile0 = _tmp1_;
	_tmp2_ = tile1;
	_tmp3_ = _g_object_ref0 (_tmp2_);
	_g_object_unref0 (self->tile1);
	self->tile1 = _tmp3_;
	return self;
}


Match* match_new (Tile* tile0, Tile* tile1) {
	return match_construct (TYPE_MATCH, tile0, tile1);
}


static void match_class_init (MatchClass * klass) {
	match_parent_class = g_type_class_peek_parent (klass);
	G_OBJECT_CLASS (klass)->finalize = match_finalize;
}


static void match_instance_init (Match * self) {
}


static void match_finalize (GObject* obj) {
	Match * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_MATCH, Match);
	_g_object_unref0 (self->tile0);
	_g_object_unref0 (self->tile1);
	G_OBJECT_CLASS (match_parent_class)->finalize (obj);
}


GType match_get_type (void) {
	static volatile gsize match_type_id__volatile = 0;
	if (g_once_init_enter (&match_type_id__volatile)) {
		static const GTypeInfo g_define_type_info = { sizeof (MatchClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) match_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Match), 0, (GInstanceInitFunc) match_instance_init, NULL };
		GType match_type_id;
		match_type_id = g_type_register_static (G_TYPE_OBJECT, "Match", &g_define_type_info, 0);
		g_once_init_leave (&match_type_id__volatile, match_type_id);
	}
	return match_type_id__volatile;
}


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


static void _g_list_free__g_object_unref0_ (GList* self) {
	g_list_foreach (self, (GFunc) _g_object_unref0_, NULL);
	g_list_free (self);
}


static gint _compare_tiles_gcompare_func (gconstpointer a, gconstpointer b) {
	gint result;
	result = compare_tiles ((Tile*) a, (Tile*) b);
	return result;
}


Game* game_construct (GType object_type, Map* map) {
	Game * self = NULL;
	Map* _tmp0_ = NULL;
	Map* _tmp1_ = NULL;
	Map* _tmp2_ = NULL;
	GList* _tmp3_ = NULL;
	gint n_pairs = 0;
	GList* _tmp10_ = NULL;
	guint _tmp11_ = 0U;
	gint* numbers = NULL;
	gint _tmp12_ = 0;
	gint* _tmp13_ = NULL;
	gint numbers_length1 = 0;
	gint _numbers_size_ = 0;
	gint* _tmp42_ = NULL;
	gint _tmp42__length1 = 0;
	g_return_val_if_fail (map != NULL, NULL);
	self = (Game*) g_object_new (object_type, NULL);
	_tmp0_ = map;
	_tmp1_ = _g_object_ref0 (_tmp0_);
	_g_object_unref0 (self->map);
	self->map = _tmp1_;
	self->move_number = 1;
	_tmp2_ = map;
	_tmp3_ = _tmp2_->slots;
	{
		GList* slot_collection = NULL;
		GList* slot_it = NULL;
		slot_collection = _tmp3_;
		for (slot_it = slot_collection; slot_it != NULL; slot_it = slot_it->next) {
			Slot* _tmp4_ = NULL;
			Slot* slot = NULL;
			_tmp4_ = _g_object_ref0 ((Slot*) slot_it->data);
			slot = _tmp4_;
			{
				Tile* tile = NULL;
				Slot* _tmp5_ = NULL;
				Tile* _tmp6_ = NULL;
				Tile* _tmp7_ = NULL;
				Tile* _tmp8_ = NULL;
				Tile* _tmp9_ = NULL;
				_tmp5_ = slot;
				_tmp6_ = tile_new (_tmp5_);
				tile = _tmp6_;
				_tmp7_ = tile;
				_tmp7_->number = 0;
				_tmp8_ = tile;
				_tmp9_ = _g_object_ref0 (_tmp8_);
				self->tiles = g_list_insert_sorted (self->tiles, _tmp9_, _compare_tiles_gcompare_func);
				_g_object_unref0 (tile);
				_g_object_unref0 (slot);
			}
		}
	}
	_tmp10_ = self->tiles;
	_tmp11_ = g_list_length (_tmp10_);
	n_pairs = ((gint) _tmp11_) / 2;
	_tmp12_ = n_pairs;
	_tmp13_ = g_new0 (gint, _tmp12_);
	numbers = _tmp13_;
	numbers_length1 = _tmp12_;
	_numbers_size_ = numbers_length1;
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp14_ = FALSE;
			_tmp14_ = TRUE;
			while (TRUE) {
				gint _tmp16_ = 0;
				gint _tmp17_ = 0;
				gint* _tmp18_ = NULL;
				gint _tmp18__length1 = 0;
				gint _tmp19_ = 0;
				gint _tmp20_ = 0;
				gint _tmp21_ = 0;
				if (!_tmp14_) {
					gint _tmp15_ = 0;
					_tmp15_ = i;
					i = _tmp15_ + 1;
				}
				_tmp14_ = FALSE;
				_tmp16_ = i;
				_tmp17_ = n_pairs;
				if (!(_tmp16_ < _tmp17_)) {
					break;
				}
				_tmp18_ = numbers;
				_tmp18__length1 = numbers_length1;
				_tmp19_ = i;
				_tmp20_ = i;
				_tmp18_[_tmp19_] = _tmp20_ * 2;
				_tmp21_ = _tmp18_[_tmp19_];
			}
		}
	}
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp22_ = FALSE;
			_tmp22_ = TRUE;
			while (TRUE) {
				gint _tmp24_ = 0;
				gint _tmp25_ = 0;
				gint32 n = 0;
				gint _tmp26_ = 0;
				gint _tmp27_ = 0;
				gint32 _tmp28_ = 0;
				gint t = 0;
				gint* _tmp29_ = NULL;
				gint _tmp29__length1 = 0;
				gint _tmp30_ = 0;
				gint _tmp31_ = 0;
				gint* _tmp32_ = NULL;
				gint _tmp32__length1 = 0;
				gint _tmp33_ = 0;
				gint* _tmp34_ = NULL;
				gint _tmp34__length1 = 0;
				gint32 _tmp35_ = 0;
				gint _tmp36_ = 0;
				gint _tmp37_ = 0;
				gint* _tmp38_ = NULL;
				gint _tmp38__length1 = 0;
				gint32 _tmp39_ = 0;
				gint _tmp40_ = 0;
				gint _tmp41_ = 0;
				if (!_tmp22_) {
					gint _tmp23_ = 0;
					_tmp23_ = i;
					i = _tmp23_ + 1;
				}
				_tmp22_ = FALSE;
				_tmp24_ = i;
				_tmp25_ = n_pairs;
				if (!(_tmp24_ < _tmp25_)) {
					break;
				}
				_tmp26_ = i;
				_tmp27_ = n_pairs;
				_tmp28_ = g_random_int_range ((gint32) _tmp26_, (gint32) _tmp27_);
				n = _tmp28_;
				_tmp29_ = numbers;
				_tmp29__length1 = numbers_length1;
				_tmp30_ = i;
				_tmp31_ = _tmp29_[_tmp30_];
				t = _tmp31_;
				_tmp32_ = numbers;
				_tmp32__length1 = numbers_length1;
				_tmp33_ = i;
				_tmp34_ = numbers;
				_tmp34__length1 = numbers_length1;
				_tmp35_ = n;
				_tmp36_ = _tmp34_[_tmp35_];
				_tmp32_[_tmp33_] = _tmp36_;
				_tmp37_ = _tmp32_[_tmp33_];
				_tmp38_ = numbers;
				_tmp38__length1 = numbers_length1;
				_tmp39_ = n;
				_tmp40_ = t;
				_tmp38_[_tmp39_] = _tmp40_;
				_tmp41_ = _tmp38_[_tmp39_];
			}
		}
	}
	_tmp42_ = numbers;
	_tmp42__length1 = numbers_length1;
	game_shuffle (self, _tmp42_, _tmp42__length1, 0);
	game_reset (self);
	numbers = (g_free (numbers), NULL);
	return self;
}


Game* game_new (Map* map) {
	return game_construct (TYPE_GAME, map);
}


void game_shuffle_remaining (Game* self, gboolean redraw) {
	guint n = 0U;
	GList* _tmp0_ = NULL;
	guint _tmp1_ = 0U;
	gboolean _tmp25_ = FALSE;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->tiles;
	_tmp1_ = g_list_length (_tmp0_);
	n = _tmp1_;
	{
		gboolean _tmp2_ = FALSE;
		_tmp2_ = TRUE;
		while (TRUE) {
			GList* _tmp20_ = NULL;
			GList* _tmp23_ = NULL;
			GList* _tmp24_ = NULL;
			if (!_tmp2_) {
				gboolean _tmp3_ = FALSE;
				gboolean _tmp4_ = FALSE;
				gboolean _tmp5_ = FALSE;
				_tmp4_ = game_get_can_move (self);
				_tmp5_ = _tmp4_;
				if (!_tmp5_) {
					gint _tmp6_ = 0;
					gint _tmp7_ = 0;
					_tmp6_ = game_get_visible_tiles (self);
					_tmp7_ = _tmp6_;
					_tmp3_ = _tmp7_ > 1;
				} else {
					_tmp3_ = FALSE;
				}
				if (!_tmp3_) {
					break;
				}
			}
			_tmp2_ = FALSE;
			{
				guint i = 0U;
				guint _tmp8_ = 0U;
				_tmp8_ = n;
				i = _tmp8_ - 1;
				{
					gboolean _tmp9_ = FALSE;
					_tmp9_ = TRUE;
					while (TRUE) {
						guint _tmp11_ = 0U;
						gint j = 0;
						guint _tmp12_ = 0U;
						gint32 _tmp13_ = 0;
						GList* _tmp14_ = NULL;
						gint _tmp15_ = 0;
						gconstpointer _tmp16_ = NULL;
						GList* _tmp17_ = NULL;
						guint _tmp18_ = 0U;
						gconstpointer _tmp19_ = NULL;
						if (!_tmp9_) {
							guint _tmp10_ = 0U;
							_tmp10_ = i;
							i = _tmp10_ - 1;
						}
						_tmp9_ = FALSE;
						_tmp11_ = i;
						if (!(_tmp11_ > ((guint) 0))) {
							break;
						}
						_tmp12_ = i;
						_tmp13_ = g_random_int_range ((gint32) 0, (gint32) (((gint) _tmp12_) + 1));
						j = (gint) _tmp13_;
						_tmp14_ = self->tiles;
						_tmp15_ = j;
						_tmp16_ = g_list_nth_data (_tmp14_, (guint) _tmp15_);
						_tmp17_ = self->tiles;
						_tmp18_ = i;
						_tmp19_ = g_list_nth_data (_tmp17_, _tmp18_);
						switch_tiles ((Tile*) _tmp16_, (Tile*) _tmp19_);
					}
				}
			}
			self->tiles = g_list_sort (self->tiles, _compare_tiles_gcompare_func);
			self->move_number = 1;
			_tmp20_ = self->tiles;
			{
				GList* tile_collection = NULL;
				GList* tile_it = NULL;
				tile_collection = _tmp20_;
				for (tile_it = tile_collection; tile_it != NULL; tile_it = tile_it->next) {
					Tile* _tmp21_ = NULL;
					Tile* tile = NULL;
					_tmp21_ = _g_object_ref0 ((Tile*) tile_it->data);
					tile = _tmp21_;
					{
						Tile* _tmp22_ = NULL;
						_tmp22_ = tile;
						_tmp22_->move_number = 0;
						_g_object_unref0 (tile);
					}
				}
			}
			_tmp23_ = game_find_matches (self, NULL);
			_tmp24_ = _tmp23_;
			__g_list_free__g_object_unref0_0 (_tmp24_);
		}
	}
	g_signal_emit_by_name (self, "moved");
	_tmp25_ = redraw;
	if (_tmp25_) {
		game_redraw_all_tiles (self);
	}
}


void game_redraw_all_tiles (Game* self) {
	GList* _tmp0_ = NULL;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->tiles;
	{
		GList* tile_collection = NULL;
		GList* tile_it = NULL;
		tile_collection = _tmp0_;
		for (tile_it = tile_collection; tile_it != NULL; tile_it = tile_it->next) {
			Tile* _tmp1_ = NULL;
			Tile* tile = NULL;
			_tmp1_ = _g_object_ref0 ((Tile*) tile_it->data);
			tile = _tmp1_;
			{
				Tile* _tmp2_ = NULL;
				gboolean _tmp3_ = FALSE;
				_tmp2_ = tile;
				_tmp3_ = _tmp2_->visible;
				if (_tmp3_) {
					Tile* _tmp4_ = NULL;
					_tmp4_ = tile;
					g_signal_emit_by_name (self, "redraw-tile", _tmp4_);
				}
				_g_object_unref0 (tile);
			}
		}
	}
}


static gboolean game_shuffle (Game* self, gint* numbers, int numbers_length1, gint depth) {
	gboolean result = FALSE;
	gint _tmp0_ = 0;
	GList* _tmp1_ = NULL;
	guint _tmp2_ = 0U;
	GList* matches = NULL;
	GList* _tmp3_ = NULL;
	guint n_matches = 0U;
	GList* _tmp4_ = NULL;
	guint _tmp5_ = 0U;
	guint _tmp6_ = 0U;
	gint32 n = 0;
	guint _tmp7_ = 0U;
	gint32 _tmp8_ = 0;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = depth;
	_tmp1_ = self->tiles;
	_tmp2_ = g_list_length (_tmp1_);
	if (((guint) _tmp0_) == (_tmp2_ / 2)) {
		result = TRUE;
		return result;
	}
	_tmp3_ = game_find_matches (self, NULL);
	matches = _tmp3_;
	_tmp4_ = matches;
	_tmp5_ = g_list_length (_tmp4_);
	n_matches = _tmp5_;
	_tmp6_ = n_matches;
	if (_tmp6_ == ((guint) 0)) {
		result = FALSE;
		__g_list_free__g_object_unref0_0 (matches);
		return result;
	}
	_tmp7_ = n_matches;
	_tmp8_ = g_random_int_range ((gint32) 0, (gint32) ((gint) _tmp7_));
	n = _tmp8_;
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp9_ = FALSE;
			_tmp9_ = TRUE;
			while (TRUE) {
				gint _tmp11_ = 0;
				guint _tmp12_ = 0U;
				Match* match = NULL;
				GList* _tmp13_ = NULL;
				gint32 _tmp14_ = 0;
				gint _tmp15_ = 0;
				guint _tmp16_ = 0U;
				gconstpointer _tmp17_ = NULL;
				Match* _tmp18_ = NULL;
				Match* _tmp19_ = NULL;
				Tile* _tmp20_ = NULL;
				gint* _tmp21_ = NULL;
				gint _tmp21__length1 = 0;
				gint _tmp22_ = 0;
				gint _tmp23_ = 0;
				Match* _tmp24_ = NULL;
				Tile* _tmp25_ = NULL;
				Match* _tmp26_ = NULL;
				Tile* _tmp27_ = NULL;
				gint* _tmp28_ = NULL;
				gint _tmp28__length1 = 0;
				gint _tmp29_ = 0;
				gint _tmp30_ = 0;
				Match* _tmp31_ = NULL;
				Tile* _tmp32_ = NULL;
				gint* _tmp33_ = NULL;
				gint _tmp33__length1 = 0;
				gint _tmp34_ = 0;
				gboolean _tmp35_ = FALSE;
				Match* _tmp36_ = NULL;
				Tile* _tmp37_ = NULL;
				Match* _tmp38_ = NULL;
				Tile* _tmp39_ = NULL;
				Match* _tmp40_ = NULL;
				Tile* _tmp41_ = NULL;
				Match* _tmp42_ = NULL;
				Tile* _tmp43_ = NULL;
				if (!_tmp9_) {
					gint _tmp10_ = 0;
					_tmp10_ = i;
					i = _tmp10_ + 1;
				}
				_tmp9_ = FALSE;
				_tmp11_ = i;
				_tmp12_ = n_matches;
				if (!(((guint) _tmp11_) < _tmp12_)) {
					break;
				}
				_tmp13_ = matches;
				_tmp14_ = n;
				_tmp15_ = i;
				_tmp16_ = n_matches;
				_tmp17_ = g_list_nth_data (_tmp13_, (_tmp14_ + _tmp15_) % _tmp16_);
				_tmp18_ = _g_object_ref0 ((Match*) _tmp17_);
				match = _tmp18_;
				_tmp19_ = match;
				_tmp20_ = _tmp19_->tile0;
				_tmp21_ = numbers;
				_tmp21__length1 = numbers_length1;
				_tmp22_ = depth;
				_tmp23_ = _tmp21_[_tmp22_];
				_tmp20_->number = _tmp23_;
				_tmp24_ = match;
				_tmp25_ = _tmp24_->tile0;
				_tmp25_->visible = FALSE;
				_tmp26_ = match;
				_tmp27_ = _tmp26_->tile1;
				_tmp28_ = numbers;
				_tmp28__length1 = numbers_length1;
				_tmp29_ = depth;
				_tmp30_ = _tmp28_[_tmp29_];
				_tmp27_->number = _tmp30_ + 1;
				_tmp31_ = match;
				_tmp32_ = _tmp31_->tile1;
				_tmp32_->visible = FALSE;
				_tmp33_ = numbers;
				_tmp33__length1 = numbers_length1;
				_tmp34_ = depth;
				_tmp35_ = game_shuffle (self, _tmp33_, _tmp33__length1, _tmp34_ + 1);
				if (_tmp35_) {
					result = TRUE;
					_g_object_unref0 (match);
					__g_list_free__g_object_unref0_0 (matches);
					return result;
				}
				_tmp36_ = match;
				_tmp37_ = _tmp36_->tile0;
				_tmp37_->number = 0;
				_tmp38_ = match;
				_tmp39_ = _tmp38_->tile0;
				_tmp39_->visible = TRUE;
				_tmp40_ = match;
				_tmp41_ = _tmp40_->tile1;
				_tmp41_->number = 0;
				_tmp42_ = match;
				_tmp43_ = _tmp42_->tile1;
				_tmp43_->visible = TRUE;
				_g_object_unref0 (match);
			}
		}
	}
	result = FALSE;
	__g_list_free__g_object_unref0_0 (matches);
	return result;
}


void game_reset (Game* self) {
	GList* _tmp0_ = NULL;
	g_return_if_fail (self != NULL);
	game_reset_clock (self);
	self->move_number = 1;
	game_set_selected_tile (self, NULL);
	game_set_hint (self, NULL, NULL);
	_tmp0_ = self->tiles;
	{
		GList* tile_collection = NULL;
		GList* tile_it = NULL;
		tile_collection = _tmp0_;
		for (tile_it = tile_collection; tile_it != NULL; tile_it = tile_it->next) {
			Tile* _tmp1_ = NULL;
			Tile* tile = NULL;
			_tmp1_ = _g_object_ref0 ((Tile*) tile_it->data);
			tile = _tmp1_;
			{
				Tile* _tmp2_ = NULL;
				Tile* _tmp3_ = NULL;
				_tmp2_ = tile;
				_tmp2_->visible = TRUE;
				_tmp3_ = tile;
				_tmp3_->move_number = 0;
				_g_object_unref0 (tile);
			}
		}
	}
	game_redraw_all_tiles (self);
}


static gboolean _game_hint_timeout_cb_gsource_func (gpointer self) {
	gboolean result;
	result = game_hint_timeout_cb ((Game*) self);
	return result;
}


void game_set_hint (Game* self, Tile* tile0, Tile* tile1) {
	Tile* _tmp0_ = NULL;
	Tile* _tmp2_ = NULL;
	gboolean _tmp4_ = FALSE;
	Tile* _tmp5_ = NULL;
	Tile* _tmp7_ = NULL;
	Tile* _tmp8_ = NULL;
	Tile* _tmp9_ = NULL;
	Tile* _tmp10_ = NULL;
	Tile* _tmp11_ = NULL;
	Tile* _tmp12_ = NULL;
	guint _tmp13_ = 0U;
	guint _tmp15_ = 0U;
	gdouble _tmp16_ = 0.0;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->hint_tiles[0];
	if (_tmp0_ != NULL) {
		Tile* _tmp1_ = NULL;
		_tmp1_ = self->hint_tiles[0];
		g_signal_emit_by_name (self, "redraw-tile", _tmp1_);
	}
	_tmp2_ = self->hint_tiles[1];
	if (_tmp2_ != NULL) {
		Tile* _tmp3_ = NULL;
		_tmp3_ = self->hint_tiles[1];
		g_signal_emit_by_name (self, "redraw-tile", _tmp3_);
	}
	_tmp5_ = tile0;
	if (_tmp5_ == NULL) {
		Tile* _tmp6_ = NULL;
		_tmp6_ = tile1;
		_tmp4_ = _tmp6_ == NULL;
	} else {
		_tmp4_ = FALSE;
	}
	if (_tmp4_) {
		self->hint_blink_counter = (guint) 0;
		game_hint_timeout_cb (self);
		return;
	}
	_tmp7_ = tile0;
	_tmp8_ = _g_object_ref0 (_tmp7_);
	_g_object_unref0 (self->hint_tiles[0]);
	self->hint_tiles[0] = _tmp8_;
	_tmp9_ = self->hint_tiles[0];
	_tmp10_ = tile1;
	_tmp11_ = _g_object_ref0 (_tmp10_);
	_g_object_unref0 (self->hint_tiles[1]);
	self->hint_tiles[1] = _tmp11_;
	_tmp12_ = self->hint_tiles[1];
	self->hint_blink_counter = (guint) 6;
	_tmp13_ = self->priv->hint_timout;
	if (_tmp13_ != ((guint) 0)) {
		guint _tmp14_ = 0U;
		_tmp14_ = self->priv->hint_timout;
		g_source_remove (_tmp14_);
	}
	_tmp15_ = g_timeout_add_full (G_PRIORITY_DEFAULT, (guint) 250, _game_hint_timeout_cb_gsource_func, g_object_ref (self), g_object_unref);
	self->priv->hint_timout = _tmp15_;
	game_hint_timeout_cb (self);
	game_start_clock (self);
	_tmp16_ = self->priv->clock_elapsed;
	self->priv->clock_elapsed = _tmp16_ + 30.0;
	g_signal_emit_by_name (self, "tick");
}


static gboolean game_hint_timeout_cb (Game* self) {
	gboolean result = FALSE;
	guint _tmp0_ = 0U;
	guint _tmp3_ = 0U;
	Tile* _tmp4_ = NULL;
	Tile* _tmp6_ = NULL;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->hint_blink_counter;
	if (_tmp0_ == ((guint) 0)) {
		guint _tmp1_ = 0U;
		_tmp1_ = self->priv->hint_timout;
		if (_tmp1_ != ((guint) 0)) {
			guint _tmp2_ = 0U;
			_tmp2_ = self->priv->hint_timout;
			g_source_remove (_tmp2_);
		}
		self->priv->hint_timout = (guint) 0;
		result = FALSE;
		return result;
	}
	_tmp3_ = self->hint_blink_counter;
	self->hint_blink_counter = _tmp3_ - 1;
	_tmp4_ = self->hint_tiles[0];
	if (_tmp4_ != NULL) {
		Tile* _tmp5_ = NULL;
		_tmp5_ = self->hint_tiles[0];
		g_signal_emit_by_name (self, "redraw-tile", _tmp5_);
	}
	_tmp6_ = self->hint_tiles[1];
	if (_tmp6_ != NULL) {
		Tile* _tmp7_ = NULL;
		_tmp7_ = self->hint_tiles[1];
		g_signal_emit_by_name (self, "redraw-tile", _tmp7_);
	}
	result = TRUE;
	return result;
}


gboolean game_tile_can_move (Game* self, Tile* tile) {
	gboolean result = FALSE;
	Tile* _tmp0_ = NULL;
	gboolean _tmp1_ = FALSE;
	gboolean blocked_left = FALSE;
	gboolean blocked_right = FALSE;
	Slot* slot = NULL;
	Tile* _tmp2_ = NULL;
	Slot* _tmp3_ = NULL;
	Slot* _tmp4_ = NULL;
	GList* _tmp5_ = NULL;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (tile != NULL, FALSE);
	_tmp0_ = tile;
	_tmp1_ = _tmp0_->visible;
	if (!_tmp1_) {
		result = FALSE;
		return result;
	}
	blocked_left = FALSE;
	blocked_right = FALSE;
	_tmp2_ = tile;
	_tmp3_ = _tmp2_->slot;
	_tmp4_ = _g_object_ref0 (_tmp3_);
	slot = _tmp4_;
	_tmp5_ = self->tiles;
	{
		GList* t_collection = NULL;
		GList* t_it = NULL;
		t_collection = _tmp5_;
		for (t_it = t_collection; t_it != NULL; t_it = t_it->next) {
			Tile* _tmp6_ = NULL;
			Tile* t = NULL;
			_tmp6_ = _g_object_ref0 ((Tile*) t_it->data);
			t = _tmp6_;
			{
				gboolean _tmp7_ = FALSE;
				Tile* _tmp8_ = NULL;
				Tile* _tmp9_ = NULL;
				Slot* s = NULL;
				Tile* _tmp12_ = NULL;
				Slot* _tmp13_ = NULL;
				Slot* _tmp14_ = NULL;
				gboolean _tmp15_ = FALSE;
				gboolean _tmp16_ = FALSE;
				Slot* _tmp17_ = NULL;
				gint _tmp18_ = 0;
				Slot* _tmp19_ = NULL;
				gint _tmp20_ = 0;
				gboolean _tmp39_ = FALSE;
				Slot* _tmp40_ = NULL;
				gint _tmp41_ = 0;
				Slot* _tmp42_ = NULL;
				gint _tmp43_ = 0;
				_tmp8_ = t;
				_tmp9_ = tile;
				if (_tmp8_ == _tmp9_) {
					_tmp7_ = TRUE;
				} else {
					Tile* _tmp10_ = NULL;
					gboolean _tmp11_ = FALSE;
					_tmp10_ = t;
					_tmp11_ = _tmp10_->visible;
					_tmp7_ = !_tmp11_;
				}
				if (_tmp7_) {
					_g_object_unref0 (t);
					continue;
				}
				_tmp12_ = t;
				_tmp13_ = _tmp12_->slot;
				_tmp14_ = _g_object_ref0 (_tmp13_);
				s = _tmp14_;
				_tmp17_ = s;
				_tmp18_ = _tmp17_->layer;
				_tmp19_ = slot;
				_tmp20_ = _tmp19_->layer;
				if (_tmp18_ == (_tmp20_ + 1)) {
					gboolean _tmp21_ = FALSE;
					Slot* _tmp22_ = NULL;
					gint _tmp23_ = 0;
					Slot* _tmp24_ = NULL;
					gint _tmp25_ = 0;
					_tmp22_ = s;
					_tmp23_ = _tmp22_->x;
					_tmp24_ = slot;
					_tmp25_ = _tmp24_->x;
					if (_tmp23_ >= (_tmp25_ - 1)) {
						Slot* _tmp26_ = NULL;
						gint _tmp27_ = 0;
						Slot* _tmp28_ = NULL;
						gint _tmp29_ = 0;
						_tmp26_ = s;
						_tmp27_ = _tmp26_->x;
						_tmp28_ = slot;
						_tmp29_ = _tmp28_->x;
						_tmp21_ = _tmp27_ <= (_tmp29_ + 1);
					} else {
						_tmp21_ = FALSE;
					}
					_tmp16_ = _tmp21_;
				} else {
					_tmp16_ = FALSE;
				}
				if (_tmp16_) {
					gboolean _tmp30_ = FALSE;
					Slot* _tmp31_ = NULL;
					gint _tmp32_ = 0;
					Slot* _tmp33_ = NULL;
					gint _tmp34_ = 0;
					_tmp31_ = s;
					_tmp32_ = _tmp31_->y;
					_tmp33_ = slot;
					_tmp34_ = _tmp33_->y;
					if (_tmp32_ >= (_tmp34_ - 1)) {
						Slot* _tmp35_ = NULL;
						gint _tmp36_ = 0;
						Slot* _tmp37_ = NULL;
						gint _tmp38_ = 0;
						_tmp35_ = s;
						_tmp36_ = _tmp35_->y;
						_tmp37_ = slot;
						_tmp38_ = _tmp37_->y;
						_tmp30_ = _tmp36_ <= (_tmp38_ + 1);
					} else {
						_tmp30_ = FALSE;
					}
					_tmp15_ = _tmp30_;
				} else {
					_tmp15_ = FALSE;
				}
				if (_tmp15_) {
					result = FALSE;
					_g_object_unref0 (s);
					_g_object_unref0 (t);
					_g_object_unref0 (slot);
					return result;
				}
				_tmp40_ = s;
				_tmp41_ = _tmp40_->layer;
				_tmp42_ = slot;
				_tmp43_ = _tmp42_->layer;
				if (_tmp41_ == _tmp43_) {
					gboolean _tmp44_ = FALSE;
					Slot* _tmp45_ = NULL;
					gint _tmp46_ = 0;
					Slot* _tmp47_ = NULL;
					gint _tmp48_ = 0;
					_tmp45_ = s;
					_tmp46_ = _tmp45_->y;
					_tmp47_ = slot;
					_tmp48_ = _tmp47_->y;
					if (_tmp46_ >= (_tmp48_ - 1)) {
						Slot* _tmp49_ = NULL;
						gint _tmp50_ = 0;
						Slot* _tmp51_ = NULL;
						gint _tmp52_ = 0;
						_tmp49_ = s;
						_tmp50_ = _tmp49_->y;
						_tmp51_ = slot;
						_tmp52_ = _tmp51_->y;
						_tmp44_ = _tmp50_ <= (_tmp52_ + 1);
					} else {
						_tmp44_ = FALSE;
					}
					_tmp39_ = _tmp44_;
				} else {
					_tmp39_ = FALSE;
				}
				if (_tmp39_) {
					Slot* _tmp53_ = NULL;
					gint _tmp54_ = 0;
					Slot* _tmp55_ = NULL;
					gint _tmp56_ = 0;
					Slot* _tmp57_ = NULL;
					gint _tmp58_ = 0;
					Slot* _tmp59_ = NULL;
					gint _tmp60_ = 0;
					gboolean _tmp61_ = FALSE;
					gboolean _tmp62_ = FALSE;
					_tmp53_ = s;
					_tmp54_ = _tmp53_->x;
					_tmp55_ = slot;
					_tmp56_ = _tmp55_->x;
					if (_tmp54_ == (_tmp56_ - 2)) {
						blocked_left = TRUE;
					}
					_tmp57_ = s;
					_tmp58_ = _tmp57_->x;
					_tmp59_ = slot;
					_tmp60_ = _tmp59_->x;
					if (_tmp58_ == (_tmp60_ + 2)) {
						blocked_right = TRUE;
					}
					_tmp62_ = blocked_left;
					if (_tmp62_) {
						gboolean _tmp63_ = FALSE;
						_tmp63_ = blocked_right;
						_tmp61_ = _tmp63_;
					} else {
						_tmp61_ = FALSE;
					}
					if (_tmp61_) {
						result = FALSE;
						_g_object_unref0 (s);
						_g_object_unref0 (t);
						_g_object_unref0 (slot);
						return result;
					}
				}
				_g_object_unref0 (s);
				_g_object_unref0 (t);
			}
		}
	}
	result = TRUE;
	_g_object_unref0 (slot);
	return result;
}


gint game_number_of_movable_tiles (Game* self) {
	gint result = 0;
	gint count = 0;
	GList* _tmp0_ = NULL;
	g_return_val_if_fail (self != NULL, 0);
	count = 0;
	_tmp0_ = self->tiles;
	{
		GList* tile_collection = NULL;
		GList* tile_it = NULL;
		tile_collection = _tmp0_;
		for (tile_it = tile_collection; tile_it != NULL; tile_it = tile_it->next) {
			Tile* _tmp1_ = NULL;
			Tile* tile = NULL;
			_tmp1_ = _g_object_ref0 ((Tile*) tile_it->data);
			tile = _tmp1_;
			{
				Tile* _tmp2_ = NULL;
				gboolean _tmp3_ = FALSE;
				_tmp2_ = tile;
				_tmp3_ = game_tile_can_move (self, _tmp2_);
				if (_tmp3_) {
					gint _tmp4_ = 0;
					_tmp4_ = count;
					count = _tmp4_ + 1;
				}
				_g_object_unref0 (tile);
			}
		}
	}
	result = count;
	return result;
}


GList* game_find_matches (Game* self, Tile* tile) {
	GList* result = NULL;
	GList* matches = NULL;
	gboolean _tmp0_ = FALSE;
	Tile* _tmp1_ = NULL;
	Tile* _tmp4_ = NULL;
	g_return_val_if_fail (self != NULL, NULL);
	matches = NULL;
	_tmp1_ = tile;
	if (_tmp1_ != NULL) {
		Tile* _tmp2_ = NULL;
		gboolean _tmp3_ = FALSE;
		_tmp2_ = tile;
		_tmp3_ = game_tile_can_move (self, _tmp2_);
		_tmp0_ = !_tmp3_;
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		result = matches;
		return result;
	}
	_tmp4_ = tile;
	if (_tmp4_ == NULL) {
		GList* _tmp5_ = NULL;
		_tmp5_ = self->tiles;
		{
			GList* t_collection = NULL;
			GList* t_it = NULL;
			t_collection = _tmp5_;
			for (t_it = t_collection; t_it != NULL; t_it = t_it->next) {
				Tile* _tmp6_ = NULL;
				Tile* t = NULL;
				_tmp6_ = _g_object_ref0 ((Tile*) t_it->data);
				t = _tmp6_;
				{
					Tile* _tmp7_ = NULL;
					GList* _tmp8_ = NULL;
					_tmp7_ = t;
					_tmp8_ = game_find_matches (self, _tmp7_);
					{
						GList* match_collection = NULL;
						GList* match_it = NULL;
						match_collection = _tmp8_;
						for (match_it = match_collection; match_it != NULL; match_it = match_it->next) {
							Match* _tmp9_ = NULL;
							Match* match = NULL;
							_tmp9_ = _g_object_ref0 ((Match*) match_it->data);
							match = _tmp9_;
							{
								gboolean already_matched = FALSE;
								GList* _tmp10_ = NULL;
								gboolean _tmp21_ = FALSE;
								already_matched = FALSE;
								_tmp10_ = matches;
								{
									GList* existing_match_collection = NULL;
									GList* existing_match_it = NULL;
									existing_match_collection = _tmp10_;
									for (existing_match_it = existing_match_collection; existing_match_it != NULL; existing_match_it = existing_match_it->next) {
										Match* _tmp11_ = NULL;
										Match* existing_match = NULL;
										_tmp11_ = _g_object_ref0 ((Match*) existing_match_it->data);
										existing_match = _tmp11_;
										{
											gboolean _tmp12_ = FALSE;
											Match* _tmp13_ = NULL;
											Tile* _tmp14_ = NULL;
											Match* _tmp15_ = NULL;
											Tile* _tmp16_ = NULL;
											_tmp13_ = existing_match;
											_tmp14_ = _tmp13_->tile0;
											_tmp15_ = match;
											_tmp16_ = _tmp15_->tile1;
											if (_tmp14_ == _tmp16_) {
												Match* _tmp17_ = NULL;
												Tile* _tmp18_ = NULL;
												Match* _tmp19_ = NULL;
												Tile* _tmp20_ = NULL;
												_tmp17_ = existing_match;
												_tmp18_ = _tmp17_->tile1;
												_tmp19_ = match;
												_tmp20_ = _tmp19_->tile0;
												_tmp12_ = _tmp18_ == _tmp20_;
											} else {
												_tmp12_ = FALSE;
											}
											if (_tmp12_) {
												already_matched = TRUE;
												_g_object_unref0 (existing_match);
												break;
											}
											_g_object_unref0 (existing_match);
										}
									}
								}
								_tmp21_ = already_matched;
								if (!_tmp21_) {
									Match* _tmp22_ = NULL;
									Match* _tmp23_ = NULL;
									_tmp22_ = match;
									_tmp23_ = _g_object_ref0 (_tmp22_);
									matches = g_list_append (matches, _tmp23_);
								}
								_g_object_unref0 (match);
							}
						}
						__g_list_free__g_object_unref0_0 (match_collection);
					}
					_g_object_unref0 (t);
				}
			}
		}
	} else {
		GList* _tmp24_ = NULL;
		_tmp24_ = self->tiles;
		{
			GList* t_collection = NULL;
			GList* t_it = NULL;
			t_collection = _tmp24_;
			for (t_it = t_collection; t_it != NULL; t_it = t_it->next) {
				Tile* _tmp25_ = NULL;
				Tile* t = NULL;
				_tmp25_ = _g_object_ref0 ((Tile*) t_it->data);
				t = _tmp25_;
				{
					gboolean _tmp26_ = FALSE;
					Tile* _tmp27_ = NULL;
					Tile* _tmp28_ = NULL;
					Tile* _tmp31_ = NULL;
					Tile* _tmp32_ = NULL;
					gboolean _tmp33_ = FALSE;
					_tmp27_ = t;
					_tmp28_ = tile;
					if (_tmp27_ == _tmp28_) {
						_tmp26_ = TRUE;
					} else {
						Tile* _tmp29_ = NULL;
						gboolean _tmp30_ = FALSE;
						_tmp29_ = t;
						_tmp30_ = game_tile_can_move (self, _tmp29_);
						_tmp26_ = !_tmp30_;
					}
					if (_tmp26_) {
						_g_object_unref0 (t);
						continue;
					}
					_tmp31_ = t;
					_tmp32_ = tile;
					_tmp33_ = tile_matches (_tmp31_, _tmp32_);
					if (_tmp33_) {
						Tile* _tmp34_ = NULL;
						Tile* _tmp35_ = NULL;
						Match* _tmp36_ = NULL;
						_tmp34_ = t;
						_tmp35_ = tile;
						_tmp36_ = match_new (_tmp34_, _tmp35_);
						matches = g_list_append (matches, _tmp36_);
					}
					_g_object_unref0 (t);
				}
			}
		}
	}
	result = matches;
	return result;
}


gboolean game_remove_pair (Game* self, Tile* tile0, Tile* tile1) {
	gboolean result = FALSE;
	gboolean _tmp0_ = FALSE;
	Tile* _tmp1_ = NULL;
	gboolean _tmp2_ = FALSE;
	Tile* _tmp5_ = NULL;
	gint _tmp6_ = 0;
	gint _tmp7_ = 0;
	Tile* _tmp8_ = NULL;
	gint _tmp9_ = 0;
	gint _tmp10_ = 0;
	GList* _tmp11_ = NULL;
	Tile* _tmp17_ = NULL;
	Tile* _tmp18_ = NULL;
	gint _tmp19_ = 0;
	Tile* _tmp20_ = NULL;
	Tile* _tmp21_ = NULL;
	gint _tmp22_ = 0;
	gint _tmp23_ = 0;
	Tile* _tmp24_ = NULL;
	Tile* _tmp25_ = NULL;
	gboolean _tmp26_ = FALSE;
	gboolean _tmp27_ = FALSE;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (tile0 != NULL, FALSE);
	g_return_val_if_fail (tile1 != NULL, FALSE);
	_tmp1_ = tile0;
	_tmp2_ = _tmp1_->visible;
	if (!_tmp2_) {
		_tmp0_ = TRUE;
	} else {
		Tile* _tmp3_ = NULL;
		gboolean _tmp4_ = FALSE;
		_tmp3_ = tile1;
		_tmp4_ = _tmp3_->visible;
		_tmp0_ = !_tmp4_;
	}
	if (_tmp0_) {
		result = FALSE;
		return result;
	}
	_tmp5_ = tile0;
	_tmp6_ = tile_get_set (_tmp5_);
	_tmp7_ = _tmp6_;
	_tmp8_ = tile1;
	_tmp9_ = tile_get_set (_tmp8_);
	_tmp10_ = _tmp9_;
	if (_tmp7_ != _tmp10_) {
		result = FALSE;
		return result;
	}
	game_set_selected_tile (self, NULL);
	game_set_hint (self, NULL, NULL);
	_tmp11_ = self->tiles;
	{
		GList* tile_collection = NULL;
		GList* tile_it = NULL;
		tile_collection = _tmp11_;
		for (tile_it = tile_collection; tile_it != NULL; tile_it = tile_it->next) {
			Tile* _tmp12_ = NULL;
			Tile* tile = NULL;
			_tmp12_ = _g_object_ref0 ((Tile*) tile_it->data);
			tile = _tmp12_;
			{
				Tile* _tmp13_ = NULL;
				gint _tmp14_ = 0;
				gint _tmp15_ = 0;
				_tmp13_ = tile;
				_tmp14_ = _tmp13_->move_number;
				_tmp15_ = self->move_number;
				if (_tmp14_ >= _tmp15_) {
					Tile* _tmp16_ = NULL;
					_tmp16_ = tile;
					_tmp16_->move_number = 0;
				}
				_g_object_unref0 (tile);
			}
		}
	}
	_tmp17_ = tile0;
	_tmp17_->visible = FALSE;
	_tmp18_ = tile0;
	_tmp19_ = self->move_number;
	_tmp18_->move_number = _tmp19_;
	_tmp20_ = tile1;
	_tmp20_->visible = FALSE;
	_tmp21_ = tile1;
	_tmp22_ = self->move_number;
	_tmp21_->move_number = _tmp22_;
	_tmp23_ = self->move_number;
	self->move_number = _tmp23_ + 1;
	_tmp24_ = tile0;
	g_signal_emit_by_name (self, "redraw-tile", _tmp24_);
	_tmp25_ = tile1;
	g_signal_emit_by_name (self, "redraw-tile", _tmp25_);
	_tmp26_ = game_get_complete (self);
	_tmp27_ = _tmp26_;
	if (_tmp27_) {
		game_stop_clock (self);
	} else {
		game_start_clock (self);
	}
	g_signal_emit_by_name (self, "moved");
	result = TRUE;
	return result;
}


static void game_start_clock (Game* self) {
	GTimer* _tmp0_ = NULL;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->clock;
	if (_tmp0_ == NULL) {
		GTimer* _tmp1_ = NULL;
		_tmp1_ = g_timer_new ();
		_g_timer_destroy0 (self->priv->clock);
		self->priv->clock = _tmp1_;
	}
	game_timeout_cb (self);
}


static void game_stop_clock (Game* self) {
	GTimer* _tmp0_ = NULL;
	guint _tmp1_ = 0U;
	GTimer* _tmp3_ = NULL;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->clock;
	if (_tmp0_ == NULL) {
		return;
	}
	_tmp1_ = self->priv->clock_timeout;
	if (_tmp1_ != ((guint) 0)) {
		guint _tmp2_ = 0U;
		_tmp2_ = self->priv->clock_timeout;
		g_source_remove (_tmp2_);
	}
	self->priv->clock_timeout = (guint) 0;
	_tmp3_ = self->priv->clock;
	g_timer_stop (_tmp3_);
	g_signal_emit_by_name (self, "tick");
}


static void game_continue_clock (Game* self) {
	GTimer* _tmp0_ = NULL;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->clock;
	if (_tmp0_ == NULL) {
		GTimer* _tmp1_ = NULL;
		_tmp1_ = g_timer_new ();
		_g_timer_destroy0 (self->priv->clock);
		self->priv->clock = _tmp1_;
	} else {
		GTimer* _tmp2_ = NULL;
		_tmp2_ = self->priv->clock;
		g_timer_continue (_tmp2_);
	}
	game_timeout_cb (self);
}


static void game_reset_clock (Game* self) {
	g_return_if_fail (self != NULL);
	game_stop_clock (self);
	_g_timer_destroy0 (self->priv->clock);
	self->priv->clock = NULL;
	self->priv->clock_elapsed = 0.0;
	g_signal_emit_by_name (self, "tick");
}


static gboolean _game_timeout_cb_gsource_func (gpointer self) {
	gboolean result;
	result = game_timeout_cb ((Game*) self);
	return result;
}


static gboolean game_timeout_cb (Game* self) {
	gboolean result = FALSE;
	GTimer* _tmp0_ = NULL;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->clock;
	if (_tmp0_ != NULL) {
		gdouble elapsed = 0.0;
		GTimer* _tmp1_ = NULL;
		gdouble _tmp2_ = 0.0;
		gint next = 0;
		gdouble _tmp3_ = 0.0;
		gdouble wait = 0.0;
		gint _tmp4_ = 0;
		gdouble _tmp5_ = 0.0;
		gdouble _tmp6_ = 0.0;
		guint _tmp7_ = 0U;
		_tmp1_ = self->priv->clock;
		_tmp2_ = g_timer_elapsed (_tmp1_, NULL);
		elapsed = _tmp2_;
		_tmp3_ = elapsed;
		next = (gint) (_tmp3_ + 1.0);
		_tmp4_ = next;
		_tmp5_ = elapsed;
		wait = _tmp4_ - _tmp5_;
		_tmp6_ = wait;
		_tmp7_ = g_timeout_add_full (G_PRIORITY_DEFAULT, (guint) ((gint) (_tmp6_ * 1000)), _game_timeout_cb_gsource_func, g_object_ref (self), g_object_unref);
		self->priv->clock_timeout = _tmp7_;
		g_signal_emit_by_name (self, "tick");
	}
	result = FALSE;
	return result;
}


void game_undo (Game* self) {
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gint _tmp2_ = 0;
	GList* _tmp3_ = NULL;
	g_return_if_fail (self != NULL);
	_tmp0_ = game_get_can_undo (self);
	_tmp1_ = _tmp0_;
	if (!_tmp1_) {
		return;
	}
	game_set_selected_tile (self, NULL);
	game_set_hint (self, NULL, NULL);
	_tmp2_ = self->move_number;
	self->move_number = _tmp2_ - 1;
	_tmp3_ = self->tiles;
	{
		GList* tile_collection = NULL;
		GList* tile_it = NULL;
		tile_collection = _tmp3_;
		for (tile_it = tile_collection; tile_it != NULL; tile_it = tile_it->next) {
			Tile* _tmp4_ = NULL;
			Tile* tile = NULL;
			_tmp4_ = _g_object_ref0 ((Tile*) tile_it->data);
			tile = _tmp4_;
			{
				Tile* _tmp5_ = NULL;
				gint _tmp6_ = 0;
				gint _tmp7_ = 0;
				_tmp5_ = tile;
				_tmp6_ = _tmp5_->move_number;
				_tmp7_ = self->move_number;
				if (_tmp6_ == _tmp7_) {
					Tile* _tmp8_ = NULL;
					Tile* _tmp9_ = NULL;
					_tmp8_ = tile;
					_tmp8_->visible = TRUE;
					_tmp9_ = tile;
					g_signal_emit_by_name (self, "redraw-tile", _tmp9_);
				}
				_g_object_unref0 (tile);
			}
		}
	}
}


void game_redo (Game* self) {
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	GList* _tmp2_ = NULL;
	gint _tmp9_ = 0;
	g_return_if_fail (self != NULL);
	_tmp0_ = game_get_can_redo (self);
	_tmp1_ = _tmp0_;
	if (!_tmp1_) {
		return;
	}
	game_set_selected_tile (self, NULL);
	game_set_hint (self, NULL, NULL);
	_tmp2_ = self->tiles;
	{
		GList* tile_collection = NULL;
		GList* tile_it = NULL;
		tile_collection = _tmp2_;
		for (tile_it = tile_collection; tile_it != NULL; tile_it = tile_it->next) {
			Tile* _tmp3_ = NULL;
			Tile* tile = NULL;
			_tmp3_ = _g_object_ref0 ((Tile*) tile_it->data);
			tile = _tmp3_;
			{
				Tile* _tmp4_ = NULL;
				gint _tmp5_ = 0;
				gint _tmp6_ = 0;
				_tmp4_ = tile;
				_tmp5_ = _tmp4_->move_number;
				_tmp6_ = self->move_number;
				if (_tmp5_ == _tmp6_) {
					Tile* _tmp7_ = NULL;
					Tile* _tmp8_ = NULL;
					_tmp7_ = tile;
					_tmp7_->visible = FALSE;
					_tmp8_ = tile;
					g_signal_emit_by_name (self, "redraw-tile", _tmp8_);
				}
				_g_object_unref0 (tile);
			}
		}
	}
	_tmp9_ = self->move_number;
	self->move_number = _tmp9_ + 1;
}


gboolean game_get_started (Game* self) {
	gboolean result;
	GTimer* _tmp0_ = NULL;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->clock;
	result = _tmp0_ != NULL;
	return result;
}


gdouble game_get_elapsed (Game* self) {
	gdouble result;
	GTimer* _tmp0_ = NULL;
	gdouble _tmp1_ = 0.0;
	GTimer* _tmp2_ = NULL;
	gdouble _tmp3_ = 0.0;
	g_return_val_if_fail (self != NULL, 0.0);
	_tmp0_ = self->priv->clock;
	if (_tmp0_ == NULL) {
		result = 0.0;
		return result;
	}
	_tmp1_ = self->priv->clock_elapsed;
	_tmp2_ = self->priv->clock;
	_tmp3_ = g_timer_elapsed (_tmp2_, NULL);
	result = _tmp1_ + _tmp3_;
	return result;
}


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


void game_set_paused (Game* self, gboolean value) {
	gboolean _tmp0_ = FALSE;
	GTimer* _tmp1_ = NULL;
	g_return_if_fail (self != NULL);
	_tmp0_ = value;
	self->priv->_paused = _tmp0_;
	_tmp1_ = self->priv->clock;
	if (_tmp1_ != NULL) {
		gboolean _tmp2_ = FALSE;
		_tmp2_ = value;
		if (_tmp2_) {
			game_stop_clock (self);
		} else {
			game_continue_clock (self);
		}
	}
	g_signal_emit_by_name (self, "paused-changed");
	g_object_notify ((GObject *) self, "paused");
}


Tile* game_get_selected_tile (Game* self) {
	Tile* result;
	Tile* _tmp0_ = NULL;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->_selected_tile;
	result = _tmp0_;
	return result;
}


void game_set_selected_tile (Game* self, Tile* value) {
	Tile* _tmp0_ = NULL;
	Tile* _tmp2_ = NULL;
	Tile* _tmp3_ = NULL;
	Tile* _tmp4_ = NULL;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->_selected_tile;
	if (_tmp0_ != NULL) {
		Tile* _tmp1_ = NULL;
		_tmp1_ = self->priv->_selected_tile;
		g_signal_emit_by_name (self, "redraw-tile", _tmp1_);
	}
	_tmp2_ = value;
	_tmp3_ = _g_object_ref0 (_tmp2_);
	_g_object_unref0 (self->priv->_selected_tile);
	self->priv->_selected_tile = _tmp3_;
	_tmp4_ = value;
	if (_tmp4_ != NULL) {
		Tile* _tmp5_ = NULL;
		_tmp5_ = value;
		g_signal_emit_by_name (self, "redraw-tile", _tmp5_);
	}
	g_object_notify ((GObject *) self, "selected-tile");
}


gint game_get_visible_tiles (Game* self) {
	gint result;
	gint n = 0;
	GList* _tmp0_ = NULL;
	gint _tmp5_ = 0;
	g_return_val_if_fail (self != NULL, 0);
	n = 0;
	_tmp0_ = self->tiles;
	{
		GList* tile_collection = NULL;
		GList* tile_it = NULL;
		tile_collection = _tmp0_;
		for (tile_it = tile_collection; tile_it != NULL; tile_it = tile_it->next) {
			Tile* _tmp1_ = NULL;
			Tile* tile = NULL;
			_tmp1_ = _g_object_ref0 ((Tile*) tile_it->data);
			tile = _tmp1_;
			{
				Tile* _tmp2_ = NULL;
				gboolean _tmp3_ = FALSE;
				_tmp2_ = tile;
				_tmp3_ = _tmp2_->visible;
				if (_tmp3_) {
					gint _tmp4_ = 0;
					_tmp4_ = n;
					n = _tmp4_ + 1;
				}
				_g_object_unref0 (tile);
			}
		}
	}
	_tmp5_ = n;
	result = _tmp5_;
	return result;
}


guint game_get_moves_left (Game* self) {
	guint result;
	GList* _tmp0_ = NULL;
	GList* _tmp1_ = NULL;
	guint _tmp2_ = 0U;
	guint _tmp3_ = 0U;
	g_return_val_if_fail (self != NULL, 0U);
	_tmp0_ = game_find_matches (self, NULL);
	_tmp1_ = _tmp0_;
	_tmp2_ = g_list_length (_tmp1_);
	_tmp3_ = _tmp2_;
	__g_list_free__g_object_unref0_0 (_tmp1_);
	result = _tmp3_;
	return result;
}


gboolean game_get_complete (Game* self) {
	gboolean result;
	gint _tmp0_ = 0;
	gint _tmp1_ = 0;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = game_get_visible_tiles (self);
	_tmp1_ = _tmp0_;
	result = _tmp1_ == 0;
	return result;
}


gboolean game_get_can_move (Game* self) {
	gboolean result;
	guint _tmp0_ = 0U;
	guint _tmp1_ = 0U;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = game_get_moves_left (self);
	_tmp1_ = _tmp0_;
	result = _tmp1_ != ((guint) 0);
	return result;
}


gboolean game_get_can_undo (Game* self) {
	gboolean result;
	gint _tmp0_ = 0;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->move_number;
	result = _tmp0_ > 1;
	return result;
}


gboolean game_get_can_redo (Game* self) {
	gboolean result;
	GList* _tmp0_ = NULL;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->tiles;
	{
		GList* tile_collection = NULL;
		GList* tile_it = NULL;
		tile_collection = _tmp0_;
		for (tile_it = tile_collection; tile_it != NULL; tile_it = tile_it->next) {
			Tile* _tmp1_ = NULL;
			Tile* tile = NULL;
			_tmp1_ = _g_object_ref0 ((Tile*) tile_it->data);
			tile = _tmp1_;
			{
				Tile* _tmp2_ = NULL;
				gint _tmp3_ = 0;
				gint _tmp4_ = 0;
				_tmp2_ = tile;
				_tmp3_ = _tmp2_->move_number;
				_tmp4_ = self->move_number;
				if (_tmp3_ >= _tmp4_) {
					result = TRUE;
					_g_object_unref0 (tile);
					return result;
				}
				_g_object_unref0 (tile);
			}
		}
	}
	result = FALSE;
	return result;
}


static void game_class_init (GameClass * klass) {
	game_parent_class = g_type_class_peek_parent (klass);
	g_type_class_add_private (klass, sizeof (GamePrivate));
	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_STARTED, g_param_spec_boolean ("started", "started", "started", FALSE, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_ELAPSED, g_param_spec_double ("elapsed", "elapsed", "elapsed", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_PAUSED, g_param_spec_boolean ("paused", "paused", "paused", FALSE, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_SELECTED_TILE, g_param_spec_object ("selected-tile", "selected-tile", "selected-tile", TYPE_TILE, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_VISIBLE_TILES, g_param_spec_int ("visible-tiles", "visible-tiles", "visible-tiles", G_MININT, G_MAXINT, 0, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_MOVES_LEFT, g_param_spec_uint ("moves-left", "moves-left", "moves-left", 0, G_MAXUINT, 0U, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_COMPLETE, g_param_spec_boolean ("complete", "complete", "complete", FALSE, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_CAN_MOVE, g_param_spec_boolean ("can-move", "can-move", "can-move", FALSE, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_CAN_UNDO, g_param_spec_boolean ("can-undo", "can-undo", "can-undo", FALSE, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_CAN_REDO, g_param_spec_boolean ("can-redo", "can-redo", "can-redo", FALSE, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
	g_signal_new ("redraw_tile", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, TYPE_TILE);
	g_signal_new ("moved", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	g_signal_new ("paused_changed", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	g_signal_new ("tick", 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) {
	self->priv = GAME_GET_PRIVATE (self);
	self->tiles = NULL;
	self->priv->hint_timout = (guint) 0;
	self->hint_blink_counter = (guint) 0;
	self->priv->_paused = FALSE;
	self->priv->_selected_tile = NULL;
}


static void game_finalize (GObject* obj) {
	Game * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_GAME, Game);
	_g_object_unref0 (self->map);
	__g_list_free__g_object_unref0_0 (self->tiles);
	_vala_array_destroy (self->hint_tiles, 2, (GDestroyNotify) g_object_unref);
	_g_timer_destroy0 (self->priv->clock);
	_g_object_unref0 (self->priv->_selected_tile);
	G_OBJECT_CLASS (game_parent_class)->finalize (obj);
}


GType game_get_type (void) {
	static volatile gsize game_type_id__volatile = 0;
	if (g_once_init_enter (&game_type_id__volatile)) {
		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);
		g_once_init_leave (&game_type_id__volatile, game_type_id);
	}
	return game_type_id__volatile;
}


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_STARTED:
		g_value_set_boolean (value, game_get_started (self));
		break;
		case GAME_ELAPSED:
		g_value_set_double (value, game_get_elapsed (self));
		break;
		case GAME_PAUSED:
		g_value_set_boolean (value, game_get_paused (self));
		break;
		case GAME_SELECTED_TILE:
		g_value_set_object (value, game_get_selected_tile (self));
		break;
		case GAME_VISIBLE_TILES:
		g_value_set_int (value, game_get_visible_tiles (self));
		break;
		case GAME_MOVES_LEFT:
		g_value_set_uint (value, game_get_moves_left (self));
		break;
		case GAME_COMPLETE:
		g_value_set_boolean (value, game_get_complete (self));
		break;
		case GAME_CAN_MOVE:
		g_value_set_boolean (value, game_get_can_move (self));
		break;
		case GAME_CAN_UNDO:
		g_value_set_boolean (value, game_get_can_undo (self));
		break;
		case GAME_CAN_REDO:
		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_PAUSED:
		game_set_paused (self, g_value_get_boolean (value));
		break;
		case GAME_SELECTED_TILE:
		game_set_selected_tile (self, g_value_get_object (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}


static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func) {
	if ((array != NULL) && (destroy_func != NULL)) {
		int 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, gint array_length, GDestroyNotify destroy_func) {
	_vala_array_destroy (array, array_length, destroy_func);
	g_free (array);
}



