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

/* SPDX-FileCopyrightText: 2010-2025 Mahjongg Contributors*/
/* SPDX-FileCopyrightText: 2010-2013 Robert Ancell*/
/* SPDX-License-Identifier: GPL-2.0-or-later*/

#include <glib-object.h>
#include <glib.h>
#include <float.h>
#include <math.h>
#include <gobject/gvaluecollector.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#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;

#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 _slot_unref0(var) ((var == NULL) ? NULL : (var = (slot_unref (var), NULL)))
typedef struct _ParamSpecTile ParamSpecTile;

#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 _tile_unref0(var) ((var == NULL) ? NULL : (var = (tile_unref (var), NULL)))
typedef struct _ParamSpecMatch ParamSpecMatch;

#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 _map_unref0(var) ((var == NULL) ? NULL : (var = (map_unref (var), NULL)))
#define _g_rand_free0(var) ((var == NULL) ? NULL : (var = (g_rand_free (var), NULL)))
#define _match_unref0(var) ((var == NULL) ? NULL : (var = (match_unref (var), NULL)))
#define _g_timer_destroy0(var) ((var == NULL) ? NULL : (var = (g_timer_destroy (var), NULL)))

#define TYPE_GAME_SAVE (game_save_get_type ())
#define GAME_SAVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_GAME_SAVE, GameSave))
#define GAME_SAVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_GAME_SAVE, GameSaveClass))
#define IS_GAME_SAVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_GAME_SAVE))
#define IS_GAME_SAVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_GAME_SAVE))
#define GAME_SAVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_GAME_SAVE, GameSaveClass))

typedef struct _GameSave GameSave;
typedef struct _GameSaveClass GameSaveClass;
typedef struct _GameSavePrivate GameSavePrivate;

#define GAME_SAVE_TYPE_ITERATOR (game_save_iterator_get_type ())
#define GAME_SAVE_ITERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAME_SAVE_TYPE_ITERATOR, GameSaveIterator))
#define GAME_SAVE_ITERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAME_SAVE_TYPE_ITERATOR, GameSaveIteratorClass))
#define GAME_SAVE_IS_ITERATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAME_SAVE_TYPE_ITERATOR))
#define GAME_SAVE_IS_ITERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAME_SAVE_TYPE_ITERATOR))
#define GAME_SAVE_ITERATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAME_SAVE_TYPE_ITERATOR, GameSaveIteratorClass))

typedef struct _GameSaveIterator GameSaveIterator;
typedef struct _GameSaveIteratorClass GameSaveIteratorClass;
#define _game_save_iterator_unref0(var) ((var == NULL) ? NULL : (var = (game_save_iterator_unref (var), NULL)))

#define GAME_TYPE_ITERATOR (game_iterator_get_type ())
#define GAME_ITERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAME_TYPE_ITERATOR, GameIterator))
#define GAME_ITERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAME_TYPE_ITERATOR, GameIteratorClass))
#define GAME_IS_ITERATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAME_TYPE_ITERATOR))
#define GAME_IS_ITERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAME_TYPE_ITERATOR))
#define GAME_ITERATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAME_TYPE_ITERATOR, GameIteratorClass))

typedef struct _GameIterator GameIterator;
typedef struct _GameIteratorClass GameIteratorClass;

#define MAP_TYPE_ITERATOR (map_iterator_get_type ())
#define MAP_ITERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAP_TYPE_ITERATOR, MapIterator))
#define MAP_ITERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MAP_TYPE_ITERATOR, MapIteratorClass))
#define MAP_IS_ITERATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAP_TYPE_ITERATOR))
#define MAP_IS_ITERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MAP_TYPE_ITERATOR))
#define MAP_ITERATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MAP_TYPE_ITERATOR, MapIteratorClass))

typedef struct _MapIterator MapIterator;
typedef struct _MapIteratorClass MapIteratorClass;
#define _map_iterator_unref0(var) ((var == NULL) ? NULL : (var = (map_iterator_unref (var), NULL)))
typedef struct _SlotPrivate SlotPrivate;
typedef struct _GameIteratorPrivate GameIteratorPrivate;
#define _game_unref0(var) ((var == NULL) ? NULL : (var = (game_unref (var), NULL)))
typedef struct _GameParamSpecIterator GameParamSpecIterator;
typedef struct _ParamSpecGame ParamSpecGame;
enum  {
	GAME_ATTEMPT_MOVE_SIGNAL,
	GAME_REDRAW_TILE_SIGNAL,
	GAME_MOVED_SIGNAL,
	GAME_PAUSED_CHANGED_SIGNAL,
	GAME_TICK_SIGNAL,
	GAME_NUM_SIGNALS
};
static guint game_signals[GAME_NUM_SIGNALS] = {0};

struct _Tile {
	GTypeInstance parent_instance;
	volatile int ref_count;
	TilePrivate * priv;
	gint number;
	gboolean visible;
	gboolean highlighted;
	gint move;
	Slot* slot;
	gboolean shaking;
	gint shake_offset;
	gdouble shake_start_time;
};

struct _TileClass {
	GTypeClass parent_class;
	void (*finalize) (Tile *self);
};

struct _TilePrivate {
	Tile** left;
	gint left_length1;
	gint _left_size_;
	Tile** right;
	gint right_length1;
	gint _right_size_;
	Tile** above;
	gint above_length1;
	gint _above_size_;
};

struct _ParamSpecTile {
	GParamSpec parent_instance;
};

struct _Match {
	GTypeInstance parent_instance;
	volatile int ref_count;
	MatchPrivate * priv;
	Tile* tile0;
	Tile* tile1;
};

struct _MatchClass {
	GTypeClass parent_class;
	void (*finalize) (Match *self);
};

struct _ParamSpecMatch {
	GParamSpec parent_instance;
};

struct _Game {
	GTypeInstance parent_instance;
	volatile int ref_count;
	GamePrivate * priv;
	Map* map;
};

struct _GameClass {
	GTypeClass parent_class;
	void (*finalize) (Game *self);
};

struct _GamePrivate {
	Tile** tiles;
	gint tiles_length1;
	gint _tiles_size_;
	GRand* random;
	Match* hint_match;
	Match** hint_matches;
	gint hint_matches_length1;
	gint _hint_matches_size_;
	gint hint_match_index;
	guint hint_timeout;
	guint hint_blink_counter;
	guint autoplay_end_game_timeout;
	gdouble clock_elapsed;
	GTimer* clock;
	guint clock_timeout;
	gint32 _seed;
	gboolean _inspecting;
	gboolean _paused;
	Tile* _selected_tile;
	gint _current_move;
};

struct _GameSave {
	GTypeInstance parent_instance;
	volatile int ref_count;
	GameSavePrivate * priv;
	Map* map;
	gdouble clock;
	gint move;
	gint32 seed;
};

struct _GameSaveClass {
	GTypeClass parent_class;
	void (*finalize) (GameSave *self);
};

struct _Slot {
	GTypeInstance parent_instance;
	volatile int ref_count;
	SlotPrivate * priv;
	gint x;
	gint y;
	gint layer;
};

struct _SlotClass {
	GTypeClass parent_class;
	void (*finalize) (Slot *self);
};

struct _GameIterator {
	GTypeInstance parent_instance;
	volatile int ref_count;
	GameIteratorPrivate * priv;
};

struct _GameIteratorClass {
	GTypeClass parent_class;
	void (*finalize) (GameIterator *self);
};

struct _GameIteratorPrivate {
	gint index;
	Game* game;
};

struct _GameParamSpecIterator {
	GParamSpec parent_instance;
};

struct _ParamSpecGame {
	GParamSpec parent_instance;
};

static gint Tile_private_offset;
static gpointer tile_parent_class = NULL;
static gpointer match_parent_class = NULL;
static gint Game_private_offset;
static gpointer game_parent_class = NULL;
static gint GameIterator_private_offset;
static gpointer game_iterator_parent_class = NULL;

VALA_EXTERN gpointer tile_ref (gpointer instance);
VALA_EXTERN void tile_unref (gpointer instance);
VALA_EXTERN GParamSpec* param_spec_tile (const gchar* name,
                             const gchar* nick,
                             const gchar* blurb,
                             GType object_type,
                             GParamFlags flags);
VALA_EXTERN void value_set_tile (GValue* value,
                     gpointer v_object);
VALA_EXTERN void value_take_tile (GValue* value,
                      gpointer v_object);
VALA_EXTERN gpointer value_get_tile (const GValue* value);
VALA_EXTERN GType tile_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (Tile, tile_unref)
VALA_EXTERN gpointer slot_ref (gpointer instance);
VALA_EXTERN void slot_unref (gpointer instance);
VALA_EXTERN GParamSpec* param_spec_slot (const gchar* name,
                             const gchar* nick,
                             const gchar* blurb,
                             GType object_type,
                             GParamFlags flags);
VALA_EXTERN void value_set_slot (GValue* value,
                     gpointer v_object);
VALA_EXTERN void value_take_slot (GValue* value,
                      gpointer v_object);
VALA_EXTERN gpointer value_get_slot (const GValue* value);
VALA_EXTERN GType slot_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (Slot, slot_unref)
VALA_EXTERN Tile* tile_new (Slot* slot);
VALA_EXTERN Tile* tile_construct (GType object_type,
                      Slot* slot);
VALA_EXTERN void tile_add_tile_left (Tile* self,
                         Tile* tile);
static void _vala_array_add1 (Tile** * array,
                       gint* length,
                       gint* size,
                       Tile* value);
VALA_EXTERN void tile_add_tile_right (Tile* self,
                          Tile* tile);
static void _vala_array_add2 (Tile** * array,
                       gint* length,
                       gint* size,
                       Tile* value);
VALA_EXTERN void tile_add_tile_above (Tile* self,
                          Tile* tile);
static void _vala_array_add3 (Tile** * array,
                       gint* length,
                       gint* size,
                       Tile* value);
VALA_EXTERN gboolean tile_matches (Tile* self,
                       Tile* tile);
VALA_EXTERN gboolean tile_get_selectable (Tile* self);
static void tile_finalize (Tile * obj);
static GType tile_get_type_once (void);
VALA_EXTERN gpointer match_ref (gpointer instance);
VALA_EXTERN void match_unref (gpointer instance);
VALA_EXTERN GParamSpec* param_spec_match (const gchar* name,
                              const gchar* nick,
                              const gchar* blurb,
                              GType object_type,
                              GParamFlags flags);
VALA_EXTERN void value_set_match (GValue* value,
                      gpointer v_object);
VALA_EXTERN void value_take_match (GValue* value,
                       gpointer v_object);
VALA_EXTERN gpointer value_get_match (const GValue* value);
VALA_EXTERN GType match_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (Match, match_unref)
VALA_EXTERN Match* match_new (Tile* tile0,
                  Tile* tile1);
VALA_EXTERN Match* match_construct (GType object_type,
                        Tile* tile0,
                        Tile* tile1);
static void match_finalize (Match * obj);
static GType match_get_type_once (void);
VALA_EXTERN gpointer game_ref (gpointer instance);
VALA_EXTERN void game_unref (gpointer instance);
VALA_EXTERN GParamSpec* param_spec_game (const gchar* name,
                             const gchar* nick,
                             const gchar* blurb,
                             GType object_type,
                             GParamFlags flags);
VALA_EXTERN void value_set_game (GValue* value,
                     gpointer v_object);
VALA_EXTERN void value_take_game (GValue* value,
                      gpointer v_object);
VALA_EXTERN gpointer value_get_game (const GValue* value);
VALA_EXTERN GType game_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (Game, game_unref)
VALA_EXTERN gpointer map_ref (gpointer instance);
VALA_EXTERN void map_unref (gpointer instance);
VALA_EXTERN GParamSpec* param_spec_map (const gchar* name,
                            const gchar* nick,
                            const gchar* blurb,
                            GType object_type,
                            GParamFlags flags);
VALA_EXTERN void value_set_map (GValue* value,
                    gpointer v_object);
VALA_EXTERN void value_take_map (GValue* value,
                     gpointer v_object);
VALA_EXTERN gpointer value_get_map (const GValue* value);
VALA_EXTERN GType map_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (Map, map_unref)
VALA_EXTERN Game* game_new (Map* map);
VALA_EXTERN Game* game_construct (GType object_type,
                      Map* map);
static void game_create_tiles (Game* self);
VALA_EXTERN void game_generate (Game* self,
                    gint32 seed);
static void game_reset_clock (Game* self);
VALA_EXTERN void game_set_selected_tile (Game* self,
                             Tile* value);
static void game_set_hint (Game* self,
                    Match* match);
static gint* game_shuffle_pair_numbers (Game* self,
                                 gint* pair_numbers,
                                 gint pair_numbers_length1,
                                 gint* result_length1);
static gint* _vala_array_dup1 (gint* self,
                        gssize length);
static gboolean game_choose_tile_pairs (Game* self,
                                 gint* pair_numbers,
                                 gint pair_numbers_length1,
                                 gint depth,
                                 gboolean check_selectable);
static void game_redraw_all_tiles (Game* self);
VALA_EXTERN gpointer game_save_ref (gpointer instance);
VALA_EXTERN void game_save_unref (gpointer instance);
VALA_EXTERN GParamSpec* param_spec_game_save (const gchar* name,
                                  const gchar* nick,
                                  const gchar* blurb,
                                  GType object_type,
                                  GParamFlags flags);
VALA_EXTERN void value_set_game_save (GValue* value,
                          gpointer v_object);
VALA_EXTERN void value_take_game_save (GValue* value,
                           gpointer v_object);
VALA_EXTERN gpointer value_get_game_save (const GValue* value);
VALA_EXTERN GType game_save_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GameSave, game_save_unref)
VALA_EXTERN void game_restore (Game* self,
                   GameSave* save);
VALA_EXTERN gpointer game_save_iterator_ref (gpointer instance);
VALA_EXTERN void game_save_iterator_unref (gpointer instance);
VALA_EXTERN GParamSpec* game_save_param_spec_iterator (const gchar* name,
                                           const gchar* nick,
                                           const gchar* blurb,
                                           GType object_type,
                                           GParamFlags flags);
VALA_EXTERN void game_save_value_set_iterator (GValue* value,
                                   gpointer v_object);
VALA_EXTERN void game_save_value_take_iterator (GValue* value,
                                    gpointer v_object);
VALA_EXTERN gpointer game_save_value_get_iterator (const GValue* value);
VALA_EXTERN GType game_save_iterator_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GameSaveIterator, game_save_iterator_unref)
VALA_EXTERN GameSaveIterator* game_save_iterator (GameSave* self);
VALA_EXTERN gboolean game_save_iterator_next (GameSaveIterator* self);
VALA_EXTERN Tile* game_save_iterator_get (GameSaveIterator* self);
VALA_EXTERN gboolean slot_equals (Slot* self,
                      Slot* b);
VALA_EXTERN void game_set_paused (Game* self,
                      gboolean value);
VALA_EXTERN void game_restart (Game* self);
VALA_EXTERN void game_destroy_timers (Game* self);
static void game_remove_hint_timeout (Game* self);
static void game_remove_autoplay_end_game_timeout (Game* self);
static void game_stop_clock (Game* self);
VALA_EXTERN Tile* game_get_tile (Game* self,
                     gint position);
VALA_EXTERN gint game_get_n_tiles (Game* self);
VALA_EXTERN void game_shake_tile (Game* self,
                      Tile* tile,
                      gint64 start_time);
VALA_EXTERN gboolean game_remove_pair (Game* self,
                           Tile* tile0,
                           Tile* tile1);
VALA_EXTERN gint game_get_current_move (Game* self);
VALA_EXTERN gboolean game_get_complete (Game* self);
static void game_start_clock (Game* self);
VALA_EXTERN void game_shuffle_remaining (Game* self);
VALA_EXTERN gboolean game_get_can_shuffle (Game* self);
static void _vala_array_add4 (Tile** * array,
                       gint* length,
                       gint* size,
                       Tile* value);
static gboolean _vala_int_array_contains (gint * stack,
                                   gssize stack_length,
                                   const gint needle);
static void _vala_array_add5 (gint* * array,
                       gint* length,
                       gint* size,
                       gint value);
static void _vala_array_add6 (gint* * array,
                       gint* length,
                       gint* size,
                       gint value);
static gint* _vala_array_dup2 (gint* self,
                        gssize length);
VALA_EXTERN void game_undo (Game* self);
VALA_EXTERN gboolean game_get_can_undo (Game* self);
VALA_EXTERN void game_redo (Game* self);
VALA_EXTERN gboolean game_get_can_redo (Game* self);
VALA_EXTERN Match* game_next_hint (Game* self);
static Match** game_find_matches_for_tile (Game* self,
                                    Tile* tile,
                                    Tile** ignored_tiles,
                                    gint ignored_tiles_length1,
                                    gboolean check_selectable,
                                    gint* result_length1);
VALA_EXTERN Tile* game_get_selected_tile (Game* self);
static Match** game_find_matches (Game* self,
                           gboolean check_selectable,
                           gint* result_length1);
VALA_EXTERN void game_show_hint (Game* self);
VALA_EXTERN void game_autoplay_end_game (Game* self);
VALA_EXTERN gboolean game_get_all_tiles_unblocked (Game* self);
static gboolean game_autoplay_end_game_timeout_cb (Game* self);
static gboolean _game_autoplay_end_game_timeout_cb_gsource_func (gpointer self);
VALA_EXTERN gpointer game_iterator_ref (gpointer instance);
VALA_EXTERN void game_iterator_unref (gpointer instance);
VALA_EXTERN GParamSpec* game_param_spec_iterator (const gchar* name,
                                      const gchar* nick,
                                      const gchar* blurb,
                                      GType object_type,
                                      GParamFlags flags);
VALA_EXTERN void game_value_set_iterator (GValue* value,
                              gpointer v_object);
VALA_EXTERN void game_value_take_iterator (GValue* value,
                               gpointer v_object);
VALA_EXTERN gpointer game_value_get_iterator (const GValue* value);
VALA_EXTERN GType game_iterator_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GameIterator, game_iterator_unref)
VALA_EXTERN GameIterator* game_iterator (Game* self);
VALA_EXTERN GameIterator* game_iterator_new (Game* game);
VALA_EXTERN GameIterator* game_iterator_construct (GType object_type,
                                       Game* game);
VALA_EXTERN gpointer map_iterator_ref (gpointer instance);
VALA_EXTERN void map_iterator_unref (gpointer instance);
VALA_EXTERN GParamSpec* map_param_spec_iterator (const gchar* name,
                                     const gchar* nick,
                                     const gchar* blurb,
                                     GType object_type,
                                     GParamFlags flags);
VALA_EXTERN void map_value_set_iterator (GValue* value,
                             gpointer v_object);
VALA_EXTERN void map_value_take_iterator (GValue* value,
                              gpointer v_object);
VALA_EXTERN gpointer map_value_get_iterator (const GValue* value);
VALA_EXTERN GType map_iterator_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MapIterator, map_iterator_unref)
VALA_EXTERN MapIterator* map_iterator (Map* self);
VALA_EXTERN gboolean map_iterator_next (MapIterator* self);
VALA_EXTERN Slot* map_iterator_get (MapIterator* self);
static void _vala_array_add7 (Tile** * array,
                       gint* length,
                       gint* size,
                       Tile* value);
static void _vala_array_add8 (Match** * array,
                       gint* length,
                       gint* size,
                       Match* value);
static void _vala_array_add9 (Tile** * array,
                       gint* length,
                       gint* size,
                       Tile* value);
static gboolean _vala_tile_array_contains (Tile* * stack,
                                    gssize stack_length,
                                    const Tile* needle);
static void _vala_array_add10 (Match** * array,
                        gint* length,
                        gint* size,
                        Match* value);
static gboolean game_hint_timeout_cb (Game* self);
static gboolean _game_hint_timeout_cb_gsource_func (gpointer self);
VALA_EXTERN gboolean game_get_started (Game* self);
static void game_redraw_hint_match (Game* self,
                             Match* match);
static gboolean game_clock_timeout_cb (Game* self);
static void game_continue_clock (Game* self);
static gboolean _game_clock_timeout_cb_gsource_func (gpointer self);
VALA_EXTERN gint32 game_get_seed (Game* self);
VALA_EXTERN gdouble game_get_elapsed (Game* self);
VALA_EXTERN gboolean game_get_inspecting (Game* self);
VALA_EXTERN gboolean game_get_paused (Game* self);
VALA_EXTERN guint game_get_moves_left (Game* self);
VALA_EXTERN gboolean game_get_can_move (Game* self);
VALA_EXTERN gboolean game_get_can_save (Game* self);
static void g_cclosure_user_marshal_BOOLEAN__VOID (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__TILE (GClosure * closure,
                                         GValue * return_value,
                                         guint n_param_values,
                                         const GValue * param_values,
                                         gpointer invocation_hint,
                                         gpointer marshal_data);
VALA_EXTERN gboolean game_iterator_next (GameIterator* self);
VALA_EXTERN Tile* game_iterator_get (GameIterator* self);
static void game_iterator_finalize (GameIterator * obj);
static GType game_iterator_get_type_once (void);
static void game_finalize (Game * obj);
static GType game_get_type_once (void);
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 inline gpointer
tile_get_instance_private (Tile* self)
{
	return G_STRUCT_MEMBER_P (self, Tile_private_offset);
}

static gpointer
_slot_ref0 (gpointer self)
{
	return self ? slot_ref (self) : NULL;
}

Tile*
tile_construct (GType object_type,
                Slot* slot)
{
	Tile* self = NULL;
	Slot* _tmp0_;
	g_return_val_if_fail (slot != NULL, NULL);
	self = (Tile*) g_type_create_instance (object_type);
	_tmp0_ = _slot_ref0 (slot);
	_slot_unref0 (self->slot);
	self->slot = _tmp0_;
	return self;
}

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

static gpointer
_tile_ref0 (gpointer self)
{
	return self ? tile_ref (self) : NULL;
}

static void
_vala_array_add1 (Tile** * array,
                  gint* length,
                  gint* size,
                  Tile* value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (Tile*, *array, (*size) + 1);
	}
	(*array)[(*length)++] = value;
	(*array)[*length] = NULL;
}

void
tile_add_tile_left (Tile* self,
                    Tile* tile)
{
	Tile* _tmp0_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (tile != NULL);
	_tmp0_ = _tile_ref0 (tile);
	_vala_array_add1 (&self->priv->left, &self->priv->left_length1, &self->priv->_left_size_, _tmp0_);
}

static void
_vala_array_add2 (Tile** * array,
                  gint* length,
                  gint* size,
                  Tile* value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (Tile*, *array, (*size) + 1);
	}
	(*array)[(*length)++] = value;
	(*array)[*length] = NULL;
}

void
tile_add_tile_right (Tile* self,
                     Tile* tile)
{
	Tile* _tmp0_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (tile != NULL);
	_tmp0_ = _tile_ref0 (tile);
	_vala_array_add2 (&self->priv->right, &self->priv->right_length1, &self->priv->_right_size_, _tmp0_);
}

static void
_vala_array_add3 (Tile** * array,
                  gint* length,
                  gint* size,
                  Tile* value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (Tile*, *array, (*size) + 1);
	}
	(*array)[(*length)++] = value;
	(*array)[*length] = NULL;
}

void
tile_add_tile_above (Tile* self,
                     Tile* tile)
{
	Tile* _tmp0_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (tile != NULL);
	_tmp0_ = _tile_ref0 (tile);
	_vala_array_add3 (&self->priv->above, &self->priv->above_length1, &self->priv->_above_size_, _tmp0_);
}

gboolean
tile_matches (Tile* self,
              Tile* tile)
{
	gint tile_face_a = 0;
	gint tile_face_b = 0;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (tile != NULL, FALSE);
	tile_face_a = self->number / 4;
	tile_face_b = tile->number / 4;
	result = tile_face_a == tile_face_b;
	return result;
}

gboolean
tile_get_selectable (Tile* self)
{
	gboolean result;
	gboolean left_blocked = FALSE;
	Tile** _tmp0_;
	gint _tmp0__length1;
	gboolean right_blocked = FALSE;
	Tile** _tmp2_;
	gint _tmp2__length1;
	gboolean _tmp4_ = FALSE;
	Tile** _tmp5_;
	gint _tmp5__length1;
	g_return_val_if_fail (self != NULL, FALSE);
	if (!self->visible) {
		result = FALSE;
		return result;
	}
	left_blocked = FALSE;
	_tmp0_ = self->priv->left;
	_tmp0__length1 = self->priv->left_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp0_;
		tile_collection_length1 = _tmp0__length1;
		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_->visible) {
					left_blocked = TRUE;
					break;
				}
			}
		}
	}
	right_blocked = FALSE;
	_tmp2_ = self->priv->right;
	_tmp2__length1 = self->priv->right_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp2_;
		tile_collection_length1 = _tmp2__length1;
		for (tile_it = 0; tile_it < tile_collection_length1; tile_it = tile_it + 1) {
			Tile* tile = NULL;
			tile = tile_collection[tile_it];
			{
				Tile* _tmp3_;
				_tmp3_ = tile;
				if (_tmp3_->visible) {
					right_blocked = TRUE;
					break;
				}
			}
		}
	}
	if (left_blocked) {
		_tmp4_ = right_blocked;
	} else {
		_tmp4_ = FALSE;
	}
	if (_tmp4_) {
		result = FALSE;
		return result;
	}
	_tmp5_ = self->priv->above;
	_tmp5__length1 = self->priv->above_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp5_;
		tile_collection_length1 = _tmp5__length1;
		for (tile_it = 0; tile_it < tile_collection_length1; tile_it = tile_it + 1) {
			Tile* tile = NULL;
			tile = tile_collection[tile_it];
			{
				Tile* _tmp6_;
				_tmp6_ = tile;
				if (_tmp6_->visible) {
					result = FALSE;
					return result;
				}
			}
		}
	}
	result = TRUE;
	return result;
}

static void
value_tile_init (GValue* value)
{
	value->data[0].v_pointer = NULL;
}

static void
value_tile_free_value (GValue* value)
{
	if (value->data[0].v_pointer) {
		tile_unref (value->data[0].v_pointer);
	}
}

static void
value_tile_copy_value (const GValue* src_value,
                       GValue* dest_value)
{
	if (src_value->data[0].v_pointer) {
		dest_value->data[0].v_pointer = tile_ref (src_value->data[0].v_pointer);
	} else {
		dest_value->data[0].v_pointer = NULL;
	}
}

static gpointer
value_tile_peek_pointer (const GValue* value)
{
	return value->data[0].v_pointer;
}

static gchar*
value_tile_collect_value (GValue* value,
                          guint n_collect_values,
                          GTypeCValue* collect_values,
                          guint collect_flags)
{
	if (collect_values[0].v_pointer) {
		Tile * object;
		object = collect_values[0].v_pointer;
		if (object->parent_instance.g_class == NULL) {
			return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		} else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) {
			return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		}
		value->data[0].v_pointer = tile_ref (object);
	} else {
		value->data[0].v_pointer = NULL;
	}
	return NULL;
}

static gchar*
value_tile_lcopy_value (const GValue* value,
                        guint n_collect_values,
                        GTypeCValue* collect_values,
                        guint collect_flags)
{
	Tile ** object_p;
	object_p = collect_values[0].v_pointer;
	if (!object_p) {
		return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
	}
	if (!value->data[0].v_pointer) {
		*object_p = NULL;
	} else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
		*object_p = value->data[0].v_pointer;
	} else {
		*object_p = tile_ref (value->data[0].v_pointer);
	}
	return NULL;
}

GParamSpec*
param_spec_tile (const gchar* name,
                 const gchar* nick,
                 const gchar* blurb,
                 GType object_type,
                 GParamFlags flags)
{
	ParamSpecTile* spec;
	g_return_val_if_fail (g_type_is_a (object_type, TYPE_TILE), NULL);
	spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
	G_PARAM_SPEC (spec)->value_type = object_type;
	return G_PARAM_SPEC (spec);
}

gpointer
value_get_tile (const GValue* value)
{
	g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_TILE), NULL);
	return value->data[0].v_pointer;
}

void
value_set_tile (GValue* value,
                gpointer v_object)
{
	Tile * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_TILE));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_TILE));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
		tile_ref (value->data[0].v_pointer);
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		tile_unref (old);
	}
}

void
value_take_tile (GValue* value,
                 gpointer v_object)
{
	Tile * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_TILE));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_TILE));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		tile_unref (old);
	}
}

static void
tile_class_init (TileClass * klass,
                 gpointer klass_data)
{
	tile_parent_class = g_type_class_peek_parent (klass);
	((TileClass *) klass)->finalize = tile_finalize;
	g_type_class_adjust_private_offset (klass, &Tile_private_offset);
}

static void
tile_instance_init (Tile * self,
                    gpointer klass)
{
	self->priv = tile_get_instance_private (self);
	self->number = -1;
	self->visible = TRUE;
	self->ref_count = 1;
}

static void
tile_finalize (Tile * obj)
{
	Tile * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_TILE, Tile);
	g_signal_handlers_destroy (self);
	_slot_unref0 (self->slot);
	self->priv->left = (_vala_array_free (self->priv->left, self->priv->left_length1, (GDestroyNotify) tile_unref), NULL);
	self->priv->right = (_vala_array_free (self->priv->right, self->priv->right_length1, (GDestroyNotify) tile_unref), NULL);
	self->priv->above = (_vala_array_free (self->priv->above, self->priv->above_length1, (GDestroyNotify) tile_unref), NULL);
}

 G_GNUC_NO_INLINE static GType
tile_get_type_once (void)
{
	static const GTypeValueTable g_define_type_value_table = { value_tile_init, value_tile_free_value, value_tile_copy_value, value_tile_peek_pointer, "p", value_tile_collect_value, "p", value_tile_lcopy_value };
	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, &g_define_type_value_table };
	static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };
	GType tile_type_id;
	tile_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Tile", &g_define_type_info, &g_define_type_fundamental_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 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;
}

gpointer
tile_ref (gpointer instance)
{
	Tile * self;
	self = instance;
	g_atomic_int_inc (&self->ref_count);
	return instance;
}

void
tile_unref (gpointer instance)
{
	Tile * self;
	self = instance;
	if (g_atomic_int_dec_and_test (&self->ref_count)) {
		TILE_GET_CLASS (self)->finalize (self);
		g_type_free_instance ((GTypeInstance *) self);
	}
}

Match*
match_construct (GType object_type,
                 Tile* tile0,
                 Tile* tile1)
{
	Match* self = NULL;
	Tile* _tmp0_;
	Tile* _tmp1_;
	g_return_val_if_fail (tile0 != NULL, NULL);
	g_return_val_if_fail (tile1 != NULL, NULL);
	self = (Match*) g_type_create_instance (object_type);
	_tmp0_ = _tile_ref0 (tile0);
	_tile_unref0 (self->tile0);
	self->tile0 = _tmp0_;
	_tmp1_ = _tile_ref0 (tile1);
	_tile_unref0 (self->tile1);
	self->tile1 = _tmp1_;
	return self;
}

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

static void
value_match_init (GValue* value)
{
	value->data[0].v_pointer = NULL;
}

static void
value_match_free_value (GValue* value)
{
	if (value->data[0].v_pointer) {
		match_unref (value->data[0].v_pointer);
	}
}

static void
value_match_copy_value (const GValue* src_value,
                        GValue* dest_value)
{
	if (src_value->data[0].v_pointer) {
		dest_value->data[0].v_pointer = match_ref (src_value->data[0].v_pointer);
	} else {
		dest_value->data[0].v_pointer = NULL;
	}
}

static gpointer
value_match_peek_pointer (const GValue* value)
{
	return value->data[0].v_pointer;
}

static gchar*
value_match_collect_value (GValue* value,
                           guint n_collect_values,
                           GTypeCValue* collect_values,
                           guint collect_flags)
{
	if (collect_values[0].v_pointer) {
		Match * object;
		object = collect_values[0].v_pointer;
		if (object->parent_instance.g_class == NULL) {
			return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		} else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) {
			return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		}
		value->data[0].v_pointer = match_ref (object);
	} else {
		value->data[0].v_pointer = NULL;
	}
	return NULL;
}

static gchar*
value_match_lcopy_value (const GValue* value,
                         guint n_collect_values,
                         GTypeCValue* collect_values,
                         guint collect_flags)
{
	Match ** object_p;
	object_p = collect_values[0].v_pointer;
	if (!object_p) {
		return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
	}
	if (!value->data[0].v_pointer) {
		*object_p = NULL;
	} else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
		*object_p = value->data[0].v_pointer;
	} else {
		*object_p = match_ref (value->data[0].v_pointer);
	}
	return NULL;
}

GParamSpec*
param_spec_match (const gchar* name,
                  const gchar* nick,
                  const gchar* blurb,
                  GType object_type,
                  GParamFlags flags)
{
	ParamSpecMatch* spec;
	g_return_val_if_fail (g_type_is_a (object_type, TYPE_MATCH), NULL);
	spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
	G_PARAM_SPEC (spec)->value_type = object_type;
	return G_PARAM_SPEC (spec);
}

gpointer
value_get_match (const GValue* value)
{
	g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_MATCH), NULL);
	return value->data[0].v_pointer;
}

void
value_set_match (GValue* value,
                 gpointer v_object)
{
	Match * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_MATCH));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_MATCH));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
		match_ref (value->data[0].v_pointer);
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		match_unref (old);
	}
}

void
value_take_match (GValue* value,
                  gpointer v_object)
{
	Match * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_MATCH));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_MATCH));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		match_unref (old);
	}
}

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

static void
match_instance_init (Match * self,
                     gpointer klass)
{
	self->ref_count = 1;
}

static void
match_finalize (Match * obj)
{
	Match * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_MATCH, Match);
	g_signal_handlers_destroy (self);
	_tile_unref0 (self->tile0);
	_tile_unref0 (self->tile1);
}

 G_GNUC_NO_INLINE static GType
match_get_type_once (void)
{
	static const GTypeValueTable g_define_type_value_table = { value_match_init, value_match_free_value, value_match_copy_value, value_match_peek_pointer, "p", value_match_collect_value, "p", value_match_lcopy_value };
	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, &g_define_type_value_table };
	static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };
	GType match_type_id;
	match_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Match", &g_define_type_info, &g_define_type_fundamental_info, 0);
	return match_type_id;
}

GType
match_get_type (void)
{
	static gsize match_type_id__once = 0;
	if (g_once_init_enter (&match_type_id__once)) {
		GType match_type_id;
		match_type_id = match_get_type_once ();
		g_once_init_leave (&match_type_id__once, match_type_id);
	}
	return match_type_id__once;
}

gpointer
match_ref (gpointer instance)
{
	Match * self;
	self = instance;
	g_atomic_int_inc (&self->ref_count);
	return instance;
}

void
match_unref (gpointer instance)
{
	Match * self;
	self = instance;
	if (g_atomic_int_dec_and_test (&self->ref_count)) {
		MATCH_GET_CLASS (self)->finalize (self);
		g_type_free_instance ((GTypeInstance *) self);
	}
}

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

static gpointer
_map_ref0 (gpointer self)
{
	return self ? map_ref (self) : NULL;
}

Game*
game_construct (GType object_type,
                Map* map)
{
	Game* self = NULL;
	Map* _tmp0_;
	g_return_val_if_fail (map != NULL, NULL);
	self = (Game*) g_type_create_instance (object_type);
	_tmp0_ = _map_ref0 (map);
	_map_unref0 (self->map);
	self->map = _tmp0_;
	game_create_tiles (self);
	return self;
}

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

static gint*
_vala_array_dup1 (gint* self,
                  gssize length)
{
	if (length > 0) {
		return g_memdup2 (self, length * sizeof (gint));
	}
	return NULL;
}

void
game_generate (Game* self,
               gint32 seed)
{
	gint32 _tmp0_ = 0;
	gint n_pairs = 0;
	Tile** _tmp1_;
	gint _tmp1__length1;
	gint* pair_numbers = NULL;
	gint* _tmp2_;
	gint pair_numbers_length1;
	gint _pair_numbers_size_;
	GRand* _tmp6_;
	gint* _tmp7_;
	gint _tmp7__length1;
	gint _tmp8_ = 0;
	gint* _tmp9_;
	gint* _tmp10_;
	gint _tmp10__length1;
	gint* _tmp11_;
	gint _tmp11__length1;
	Tile** _tmp12_;
	gint _tmp12__length1;
	g_return_if_fail (self != NULL);
	if (seed != ((gint32) -1)) {
		_tmp0_ = seed;
	} else {
		_tmp0_ = g_random_int_range ((gint32) 0, G_MAXINT32);
	}
	self->priv->_seed = _tmp0_;
	_tmp1_ = self->priv->tiles;
	_tmp1__length1 = self->priv->tiles_length1;
	n_pairs = ((gint) _tmp1__length1) / 2;
	_tmp2_ = g_new0 (gint, n_pairs);
	pair_numbers = _tmp2_;
	pair_numbers_length1 = n_pairs;
	_pair_numbers_size_ = pair_numbers_length1;
	self->priv->_paused = FALSE;
	g_signal_emit (self, game_signals[GAME_PAUSED_CHANGED_SIGNAL], 0);
	game_reset_clock (self);
	game_set_selected_tile (self, NULL);
	game_set_hint (self, NULL);
	self->priv->_current_move = 1;
	self->priv->_inspecting = FALSE;
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp3_ = FALSE;
			_tmp3_ = TRUE;
			while (TRUE) {
				gint* _tmp5_;
				gint _tmp5__length1;
				if (!_tmp3_) {
					gint _tmp4_;
					_tmp4_ = i;
					i = _tmp4_ + 1;
				}
				_tmp3_ = FALSE;
				if (!(i < n_pairs)) {
					break;
				}
				_tmp5_ = pair_numbers;
				_tmp5__length1 = pair_numbers_length1;
				_tmp5_[i] = i * 2;
			}
		}
	}
	_tmp6_ = g_rand_new_with_seed ((guint32) self->priv->_seed);
	_g_rand_free0 (self->priv->random);
	self->priv->random = _tmp6_;
	_tmp7_ = pair_numbers;
	_tmp7__length1 = pair_numbers_length1;
	_tmp9_ = game_shuffle_pair_numbers (self, _tmp7_, (gint) _tmp7__length1, &_tmp8_);
	_tmp10_ = (_tmp9_ != NULL) ? _vala_array_dup1 (_tmp9_, _tmp8_) : _tmp9_;
	_tmp10__length1 = _tmp8_;
	pair_numbers = (g_free (pair_numbers), NULL);
	pair_numbers = _tmp10_;
	pair_numbers_length1 = _tmp10__length1;
	_pair_numbers_size_ = pair_numbers_length1;
	_tmp11_ = pair_numbers;
	_tmp11__length1 = pair_numbers_length1;
	game_choose_tile_pairs (self, _tmp11_, (gint) _tmp11__length1, 0, TRUE);
	_tmp12_ = self->priv->tiles;
	_tmp12__length1 = self->priv->tiles_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp12_;
		tile_collection_length1 = _tmp12__length1;
		for (tile_it = 0; tile_it < tile_collection_length1; tile_it = tile_it + 1) {
			Tile* tile = NULL;
			tile = tile_collection[tile_it];
			{
				Tile* _tmp13_;
				Tile* _tmp14_;
				_tmp13_ = tile;
				_tmp13_->visible = TRUE;
				_tmp14_ = tile;
				_tmp14_->move = 0;
			}
		}
	}
	game_redraw_all_tiles (self);
	g_signal_emit (self, game_signals[GAME_MOVED_SIGNAL], 0);
	pair_numbers = (g_free (pair_numbers), NULL);
}

void
game_restore (Game* self,
              GameSave* save)
{
	GRand* _tmp0_;
	Tile** _tmp1_;
	gint _tmp1__length1;
	GTimer* _tmp16_;
	GTimer* _tmp17_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (save != NULL);
	self->priv->_seed = save->seed;
	self->priv->_current_move = save->move;
	_tmp0_ = g_rand_new_with_seed ((guint32) self->priv->_seed);
	_g_rand_free0 (self->priv->random);
	self->priv->random = _tmp0_;
	_tmp1_ = self->priv->tiles;
	_tmp1__length1 = self->priv->tiles_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp1_;
		tile_collection_length1 = _tmp1__length1;
		for (tile_it = 0; tile_it < tile_collection_length1; tile_it = tile_it + 1) {
			Tile* tile = NULL;
			tile = tile_collection[tile_it];
			{
				{
					GameSaveIterator* _t_it = NULL;
					GameSaveIterator* _tmp2_;
					_tmp2_ = game_save_iterator (save);
					_t_it = _tmp2_;
					while (TRUE) {
						GameSaveIterator* _tmp3_;
						Tile* t = NULL;
						GameSaveIterator* _tmp4_;
						Tile* _tmp5_;
						Tile* _tmp6_;
						Slot* _tmp7_;
						Tile* _tmp8_;
						Slot* _tmp9_;
						_tmp3_ = _t_it;
						if (!game_save_iterator_next (_tmp3_)) {
							break;
						}
						_tmp4_ = _t_it;
						_tmp5_ = game_save_iterator_get (_tmp4_);
						t = _tmp5_;
						_tmp6_ = tile;
						_tmp7_ = _tmp6_->slot;
						_tmp8_ = t;
						_tmp9_ = _tmp8_->slot;
						if (slot_equals (_tmp7_, _tmp9_)) {
							Tile* _tmp10_;
							Tile* _tmp11_;
							Tile* _tmp12_;
							Tile* _tmp13_;
							Tile* _tmp14_;
							Tile* _tmp15_;
							_tmp10_ = tile;
							_tmp11_ = t;
							_tmp10_->number = _tmp11_->number;
							_tmp12_ = tile;
							_tmp13_ = t;
							_tmp12_->move = _tmp13_->move;
							_tmp14_ = tile;
							_tmp15_ = t;
							_tmp14_->visible = _tmp15_->visible;
						}
					}
					_game_save_iterator_unref0 (_t_it);
				}
			}
		}
	}
	_tmp16_ = g_timer_new ();
	_g_timer_destroy0 (self->priv->clock);
	self->priv->clock = _tmp16_;
	_tmp17_ = self->priv->clock;
	g_timer_stop (_tmp17_);
	self->priv->clock_elapsed = save->clock;
	g_signal_emit (self, game_signals[GAME_TICK_SIGNAL], 0);
	game_redraw_all_tiles (self);
	g_signal_emit (self, game_signals[GAME_MOVED_SIGNAL], 0);
	game_set_paused (self, TRUE);
}

void
game_restart (Game* self)
{
	Tile** _tmp0_;
	gint _tmp0__length1;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->tiles;
	_tmp0__length1 = self->priv->tiles_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp0_;
		tile_collection_length1 = _tmp0__length1;
		for (tile_it = 0; tile_it < tile_collection_length1; tile_it = tile_it + 1) {
			Tile* tile = NULL;
			tile = tile_collection[tile_it];
			{
				Tile* _tmp1_;
				Tile* _tmp2_;
				_tmp1_ = tile;
				_tmp1_->number = -1;
				_tmp2_ = tile;
				_tmp2_->visible = TRUE;
			}
		}
	}
	game_generate (self, self->priv->_seed);
}

void
game_destroy_timers (Game* self)
{
	g_return_if_fail (self != NULL);
	game_remove_hint_timeout (self);
	game_remove_autoplay_end_game_timeout (self);
	game_stop_clock (self);
}

Tile*
game_get_tile (Game* self,
               gint position)
{
	gboolean _tmp0_ = FALSE;
	Tile** _tmp3_;
	gint _tmp3__length1;
	Tile* _tmp4_;
	Tile* _tmp5_;
	Tile* result;
	g_return_val_if_fail (self != NULL, NULL);
	if (position < 0) {
		_tmp0_ = TRUE;
	} else {
		gint _tmp1_;
		gint _tmp2_;
		_tmp1_ = game_get_n_tiles (self);
		_tmp2_ = _tmp1_;
		_tmp0_ = position >= _tmp2_;
	}
	if (_tmp0_) {
		result = NULL;
		return result;
	}
	_tmp3_ = self->priv->tiles;
	_tmp3__length1 = self->priv->tiles_length1;
	_tmp4_ = _tmp3_[position];
	_tmp5_ = _tile_ref0 (_tmp4_);
	result = _tmp5_;
	return result;
}

void
game_shake_tile (Game* self,
                 Tile* tile,
                 gint64 start_time)
{
	g_return_if_fail (self != NULL);
	g_return_if_fail (tile != NULL);
	tile->shaking = TRUE;
	tile->shake_offset = 0;
	tile->shake_start_time = (gdouble) start_time;
	g_signal_emit (self, game_signals[GAME_REDRAW_TILE_SIGNAL], 0, tile);
}

gboolean
game_remove_pair (Game* self,
                  Tile* tile0,
                  Tile* tile1)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	Tile** _tmp2_;
	gint _tmp2__length1;
	gint _tmp5_;
	gint _tmp6_;
	gint _tmp7_;
	gint _tmp8_;
	gint _tmp9_;
	gboolean _tmp10_;
	gboolean _tmp11_;
	gboolean _tmp12_;
	gboolean _tmp13_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (tile0 != NULL, FALSE);
	g_return_val_if_fail (tile1 != NULL, FALSE);
	if (!tile0->visible) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = !tile1->visible;
	}
	if (_tmp0_) {
		result = FALSE;
		return result;
	}
	if (tile0 == tile1) {
		_tmp1_ = TRUE;
	} else {
		_tmp1_ = !tile_matches (tile0, tile1);
	}
	if (_tmp1_) {
		result = FALSE;
		return result;
	}
	game_set_selected_tile (self, NULL);
	game_set_hint (self, NULL);
	_tmp2_ = self->priv->tiles;
	_tmp2__length1 = self->priv->tiles_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp2_;
		tile_collection_length1 = _tmp2__length1;
		for (tile_it = 0; tile_it < tile_collection_length1; tile_it = tile_it + 1) {
			Tile* tile = NULL;
			tile = tile_collection[tile_it];
			{
				Tile* _tmp3_;
				_tmp3_ = tile;
				if (_tmp3_->move >= self->priv->_current_move) {
					Tile* _tmp4_;
					_tmp4_ = tile;
					_tmp4_->move = 0;
				}
			}
		}
	}
	tile0->visible = FALSE;
	_tmp5_ = game_get_current_move (self);
	_tmp6_ = _tmp5_;
	tile0->move = _tmp6_;
	tile1->visible = FALSE;
	_tmp7_ = game_get_current_move (self);
	_tmp8_ = _tmp7_;
	tile1->move = _tmp8_;
	_tmp9_ = self->priv->_current_move;
	self->priv->_current_move = _tmp9_ + 1;
	g_signal_emit (self, game_signals[GAME_REDRAW_TILE_SIGNAL], 0, tile0);
	g_signal_emit (self, game_signals[GAME_REDRAW_TILE_SIGNAL], 0, tile1);
	_tmp10_ = game_get_complete (self);
	_tmp11_ = _tmp10_;
	if (_tmp11_) {
		game_stop_clock (self);
	} else {
		game_start_clock (self);
	}
	g_signal_emit (self, game_signals[GAME_MOVED_SIGNAL], 0);
	_tmp12_ = game_get_complete (self);
	_tmp13_ = _tmp12_;
	if (_tmp13_) {
		self->priv->_inspecting = TRUE;
	}
	result = TRUE;
	return result;
}

static void
_vala_array_add4 (Tile** * array,
                  gint* length,
                  gint* size,
                  Tile* value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (Tile*, *array, (*size) + 1);
	}
	(*array)[(*length)++] = value;
	(*array)[*length] = NULL;
}

static gboolean
_vala_int_array_contains (gint * stack,
                          gssize stack_length,
                          const gint needle)
{
	gssize i;
	for (i = 0; i < stack_length; i++) {
		if (needle == stack[i]) {
			return TRUE;
		}
	}
	return FALSE;
}

static void
_vala_array_add5 (gint* * array,
                  gint* length,
                  gint* size,
                  gint value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (gint, *array, *size);
	}
	(*array)[(*length)++] = value;
}

static void
_vala_array_add6 (gint* * array,
                  gint* length,
                  gint* size,
                  gint value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (gint, *array, *size);
	}
	(*array)[(*length)++] = value;
}

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

void
game_shuffle_remaining (Game* self)
{
	gboolean _tmp0_;
	gboolean _tmp1_;
	gint* removed_tile_faces = NULL;
	gint* _tmp2_;
	gint removed_tile_faces_length1;
	gint _removed_tile_faces_size_;
	gint* pair_numbers = NULL;
	gint* _tmp3_;
	gint pair_numbers_length1;
	gint _pair_numbers_size_;
	Tile** tiles_to_shuffle = NULL;
	Tile** _tmp4_;
	gint tiles_to_shuffle_length1;
	gint _tiles_to_shuffle_size_;
	Tile** _tmp5_;
	gint _tmp5__length1;
	Tile** _tmp12_;
	gint _tmp12__length1;
	gint* _tmp19_;
	gint _tmp19__length1;
	gint _tmp20_ = 0;
	gint* _tmp21_;
	gint* _tmp22_;
	gint _tmp22__length1;
	gint* _tmp23_;
	gint _tmp23__length1;
	Tile** _tmp24_;
	gint _tmp24__length1;
	g_return_if_fail (self != NULL);
	_tmp0_ = game_get_can_shuffle (self);
	_tmp1_ = _tmp0_;
	if (!_tmp1_) {
		return;
	}
	_tmp2_ = g_new0 (gint, 0);
	removed_tile_faces = _tmp2_;
	removed_tile_faces_length1 = 0;
	_removed_tile_faces_size_ = removed_tile_faces_length1;
	_tmp3_ = g_new0 (gint, 0);
	pair_numbers = _tmp3_;
	pair_numbers_length1 = 0;
	_pair_numbers_size_ = pair_numbers_length1;
	_tmp4_ = g_new0 (Tile*, 0 + 1);
	tiles_to_shuffle = _tmp4_;
	tiles_to_shuffle_length1 = 0;
	_tiles_to_shuffle_size_ = tiles_to_shuffle_length1;
	self->priv->_current_move = 1;
	_tmp5_ = self->priv->tiles;
	_tmp5__length1 = self->priv->tiles_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp5_;
		tile_collection_length1 = _tmp5__length1;
		for (tile_it = 0; tile_it < tile_collection_length1; tile_it = tile_it + 1) {
			Tile* tile = NULL;
			tile = tile_collection[tile_it];
			{
				Tile* _tmp6_;
				Tile* _tmp7_;
				gint tile_face = 0;
				Tile* _tmp10_;
				gint* _tmp11_;
				gint _tmp11__length1;
				_tmp6_ = tile;
				_tmp6_->move = 0;
				_tmp7_ = tile;
				if (_tmp7_->visible) {
					Tile* _tmp8_;
					Tile* _tmp9_;
					_tmp8_ = tile;
					_tmp9_ = _tile_ref0 (_tmp8_);
					_vala_array_add4 (&tiles_to_shuffle, &tiles_to_shuffle_length1, &_tiles_to_shuffle_size_, _tmp9_);
					continue;
				}
				_tmp10_ = tile;
				tile_face = _tmp10_->number / 4;
				_tmp11_ = removed_tile_faces;
				_tmp11__length1 = removed_tile_faces_length1;
				if (!_vala_int_array_contains (_tmp11_, _tmp11__length1, tile_face)) {
					_vala_array_add5 (&removed_tile_faces, &removed_tile_faces_length1, &_removed_tile_faces_size_, tile_face);
				}
			}
		}
	}
	_tmp12_ = tiles_to_shuffle;
	_tmp12__length1 = tiles_to_shuffle_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp12_;
		tile_collection_length1 = _tmp12__length1;
		for (tile_it = 0; tile_it < tile_collection_length1; tile_it = tile_it + 1) {
			Tile* tile = NULL;
			tile = tile_collection[tile_it];
			{
				gint tile_face = 0;
				Tile* _tmp13_;
				gint pair_number = 0;
				Tile* _tmp14_;
				Tile* _tmp15_;
				Tile* _tmp16_;
				gint* _tmp17_;
				gint _tmp17__length1;
				gint* _tmp18_;
				gint _tmp18__length1;
				_tmp13_ = tile;
				tile_face = _tmp13_->number / 4;
				_tmp14_ = tile;
				_tmp15_ = tile;
				pair_number = _tmp14_->number - (_tmp15_->number % 2);
				_tmp16_ = tile;
				_tmp16_->number = -1;
				_tmp17_ = removed_tile_faces;
				_tmp17__length1 = removed_tile_faces_length1;
				if (_vala_int_array_contains (_tmp17_, _tmp17__length1, tile_face)) {
					pair_number = tile_face * 4;
				}
				_tmp18_ = pair_numbers;
				_tmp18__length1 = pair_numbers_length1;
				if (!_vala_int_array_contains (_tmp18_, _tmp18__length1, pair_number)) {
					_vala_array_add6 (&pair_numbers, &pair_numbers_length1, &_pair_numbers_size_, pair_number);
				}
			}
		}
	}
	_tmp19_ = pair_numbers;
	_tmp19__length1 = pair_numbers_length1;
	_tmp21_ = game_shuffle_pair_numbers (self, _tmp19_, (gint) _tmp19__length1, &_tmp20_);
	_tmp22_ = (_tmp21_ != NULL) ? _vala_array_dup2 (_tmp21_, _tmp20_) : _tmp21_;
	_tmp22__length1 = _tmp20_;
	pair_numbers = (g_free (pair_numbers), NULL);
	pair_numbers = _tmp22_;
	pair_numbers_length1 = _tmp22__length1;
	_pair_numbers_size_ = pair_numbers_length1;
	_tmp23_ = pair_numbers;
	_tmp23__length1 = pair_numbers_length1;
	game_choose_tile_pairs (self, _tmp23_, (gint) _tmp23__length1, 0, TRUE);
	_tmp24_ = tiles_to_shuffle;
	_tmp24__length1 = tiles_to_shuffle_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp24_;
		tile_collection_length1 = _tmp24__length1;
		for (tile_it = 0; tile_it < tile_collection_length1; tile_it = tile_it + 1) {
			Tile* tile = NULL;
			tile = tile_collection[tile_it];
			{
				Tile* _tmp25_;
				_tmp25_ = tile;
				_tmp25_->visible = TRUE;
			}
		}
	}
	g_signal_emit (self, game_signals[GAME_MOVED_SIGNAL], 0);
	game_redraw_all_tiles (self);
	game_start_clock (self);
	self->priv->clock_elapsed = self->priv->clock_elapsed + 60.0;
	g_signal_emit (self, game_signals[GAME_TICK_SIGNAL], 0);
	tiles_to_shuffle = (_vala_array_free (tiles_to_shuffle, tiles_to_shuffle_length1, (GDestroyNotify) tile_unref), NULL);
	pair_numbers = (g_free (pair_numbers), NULL);
	removed_tile_faces = (g_free (removed_tile_faces), NULL);
}

void
game_undo (Game* self)
{
	gboolean _tmp0_;
	gboolean _tmp1_;
	gint _tmp2_;
	Tile** _tmp3_;
	gint _tmp3__length1;
	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);
	_tmp2_ = self->priv->_current_move;
	self->priv->_current_move = _tmp2_ - 1;
	_tmp3_ = self->priv->tiles;
	_tmp3__length1 = self->priv->tiles_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp3_;
		tile_collection_length1 = _tmp3__length1;
		for (tile_it = 0; tile_it < tile_collection_length1; tile_it = tile_it + 1) {
			Tile* tile = NULL;
			tile = tile_collection[tile_it];
			{
				Tile* _tmp4_;
				_tmp4_ = tile;
				if (_tmp4_->move == self->priv->_current_move) {
					Tile* _tmp5_;
					Tile* _tmp6_;
					_tmp5_ = tile;
					_tmp5_->visible = TRUE;
					_tmp6_ = tile;
					g_signal_emit (self, game_signals[GAME_REDRAW_TILE_SIGNAL], 0, _tmp6_);
				}
			}
		}
	}
	g_signal_emit (self, game_signals[GAME_MOVED_SIGNAL], 0);
}

void
game_redo (Game* self)
{
	gboolean _tmp0_;
	gboolean _tmp1_;
	Tile** _tmp2_;
	gint _tmp2__length1;
	gint _tmp6_;
	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);
	_tmp2_ = self->priv->tiles;
	_tmp2__length1 = self->priv->tiles_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp2_;
		tile_collection_length1 = _tmp2__length1;
		for (tile_it = 0; tile_it < tile_collection_length1; tile_it = tile_it + 1) {
			Tile* tile = NULL;
			tile = tile_collection[tile_it];
			{
				Tile* _tmp3_;
				_tmp3_ = tile;
				if (_tmp3_->move == self->priv->_current_move) {
					Tile* _tmp4_;
					Tile* _tmp5_;
					_tmp4_ = tile;
					_tmp4_->visible = FALSE;
					_tmp5_ = tile;
					g_signal_emit (self, game_signals[GAME_REDRAW_TILE_SIGNAL], 0, _tmp5_);
				}
			}
		}
	}
	_tmp6_ = self->priv->_current_move;
	self->priv->_current_move = _tmp6_ + 1;
	g_signal_emit (self, game_signals[GAME_MOVED_SIGNAL], 0);
}

static gpointer
_match_ref0 (gpointer self)
{
	return self ? match_ref (self) : NULL;
}

Match*
game_next_hint (Game* self)
{
	Match** _tmp0_;
	gint _tmp0__length1;
	gint _tmp13_;
	Match** _tmp14_;
	gint _tmp14__length1;
	Match* match = NULL;
	Match** _tmp15_;
	gint _tmp15__length1;
	Match* _tmp16_;
	Match* _tmp17_;
	Match* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->hint_matches;
	_tmp0__length1 = self->priv->hint_matches_length1;
	if (_tmp0__length1 == 0) {
		Tile* _tmp1_;
		Tile* _tmp2_;
		Tile** _tmp3_;
		Tile** _tmp4_;
		gint _tmp4__length1;
		gint _tmp5_ = 0;
		Match** _tmp6_;
		Match** _tmp7_;
		gint _tmp7__length1;
		Match** _tmp10_;
		gint _tmp10__length1;
		GRand* _tmp11_;
		Match** _tmp12_;
		gint _tmp12__length1;
		_tmp1_ = game_get_selected_tile (self);
		_tmp2_ = _tmp1_;
		_tmp3_ = g_new0 (Tile*, 0 + 1);
		_tmp4_ = _tmp3_;
		_tmp4__length1 = 0;
		_tmp6_ = game_find_matches_for_tile (self, _tmp2_, _tmp4_, (gint) 0, TRUE, &_tmp5_);
		self->priv->hint_matches = (_vala_array_free (self->priv->hint_matches, self->priv->hint_matches_length1, (GDestroyNotify) match_unref), NULL);
		self->priv->hint_matches = _tmp6_;
		self->priv->hint_matches_length1 = _tmp5_;
		self->priv->_hint_matches_size_ = self->priv->hint_matches_length1;
		_tmp4_ = (_vala_array_free (_tmp4_, _tmp4__length1, (GDestroyNotify) tile_unref), NULL);
		_tmp7_ = self->priv->hint_matches;
		_tmp7__length1 = self->priv->hint_matches_length1;
		if (_tmp7__length1 == 0) {
			gint _tmp8_ = 0;
			Match** _tmp9_;
			_tmp9_ = game_find_matches (self, TRUE, &_tmp8_);
			self->priv->hint_matches = (_vala_array_free (self->priv->hint_matches, self->priv->hint_matches_length1, (GDestroyNotify) match_unref), NULL);
			self->priv->hint_matches = _tmp9_;
			self->priv->hint_matches_length1 = _tmp8_;
			self->priv->_hint_matches_size_ = self->priv->hint_matches_length1;
		}
		_tmp10_ = self->priv->hint_matches;
		_tmp10__length1 = self->priv->hint_matches_length1;
		if (_tmp10__length1 == 0) {
			result = NULL;
			return result;
		}
		_tmp11_ = self->priv->random;
		_tmp12_ = self->priv->hint_matches;
		_tmp12__length1 = self->priv->hint_matches_length1;
		self->priv->hint_match_index = (gint) g_rand_int_range (_tmp11_, (gint32) 0, (gint32) ((gint) _tmp12__length1));
	}
	_tmp13_ = self->priv->hint_match_index;
	self->priv->hint_match_index = _tmp13_ + 1;
	_tmp14_ = self->priv->hint_matches;
	_tmp14__length1 = self->priv->hint_matches_length1;
	if (self->priv->hint_match_index >= _tmp14__length1) {
		self->priv->hint_match_index = 0;
	}
	_tmp15_ = self->priv->hint_matches;
	_tmp15__length1 = self->priv->hint_matches_length1;
	_tmp16_ = _tmp15_[self->priv->hint_match_index];
	_tmp17_ = _match_ref0 (_tmp16_);
	match = _tmp17_;
	result = match;
	return result;
}

void
game_show_hint (Game* self)
{
	Match* _tmp0_;
	Match* _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = game_next_hint (self);
	_tmp1_ = _tmp0_;
	game_set_hint (self, _tmp1_);
	_match_unref0 (_tmp1_);
}

static gboolean
_game_autoplay_end_game_timeout_cb_gsource_func (gpointer self)
{
	gboolean result;
	result = game_autoplay_end_game_timeout_cb ((Game*) self);
	return result;
}

void
game_autoplay_end_game (Game* self)
{
	gboolean _tmp0_;
	gboolean _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = game_get_all_tiles_unblocked (self);
	_tmp1_ = _tmp0_;
	if (!_tmp1_) {
		return;
	}
	self->priv->autoplay_end_game_timeout = g_timeout_add_full (G_PRIORITY_DEFAULT, (guint) 500, _game_autoplay_end_game_timeout_cb_gsource_func, game_ref (self), game_unref);
	game_autoplay_end_game_timeout_cb (self);
}

GameIterator*
game_iterator (Game* self)
{
	GameIterator* _tmp0_;
	GameIterator* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = game_iterator_new (self);
	result = _tmp0_;
	return result;
}

static void
_vala_array_add7 (Tile** * array,
                  gint* length,
                  gint* size,
                  Tile* value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (Tile*, *array, (*size) + 1);
	}
	(*array)[(*length)++] = value;
	(*array)[*length] = NULL;
}

static void
game_create_tiles (Game* self)
{
	Tile** _tmp7_;
	gint _tmp7__length1;
	g_return_if_fail (self != NULL);
	{
		MapIterator* _slot_it = NULL;
		Map* _tmp0_;
		MapIterator* _tmp1_;
		_tmp0_ = self->map;
		_tmp1_ = map_iterator (_tmp0_);
		_slot_it = _tmp1_;
		while (TRUE) {
			MapIterator* _tmp2_;
			Slot* slot = NULL;
			MapIterator* _tmp3_;
			Slot* _tmp4_;
			Slot* _tmp5_;
			Tile* _tmp6_;
			_tmp2_ = _slot_it;
			if (!map_iterator_next (_tmp2_)) {
				break;
			}
			_tmp3_ = _slot_it;
			_tmp4_ = map_iterator_get (_tmp3_);
			slot = _tmp4_;
			_tmp5_ = slot;
			_tmp6_ = tile_new (_tmp5_);
			_vala_array_add7 (&self->priv->tiles, &self->priv->tiles_length1, &self->priv->_tiles_size_, _tmp6_);
		}
		_map_iterator_unref0 (_slot_it);
	}
	_tmp7_ = self->priv->tiles;
	_tmp7__length1 = self->priv->tiles_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp7_;
		tile_collection_length1 = _tmp7__length1;
		for (tile_it = 0; tile_it < tile_collection_length1; tile_it = tile_it + 1) {
			Tile* tile = NULL;
			tile = tile_collection[tile_it];
			{
				Slot* slot = NULL;
				Tile* _tmp8_;
				Slot* _tmp9_;
				gint x = 0;
				Slot* _tmp10_;
				gint y_above = 0;
				Slot* _tmp11_;
				gint y_bottom_half = 0;
				Slot* _tmp12_;
				gint layer = 0;
				Slot* _tmp13_;
				Tile** _tmp14_;
				gint _tmp14__length1;
				_tmp8_ = tile;
				_tmp9_ = _tmp8_->slot;
				slot = _tmp9_;
				_tmp10_ = slot;
				x = _tmp10_->x;
				_tmp11_ = slot;
				y_above = _tmp11_->y - 1;
				_tmp12_ = slot;
				y_bottom_half = _tmp12_->y + 1;
				_tmp13_ = slot;
				layer = _tmp13_->layer;
				_tmp14_ = self->priv->tiles;
				_tmp14__length1 = self->priv->tiles_length1;
				{
					Tile** t_collection = NULL;
					gint t_collection_length1 = 0;
					gint _t_collection_size_ = 0;
					gint t_it = 0;
					t_collection = _tmp14_;
					t_collection_length1 = _tmp14__length1;
					for (t_it = 0; t_it < t_collection_length1; t_it = t_it + 1) {
						Tile* t = NULL;
						t = t_collection[t_it];
						{
							Tile* _tmp15_;
							Tile* _tmp16_;
							Slot* s = NULL;
							Tile* _tmp17_;
							Slot* _tmp18_;
							gint s_y = 0;
							Slot* _tmp19_;
							gboolean _tmp20_ = FALSE;
							gint s_layer = 0;
							Slot* _tmp21_;
							_tmp15_ = t;
							_tmp16_ = tile;
							if (_tmp15_ == _tmp16_) {
								continue;
							}
							_tmp17_ = t;
							_tmp18_ = _tmp17_->slot;
							s = _tmp18_;
							_tmp19_ = s;
							s_y = _tmp19_->y;
							if (s_y < y_above) {
								_tmp20_ = TRUE;
							} else {
								_tmp20_ = s_y > y_bottom_half;
							}
							if (_tmp20_) {
								continue;
							}
							_tmp21_ = s;
							s_layer = _tmp21_->layer;
							if (s_layer == layer) {
								gint s_x = 0;
								Slot* _tmp22_;
								_tmp22_ = s;
								s_x = _tmp22_->x;
								if (s_x == (x - 2)) {
									Tile* _tmp23_;
									Tile* _tmp24_;
									_tmp23_ = tile;
									_tmp24_ = t;
									tile_add_tile_left (_tmp23_, _tmp24_);
								}
								if (s_x == (x + 2)) {
									Tile* _tmp25_;
									Tile* _tmp26_;
									_tmp25_ = tile;
									_tmp26_ = t;
									tile_add_tile_right (_tmp25_, _tmp26_);
								}
							} else {
								if (s_layer > layer) {
									gint s_x = 0;
									Slot* _tmp27_;
									gboolean _tmp28_ = FALSE;
									_tmp27_ = s;
									s_x = _tmp27_->x;
									if (s_x >= (x - 1)) {
										_tmp28_ = s_x <= (x + 1);
									} else {
										_tmp28_ = FALSE;
									}
									if (_tmp28_) {
										Tile* _tmp29_;
										Tile* _tmp30_;
										_tmp29_ = tile;
										_tmp30_ = t;
										tile_add_tile_above (_tmp29_, _tmp30_);
									}
								}
							}
						}
					}
				}
			}
		}
	}
}

static gint*
game_shuffle_pair_numbers (Game* self,
                           gint* pair_numbers,
                           gint pair_numbers_length1,
                           gint* result_length1)
{
	gint* _tmp5_;
	gint _tmp5__length1;
	gint* result;
	g_return_val_if_fail (self != NULL, NULL);
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp0_ = FALSE;
			_tmp0_ = TRUE;
			while (TRUE) {
				gint32 n = 0;
				GRand* _tmp2_;
				gint tile_number = 0;
				gint _tmp3_;
				gint _tmp4_;
				if (!_tmp0_) {
					gint _tmp1_;
					_tmp1_ = i;
					i = _tmp1_ + 1;
				}
				_tmp0_ = FALSE;
				if (!(i < pair_numbers_length1)) {
					break;
				}
				_tmp2_ = self->priv->random;
				n = g_rand_int_range (_tmp2_, (gint32) i, (gint32) pair_numbers_length1);
				_tmp3_ = pair_numbers[i];
				tile_number = _tmp3_;
				_tmp4_ = pair_numbers[n];
				pair_numbers[i] = _tmp4_;
				pair_numbers[n] = tile_number;
			}
		}
	}
	_tmp5_ = pair_numbers;
	_tmp5__length1 = pair_numbers_length1;
	if (result_length1) {
		*result_length1 = _tmp5__length1;
	}
	result = _tmp5_;
	return result;
}

static gboolean
game_choose_tile_pairs (Game* self,
                        gint* pair_numbers,
                        gint pair_numbers_length1,
                        gint depth,
                        gboolean check_selectable)
{
	Match** matches = NULL;
	gint _tmp0_ = 0;
	Match** _tmp1_;
	gint matches_length1;
	gint _matches_size_;
	gint n_matches = 0;
	Match** _tmp2_;
	gint _tmp2__length1;
	gint32 n = 0;
	GRand* _tmp3_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	if (depth == pair_numbers_length1) {
		result = TRUE;
		return result;
	}
	_tmp1_ = game_find_matches (self, check_selectable, &_tmp0_);
	matches = _tmp1_;
	matches_length1 = _tmp0_;
	_matches_size_ = matches_length1;
	_tmp2_ = matches;
	_tmp2__length1 = matches_length1;
	n_matches = _tmp2__length1;
	if (n_matches == 0) {
		result = FALSE;
		matches = (_vala_array_free (matches, matches_length1, (GDestroyNotify) match_unref), NULL);
		return result;
	}
	_tmp3_ = self->priv->random;
	n = g_rand_int_range (_tmp3_, (gint32) 0, (gint32) ((gint) n_matches));
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp4_ = FALSE;
			_tmp4_ = TRUE;
			while (TRUE) {
				gint number = 0;
				gint _tmp6_;
				Match* match = NULL;
				Match** _tmp7_;
				gint _tmp7__length1;
				Match* _tmp8_;
				Tile* tile0 = NULL;
				Match* _tmp9_;
				Tile* _tmp10_;
				Tile* tile1 = NULL;
				Match* _tmp11_;
				Tile* _tmp12_;
				Tile* _tmp13_;
				Tile* _tmp14_;
				gboolean _tmp17_ = FALSE;
				gboolean _tmp18_ = FALSE;
				Tile* _tmp20_;
				Tile* _tmp21_;
				if (!_tmp4_) {
					gint _tmp5_;
					_tmp5_ = i;
					i = _tmp5_ + 1;
				}
				_tmp4_ = FALSE;
				if (!(i < n_matches)) {
					break;
				}
				_tmp6_ = pair_numbers[depth];
				number = _tmp6_;
				_tmp7_ = matches;
				_tmp7__length1 = matches_length1;
				_tmp8_ = _tmp7_[(n + i) % n_matches];
				match = _tmp8_;
				_tmp9_ = match;
				_tmp10_ = _tmp9_->tile0;
				tile0 = _tmp10_;
				_tmp11_ = match;
				_tmp12_ = _tmp11_->tile1;
				tile1 = _tmp12_;
				_tmp13_ = tile0;
				_tmp13_->visible = FALSE;
				_tmp14_ = tile1;
				_tmp14_->visible = FALSE;
				if (game_choose_tile_pairs (self, pair_numbers, (gint) pair_numbers_length1, depth + 1, check_selectable)) {
					Tile* _tmp15_;
					Tile* _tmp16_;
					_tmp15_ = tile0;
					_tmp15_->number = number;
					_tmp16_ = tile1;
					_tmp16_->number = number + 1;
					result = TRUE;
					matches = (_vala_array_free (matches, matches_length1, (GDestroyNotify) match_unref), NULL);
					return result;
				}
				if (check_selectable) {
					_tmp18_ = depth == 0;
				} else {
					_tmp18_ = FALSE;
				}
				if (_tmp18_) {
					_tmp17_ = i == (n_matches - 1);
				} else {
					_tmp17_ = FALSE;
				}
				if (_tmp17_) {
					gint _tmp19_;
					check_selectable = FALSE;
					_tmp19_ = i;
					i = _tmp19_ - 1;
				}
				_tmp20_ = tile0;
				_tmp20_->visible = TRUE;
				_tmp21_ = tile1;
				_tmp21_->visible = TRUE;
			}
		}
	}
	result = FALSE;
	matches = (_vala_array_free (matches, matches_length1, (GDestroyNotify) match_unref), NULL);
	return result;
}

static void
_vala_array_add8 (Match** * array,
                  gint* length,
                  gint* size,
                  Match* value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (Match*, *array, (*size) + 1);
	}
	(*array)[(*length)++] = value;
	(*array)[*length] = NULL;
}

static void
_vala_array_add9 (Tile** * array,
                  gint* length,
                  gint* size,
                  Tile* value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (Tile*, *array, (*size) + 1);
	}
	(*array)[(*length)++] = value;
	(*array)[*length] = NULL;
}

static Match**
game_find_matches (Game* self,
                   gboolean check_selectable,
                   gint* result_length1)
{
	Match** matches = NULL;
	Match** _tmp0_;
	gint matches_length1;
	gint _matches_size_;
	Tile** processed_tiles = NULL;
	Tile** _tmp1_;
	gint processed_tiles_length1;
	gint _processed_tiles_size_;
	Tile** _tmp2_;
	gint _tmp2__length1;
	Match** _tmp13_;
	gint _tmp13__length1;
	Match** result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = g_new0 (Match*, 0 + 1);
	matches = _tmp0_;
	matches_length1 = 0;
	_matches_size_ = matches_length1;
	_tmp1_ = g_new0 (Tile*, 0 + 1);
	processed_tiles = _tmp1_;
	processed_tiles_length1 = 0;
	_processed_tiles_size_ = processed_tiles_length1;
	_tmp2_ = self->priv->tiles;
	_tmp2__length1 = self->priv->tiles_length1;
	{
		Tile** t_collection = NULL;
		gint t_collection_length1 = 0;
		gint _t_collection_size_ = 0;
		gint t_it = 0;
		t_collection = _tmp2_;
		t_collection_length1 = _tmp2__length1;
		for (t_it = 0; t_it < t_collection_length1; t_it = t_it + 1) {
			Tile* t = NULL;
			t = t_collection[t_it];
			{
				Match** submatches = NULL;
				Tile* _tmp3_;
				Tile** _tmp4_;
				gint _tmp4__length1;
				gint _tmp5_ = 0;
				Match** _tmp6_;
				gint submatches_length1;
				gint _submatches_size_;
				Match** _tmp7_;
				gint _tmp7__length1;
				Match** _tmp10_;
				gint _tmp10__length1;
				_tmp3_ = t;
				_tmp4_ = processed_tiles;
				_tmp4__length1 = processed_tiles_length1;
				_tmp6_ = game_find_matches_for_tile (self, _tmp3_, _tmp4_, (gint) _tmp4__length1, check_selectable, &_tmp5_);
				submatches = _tmp6_;
				submatches_length1 = _tmp5_;
				_submatches_size_ = submatches_length1;
				_tmp7_ = submatches;
				_tmp7__length1 = submatches_length1;
				{
					Match** match_collection = NULL;
					gint match_collection_length1 = 0;
					gint _match_collection_size_ = 0;
					gint match_it = 0;
					match_collection = _tmp7_;
					match_collection_length1 = _tmp7__length1;
					for (match_it = 0; match_it < match_collection_length1; match_it = match_it + 1) {
						Match* match = NULL;
						match = match_collection[match_it];
						{
							Match* _tmp8_;
							Match* _tmp9_;
							_tmp8_ = match;
							_tmp9_ = _match_ref0 (_tmp8_);
							_vala_array_add8 (&matches, &matches_length1, &_matches_size_, _tmp9_);
						}
					}
				}
				_tmp10_ = submatches;
				_tmp10__length1 = submatches_length1;
				if (_tmp10__length1 > 0) {
					Tile* _tmp11_;
					Tile* _tmp12_;
					_tmp11_ = t;
					_tmp12_ = _tile_ref0 (_tmp11_);
					_vala_array_add9 (&processed_tiles, &processed_tiles_length1, &_processed_tiles_size_, _tmp12_);
				}
				submatches = (_vala_array_free (submatches, submatches_length1, (GDestroyNotify) match_unref), NULL);
			}
		}
	}
	_tmp13_ = matches;
	_tmp13__length1 = matches_length1;
	if (result_length1) {
		*result_length1 = _tmp13__length1;
	}
	result = _tmp13_;
	processed_tiles = (_vala_array_free (processed_tiles, processed_tiles_length1, (GDestroyNotify) tile_unref), NULL);
	return result;
}

static gboolean
_vala_tile_array_contains (Tile* * stack,
                           gssize stack_length,
                           const Tile* needle)
{
	gssize i;
	for (i = 0; i < stack_length; i++) {
		if (needle == stack[i]) {
			return TRUE;
		}
	}
	return FALSE;
}

static void
_vala_array_add10 (Match** * array,
                   gint* length,
                   gint* size,
                   Match* value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (Match*, *array, (*size) + 1);
	}
	(*array)[(*length)++] = value;
	(*array)[*length] = NULL;
}

static Match**
game_find_matches_for_tile (Game* self,
                            Tile* tile,
                            Tile** ignored_tiles,
                            gint ignored_tiles_length1,
                            gboolean check_selectable,
                            gint* result_length1)
{
	Match** matches = NULL;
	Match** _tmp0_;
	gint matches_length1;
	gint _matches_size_;
	gboolean _tmp1_ = FALSE;
	gboolean _tmp3_ = FALSE;
	Tile** _tmp7_;
	gint _tmp7__length1;
	Match** _tmp21_;
	gint _tmp21__length1;
	Match** result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = g_new0 (Match*, 0 + 1);
	matches = _tmp0_;
	matches_length1 = 0;
	_matches_size_ = matches_length1;
	if (tile == NULL) {
		_tmp1_ = TRUE;
	} else {
		_tmp1_ = !tile->visible;
	}
	if (_tmp1_) {
		Match** _tmp2_;
		gint _tmp2__length1;
		_tmp2_ = matches;
		_tmp2__length1 = matches_length1;
		if (result_length1) {
			*result_length1 = _tmp2__length1;
		}
		result = _tmp2_;
		return result;
	}
	if (check_selectable) {
		gboolean _tmp4_;
		gboolean _tmp5_;
		_tmp4_ = tile_get_selectable (tile);
		_tmp5_ = _tmp4_;
		_tmp3_ = !_tmp5_;
	} else {
		_tmp3_ = FALSE;
	}
	if (_tmp3_) {
		Match** _tmp6_;
		gint _tmp6__length1;
		_tmp6_ = matches;
		_tmp6__length1 = matches_length1;
		if (result_length1) {
			*result_length1 = _tmp6__length1;
		}
		result = _tmp6_;
		return result;
	}
	_tmp7_ = self->priv->tiles;
	_tmp7__length1 = self->priv->tiles_length1;
	{
		Tile** t_collection = NULL;
		gint t_collection_length1 = 0;
		gint _t_collection_size_ = 0;
		gint t_it = 0;
		t_collection = _tmp7_;
		t_collection_length1 = _tmp7__length1;
		for (t_it = 0; t_it < t_collection_length1; t_it = t_it + 1) {
			Tile* t = NULL;
			t = t_collection[t_it];
			{
				gboolean _tmp8_ = FALSE;
				Tile* _tmp9_;
				gboolean _tmp11_ = FALSE;
				gboolean _tmp12_ = FALSE;
				Tile* _tmp13_;
				_tmp9_ = t;
				if (_tmp9_ == tile) {
					_tmp8_ = TRUE;
				} else {
					Tile* _tmp10_;
					_tmp10_ = t;
					_tmp8_ = !_tmp10_->visible;
				}
				if (_tmp8_) {
					continue;
				}
				_tmp13_ = t;
				if (tile_matches (_tmp13_, tile)) {
					gboolean _tmp14_ = FALSE;
					if (!check_selectable) {
						_tmp14_ = TRUE;
					} else {
						Tile* _tmp15_;
						gboolean _tmp16_;
						gboolean _tmp17_;
						_tmp15_ = t;
						_tmp16_ = tile_get_selectable (_tmp15_);
						_tmp17_ = _tmp16_;
						_tmp14_ = _tmp17_;
					}
					_tmp12_ = _tmp14_;
				} else {
					_tmp12_ = FALSE;
				}
				if (_tmp12_) {
					Tile* _tmp18_;
					_tmp18_ = t;
					_tmp11_ = !_vala_tile_array_contains (ignored_tiles, ignored_tiles_length1, _tmp18_);
				} else {
					_tmp11_ = FALSE;
				}
				if (_tmp11_) {
					Tile* _tmp19_;
					Match* _tmp20_;
					_tmp19_ = t;
					_tmp20_ = match_new (_tmp19_, tile);
					_vala_array_add10 (&matches, &matches_length1, &_matches_size_, _tmp20_);
				}
			}
		}
	}
	_tmp21_ = matches;
	_tmp21__length1 = matches_length1;
	if (result_length1) {
		*result_length1 = _tmp21__length1;
	}
	result = _tmp21_;
	return result;
}

static void
game_redraw_all_tiles (Game* self)
{
	Tile** _tmp0_;
	gint _tmp0__length1;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->tiles;
	_tmp0__length1 = self->priv->tiles_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp0_;
		tile_collection_length1 = _tmp0__length1;
		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_->visible) {
					Tile* _tmp2_;
					_tmp2_ = tile;
					g_signal_emit (self, game_signals[GAME_REDRAW_TILE_SIGNAL], 0, _tmp2_);
				}
			}
		}
	}
}

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

static void
game_set_hint (Game* self,
               Match* match)
{
	Match* _tmp1_;
	gboolean had_started = FALSE;
	gboolean _tmp2_;
	gboolean _tmp3_;
	g_return_if_fail (self != NULL);
	game_remove_hint_timeout (self);
	if (match == NULL) {
		Match** _tmp0_;
		_match_unref0 (self->priv->hint_match);
		self->priv->hint_match = NULL;
		_tmp0_ = g_new0 (Match*, 0 + 1);
		self->priv->hint_matches = (_vala_array_free (self->priv->hint_matches, self->priv->hint_matches_length1, (GDestroyNotify) match_unref), NULL);
		self->priv->hint_matches = _tmp0_;
		self->priv->hint_matches_length1 = 0;
		self->priv->_hint_matches_size_ = self->priv->hint_matches_length1;
		return;
	}
	_tmp1_ = _match_ref0 (match);
	_match_unref0 (self->priv->hint_match);
	self->priv->hint_match = _tmp1_;
	self->priv->hint_blink_counter = (guint) 6;
	self->priv->hint_timeout = g_timeout_add_full (G_PRIORITY_DEFAULT, (guint) 250, _game_hint_timeout_cb_gsource_func, game_ref (self), game_unref);
	game_hint_timeout_cb (self);
	if (self->priv->_inspecting) {
		return;
	}
	_tmp2_ = game_get_started (self);
	_tmp3_ = _tmp2_;
	had_started = _tmp3_;
	game_start_clock (self);
	self->priv->clock_elapsed = self->priv->clock_elapsed + 30.0;
	g_signal_emit (self, game_signals[GAME_TICK_SIGNAL], 0);
	if (!had_started) {
		g_signal_emit (self, game_signals[GAME_MOVED_SIGNAL], 0);
	}
}

static void
game_redraw_hint_match (Game* self,
                        Match* match)
{
	gboolean _tmp0_ = FALSE;
	Tile* _tmp4_;
	Tile* _tmp5_;
	gboolean _tmp6_ = FALSE;
	Tile* _tmp10_;
	Tile* _tmp11_;
	g_return_if_fail (self != NULL);
	if (match == NULL) {
		return;
	}
	if ((self->priv->hint_blink_counter % 2) != ((guint) 0)) {
		_tmp0_ = TRUE;
	} else {
		Tile* _tmp1_;
		Tile* _tmp2_;
		Tile* _tmp3_;
		_tmp1_ = match->tile0;
		_tmp2_ = game_get_selected_tile (self);
		_tmp3_ = _tmp2_;
		_tmp0_ = _tmp1_ == _tmp3_;
	}
	_tmp4_ = match->tile0;
	_tmp4_->highlighted = _tmp0_;
	_tmp5_ = match->tile0;
	g_signal_emit (self, game_signals[GAME_REDRAW_TILE_SIGNAL], 0, _tmp5_);
	if ((self->priv->hint_blink_counter % 2) != ((guint) 0)) {
		_tmp6_ = TRUE;
	} else {
		Tile* _tmp7_;
		Tile* _tmp8_;
		Tile* _tmp9_;
		_tmp7_ = match->tile1;
		_tmp8_ = game_get_selected_tile (self);
		_tmp9_ = _tmp8_;
		_tmp6_ = _tmp7_ == _tmp9_;
	}
	_tmp10_ = match->tile1;
	_tmp10_->highlighted = _tmp6_;
	_tmp11_ = match->tile1;
	g_signal_emit (self, game_signals[GAME_REDRAW_TILE_SIGNAL], 0, _tmp11_);
}

static void
game_remove_hint_timeout (Game* self)
{
	Match* _tmp0_;
	g_return_if_fail (self != NULL);
	if (self->priv->hint_timeout != ((guint) 0)) {
		g_source_remove (self->priv->hint_timeout);
	}
	self->priv->hint_timeout = (guint) 0;
	self->priv->hint_blink_counter = (guint) 0;
	_tmp0_ = self->priv->hint_match;
	game_redraw_hint_match (self, _tmp0_);
}

static gboolean
game_hint_timeout_cb (Game* self)
{
	guint _tmp0_;
	Match* _tmp1_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	if (self->priv->hint_blink_counter == ((guint) 0)) {
		game_remove_hint_timeout (self);
		result = FALSE;
		return result;
	}
	_tmp0_ = self->priv->hint_blink_counter;
	self->priv->hint_blink_counter = _tmp0_ - 1;
	_tmp1_ = self->priv->hint_match;
	game_redraw_hint_match (self, _tmp1_);
	result = TRUE;
	return result;
}

static void
game_remove_autoplay_end_game_timeout (Game* self)
{
	g_return_if_fail (self != NULL);
	if (self->priv->autoplay_end_game_timeout != ((guint) 0)) {
		g_source_remove (self->priv->autoplay_end_game_timeout);
	}
	self->priv->autoplay_end_game_timeout = (guint) 0;
}

static gboolean
game_autoplay_end_game_timeout_cb (Game* self)
{
	Match* match = NULL;
	Match* _tmp0_;
	Match* _tmp1_;
	Match* _tmp2_;
	Tile* _tmp3_;
	Match* _tmp4_;
	Tile* _tmp5_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = game_next_hint (self);
	match = _tmp0_;
	_tmp1_ = match;
	if (_tmp1_ == NULL) {
		game_remove_autoplay_end_game_timeout (self);
		result = FALSE;
		_match_unref0 (match);
		return result;
	}
	_tmp2_ = match;
	_tmp3_ = _tmp2_->tile0;
	_tmp4_ = match;
	_tmp5_ = _tmp4_->tile1;
	game_remove_pair (self, _tmp3_, _tmp5_);
	result = TRUE;
	_match_unref0 (match);
	return result;
}

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

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

static void
game_continue_clock (Game* self)
{
	GTimer* _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->clock;
	if (_tmp0_ == NULL) {
		GTimer* _tmp1_;
		_tmp1_ = g_timer_new ();
		_g_timer_destroy0 (self->priv->clock);
		self->priv->clock = _tmp1_;
	} else {
		GTimer* _tmp2_;
		_tmp2_ = self->priv->clock;
		if (!g_timer_is_active (_tmp2_)) {
			GTimer* _tmp3_;
			_tmp3_ = self->priv->clock;
			g_timer_continue (_tmp3_);
		}
	}
	game_clock_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 (self, game_signals[GAME_TICK_SIGNAL], 0);
}

static gboolean
_game_clock_timeout_cb_gsource_func (gpointer self)
{
	gboolean result;
	result = game_clock_timeout_cb ((Game*) self);
	return result;
}

static gboolean
game_clock_timeout_cb (Game* self)
{
	GTimer* _tmp0_;
	gint wait = 0;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->clock;
	if (_tmp0_ == NULL) {
		result = G_SOURCE_REMOVE;
		return result;
	}
	wait = 0;
	while (TRUE) {
		gdouble elapsed = 0.0;
		GTimer* _tmp1_;
		gint next = 0;
		if (!(wait <= 0)) {
			break;
		}
		_tmp1_ = self->priv->clock;
		elapsed = g_timer_elapsed (_tmp1_, NULL);
		next = (gint) (elapsed + 1);
		wait = (gint) ((next - elapsed) * 1000);
	}
	self->priv->clock_timeout = g_timeout_add_full (G_PRIORITY_DEFAULT, (guint) wait, _game_clock_timeout_cb_gsource_func, game_ref (self), game_unref);
	g_signal_emit (self, game_signals[GAME_TICK_SIGNAL], 0);
	result = G_SOURCE_REMOVE;
	return result;
}

gint32
game_get_seed (Game* self)
{
	gint32 result;
	g_return_val_if_fail (self != NULL, -1);
	result = self->priv->_seed;
	return result;
}

gboolean
game_get_started (Game* self)
{
	gboolean result;
	GTimer* _tmp0_;
	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_;
	GTimer* _tmp1_;
	g_return_val_if_fail (self != NULL, -1.0);
	_tmp0_ = self->priv->clock;
	if (_tmp0_ == NULL) {
		result = 0.0;
		return result;
	}
	_tmp1_ = self->priv->clock;
	result = self->priv->clock_elapsed + g_timer_elapsed (_tmp1_, NULL);
	return result;
}

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

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

void
game_set_paused (Game* self,
                 gboolean value)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean _tmp2_;
	gboolean _tmp3_;
	GTimer* _tmp8_;
	g_return_if_fail (self != NULL);
	if (value == self->priv->_paused) {
		return;
	}
	_tmp2_ = game_get_started (self);
	_tmp3_ = _tmp2_;
	if (!_tmp3_) {
		_tmp1_ = TRUE;
	} else {
		gboolean _tmp4_;
		gboolean _tmp5_;
		_tmp4_ = game_get_inspecting (self);
		_tmp5_ = _tmp4_;
		_tmp1_ = _tmp5_;
	}
	if (_tmp1_) {
		_tmp0_ = TRUE;
	} else {
		gboolean _tmp6_;
		gboolean _tmp7_;
		_tmp6_ = game_get_complete (self);
		_tmp7_ = _tmp6_;
		_tmp0_ = _tmp7_;
	}
	if (_tmp0_) {
		return;
	}
	self->priv->_paused = value;
	_tmp8_ = self->priv->clock;
	if (_tmp8_ != NULL) {
		if (value) {
			game_stop_clock (self);
		} else {
			game_continue_clock (self);
		}
	}
	game_set_selected_tile (self, NULL);
	game_set_hint (self, NULL);
	g_signal_emit (self, game_signals[GAME_PAUSED_CHANGED_SIGNAL], 0);
}

Tile*
game_get_selected_tile (Game* self)
{
	Tile* result;
	Tile* _tmp0_;
	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_;
	Tile* _tmp3_;
	Tile* _tmp4_;
	Match** _tmp7_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->_selected_tile;
	if (_tmp0_ != NULL) {
		Tile* _tmp1_;
		Tile* _tmp2_;
		_tmp1_ = self->priv->_selected_tile;
		_tmp1_->highlighted = FALSE;
		_tmp2_ = self->priv->_selected_tile;
		g_signal_emit (self, game_signals[GAME_REDRAW_TILE_SIGNAL], 0, _tmp2_);
	}
	_tmp3_ = _tile_ref0 (value);
	_tile_unref0 (self->priv->_selected_tile);
	self->priv->_selected_tile = _tmp3_;
	_tmp4_ = self->priv->_selected_tile;
	if (_tmp4_ != NULL) {
		Tile* _tmp5_;
		Tile* _tmp6_;
		_tmp5_ = self->priv->_selected_tile;
		_tmp5_->highlighted = TRUE;
		_tmp6_ = self->priv->_selected_tile;
		g_signal_emit (self, game_signals[GAME_REDRAW_TILE_SIGNAL], 0, _tmp6_);
	}
	_tmp7_ = g_new0 (Match*, 0 + 1);
	self->priv->hint_matches = (_vala_array_free (self->priv->hint_matches, self->priv->hint_matches_length1, (GDestroyNotify) match_unref), NULL);
	self->priv->hint_matches = _tmp7_;
	self->priv->hint_matches_length1 = 0;
	self->priv->_hint_matches_size_ = self->priv->hint_matches_length1;
}

gint
game_get_current_move (Game* self)
{
	gint result;
	g_return_val_if_fail (self != NULL, -1);
	result = self->priv->_current_move;
	return result;
}

guint
game_get_moves_left (Game* self)
{
	guint result;
	gint _tmp0_ = 0;
	Match** _tmp1_;
	Match** _tmp2_;
	gint _tmp2__length1;
	guint _tmp3_;
	g_return_val_if_fail (self != NULL, 0U);
	_tmp1_ = game_find_matches (self, TRUE, &_tmp0_);
	_tmp2_ = _tmp1_;
	_tmp2__length1 = _tmp0_;
	_tmp3_ = (guint) _tmp0_;
	_tmp2_ = (_vala_array_free (_tmp2_, _tmp2__length1, (GDestroyNotify) match_unref), NULL);
	result = _tmp3_;
	return result;
}

gboolean
game_get_complete (Game* self)
{
	gboolean result;
	Tile** _tmp0_;
	gint _tmp0__length1;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->tiles;
	_tmp0__length1 = self->priv->tiles_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp0_;
		tile_collection_length1 = _tmp0__length1;
		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_->visible) {
					result = FALSE;
					return result;
				}
			}
		}
	}
	result = TRUE;
	return result;
}

gboolean
game_get_can_move (Game* self)
{
	gboolean result;
	guint _tmp0_;
	guint _tmp1_;
	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_shuffle (Game* self)
{
	gboolean result;
	gint num_selectable_tiles = 0;
	Tile** _tmp0_;
	gint _tmp0__length1;
	g_return_val_if_fail (self != NULL, FALSE);
	num_selectable_tiles = 0;
	_tmp0_ = self->priv->tiles;
	_tmp0__length1 = self->priv->tiles_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp0_;
		tile_collection_length1 = _tmp0__length1;
		for (tile_it = 0; tile_it < tile_collection_length1; tile_it = tile_it + 1) {
			Tile* tile = NULL;
			tile = tile_collection[tile_it];
			{
				Tile* _tmp1_;
				gboolean _tmp2_;
				gboolean _tmp3_;
				_tmp1_ = tile;
				_tmp2_ = tile_get_selectable (_tmp1_);
				_tmp3_ = _tmp2_;
				if (_tmp3_) {
					gint _tmp4_;
					_tmp4_ = num_selectable_tiles;
					num_selectable_tiles = _tmp4_ + 1;
					if (num_selectable_tiles == 2) {
						result = TRUE;
						return result;
					}
				}
			}
		}
	}
	result = FALSE;
	return result;
}

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

gboolean
game_get_can_redo (Game* self)
{
	gboolean result;
	Tile** _tmp0_;
	gint _tmp0__length1;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->tiles;
	_tmp0__length1 = self->priv->tiles_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp0_;
		tile_collection_length1 = _tmp0__length1;
		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_->move >= self->priv->_current_move) {
					result = TRUE;
					return result;
				}
			}
		}
	}
	result = FALSE;
	return result;
}

gboolean
game_get_can_save (Game* self)
{
	gboolean result;
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean _tmp2_;
	gboolean _tmp3_;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp2_ = game_get_started (self);
	_tmp3_ = _tmp2_;
	if (_tmp3_) {
		gboolean _tmp4_;
		gboolean _tmp5_;
		_tmp4_ = game_get_can_move (self);
		_tmp5_ = _tmp4_;
		_tmp1_ = _tmp5_;
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		gboolean _tmp6_;
		gboolean _tmp7_;
		_tmp6_ = game_get_inspecting (self);
		_tmp7_ = _tmp6_;
		_tmp0_ = !_tmp7_;
	} else {
		_tmp0_ = FALSE;
	}
	result = _tmp0_;
	return result;
}

gboolean
game_get_all_tiles_unblocked (Game* self)
{
	gboolean result;
	Tile** _tmp0_;
	gint _tmp0__length1;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->tiles;
	_tmp0__length1 = self->priv->tiles_length1;
	{
		Tile** tile_collection = NULL;
		gint tile_collection_length1 = 0;
		gint _tile_collection_size_ = 0;
		gint tile_it = 0;
		tile_collection = _tmp0_;
		tile_collection_length1 = _tmp0__length1;
		for (tile_it = 0; tile_it < tile_collection_length1; tile_it = tile_it + 1) {
			Tile* tile = NULL;
			tile = tile_collection[tile_it];
			{
				gboolean _tmp1_ = FALSE;
				Tile* _tmp2_;
				_tmp2_ = tile;
				if (_tmp2_->visible) {
					Tile* _tmp3_;
					gboolean _tmp4_;
					gboolean _tmp5_;
					_tmp3_ = tile;
					_tmp4_ = tile_get_selectable (_tmp3_);
					_tmp5_ = _tmp4_;
					_tmp1_ = !_tmp5_;
				} else {
					_tmp1_ = FALSE;
				}
				if (_tmp1_) {
					result = FALSE;
					return result;
				}
			}
		}
	}
	result = TRUE;
	return result;
}

gint
game_get_n_tiles (Game* self)
{
	gint result;
	Tile** _tmp0_;
	gint _tmp0__length1;
	g_return_val_if_fail (self != NULL, -1);
	_tmp0_ = self->priv->tiles;
	_tmp0__length1 = self->priv->tiles_length1;
	result = _tmp0__length1;
	return result;
}

static void
g_cclosure_user_marshal_BOOLEAN__VOID (GClosure * closure,
                                       GValue * return_value,
                                       guint n_param_values,
                                       const GValue * param_values,
                                       gpointer invocation_hint,
                                       gpointer marshal_data)
{
	typedef gboolean (*GMarshalFunc_BOOLEAN__VOID) (gpointer data1, gpointer data2);
	register GMarshalFunc_BOOLEAN__VOID callback;
	register GCClosure * cc;
	register gpointer data1;
	register gpointer data2;
	gboolean v_return;
	cc = (GCClosure *) closure;
	g_return_if_fail (return_value != NULL);
	g_return_if_fail (n_param_values == 1);
	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_BOOLEAN__VOID) (marshal_data ? marshal_data : cc->callback);
	v_return = callback (data1, data2);
	g_value_set_boolean (return_value, v_return);
}

static void
g_cclosure_user_marshal_VOID__TILE (GClosure * closure,
                                    GValue * return_value,
                                    guint n_param_values,
                                    const GValue * param_values,
                                    gpointer invocation_hint,
                                    gpointer marshal_data)
{
	typedef void (*GMarshalFunc_VOID__TILE) (gpointer data1, gpointer arg_1, gpointer data2);
	register GMarshalFunc_VOID__TILE callback;
	register GCClosure * cc;
	register gpointer data1;
	register gpointer data2;
	cc = (GCClosure *) closure;
	g_return_if_fail (n_param_values == 2);
	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__TILE) (marshal_data ? marshal_data : cc->callback);
	callback (data1, value_get_tile (param_values + 1), data2);
}

static inline gpointer
game_iterator_get_instance_private (GameIterator* self)
{
	return G_STRUCT_MEMBER_P (self, GameIterator_private_offset);
}

static gpointer
_game_ref0 (gpointer self)
{
	return self ? game_ref (self) : NULL;
}

GameIterator*
game_iterator_construct (GType object_type,
                         Game* game)
{
	GameIterator* self = NULL;
	Game* _tmp0_;
	g_return_val_if_fail (game != NULL, NULL);
	self = (GameIterator*) g_type_create_instance (object_type);
	_tmp0_ = _game_ref0 (game);
	_game_unref0 (self->priv->game);
	self->priv->game = _tmp0_;
	return self;
}

GameIterator*
game_iterator_new (Game* game)
{
	return game_iterator_construct (GAME_TYPE_ITERATOR, game);
}

gboolean
game_iterator_next (GameIterator* self)
{
	Game* _tmp0_;
	Tile** _tmp1_;
	gint _tmp1__length1;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->game;
	_tmp1_ = _tmp0_->priv->tiles;
	_tmp1__length1 = _tmp0_->priv->tiles_length1;
	result = self->priv->index < _tmp1__length1;
	return result;
}

Tile*
game_iterator_get (GameIterator* self)
{
	Game* _tmp0_;
	Tile** _tmp1_;
	gint _tmp1__length1;
	gint _tmp2_;
	Tile* _tmp3_;
	Tile* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->game;
	_tmp1_ = _tmp0_->priv->tiles;
	_tmp1__length1 = _tmp0_->priv->tiles_length1;
	_tmp2_ = self->priv->index;
	self->priv->index = _tmp2_ + 1;
	_tmp3_ = _tmp1_[_tmp2_];
	result = _tmp3_;
	return result;
}

static void
game_value_iterator_init (GValue* value)
{
	value->data[0].v_pointer = NULL;
}

static void
game_value_iterator_free_value (GValue* value)
{
	if (value->data[0].v_pointer) {
		game_iterator_unref (value->data[0].v_pointer);
	}
}

static void
game_value_iterator_copy_value (const GValue* src_value,
                                GValue* dest_value)
{
	if (src_value->data[0].v_pointer) {
		dest_value->data[0].v_pointer = game_iterator_ref (src_value->data[0].v_pointer);
	} else {
		dest_value->data[0].v_pointer = NULL;
	}
}

static gpointer
game_value_iterator_peek_pointer (const GValue* value)
{
	return value->data[0].v_pointer;
}

static gchar*
game_value_iterator_collect_value (GValue* value,
                                   guint n_collect_values,
                                   GTypeCValue* collect_values,
                                   guint collect_flags)
{
	if (collect_values[0].v_pointer) {
		GameIterator * object;
		object = collect_values[0].v_pointer;
		if (object->parent_instance.g_class == NULL) {
			return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		} else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) {
			return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		}
		value->data[0].v_pointer = game_iterator_ref (object);
	} else {
		value->data[0].v_pointer = NULL;
	}
	return NULL;
}

static gchar*
game_value_iterator_lcopy_value (const GValue* value,
                                 guint n_collect_values,
                                 GTypeCValue* collect_values,
                                 guint collect_flags)
{
	GameIterator ** object_p;
	object_p = collect_values[0].v_pointer;
	if (!object_p) {
		return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
	}
	if (!value->data[0].v_pointer) {
		*object_p = NULL;
	} else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
		*object_p = value->data[0].v_pointer;
	} else {
		*object_p = game_iterator_ref (value->data[0].v_pointer);
	}
	return NULL;
}

GParamSpec*
game_param_spec_iterator (const gchar* name,
                          const gchar* nick,
                          const gchar* blurb,
                          GType object_type,
                          GParamFlags flags)
{
	GameParamSpecIterator* spec;
	g_return_val_if_fail (g_type_is_a (object_type, GAME_TYPE_ITERATOR), NULL);
	spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
	G_PARAM_SPEC (spec)->value_type = object_type;
	return G_PARAM_SPEC (spec);
}

gpointer
game_value_get_iterator (const GValue* value)
{
	g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, GAME_TYPE_ITERATOR), NULL);
	return value->data[0].v_pointer;
}

void
game_value_set_iterator (GValue* value,
                         gpointer v_object)
{
	GameIterator * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, GAME_TYPE_ITERATOR));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, GAME_TYPE_ITERATOR));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
		game_iterator_ref (value->data[0].v_pointer);
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		game_iterator_unref (old);
	}
}

void
game_value_take_iterator (GValue* value,
                          gpointer v_object)
{
	GameIterator * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, GAME_TYPE_ITERATOR));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, GAME_TYPE_ITERATOR));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		game_iterator_unref (old);
	}
}

static void
game_iterator_class_init (GameIteratorClass * klass,
                          gpointer klass_data)
{
	game_iterator_parent_class = g_type_class_peek_parent (klass);
	((GameIteratorClass *) klass)->finalize = game_iterator_finalize;
	g_type_class_adjust_private_offset (klass, &GameIterator_private_offset);
}

static void
game_iterator_instance_init (GameIterator * self,
                             gpointer klass)
{
	self->priv = game_iterator_get_instance_private (self);
	self->ref_count = 1;
}

static void
game_iterator_finalize (GameIterator * obj)
{
	GameIterator * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, GAME_TYPE_ITERATOR, GameIterator);
	g_signal_handlers_destroy (self);
	_game_unref0 (self->priv->game);
}

 G_GNUC_NO_INLINE static GType
game_iterator_get_type_once (void)
{
	static const GTypeValueTable g_define_type_value_table = { game_value_iterator_init, game_value_iterator_free_value, game_value_iterator_copy_value, game_value_iterator_peek_pointer, "p", game_value_iterator_collect_value, "p", game_value_iterator_lcopy_value };
	static const GTypeInfo g_define_type_info = { sizeof (GameIteratorClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) game_iterator_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GameIterator), 0, (GInstanceInitFunc) game_iterator_instance_init, &g_define_type_value_table };
	static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };
	GType game_iterator_type_id;
	game_iterator_type_id = g_type_register_fundamental (g_type_fundamental_next (), "GameIterator", &g_define_type_info, &g_define_type_fundamental_info, 0);
	GameIterator_private_offset = g_type_add_instance_private (game_iterator_type_id, sizeof (GameIteratorPrivate));
	return game_iterator_type_id;
}

GType
game_iterator_get_type (void)
{
	static gsize game_iterator_type_id__once = 0;
	if (g_once_init_enter (&game_iterator_type_id__once)) {
		GType game_iterator_type_id;
		game_iterator_type_id = game_iterator_get_type_once ();
		g_once_init_leave (&game_iterator_type_id__once, game_iterator_type_id);
	}
	return game_iterator_type_id__once;
}

gpointer
game_iterator_ref (gpointer instance)
{
	GameIterator * self;
	self = instance;
	g_atomic_int_inc (&self->ref_count);
	return instance;
}

void
game_iterator_unref (gpointer instance)
{
	GameIterator * self;
	self = instance;
	if (g_atomic_int_dec_and_test (&self->ref_count)) {
		GAME_ITERATOR_GET_CLASS (self)->finalize (self);
		g_type_free_instance ((GTypeInstance *) self);
	}
}

static void
value_game_init (GValue* value)
{
	value->data[0].v_pointer = NULL;
}

static void
value_game_free_value (GValue* value)
{
	if (value->data[0].v_pointer) {
		game_unref (value->data[0].v_pointer);
	}
}

static void
value_game_copy_value (const GValue* src_value,
                       GValue* dest_value)
{
	if (src_value->data[0].v_pointer) {
		dest_value->data[0].v_pointer = game_ref (src_value->data[0].v_pointer);
	} else {
		dest_value->data[0].v_pointer = NULL;
	}
}

static gpointer
value_game_peek_pointer (const GValue* value)
{
	return value->data[0].v_pointer;
}

static gchar*
value_game_collect_value (GValue* value,
                          guint n_collect_values,
                          GTypeCValue* collect_values,
                          guint collect_flags)
{
	if (collect_values[0].v_pointer) {
		Game * object;
		object = collect_values[0].v_pointer;
		if (object->parent_instance.g_class == NULL) {
			return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		} else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) {
			return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		}
		value->data[0].v_pointer = game_ref (object);
	} else {
		value->data[0].v_pointer = NULL;
	}
	return NULL;
}

static gchar*
value_game_lcopy_value (const GValue* value,
                        guint n_collect_values,
                        GTypeCValue* collect_values,
                        guint collect_flags)
{
	Game ** object_p;
	object_p = collect_values[0].v_pointer;
	if (!object_p) {
		return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
	}
	if (!value->data[0].v_pointer) {
		*object_p = NULL;
	} else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
		*object_p = value->data[0].v_pointer;
	} else {
		*object_p = game_ref (value->data[0].v_pointer);
	}
	return NULL;
}

GParamSpec*
param_spec_game (const gchar* name,
                 const gchar* nick,
                 const gchar* blurb,
                 GType object_type,
                 GParamFlags flags)
{
	ParamSpecGame* spec;
	g_return_val_if_fail (g_type_is_a (object_type, TYPE_GAME), NULL);
	spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
	G_PARAM_SPEC (spec)->value_type = object_type;
	return G_PARAM_SPEC (spec);
}

gpointer
value_get_game (const GValue* value)
{
	g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_GAME), NULL);
	return value->data[0].v_pointer;
}

void
value_set_game (GValue* value,
                gpointer v_object)
{
	Game * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_GAME));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_GAME));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
		game_ref (value->data[0].v_pointer);
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		game_unref (old);
	}
}

void
value_take_game (GValue* value,
                 gpointer v_object)
{
	Game * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_GAME));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_GAME));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		game_unref (old);
	}
}

static void
game_class_init (GameClass * klass,
                 gpointer klass_data)
{
	game_parent_class = g_type_class_peek_parent (klass);
	((GameClass *) klass)->finalize = game_finalize;
	g_type_class_adjust_private_offset (klass, &Game_private_offset);
	game_signals[GAME_ATTEMPT_MOVE_SIGNAL] = g_signal_new ("attempt-move", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_BOOLEAN__VOID, G_TYPE_BOOLEAN, 0);
	game_signals[GAME_REDRAW_TILE_SIGNAL] = g_signal_new ("redraw-tile", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__TILE, G_TYPE_NONE, 1, TYPE_TILE);
	game_signals[GAME_MOVED_SIGNAL] = g_signal_new ("moved", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	game_signals[GAME_PAUSED_CHANGED_SIGNAL] = g_signal_new ("paused-changed", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	game_signals[GAME_TICK_SIGNAL] = 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,
                    gpointer klass)
{
	self->priv = game_get_instance_private (self);
	self->priv->_seed = (gint32) -1;
	self->ref_count = 1;
}

static void
game_finalize (Game * obj)
{
	Game * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_GAME, Game);
	g_signal_handlers_destroy (self);
	_map_unref0 (self->map);
	self->priv->tiles = (_vala_array_free (self->priv->tiles, self->priv->tiles_length1, (GDestroyNotify) tile_unref), NULL);
	_g_rand_free0 (self->priv->random);
	_match_unref0 (self->priv->hint_match);
	self->priv->hint_matches = (_vala_array_free (self->priv->hint_matches, self->priv->hint_matches_length1, (GDestroyNotify) match_unref), NULL);
	_g_timer_destroy0 (self->priv->clock);
	_tile_unref0 (self->priv->_selected_tile);
}

 G_GNUC_NO_INLINE static GType
game_get_type_once (void)
{
	static const GTypeValueTable g_define_type_value_table = { value_game_init, value_game_free_value, value_game_copy_value, value_game_peek_pointer, "p", value_game_collect_value, "p", value_game_lcopy_value };
	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, &g_define_type_value_table };
	static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };
	GType game_type_id;
	game_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Game", &g_define_type_info, &g_define_type_fundamental_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 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;
}

gpointer
game_ref (gpointer instance)
{
	Game * self;
	self = instance;
	g_atomic_int_inc (&self->ref_count);
	return instance;
}

void
game_unref (gpointer instance)
{
	Game * self;
	self = instance;
	if (g_atomic_int_dec_and_test (&self->ref_count)) {
		GAME_GET_CLASS (self)->finalize (self);
		g_type_free_instance ((GTypeInstance *) self);
	}
}

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);
}

