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

/* game.vala
 * 
 * Copyright 2010-2013 Robert Ancell
 * Copyright 2009 Lubomir Rintel <lkundrak@v3.sk>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 */

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

#define NCOLORS 7
#define AUTOMOVE_ACTIVATION_TIME 200
#define AUTOMOVE_INTERVAL 40
#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_BLOCK (block_get_type ())
#define BLOCK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BLOCK, Block))
#define BLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BLOCK, BlockClass))
#define IS_BLOCK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BLOCK))
#define IS_BLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BLOCK))
#define BLOCK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BLOCK, BlockClass))

typedef struct _Block Block;
typedef struct _BlockClass BlockClass;
typedef struct _BlockPrivate BlockPrivate;
enum  {
	BLOCK_0_PROPERTY,
	BLOCK_NUM_PROPERTIES
};
static GParamSpec* block_properties[BLOCK_NUM_PROPERTIES];

#define TYPE_SHAPE (shape_get_type ())
#define SHAPE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SHAPE, Shape))
#define SHAPE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SHAPE, ShapeClass))
#define IS_SHAPE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SHAPE))
#define IS_SHAPE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SHAPE))
#define SHAPE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SHAPE, ShapeClass))

typedef struct _Shape Shape;
typedef struct _ShapeClass ShapeClass;
typedef struct _ShapePrivate ShapePrivate;
enum  {
	SHAPE_0_PROPERTY,
	SHAPE_NUM_PROPERTIES
};
static GParamSpec* shape_properties[SHAPE_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))

#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;
enum  {
	GAME_0_PROPERTY,
	GAME_WIDTH_PROPERTY,
	GAME_HEIGHT_PROPERTY,
	GAME_LEVEL_PROPERTY,
	GAME_PAUSED_PROPERTY,
	GAME_SHADOW_Y_PROPERTY,
	GAME_NUM_PROPERTIES
};
static GParamSpec* game_properties[GAME_NUM_PROPERTIES];
enum  {
	GAME_STARTED_SIGNAL,
	GAME_SHAPE_ADDED_SIGNAL,
	GAME_SHAPE_HELD_SIGNAL,
	GAME_SHAPE_MOVED_SIGNAL,
	GAME_SHAPE_REMOVED_SIGNAL,
	GAME_SHAPE_DROPPED_SIGNAL,
	GAME_SHAPE_ROTATED_SIGNAL,
	GAME_SHAPE_LANDED_SIGNAL,
	GAME_PAUSE_CHANGED_SIGNAL,
	GAME_COMPLETE_SIGNAL,
	GAME_NUM_SIGNALS
};
static guint game_signals[GAME_NUM_SIGNALS] = {0};

struct _Block {
	GObject parent_instance;
	BlockPrivate * priv;
	gint x;
	gint y;
	gint color;
};

struct _BlockClass {
	GObjectClass parent_class;
};

struct _Shape {
	GObject parent_instance;
	ShapePrivate * priv;
	gint x;
	gint y;
	gint rotation;
	gint type;
	GList* blocks;
};

struct _ShapeClass {
	GObjectClass parent_class;
};

struct _Game {
	GObject parent_instance;
	GamePrivate * priv;
	Shape* shape;
	Shape* next_shape;
	Shape* held_shape;
	Block** blocks;
	gint blocks_length1;
	gint blocks_length2;
	gint n_lines_destroyed;
	gint score;
	gint difficulty;
	gboolean pick_difficult_blocks;
	gboolean game_over;
};

struct _GameClass {
	GObjectClass parent_class;
};

struct _GamePrivate {
	gint fast_move_direction;
	guint fast_move_timeout;
	gboolean fast_forward;
	guint drop_timeout;
	gboolean has_started;
	gboolean is_hold_used;
	gboolean _paused;
	gint* distshapecount;
	gint distshapecount_length1;
	gint _distshapecount_size_;
};

static gpointer block_parent_class = NULL;
static gpointer shape_parent_class = NULL;
static gint Game_private_offset;
static gpointer game_parent_class = NULL;

VALA_EXTERN GType block_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (Block, g_object_unref)
VALA_EXTERN Block* block_copy (Block* self);
VALA_EXTERN Block* block_new (void);
VALA_EXTERN Block* block_construct (GType object_type);
static void block_finalize (GObject * obj);
static GType block_get_type_once (void);
VALA_EXTERN GType shape_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (Shape, g_object_unref)
static void _g_object_unref0_ (gpointer var);
static inline void _g_list_free__g_object_unref0_ (GList* self);
VALA_EXTERN Shape* shape_copy (Shape* self);
VALA_EXTERN Shape* shape_new (void);
VALA_EXTERN Shape* shape_construct (GType object_type);
static void shape_finalize (GObject * obj);
static GType shape_get_type_once (void);
VALA_EXTERN GType game_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (Game, g_object_unref)
VALA_EXTERN Game* game_new (gint lines,
                gint columns,
                gint difficulty,
                gint filled_lines,
                gint fill_prob,
                gboolean pick_difficult_blocks);
VALA_EXTERN Game* game_construct (GType object_type,
                      gint lines,
                      gint columns,
                      gint difficulty,
                      gint filled_lines,
                      gint fill_prob,
                      gboolean pick_difficult_blocks);
VALA_EXTERN gint game_get_height (Game* self);
VALA_EXTERN gint game_get_width (Game* self);
static Shape* game_pick_random_shape (Game* self);
VALA_EXTERN Game* game_copy (Game* self);
VALA_EXTERN void game_start (Game* self);
static void game_make_next_shape (Game* self);
static void game_add_shape (Game* self);
static void game_setup_drop_timer (Game* self);
VALA_EXTERN gboolean game_move_left (Game* self);
static gboolean game_move_direction (Game* self,
                              gint direction);
VALA_EXTERN gboolean game_move_right (Game* self);
VALA_EXTERN gboolean game_stop_moving (Game* self);
VALA_EXTERN gboolean game_rotate_left (Game* self);
static gboolean game_try_rotate (Game* self,
                          gint r_step);
VALA_EXTERN gboolean game_rotate_right (Game* self);
static gboolean game_move_shape (Game* self,
                          gint x_step,
                          gint y_step,
                          gint r_step);
VALA_EXTERN gboolean game_get_fast_forward (Game* self);
VALA_EXTERN void game_set_fast_forward (Game* self,
                            gboolean enable);
VALA_EXTERN void game_drop (Game* self);
static gboolean game_fall_timeout_cb (Game* self);
VALA_EXTERN void game_hold (Game* self);
static void game_remove_shape (Game* self);
static Shape* game_make_shape (Game* self,
                        gint type,
                        gint rotation);
static void game_add_shape_internal (Game* self);
VALA_EXTERN void game_stop (Game* self);
static gboolean game_move (Game* self);
static gboolean game_setup_fast_move_cb (Game* self);
static gboolean _game_setup_fast_move_cb_gsource_func (gpointer self);
static gboolean _game_move_gsource_func (gpointer self);
VALA_EXTERN gint game_get_level (Game* self);
VALA_EXTERN gboolean game_get_paused (Game* self);
static gboolean _game_fall_timeout_cb_gsource_func (gpointer self);
static void game_land_shape (Game* self);
static Shape* game_pick_difficult_shapes (Game* self);
static void game_rotate_shape (Game* self,
                        gint r_step);
VALA_EXTERN void game_set_paused (Game* self,
                      gboolean value);
VALA_EXTERN gint game_get_shadow_y (Game* self);
static void g_cclosure_user_marshal_VOID__POINTER_INT_POINTER (GClosure * closure,
                                                        GValue * return_value,
                                                        guint n_param_values,
                                                        const GValue * param_values,
                                                        gpointer invocation_hint,
                                                        gpointer marshal_data);
static void game_finalize (GObject * obj);
static GType game_get_type_once (void);
static void _vala_game_get_property (GObject * object,
                              guint property_id,
                              GValue * value,
                              GParamSpec * pspec);
static void _vala_game_set_property (GObject * object,
                              guint property_id,
                              const GValue * value,
                              GParamSpec * pspec);
static void _vala_array_destroy (gpointer array,
                          gssize array_length,
                          GDestroyNotify destroy_func);
static void _vala_array_free (gpointer array,
                       gssize array_length,
                       GDestroyNotify destroy_func);

const gint BLOCK_TABLE[448] = {0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0};

Block*
block_copy (Block* self)
{
	Block* b = NULL;
	Block* _tmp0_;
	Block* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = block_new ();
	b = _tmp0_;
	b->x = self->x;
	b->y = self->y;
	b->color = self->color;
	result = b;
	return result;
}

Block*
block_construct (GType object_type)
{
	Block * self = NULL;
	self = (Block*) g_object_new (object_type, NULL);
	return self;
}

Block*
block_new (void)
{
	return block_construct (TYPE_BLOCK);
}

static void
block_class_init (BlockClass * klass,
                  gpointer klass_data)
{
	block_parent_class = g_type_class_peek_parent (klass);
	G_OBJECT_CLASS (klass)->finalize = block_finalize;
}

static void
block_instance_init (Block * self,
                     gpointer klass)
{
}

static void
block_finalize (GObject * obj)
{
	Block * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_BLOCK, Block);
	G_OBJECT_CLASS (block_parent_class)->finalize (obj);
}

static GType
block_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (BlockClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) block_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Block), 0, (GInstanceInitFunc) block_instance_init, NULL };
	GType block_type_id;
	block_type_id = g_type_register_static (G_TYPE_OBJECT, "Block", &g_define_type_info, 0);
	return block_type_id;
}

GType
block_get_type (void)
{
	static volatile gsize block_type_id__once = 0;
	if (g_once_init_enter (&block_type_id__once)) {
		GType block_type_id;
		block_type_id = block_get_type_once ();
		g_once_init_leave (&block_type_id__once, block_type_id);
	}
	return block_type_id__once;
}

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

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

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

Shape*
shape_copy (Shape* self)
{
	Shape* s = NULL;
	Shape* _tmp0_;
	Shape* _tmp1_;
	Shape* _tmp2_;
	Shape* _tmp3_;
	Shape* _tmp4_;
	GList* _tmp5_;
	Shape* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = shape_new ();
	s = _tmp0_;
	_tmp1_ = s;
	_tmp1_->x = self->x;
	_tmp2_ = s;
	_tmp2_->y = self->y;
	_tmp3_ = s;
	_tmp3_->rotation = self->rotation;
	_tmp4_ = s;
	_tmp4_->type = self->type;
	_tmp5_ = self->blocks;
	{
		GList* b_collection = NULL;
		GList* b_it = NULL;
		b_collection = _tmp5_;
		for (b_it = b_collection; b_it != NULL; b_it = b_it->next) {
			Block* _tmp6_;
			Block* b = NULL;
			_tmp6_ = _g_object_ref0 ((Block*) b_it->data);
			b = _tmp6_;
			{
				Shape* _tmp7_;
				Block* _tmp8_;
				Block* _tmp9_;
				_tmp7_ = s;
				_tmp8_ = b;
				_tmp9_ = block_copy (_tmp8_);
				_tmp7_->blocks = g_list_append (_tmp7_->blocks, _tmp9_);
				_g_object_unref0 (b);
			}
		}
	}
	result = s;
	return result;
}

Shape*
shape_construct (GType object_type)
{
	Shape * self = NULL;
	self = (Shape*) g_object_new (object_type, NULL);
	return self;
}

Shape*
shape_new (void)
{
	return shape_construct (TYPE_SHAPE);
}

static void
shape_class_init (ShapeClass * klass,
                  gpointer klass_data)
{
	shape_parent_class = g_type_class_peek_parent (klass);
	G_OBJECT_CLASS (klass)->finalize = shape_finalize;
}

static void
shape_instance_init (Shape * self,
                     gpointer klass)
{
	self->blocks = NULL;
}

static void
shape_finalize (GObject * obj)
{
	Shape * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_SHAPE, Shape);
	(self->blocks == NULL) ? NULL : (self->blocks = (_g_list_free__g_object_unref0_ (self->blocks), NULL));
	G_OBJECT_CLASS (shape_parent_class)->finalize (obj);
}

static GType
shape_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (ShapeClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) shape_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Shape), 0, (GInstanceInitFunc) shape_instance_init, NULL };
	GType shape_type_id;
	shape_type_id = g_type_register_static (G_TYPE_OBJECT, "Shape", &g_define_type_info, 0);
	return shape_type_id;
}

GType
shape_get_type (void)
{
	static volatile gsize shape_type_id__once = 0;
	if (g_once_init_enter (&shape_type_id__once)) {
		GType shape_type_id;
		shape_type_id = shape_get_type_once ();
		g_once_init_leave (&shape_type_id__once, shape_type_id);
	}
	return shape_type_id__once;
}

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

Game*
game_construct (GType object_type,
                gint lines,
                gint columns,
                gint difficulty,
                gint filled_lines,
                gint fill_prob,
                gboolean pick_difficult_blocks)
{
	Game * self = NULL;
	Block** _tmp0_;
	self = (Game*) g_object_new (object_type, NULL);
	self->difficulty = difficulty;
	self->pick_difficult_blocks = pick_difficult_blocks;
	_tmp0_ = g_new0 (Block*, (columns * lines) + 1);
	self->blocks = (_vala_array_free (self->blocks, self->blocks_length1 * self->blocks_length2, (GDestroyNotify) g_object_unref), NULL);
	self->blocks = _tmp0_;
	self->blocks_length1 = columns;
	self->blocks_length2 = lines;
	{
		gint y = 0;
		y = 0;
		{
			gboolean _tmp1_ = FALSE;
			_tmp1_ = TRUE;
			while (TRUE) {
				gint _tmp3_;
				gint _tmp4_;
				gint32 blank = 0;
				gint _tmp5_;
				gint _tmp6_;
				if (!_tmp1_) {
					gint _tmp2_;
					_tmp2_ = y;
					y = _tmp2_ + 1;
				}
				_tmp1_ = FALSE;
				_tmp3_ = game_get_height (self);
				_tmp4_ = _tmp3_;
				if (!(y < _tmp4_)) {
					break;
				}
				_tmp5_ = game_get_width (self);
				_tmp6_ = _tmp5_;
				blank = g_random_int_range ((gint32) 0, (gint32) _tmp6_);
				{
					gint x = 0;
					x = 0;
					{
						gboolean _tmp7_ = FALSE;
						_tmp7_ = TRUE;
						while (TRUE) {
							gint _tmp9_;
							gint _tmp10_;
							gboolean _tmp11_ = FALSE;
							gboolean _tmp12_ = FALSE;
							gint _tmp13_;
							gint _tmp14_;
							if (!_tmp7_) {
								gint _tmp8_;
								_tmp8_ = x;
								x = _tmp8_ + 1;
							}
							_tmp7_ = FALSE;
							_tmp9_ = game_get_width (self);
							_tmp10_ = _tmp9_;
							if (!(x < _tmp10_)) {
								break;
							}
							_tmp13_ = game_get_height (self);
							_tmp14_ = _tmp13_;
							if (y >= (_tmp14_ - filled_lines)) {
								_tmp12_ = x != ((gint) blank);
							} else {
								_tmp12_ = FALSE;
							}
							if (_tmp12_) {
								_tmp11_ = g_random_int_range ((gint32) 0, (gint32) 10) < ((gint32) fill_prob);
							} else {
								_tmp11_ = FALSE;
							}
							if (_tmp11_) {
								Block** _tmp15_;
								gint _tmp15__length1;
								gint _tmp15__length2;
								Block* _tmp16_;
								Block** _tmp17_;
								gint _tmp17__length1;
								gint _tmp17__length2;
								Block* _tmp18_;
								Block** _tmp19_;
								gint _tmp19__length1;
								gint _tmp19__length2;
								Block* _tmp20_;
								Block** _tmp21_;
								gint _tmp21__length1;
								gint _tmp21__length2;
								Block* _tmp22_;
								_tmp15_ = self->blocks;
								_tmp15__length1 = self->blocks_length1;
								_tmp15__length2 = self->blocks_length2;
								_tmp16_ = block_new ();
								_g_object_unref0 (_tmp15_[(x * _tmp15__length2) + y]);
								_tmp15_[(x * _tmp15__length2) + y] = _tmp16_;
								_tmp17_ = self->blocks;
								_tmp17__length1 = self->blocks_length1;
								_tmp17__length2 = self->blocks_length2;
								_tmp18_ = _tmp17_[(x * _tmp17__length2) + y];
								_tmp18_->x = x;
								_tmp19_ = self->blocks;
								_tmp19__length1 = self->blocks_length1;
								_tmp19__length2 = self->blocks_length2;
								_tmp20_ = _tmp19_[(x * _tmp19__length2) + y];
								_tmp20_->y = y;
								_tmp21_ = self->blocks;
								_tmp21__length1 = self->blocks_length1;
								_tmp21__length2 = self->blocks_length2;
								_tmp22_ = _tmp21_[(x * _tmp21__length2) + y];
								_tmp22_->color = (gint) g_random_int_range ((gint32) 0, (gint32) NCOLORS);
							} else {
								Block** _tmp23_;
								gint _tmp23__length1;
								gint _tmp23__length2;
								_tmp23_ = self->blocks;
								_tmp23__length1 = self->blocks_length1;
								_tmp23__length2 = self->blocks_length2;
								_g_object_unref0 (_tmp23_[(x * _tmp23__length2) + y]);
								_tmp23_[(x * _tmp23__length2) + y] = NULL;
							}
						}
					}
				}
			}
		}
	}
	if (!pick_difficult_blocks) {
		Shape* _tmp24_;
		_tmp24_ = game_pick_random_shape (self);
		_g_object_unref0 (self->next_shape);
		self->next_shape = _tmp24_;
	}
	return self;
}

Game*
game_new (gint lines,
          gint columns,
          gint difficulty,
          gint filled_lines,
          gint fill_prob,
          gboolean pick_difficult_blocks)
{
	return game_construct (TYPE_GAME, lines, columns, difficulty, filled_lines, fill_prob, pick_difficult_blocks);
}

Game*
game_copy (Game* self)
{
	Game* g = NULL;
	Game* _tmp0_;
	Shape* _tmp1_;
	Shape* _tmp5_;
	Game* _tmp24_;
	Game* _tmp25_;
	Game* _tmp26_;
	Game* _tmp27_;
	Game* _tmp28_;
	Game* _tmp29_;
	Game* _tmp30_;
	Game* _tmp31_;
	Game* _tmp32_;
	Game* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = game_new (20, 10, 0, 0, 5, FALSE);
	g = _tmp0_;
	_tmp1_ = self->shape;
	if (_tmp1_ != NULL) {
		Game* _tmp2_;
		Shape* _tmp3_;
		Shape* _tmp4_;
		_tmp2_ = g;
		_tmp3_ = self->shape;
		_tmp4_ = shape_copy (_tmp3_);
		_g_object_unref0 (_tmp2_->shape);
		_tmp2_->shape = _tmp4_;
	}
	_tmp5_ = self->next_shape;
	if (_tmp5_ != NULL) {
		Game* _tmp6_;
		Shape* _tmp7_;
		Shape* _tmp8_;
		_tmp6_ = g;
		_tmp7_ = self->next_shape;
		_tmp8_ = shape_copy (_tmp7_);
		_g_object_unref0 (_tmp6_->next_shape);
		_tmp6_->next_shape = _tmp8_;
	}
	{
		gint x = 0;
		x = 0;
		{
			gboolean _tmp9_ = FALSE;
			_tmp9_ = TRUE;
			while (TRUE) {
				gint _tmp11_;
				gint _tmp12_;
				if (!_tmp9_) {
					gint _tmp10_;
					_tmp10_ = x;
					x = _tmp10_ + 1;
				}
				_tmp9_ = FALSE;
				_tmp11_ = game_get_width (self);
				_tmp12_ = _tmp11_;
				if (!(x < _tmp12_)) {
					break;
				}
				{
					gint y = 0;
					y = 0;
					{
						gboolean _tmp13_ = FALSE;
						_tmp13_ = TRUE;
						while (TRUE) {
							gint _tmp15_;
							gint _tmp16_;
							Block** _tmp17_;
							gint _tmp17__length1;
							gint _tmp17__length2;
							Block* _tmp18_;
							if (!_tmp13_) {
								gint _tmp14_;
								_tmp14_ = y;
								y = _tmp14_ + 1;
							}
							_tmp13_ = FALSE;
							_tmp15_ = game_get_height (self);
							_tmp16_ = _tmp15_;
							if (!(y < _tmp16_)) {
								break;
							}
							_tmp17_ = self->blocks;
							_tmp17__length1 = self->blocks_length1;
							_tmp17__length2 = self->blocks_length2;
							_tmp18_ = _tmp17_[(x * _tmp17__length2) + y];
							if (_tmp18_ != NULL) {
								Game* _tmp19_;
								Block** _tmp20_;
								gint _tmp20__length1;
								gint _tmp20__length2;
								Block** _tmp21_;
								gint _tmp21__length1;
								gint _tmp21__length2;
								Block* _tmp22_;
								Block* _tmp23_;
								_tmp19_ = g;
								_tmp20_ = _tmp19_->blocks;
								_tmp20__length1 = _tmp19_->blocks_length1;
								_tmp20__length2 = _tmp19_->blocks_length2;
								_tmp21_ = self->blocks;
								_tmp21__length1 = self->blocks_length1;
								_tmp21__length2 = self->blocks_length2;
								_tmp22_ = _tmp21_[(x * _tmp21__length2) + y];
								_tmp23_ = block_copy (_tmp22_);
								_g_object_unref0 (_tmp20_[(x * _tmp20__length2) + y]);
								_tmp20_[(x * _tmp20__length2) + y] = _tmp23_;
							}
						}
					}
				}
			}
		}
	}
	_tmp24_ = g;
	_tmp24_->n_lines_destroyed = self->n_lines_destroyed;
	_tmp25_ = g;
	_tmp25_->score = self->score;
	_tmp26_ = g;
	_tmp26_->difficulty = self->difficulty;
	_tmp27_ = g;
	_tmp27_->pick_difficult_blocks = self->pick_difficult_blocks;
	_tmp28_ = g;
	_tmp28_->priv->fast_move_direction = self->priv->fast_move_direction;
	_tmp29_ = g;
	_tmp29_->priv->fast_forward = self->priv->fast_forward;
	_tmp30_ = g;
	_tmp30_->priv->has_started = self->priv->has_started;
	_tmp31_ = g;
	_tmp31_->priv->_paused = self->priv->_paused;
	_tmp32_ = g;
	_tmp32_->game_over = self->game_over;
	result = g;
	return result;
}

void
game_start (Game* self)
{
	g_return_if_fail (self != NULL);
	self->priv->has_started = TRUE;
	game_make_next_shape (self);
	game_add_shape (self);
	game_setup_drop_timer (self);
	g_signal_emit (self, game_signals[GAME_STARTED_SIGNAL], 0);
	g_signal_emit (self, game_signals[GAME_PAUSE_CHANGED_SIGNAL], 0);
}

gboolean
game_move_left (Game* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = game_move_direction (self, -1);
	return result;
}

gboolean
game_move_right (Game* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = game_move_direction (self, 1);
	return result;
}

gboolean
game_stop_moving (Game* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	if (self->game_over) {
		result = FALSE;
		return result;
	}
	if (self->priv->fast_move_timeout != ((guint) 0)) {
		g_source_remove (self->priv->fast_move_timeout);
	}
	self->priv->fast_move_timeout = (guint) 0;
	self->priv->fast_move_direction = 0;
	result = TRUE;
	return result;
}

gboolean
game_rotate_left (Game* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = game_try_rotate (self, 1);
	return result;
}

gboolean
game_rotate_right (Game* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = game_try_rotate (self, -1);
	return result;
}

static gboolean
game_try_rotate (Game* self,
                 gint r_step)
{
	gint vmove = 0;
	Shape* _tmp0_;
	GList* hmoves = NULL;
	gboolean _result_ = FALSE;
	GList* _tmp1_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	if (self->game_over) {
		result = FALSE;
		return result;
	}
	vmove = 0;
	_tmp0_ = self->shape;
	if (_tmp0_->y < 0) {
		vmove = 1;
	}
	hmoves = NULL;
	hmoves = g_list_append (hmoves, (gpointer) ((gintptr) 0));
	hmoves = g_list_append (hmoves, (gpointer) ((gintptr) 1));
	hmoves = g_list_append (hmoves, (gpointer) ((gintptr) -1));
	hmoves = g_list_append (hmoves, (gpointer) ((gintptr) 2));
	hmoves = g_list_append (hmoves, (gpointer) ((gintptr) -2));
	_result_ = FALSE;
	_tmp1_ = hmoves;
	{
		GList* hmove_collection = NULL;
		GList* hmove_it = NULL;
		hmove_collection = _tmp1_;
		for (hmove_it = hmove_collection; hmove_it != NULL; hmove_it = hmove_it->next) {
			gint hmove = 0;
			hmove = (gint) ((gintptr) hmove_it->data);
			{
				_result_ = game_move_shape (self, hmove, vmove, r_step);
				if (_result_) {
					break;
				}
			}
		}
	}
	result = _result_;
	(hmoves == NULL) ? NULL : (hmoves = (g_list_free (hmoves), NULL));
	return result;
}

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

void
game_set_fast_forward (Game* self,
                       gboolean enable)
{
	gboolean _tmp0_ = FALSE;
	g_return_if_fail (self != NULL);
	if (self->priv->fast_forward == enable) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = self->game_over;
	}
	if (_tmp0_) {
		return;
	}
	if (enable) {
		if (!game_move_shape (self, 0, 1, 0)) {
			return;
		}
	}
	self->priv->fast_forward = enable;
	game_setup_drop_timer (self);
}

void
game_drop (Game* self)
{
	Shape* _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->shape;
	if (_tmp0_ == NULL) {
		return;
	}
	while (TRUE) {
		if (!game_move_shape (self, 0, 1, 0)) {
			break;
		}
	}
	game_fall_timeout_cb (self);
}

void
game_hold (Game* self)
{
	gboolean _tmp0_ = FALSE;
	Shape* _tmp1_;
	Shape* removed_shape = NULL;
	Shape* _tmp2_;
	Shape* _tmp3_;
	Shape* _tmp4_;
	g_return_if_fail (self != NULL);
	_tmp1_ = self->shape;
	if (_tmp1_ == NULL) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = self->priv->is_hold_used;
	}
	if (_tmp0_) {
		return;
	}
	self->priv->is_hold_used = TRUE;
	_tmp2_ = self->shape;
	_tmp3_ = _g_object_ref0 (_tmp2_);
	removed_shape = _tmp3_;
	game_remove_shape (self);
	_tmp4_ = self->held_shape;
	if (_tmp4_ == NULL) {
		Shape* _tmp5_;
		Shape* _tmp6_;
		game_add_shape (self);
		_tmp5_ = removed_shape;
		_tmp6_ = game_make_shape (self, _tmp5_->type, 0);
		_g_object_unref0 (self->held_shape);
		self->held_shape = _tmp6_;
		g_signal_emit (self, game_signals[GAME_SHAPE_HELD_SIGNAL], 0);
	} else {
		Shape* _tmp7_;
		Shape* _tmp8_;
		Shape* _tmp9_;
		Shape* _tmp10_;
		_tmp7_ = self->held_shape;
		_tmp8_ = _g_object_ref0 (_tmp7_);
		_g_object_unref0 (self->shape);
		self->shape = _tmp8_;
		_tmp9_ = removed_shape;
		_tmp10_ = game_make_shape (self, _tmp9_->type, 0);
		_g_object_unref0 (self->next_shape);
		self->next_shape = _tmp10_;
		_g_object_unref0 (self->held_shape);
		self->held_shape = NULL;
		game_add_shape_internal (self);
	}
	_g_object_unref0 (removed_shape);
}

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

static gboolean
_game_setup_fast_move_cb_gsource_func (gpointer self)
{
	gboolean result;
	result = game_setup_fast_move_cb ((Game*) self);
	return result;
}

static gboolean
game_move_direction (Game* self,
                     gint direction)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	if (self->game_over) {
		result = FALSE;
		return result;
	}
	if (self->priv->fast_move_direction == direction) {
		result = TRUE;
		return result;
	}
	if (self->priv->fast_move_direction != 0) {
		result = FALSE;
		return result;
	}
	if (self->priv->fast_move_timeout != ((guint) 0)) {
		g_source_remove (self->priv->fast_move_timeout);
	}
	self->priv->fast_move_timeout = (guint) 0;
	self->priv->fast_move_direction = direction;
	if (!game_move (self)) {
		result = FALSE;
		return result;
	}
	self->priv->fast_move_timeout = g_timeout_add_full (G_PRIORITY_DEFAULT, (guint) AUTOMOVE_ACTIVATION_TIME, _game_setup_fast_move_cb_gsource_func, g_object_ref (self), g_object_unref);
	result = TRUE;
	return result;
}

static gboolean
_game_move_gsource_func (gpointer self)
{
	gboolean result;
	result = game_move ((Game*) self);
	return result;
}

static gboolean
game_setup_fast_move_cb (Game* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	if (!game_move (self)) {
		result = FALSE;
		return result;
	}
	self->priv->fast_move_timeout = g_timeout_add_full (G_PRIORITY_DEFAULT, (guint) AUTOMOVE_INTERVAL, _game_move_gsource_func, g_object_ref (self), g_object_unref);
	result = FALSE;
	return result;
}

static gboolean
game_move (Game* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	game_move_shape (self, self->priv->fast_move_direction, 0, 0);
	result = TRUE;
	return result;
}

static gboolean
_game_fall_timeout_cb_gsource_func (gpointer self)
{
	gboolean result;
	result = game_fall_timeout_cb ((Game*) self);
	return result;
}

static void
game_setup_drop_timer (Game* self)
{
	gint timestep = 0;
	gint _tmp0_;
	gint _tmp1_;
	gboolean _tmp2_;
	gboolean _tmp3_;
	g_return_if_fail (self != NULL);
	_tmp0_ = game_get_level (self);
	_tmp1_ = _tmp0_;
	timestep = (gint) round (80 + (800.0 * pow (0.75, (gdouble) (_tmp1_ - 1))));
	timestep = MAX (10, timestep);
	if (self->priv->fast_forward) {
		timestep = 80;
	}
	if (self->priv->drop_timeout != ((guint) 0)) {
		g_source_remove (self->priv->drop_timeout);
	}
	self->priv->drop_timeout = (guint) 0;
	_tmp2_ = game_get_paused (self);
	_tmp3_ = _tmp2_;
	if (!_tmp3_) {
		self->priv->drop_timeout = g_timeout_add_full (G_PRIORITY_DEFAULT, (guint) timestep, _game_fall_timeout_cb_gsource_func, g_object_ref (self), g_object_unref);
	}
}

static gboolean
game_fall_timeout_cb (Game* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	if (!game_move_shape (self, 0, 1, 0)) {
		game_land_shape (self);
		game_add_shape (self);
	}
	result = TRUE;
	return result;
}

static void
game_make_next_shape (Game* self)
{
	g_return_if_fail (self != NULL);
	if (self->pick_difficult_blocks) {
		Shape* _tmp0_;
		_tmp0_ = game_pick_difficult_shapes (self);
		_g_object_unref0 (self->next_shape);
		self->next_shape = _tmp0_;
	} else {
		Shape* _tmp1_;
		_tmp1_ = game_pick_random_shape (self);
		_g_object_unref0 (self->next_shape);
		self->next_shape = _tmp1_;
	}
}

static void
game_add_shape (Game* self)
{
	Shape* _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->next_shape;
	self->next_shape = NULL;
	_g_object_unref0 (self->shape);
	self->shape = _tmp0_;
	game_make_next_shape (self);
	game_add_shape_internal (self);
}

static void
game_add_shape_internal (Game* self)
{
	Shape* _tmp0_;
	GList* _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->shape;
	_tmp1_ = _tmp0_->blocks;
	{
		GList* b_collection = NULL;
		GList* b_it = NULL;
		b_collection = _tmp1_;
		for (b_it = b_collection; b_it != NULL; b_it = b_it->next) {
			Block* _tmp2_;
			Block* b = NULL;
			_tmp2_ = _g_object_ref0 ((Block*) b_it->data);
			b = _tmp2_;
			{
				gint x = 0;
				Shape* _tmp3_;
				Block* _tmp4_;
				gint y = 0;
				Shape* _tmp5_;
				Block* _tmp6_;
				gboolean _tmp7_ = FALSE;
				_tmp3_ = self->shape;
				_tmp4_ = b;
				x = _tmp3_->x + _tmp4_->x;
				_tmp5_ = self->shape;
				_tmp6_ = b;
				y = _tmp5_->y + _tmp6_->y;
				if (y >= 0) {
					Block** _tmp8_;
					gint _tmp8__length1;
					gint _tmp8__length2;
					Block* _tmp9_;
					_tmp8_ = self->blocks;
					_tmp8__length1 = self->blocks_length1;
					_tmp8__length2 = self->blocks_length2;
					_tmp9_ = _tmp8_[(x * _tmp8__length2) + y];
					_tmp7_ = _tmp9_ != NULL;
				} else {
					_tmp7_ = FALSE;
				}
				if (_tmp7_) {
					if (self->priv->drop_timeout != ((guint) 0)) {
						g_source_remove (self->priv->drop_timeout);
					}
					self->priv->drop_timeout = (guint) 0;
					_g_object_unref0 (self->shape);
					self->shape = NULL;
					self->game_over = TRUE;
					g_signal_emit (self, game_signals[GAME_COMPLETE_SIGNAL], 0);
					_g_object_unref0 (b);
					return;
				}
				_g_object_unref0 (b);
			}
		}
	}
	g_signal_emit (self, game_signals[GAME_SHAPE_ADDED_SIGNAL], 0);
}

static Shape*
game_pick_random_shape (Game* self)
{
	gint shapecount = 0;
	gint lowerbound = 0;
	gint* _tmp0_;
	gint _tmp0__length1;
	gint _tmp1_;
	gdouble sum = 0.0;
	gdouble rndshape = 0.0;
	gdouble currentpos = 0.0;
	gint newshape = 0;
	gint* _tmp17_;
	gint _tmp17__length1;
	gint _tmp18_;
	Shape* _tmp19_;
	Shape* result;
	g_return_val_if_fail (self != NULL, NULL);
	shapecount = 7;
	_tmp0_ = self->priv->distshapecount;
	_tmp0__length1 = self->priv->distshapecount_length1;
	_tmp1_ = _tmp0_[0];
	lowerbound = _tmp1_;
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp2_ = FALSE;
			_tmp2_ = TRUE;
			while (TRUE) {
				gint* _tmp4_;
				gint _tmp4__length1;
				gint _tmp5_;
				if (!_tmp2_) {
					gint _tmp3_;
					_tmp3_ = i;
					i = _tmp3_ + 1;
				}
				_tmp2_ = FALSE;
				if (!(i < shapecount)) {
					break;
				}
				_tmp4_ = self->priv->distshapecount;
				_tmp4__length1 = self->priv->distshapecount_length1;
				_tmp5_ = _tmp4_[i];
				if (_tmp5_ < lowerbound) {
					gint* _tmp6_;
					gint _tmp6__length1;
					gint _tmp7_;
					_tmp6_ = self->priv->distshapecount;
					_tmp6__length1 = self->priv->distshapecount_length1;
					_tmp7_ = _tmp6_[i];
					lowerbound = _tmp7_;
				}
			}
		}
	}
	sum = 0.;
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp8_ = FALSE;
			_tmp8_ = TRUE;
			while (TRUE) {
				gint rel = 0;
				gint* _tmp10_;
				gint _tmp10__length1;
				gint _tmp11_;
				gdouble weigh = 0.0;
				if (!_tmp8_) {
					gint _tmp9_;
					_tmp9_ = i;
					i = _tmp9_ + 1;
				}
				_tmp8_ = FALSE;
				if (!(i < shapecount)) {
					break;
				}
				_tmp10_ = self->priv->distshapecount;
				_tmp10__length1 = self->priv->distshapecount_length1;
				_tmp11_ = _tmp10_[i];
				rel = _tmp11_ - lowerbound;
				if (rel < 1) {
					rel = 1;
				}
				weigh = 1. / ((gdouble) (rel * rel));
				sum += weigh;
			}
		}
	}
	rndshape = sum * g_random_double ();
	currentpos = 0.;
	newshape = 0;
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp12_ = FALSE;
			_tmp12_ = TRUE;
			while (TRUE) {
				gint rel = 0;
				gint* _tmp14_;
				gint _tmp14__length1;
				gint _tmp15_;
				gdouble weigh = 0.0;
				gint _tmp16_;
				if (!_tmp12_) {
					gint _tmp13_;
					_tmp13_ = i;
					i = _tmp13_ + 1;
				}
				_tmp12_ = FALSE;
				if (!(i < shapecount)) {
					break;
				}
				_tmp14_ = self->priv->distshapecount;
				_tmp14__length1 = self->priv->distshapecount_length1;
				_tmp15_ = _tmp14_[i];
				rel = _tmp15_ - lowerbound;
				if (rel < 1) {
					rel = 1;
				}
				weigh = 1. / ((gdouble) (rel * rel));
				currentpos += weigh;
				if (rndshape < currentpos) {
					break;
				}
				_tmp16_ = newshape;
				newshape = _tmp16_ + 1;
			}
		}
	}
	_tmp17_ = self->priv->distshapecount;
	_tmp17__length1 = self->priv->distshapecount_length1;
	_tmp18_ = _tmp17_[newshape];
	_tmp17_[newshape] = _tmp18_ + 1;
	_tmp19_ = game_make_shape (self, newshape, 0);
	result = _tmp19_;
	return result;
}

static Shape*
game_pick_difficult_shapes (Game* self)
{
	gint* metrics = NULL;
	gint* _tmp0_;
	gint metrics_length1;
	gint _metrics_size_;
	gint* possible_types = NULL;
	gint* _tmp41_;
	gint possible_types_length1;
	gint _possible_types_size_;
	Shape* new_shape = NULL;
	Shape* _tmp63_;
	gint32 rnd = 0;
	Shape* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = g_new0 (gint, NCOLORS);
	metrics = _tmp0_;
	metrics_length1 = NCOLORS;
	_metrics_size_ = metrics_length1;
	{
		gint type = 0;
		type = 0;
		{
			gboolean _tmp1_ = FALSE;
			_tmp1_ = TRUE;
			while (TRUE) {
				gint* _tmp3_;
				gint _tmp3__length1;
				if (!_tmp1_) {
					gint _tmp2_;
					_tmp2_ = type;
					type = _tmp2_ + 1;
				}
				_tmp1_ = FALSE;
				if (!(type < NCOLORS)) {
					break;
				}
				_tmp3_ = metrics;
				_tmp3__length1 = metrics_length1;
				_tmp3_[type] = -32000;
				{
					gint rotation = 0;
					rotation = 0;
					{
						gboolean _tmp4_ = FALSE;
						_tmp4_ = TRUE;
						while (TRUE) {
							if (!_tmp4_) {
								gint _tmp5_;
								_tmp5_ = rotation;
								rotation = _tmp5_ + 1;
							}
							_tmp4_ = FALSE;
							if (!(rotation < 4)) {
								break;
							}
							{
								gint pos = 0;
								pos = 0;
								{
									gboolean _tmp6_ = FALSE;
									_tmp6_ = TRUE;
									while (TRUE) {
										gint _tmp8_;
										gint _tmp9_;
										Game* g = NULL;
										Game* _tmp10_;
										Game* _tmp11_;
										Game* _tmp12_;
										Shape* _tmp13_;
										gboolean valid_position = FALSE;
										gint orig_lines = 0;
										Game* _tmp18_;
										Game* _tmp19_;
										gint metric = 0;
										Game* _tmp20_;
										gint* _tmp34_;
										gint _tmp34__length1;
										gint _tmp35_;
										Game* _tmp37_;
										if (!_tmp6_) {
											gint _tmp7_;
											_tmp7_ = pos;
											pos = _tmp7_ + 1;
										}
										_tmp6_ = FALSE;
										_tmp8_ = game_get_width (self);
										_tmp9_ = _tmp8_;
										if (!(pos < _tmp9_)) {
											break;
										}
										_tmp10_ = game_copy (self);
										g = _tmp10_;
										_tmp11_ = g;
										_tmp11_->pick_difficult_blocks = FALSE;
										_tmp12_ = g;
										_tmp13_ = game_make_shape (self, type, rotation);
										_g_object_unref0 (_tmp12_->shape);
										_tmp12_->shape = _tmp13_;
										valid_position = TRUE;
										while (TRUE) {
											Game* _tmp14_;
											_tmp14_ = g;
											if (!game_move_shape (_tmp14_, -1, 0, 0)) {
												break;
											}
										}
										{
											gint x = 0;
											x = 0;
											{
												gboolean _tmp15_ = FALSE;
												_tmp15_ = TRUE;
												while (TRUE) {
													Game* _tmp17_;
													if (!_tmp15_) {
														gint _tmp16_;
														_tmp16_ = x;
														x = _tmp16_ + 1;
													}
													_tmp15_ = FALSE;
													if (!(x < pos)) {
														break;
													}
													_tmp17_ = g;
													if (!game_move_shape (_tmp17_, 1, 0, 0)) {
														valid_position = FALSE;
														break;
													}
												}
											}
										}
										if (!valid_position) {
											_g_object_unref0 (g);
											break;
										}
										_tmp18_ = g;
										orig_lines = _tmp18_->n_lines_destroyed;
										_tmp19_ = g;
										game_drop (_tmp19_);
										_tmp20_ = g;
										metric = (_tmp20_->n_lines_destroyed - orig_lines) * 5000;
										{
											gint x = 0;
											x = 0;
											{
												gboolean _tmp21_ = FALSE;
												_tmp21_ = TRUE;
												while (TRUE) {
													gint _tmp23_;
													gint _tmp24_;
													gint y = 0;
													gint _tmp32_;
													gint _tmp33_;
													if (!_tmp21_) {
														gint _tmp22_;
														_tmp22_ = x;
														x = _tmp22_ + 1;
													}
													_tmp21_ = FALSE;
													_tmp23_ = game_get_width (self);
													_tmp24_ = _tmp23_;
													if (!(x < _tmp24_)) {
														break;
													}
													{
														gboolean _tmp25_ = FALSE;
														y = 0;
														_tmp25_ = TRUE;
														while (TRUE) {
															gint _tmp27_;
															gint _tmp28_;
															Game* _tmp29_;
															Block** _tmp30_;
															gint _tmp30__length1;
															gint _tmp30__length2;
															Block* _tmp31_;
															if (!_tmp25_) {
																gint _tmp26_;
																_tmp26_ = y;
																y = _tmp26_ + 1;
															}
															_tmp25_ = FALSE;
															_tmp27_ = game_get_height (self);
															_tmp28_ = _tmp27_;
															if (!(y < _tmp28_)) {
																break;
															}
															_tmp29_ = g;
															_tmp30_ = _tmp29_->blocks;
															_tmp30__length1 = _tmp29_->blocks_length1;
															_tmp30__length2 = _tmp29_->blocks_length2;
															_tmp31_ = _tmp30_[(x * _tmp30__length2) + y];
															if (_tmp31_ != NULL) {
																break;
															}
														}
													}
													_tmp32_ = game_get_height (self);
													_tmp33_ = _tmp32_;
													metric -= 5 * (_tmp33_ - y);
												}
											}
										}
										_tmp34_ = metrics;
										_tmp34__length1 = metrics_length1;
										_tmp35_ = _tmp34_[type];
										if (metric > _tmp35_) {
											gint* _tmp36_;
											gint _tmp36__length1;
											_tmp36_ = metrics;
											_tmp36__length1 = metrics_length1;
											_tmp36_[type] = metric;
										}
										_tmp37_ = g;
										game_stop (_tmp37_);
										_g_object_unref0 (g);
									}
								}
							}
						}
					}
				}
			}
		}
	}
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp38_ = FALSE;
			_tmp38_ = TRUE;
			while (TRUE) {
				gint* _tmp40_;
				gint _tmp40__length1;
				if (!_tmp38_) {
					gint _tmp39_;
					_tmp39_ = i;
					i = _tmp39_ + 1;
				}
				_tmp38_ = FALSE;
				if (!(i < NCOLORS)) {
					break;
				}
				_tmp40_ = metrics;
				_tmp40__length1 = metrics_length1;
				_tmp40_[i] += (gint) g_random_int_range ((gint32) -2, (gint32) 2);
			}
		}
	}
	_tmp41_ = g_new0 (gint, NCOLORS);
	possible_types = _tmp41_;
	possible_types_length1 = NCOLORS;
	_possible_types_size_ = possible_types_length1;
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp42_ = FALSE;
			_tmp42_ = TRUE;
			while (TRUE) {
				gint* _tmp44_;
				gint _tmp44__length1;
				if (!_tmp42_) {
					gint _tmp43_;
					_tmp43_ = i;
					i = _tmp43_ + 1;
				}
				_tmp42_ = FALSE;
				if (!(i < NCOLORS)) {
					break;
				}
				_tmp44_ = possible_types;
				_tmp44__length1 = possible_types_length1;
				_tmp44_[i] = i;
			}
		}
	}
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp45_ = FALSE;
			_tmp45_ = TRUE;
			while (TRUE) {
				if (!_tmp45_) {
					gint _tmp46_;
					_tmp46_ = i;
					i = _tmp46_ + 1;
				}
				_tmp45_ = FALSE;
				if (!(i < NCOLORS)) {
					break;
				}
				{
					gint j = 0;
					j = 0;
					{
						gboolean _tmp47_ = FALSE;
						_tmp47_ = TRUE;
						while (TRUE) {
							gint* _tmp49_;
							gint _tmp49__length1;
							gint* _tmp50_;
							gint _tmp50__length1;
							gint _tmp51_;
							gint _tmp52_;
							gint* _tmp53_;
							gint _tmp53__length1;
							gint* _tmp54_;
							gint _tmp54__length1;
							gint _tmp55_;
							gint _tmp56_;
							if (!_tmp47_) {
								gint _tmp48_;
								_tmp48_ = j;
								j = _tmp48_ + 1;
							}
							_tmp47_ = FALSE;
							if (!(j < (NCOLORS - 1))) {
								break;
							}
							_tmp49_ = metrics;
							_tmp49__length1 = metrics_length1;
							_tmp50_ = possible_types;
							_tmp50__length1 = possible_types_length1;
							_tmp51_ = _tmp50_[j];
							_tmp52_ = _tmp49_[_tmp51_];
							_tmp53_ = metrics;
							_tmp53__length1 = metrics_length1;
							_tmp54_ = possible_types;
							_tmp54__length1 = possible_types_length1;
							_tmp55_ = _tmp54_[j + 1];
							_tmp56_ = _tmp53_[_tmp55_];
							if (_tmp52_ > _tmp56_) {
								gint t = 0;
								gint* _tmp57_;
								gint _tmp57__length1;
								gint _tmp58_;
								gint* _tmp59_;
								gint _tmp59__length1;
								gint* _tmp60_;
								gint _tmp60__length1;
								gint _tmp61_;
								gint* _tmp62_;
								gint _tmp62__length1;
								_tmp57_ = possible_types;
								_tmp57__length1 = possible_types_length1;
								_tmp58_ = _tmp57_[j];
								t = _tmp58_;
								_tmp59_ = possible_types;
								_tmp59__length1 = possible_types_length1;
								_tmp60_ = possible_types;
								_tmp60__length1 = possible_types_length1;
								_tmp61_ = _tmp60_[j + 1];
								_tmp59_[j] = _tmp61_;
								_tmp62_ = possible_types;
								_tmp62__length1 = possible_types_length1;
								_tmp62_[j + 1] = t;
							}
						}
					}
				}
			}
		}
	}
	_tmp63_ = shape_new ();
	new_shape = _tmp63_;
	rnd = g_random_int_range ((gint32) 0, (gint32) 99);
	if (rnd < ((gint32) 75)) {
		gint* _tmp64_;
		gint _tmp64__length1;
		gint _tmp65_;
		Shape* _tmp66_;
		_tmp64_ = possible_types;
		_tmp64__length1 = possible_types_length1;
		_tmp65_ = _tmp64_[0];
		_tmp66_ = game_make_shape (self, _tmp65_, (gint) g_random_int_range ((gint32) 0, (gint32) 4));
		_g_object_unref0 (new_shape);
		new_shape = _tmp66_;
	} else {
		if (rnd < ((gint32) 92)) {
			gint* _tmp67_;
			gint _tmp67__length1;
			gint _tmp68_;
			Shape* _tmp69_;
			_tmp67_ = possible_types;
			_tmp67__length1 = possible_types_length1;
			_tmp68_ = _tmp67_[1];
			_tmp69_ = game_make_shape (self, _tmp68_, (gint) g_random_int_range ((gint32) 0, (gint32) 4));
			_g_object_unref0 (new_shape);
			new_shape = _tmp69_;
		} else {
			if (rnd < ((gint32) 98)) {
				gint* _tmp70_;
				gint _tmp70__length1;
				gint _tmp71_;
				Shape* _tmp72_;
				_tmp70_ = possible_types;
				_tmp70__length1 = possible_types_length1;
				_tmp71_ = _tmp70_[2];
				_tmp72_ = game_make_shape (self, _tmp71_, (gint) g_random_int_range ((gint32) 0, (gint32) 4));
				_g_object_unref0 (new_shape);
				new_shape = _tmp72_;
			} else {
				gint* _tmp73_;
				gint _tmp73__length1;
				gint _tmp74_;
				Shape* _tmp75_;
				_tmp73_ = possible_types;
				_tmp73__length1 = possible_types_length1;
				_tmp74_ = _tmp73_[3];
				_tmp75_ = game_make_shape (self, _tmp74_, (gint) g_random_int_range ((gint32) 0, (gint32) 4));
				_g_object_unref0 (new_shape);
				new_shape = _tmp75_;
			}
		}
	}
	result = new_shape;
	possible_types = (g_free (possible_types), NULL);
	metrics = (g_free (metrics), NULL);
	return result;
}

static Shape*
game_make_shape (Game* self,
                 gint type,
                 gint rotation)
{
	Shape* shape = NULL;
	Shape* _tmp0_;
	Shape* _tmp1_;
	Shape* _tmp2_;
	gint offset = 0;
	Shape* _tmp3_;
	Shape* _tmp4_;
	gint min_width = 0;
	gint max_width = 0;
	gint min_height = 0;
	gint max_height = 0;
	gint block_width = 0;
	Shape* _tmp18_;
	gint _tmp19_;
	gint _tmp20_;
	Shape* _tmp21_;
	Shape* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = shape_new ();
	shape = _tmp0_;
	_tmp1_ = shape;
	_tmp1_->type = type;
	_tmp2_ = shape;
	_tmp2_->rotation = rotation;
	_tmp3_ = shape;
	_tmp4_ = shape;
	offset = (_tmp3_->type * 64) + (_tmp4_->rotation * 16);
	min_width = 4;
	max_width = 0;
	min_height = 4;
	max_height = 0;
	{
		gint x = 0;
		x = 0;
		{
			gboolean _tmp5_ = FALSE;
			_tmp5_ = TRUE;
			while (TRUE) {
				if (!_tmp5_) {
					gint _tmp6_;
					_tmp6_ = x;
					x = _tmp6_ + 1;
				}
				_tmp5_ = FALSE;
				if (!(x < 4)) {
					break;
				}
				{
					gint y = 0;
					y = 0;
					{
						gboolean _tmp7_ = FALSE;
						_tmp7_ = TRUE;
						while (TRUE) {
							gint _tmp9_;
							Block* b = NULL;
							Block* _tmp10_;
							Block* _tmp11_;
							Shape* _tmp12_;
							Block* _tmp13_;
							Block* _tmp14_;
							Shape* _tmp15_;
							Block* _tmp16_;
							Block* _tmp17_;
							if (!_tmp7_) {
								gint _tmp8_;
								_tmp8_ = y;
								y = _tmp8_ + 1;
							}
							_tmp7_ = FALSE;
							if (!(y < 4)) {
								break;
							}
							_tmp9_ = BLOCK_TABLE[(offset + (y * 4)) + x];
							if (_tmp9_ == 0) {
								continue;
							}
							min_width = MIN (x, min_width);
							max_width = MAX (x + 1, max_width);
							min_height = MIN (y, min_height);
							max_height = MAX (y + 1, max_height);
							_tmp10_ = block_new ();
							b = _tmp10_;
							_tmp11_ = b;
							_tmp12_ = shape;
							_tmp11_->color = _tmp12_->type;
							_tmp13_ = b;
							_tmp13_->x = x;
							_tmp14_ = b;
							_tmp14_->y = y;
							_tmp15_ = shape;
							_tmp16_ = b;
							_tmp17_ = _g_object_ref0 (_tmp16_);
							_tmp15_->blocks = g_list_append (_tmp15_->blocks, _tmp17_);
							_g_object_unref0 (b);
						}
					}
				}
			}
		}
	}
	block_width = max_width - min_width;
	_tmp18_ = shape;
	_tmp19_ = game_get_width (self);
	_tmp20_ = _tmp19_;
	_tmp18_->x = ((_tmp20_ - block_width) / 2) - min_width;
	_tmp21_ = shape;
	_tmp21_->y = -min_height;
	result = shape;
	return result;
}

static void
game_land_shape (Game* self)
{
	Shape* _tmp0_;
	GList* _tmp1_;
	gint fall_distance = 0;
	gint* lines = NULL;
	gint* _tmp14_;
	gint lines_length1;
	gint _lines_size_;
	gint n_lines = 0;
	gboolean base_line_destroyed = FALSE;
	gint _tmp29_;
	GList* line_blocks = NULL;
	gint old_level = 0;
	gint _tmp65_;
	gint _tmp66_;
	gint _tmp77_;
	gint _tmp78_;
	gint* _tmp79_;
	gint _tmp79__length1;
	GList* _tmp80_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->shape;
	_tmp1_ = _tmp0_->blocks;
	{
		GList* b_collection = NULL;
		GList* b_it = NULL;
		b_collection = _tmp1_;
		for (b_it = b_collection; b_it != NULL; b_it = b_it->next) {
			Block* _tmp2_;
			Block* b = NULL;
			_tmp2_ = _g_object_ref0 ((Block*) b_it->data);
			b = _tmp2_;
			{
				Block* _tmp3_;
				Block* _tmp4_;
				Shape* _tmp5_;
				Block* _tmp6_;
				Block* _tmp7_;
				Shape* _tmp8_;
				Block** _tmp9_;
				gint _tmp9__length1;
				gint _tmp9__length2;
				Block* _tmp10_;
				Block* _tmp11_;
				Block* _tmp12_;
				Block* _tmp13_;
				_tmp3_ = b;
				_tmp4_ = b;
				_tmp5_ = self->shape;
				_tmp4_->x = _tmp4_->x + _tmp5_->x;
				_tmp6_ = b;
				_tmp7_ = b;
				_tmp8_ = self->shape;
				_tmp7_->y = _tmp7_->y + _tmp8_->y;
				_tmp9_ = self->blocks;
				_tmp9__length1 = self->blocks_length1;
				_tmp9__length2 = self->blocks_length2;
				_tmp10_ = b;
				_tmp11_ = b;
				_tmp12_ = b;
				_tmp13_ = _g_object_ref0 (_tmp12_);
				_g_object_unref0 (_tmp9_[(_tmp10_->x * _tmp9__length2) + _tmp11_->y]);
				_tmp9_[(_tmp10_->x * _tmp9__length2) + _tmp11_->y] = _tmp13_;
				_g_object_unref0 (b);
			}
		}
	}
	fall_distance = 0;
	_tmp14_ = g_new0 (gint, 4);
	lines = _tmp14_;
	lines_length1 = 4;
	_lines_size_ = lines_length1;
	n_lines = 0;
	base_line_destroyed = FALSE;
	{
		gint y = 0;
		gint _tmp15_;
		gint _tmp16_;
		_tmp15_ = game_get_height (self);
		_tmp16_ = _tmp15_;
		y = _tmp16_ - 1;
		{
			gboolean _tmp17_ = FALSE;
			_tmp17_ = TRUE;
			while (TRUE) {
				gboolean explode = FALSE;
				if (!_tmp17_) {
					gint _tmp18_;
					_tmp18_ = y;
					y = _tmp18_ - 1;
				}
				_tmp17_ = FALSE;
				if (!(y >= 0)) {
					break;
				}
				explode = TRUE;
				{
					gint x = 0;
					x = 0;
					{
						gboolean _tmp19_ = FALSE;
						_tmp19_ = TRUE;
						while (TRUE) {
							gint _tmp21_;
							gint _tmp22_;
							Block** _tmp23_;
							gint _tmp23__length1;
							gint _tmp23__length2;
							Block* _tmp24_;
							if (!_tmp19_) {
								gint _tmp20_;
								_tmp20_ = x;
								x = _tmp20_ + 1;
							}
							_tmp19_ = FALSE;
							_tmp21_ = game_get_width (self);
							_tmp22_ = _tmp21_;
							if (!(x < _tmp22_)) {
								break;
							}
							_tmp23_ = self->blocks;
							_tmp23__length1 = self->blocks_length1;
							_tmp23__length2 = self->blocks_length2;
							_tmp24_ = _tmp23_[(x * _tmp23__length2) + y];
							if (_tmp24_ == NULL) {
								explode = FALSE;
								break;
							}
						}
					}
				}
				if (explode) {
					gint _tmp25_;
					gint _tmp26_;
					gint* _tmp27_;
					gint _tmp27__length1;
					gint _tmp28_;
					_tmp25_ = game_get_height (self);
					_tmp26_ = _tmp25_;
					if (y == (_tmp26_ - 1)) {
						base_line_destroyed = TRUE;
					}
					_tmp27_ = lines;
					_tmp27__length1 = lines_length1;
					_tmp27_[n_lines] = y;
					_tmp28_ = n_lines;
					n_lines = _tmp28_ + 1;
				}
			}
		}
	}
	_tmp29_ = n_lines;
	lines = g_renew (gint, lines, n_lines);
	(_tmp29_ > lines_length1) ? memset (lines + lines_length1, 0, sizeof (gint) * (_tmp29_ - lines_length1)) : NULL;
	lines_length1 = _tmp29_;
	_lines_size_ = _tmp29_;
	line_blocks = NULL;
	{
		gint y = 0;
		gint _tmp30_;
		gint _tmp31_;
		_tmp30_ = game_get_height (self);
		_tmp31_ = _tmp30_;
		y = _tmp31_ - 1;
		{
			gboolean _tmp32_ = FALSE;
			_tmp32_ = TRUE;
			while (TRUE) {
				gboolean explode = FALSE;
				if (!_tmp32_) {
					gint _tmp33_;
					_tmp33_ = y;
					y = _tmp33_ - 1;
				}
				_tmp32_ = FALSE;
				if (!(y >= 0)) {
					break;
				}
				explode = TRUE;
				{
					gint x = 0;
					x = 0;
					{
						gboolean _tmp34_ = FALSE;
						_tmp34_ = TRUE;
						while (TRUE) {
							gint _tmp36_;
							gint _tmp37_;
							Block** _tmp38_;
							gint _tmp38__length1;
							gint _tmp38__length2;
							Block* _tmp39_;
							if (!_tmp34_) {
								gint _tmp35_;
								_tmp35_ = x;
								x = _tmp35_ + 1;
							}
							_tmp34_ = FALSE;
							_tmp36_ = game_get_width (self);
							_tmp37_ = _tmp36_;
							if (!(x < _tmp37_)) {
								break;
							}
							_tmp38_ = self->blocks;
							_tmp38__length1 = self->blocks_length1;
							_tmp38__length2 = self->blocks_length2;
							_tmp39_ = _tmp38_[(x * _tmp38__length2) + y];
							if (_tmp39_ == NULL) {
								explode = FALSE;
								break;
							}
						}
					}
				}
				if (explode) {
					gint _tmp48_;
					{
						gint x = 0;
						x = 0;
						{
							gboolean _tmp40_ = FALSE;
							_tmp40_ = TRUE;
							while (TRUE) {
								gint _tmp42_;
								gint _tmp43_;
								Block** _tmp44_;
								gint _tmp44__length1;
								gint _tmp44__length2;
								Block* _tmp45_;
								Block* _tmp46_;
								Block** _tmp47_;
								gint _tmp47__length1;
								gint _tmp47__length2;
								if (!_tmp40_) {
									gint _tmp41_;
									_tmp41_ = x;
									x = _tmp41_ + 1;
								}
								_tmp40_ = FALSE;
								_tmp42_ = game_get_width (self);
								_tmp43_ = _tmp42_;
								if (!(x < _tmp43_)) {
									break;
								}
								_tmp44_ = self->blocks;
								_tmp44__length1 = self->blocks_length1;
								_tmp44__length2 = self->blocks_length2;
								_tmp45_ = _tmp44_[(x * _tmp44__length2) + y];
								_tmp46_ = _g_object_ref0 (_tmp45_);
								line_blocks = g_list_append (line_blocks, _tmp46_);
								_tmp47_ = self->blocks;
								_tmp47__length1 = self->blocks_length1;
								_tmp47__length2 = self->blocks_length2;
								_g_object_unref0 (_tmp47_[(x * _tmp47__length2) + y]);
								_tmp47_[(x * _tmp47__length2) + y] = NULL;
							}
						}
					}
					_tmp48_ = fall_distance;
					fall_distance = _tmp48_ + 1;
				} else {
					if (fall_distance > 0) {
						{
							gint x = 0;
							x = 0;
							{
								gboolean _tmp49_ = FALSE;
								_tmp49_ = TRUE;
								while (TRUE) {
									gint _tmp51_;
									gint _tmp52_;
									Block* b = NULL;
									Block** _tmp53_;
									gint _tmp53__length1;
									gint _tmp53__length2;
									Block* _tmp54_;
									Block* _tmp55_;
									Block* _tmp56_;
									if (!_tmp49_) {
										gint _tmp50_;
										_tmp50_ = x;
										x = _tmp50_ + 1;
									}
									_tmp49_ = FALSE;
									_tmp51_ = game_get_width (self);
									_tmp52_ = _tmp51_;
									if (!(x < _tmp52_)) {
										break;
									}
									_tmp53_ = self->blocks;
									_tmp53__length1 = self->blocks_length1;
									_tmp53__length2 = self->blocks_length2;
									_tmp54_ = _tmp53_[(x * _tmp53__length2) + y];
									_tmp55_ = _g_object_ref0 (_tmp54_);
									b = _tmp55_;
									_tmp56_ = b;
									if (_tmp56_ != NULL) {
										Block* _tmp57_;
										Block* _tmp58_;
										Block** _tmp59_;
										gint _tmp59__length1;
										gint _tmp59__length2;
										Block* _tmp60_;
										Block* _tmp61_;
										Block* _tmp62_;
										Block* _tmp63_;
										Block** _tmp64_;
										gint _tmp64__length1;
										gint _tmp64__length2;
										_tmp57_ = b;
										_tmp58_ = b;
										_tmp58_->y = _tmp58_->y + fall_distance;
										_tmp59_ = self->blocks;
										_tmp59__length1 = self->blocks_length1;
										_tmp59__length2 = self->blocks_length2;
										_tmp60_ = b;
										_tmp61_ = b;
										_tmp62_ = b;
										_tmp63_ = _g_object_ref0 (_tmp62_);
										_g_object_unref0 (_tmp59_[(_tmp60_->x * _tmp59__length2) + _tmp61_->y]);
										_tmp59_[(_tmp60_->x * _tmp59__length2) + _tmp61_->y] = _tmp63_;
										_tmp64_ = self->blocks;
										_tmp64__length1 = self->blocks_length1;
										_tmp64__length2 = self->blocks_length2;
										_g_object_unref0 (_tmp64_[(x * _tmp64__length2) + y]);
										_tmp64_[(x * _tmp64__length2) + y] = NULL;
									}
									_g_object_unref0 (b);
								}
							}
						}
					}
				}
			}
		}
	}
	_tmp65_ = game_get_level (self);
	_tmp66_ = _tmp65_;
	old_level = _tmp66_;
	self->n_lines_destroyed = self->n_lines_destroyed + n_lines;
	switch (n_lines) {
		case 0:
		{
			break;
		}
		case 1:
		{
			gint _tmp67_;
			gint _tmp68_;
			_tmp67_ = game_get_level (self);
			_tmp68_ = _tmp67_;
			self->score = self->score + (40 * _tmp68_);
			break;
		}
		case 2:
		{
			gint _tmp69_;
			gint _tmp70_;
			_tmp69_ = game_get_level (self);
			_tmp70_ = _tmp69_;
			self->score = self->score + (100 * _tmp70_);
			break;
		}
		case 3:
		{
			gint _tmp71_;
			gint _tmp72_;
			_tmp71_ = game_get_level (self);
			_tmp72_ = _tmp71_;
			self->score = self->score + (300 * _tmp72_);
			break;
		}
		case 4:
		{
			gint _tmp73_;
			gint _tmp74_;
			_tmp73_ = game_get_level (self);
			_tmp74_ = _tmp73_;
			self->score = self->score + (1200 * _tmp74_);
			break;
		}
		default:
		break;
	}
	if (base_line_destroyed) {
		gint _tmp75_;
		gint _tmp76_;
		_tmp75_ = game_get_level (self);
		_tmp76_ = _tmp75_;
		self->score = self->score + ((100 * _tmp76_) * n_lines);
	}
	_tmp77_ = game_get_level (self);
	_tmp78_ = _tmp77_;
	if (_tmp78_ != old_level) {
		game_setup_drop_timer (self);
	}
	_tmp79_ = lines;
	_tmp79__length1 = lines_length1;
	_tmp80_ = line_blocks;
	g_signal_emit (self, game_signals[GAME_SHAPE_LANDED_SIGNAL], 0, _tmp79_, (gint) _tmp79__length1, _tmp80_);
	_g_object_unref0 (self->shape);
	self->shape = NULL;
	self->priv->is_hold_used = FALSE;
	(line_blocks == NULL) ? NULL : (line_blocks = (_g_list_free__g_object_unref0_ (line_blocks), NULL));
	lines = (g_free (lines), NULL);
}

static gboolean
game_move_shape (Game* self,
                 gint x_step,
                 gint y_step,
                 gint r_step)
{
	Shape* _tmp0_;
	gboolean can_move = FALSE;
	Shape* _tmp1_;
	GList* _tmp2_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->shape;
	if (_tmp0_ == NULL) {
		result = FALSE;
		return result;
	}
	game_rotate_shape (self, r_step);
	can_move = TRUE;
	_tmp1_ = self->shape;
	_tmp2_ = _tmp1_->blocks;
	{
		GList* b_collection = NULL;
		GList* b_it = NULL;
		b_collection = _tmp2_;
		for (b_it = b_collection; b_it != NULL; b_it = b_it->next) {
			Block* _tmp3_;
			Block* b = NULL;
			_tmp3_ = _g_object_ref0 ((Block*) b_it->data);
			b = _tmp3_;
			{
				gint x = 0;
				Shape* _tmp4_;
				Block* _tmp5_;
				gint y = 0;
				Shape* _tmp6_;
				Block* _tmp7_;
				gboolean _tmp8_ = FALSE;
				gboolean _tmp9_ = FALSE;
				gboolean _tmp10_ = FALSE;
				_tmp4_ = self->shape;
				_tmp5_ = b;
				x = (_tmp4_->x + x_step) + _tmp5_->x;
				_tmp6_ = self->shape;
				_tmp7_ = b;
				y = (_tmp6_->y + y_step) + _tmp7_->y;
				if (x < 0) {
					_tmp10_ = TRUE;
				} else {
					gint _tmp11_;
					gint _tmp12_;
					_tmp11_ = game_get_width (self);
					_tmp12_ = _tmp11_;
					_tmp10_ = x >= _tmp12_;
				}
				if (_tmp10_) {
					_tmp9_ = TRUE;
				} else {
					gint _tmp13_;
					gint _tmp14_;
					_tmp13_ = game_get_height (self);
					_tmp14_ = _tmp13_;
					_tmp9_ = y >= _tmp14_;
				}
				if (_tmp9_) {
					_tmp8_ = TRUE;
				} else {
					gboolean _tmp15_ = FALSE;
					if (y >= 0) {
						Block** _tmp16_;
						gint _tmp16__length1;
						gint _tmp16__length2;
						Block* _tmp17_;
						_tmp16_ = self->blocks;
						_tmp16__length1 = self->blocks_length1;
						_tmp16__length2 = self->blocks_length2;
						_tmp17_ = _tmp16_[(x * _tmp16__length2) + y];
						_tmp15_ = _tmp17_ != NULL;
					} else {
						_tmp15_ = FALSE;
					}
					_tmp8_ = _tmp15_;
				}
				if (_tmp8_) {
					can_move = FALSE;
					_g_object_unref0 (b);
					break;
				}
				_g_object_unref0 (b);
			}
		}
	}
	if (can_move) {
		Shape* _tmp18_;
		Shape* _tmp19_;
		Shape* _tmp20_;
		Shape* _tmp21_;
		_tmp18_ = self->shape;
		_tmp19_ = self->shape;
		_tmp19_->x = _tmp19_->x + x_step;
		_tmp20_ = self->shape;
		_tmp21_ = self->shape;
		_tmp21_->y = _tmp21_->y + y_step;
		if (x_step != 0) {
			g_signal_emit (self, game_signals[GAME_SHAPE_MOVED_SIGNAL], 0);
		}
		if (y_step != 0) {
			g_signal_emit (self, game_signals[GAME_SHAPE_DROPPED_SIGNAL], 0);
		}
		if (r_step != 0) {
			g_signal_emit (self, game_signals[GAME_SHAPE_ROTATED_SIGNAL], 0);
		}
	} else {
		game_rotate_shape (self, -r_step);
	}
	result = can_move;
	return result;
}

static void
game_rotate_shape (Game* self,
                   gint r_step)
{
	gint r = 0;
	Shape* _tmp0_;
	Shape* _tmp1_;
	Shape* _tmp2_;
	GList* b = NULL;
	Shape* _tmp3_;
	GList* _tmp4_;
	gint offset = 0;
	Shape* _tmp5_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->shape;
	r = _tmp0_->rotation + r_step;
	if (r < 0) {
		r += 4;
	}
	if (r >= 4) {
		r -= 4;
	}
	_tmp1_ = self->shape;
	if (r == _tmp1_->rotation) {
		return;
	}
	_tmp2_ = self->shape;
	_tmp2_->rotation = r;
	_tmp3_ = self->shape;
	_tmp4_ = _tmp3_->blocks;
	b = _tmp4_;
	_tmp5_ = self->shape;
	offset = (_tmp5_->type * 64) + (r * 16);
	{
		gint x = 0;
		x = 0;
		{
			gboolean _tmp6_ = FALSE;
			_tmp6_ = TRUE;
			while (TRUE) {
				if (!_tmp6_) {
					gint _tmp7_;
					_tmp7_ = x;
					x = _tmp7_ + 1;
				}
				_tmp6_ = FALSE;
				if (!(x < 4)) {
					break;
				}
				{
					gint y = 0;
					y = 0;
					{
						gboolean _tmp8_ = FALSE;
						_tmp8_ = TRUE;
						while (TRUE) {
							gint _tmp10_;
							if (!_tmp8_) {
								gint _tmp9_;
								_tmp9_ = y;
								y = _tmp9_ + 1;
							}
							_tmp8_ = FALSE;
							if (!(y < 4)) {
								break;
							}
							_tmp10_ = BLOCK_TABLE[(offset + (y * 4)) + x];
							if (_tmp10_ != 0) {
								GList* _tmp11_;
								gconstpointer _tmp12_;
								GList* _tmp13_;
								gconstpointer _tmp14_;
								GList* _tmp15_;
								GList* _tmp16_;
								_tmp11_ = b;
								_tmp12_ = _tmp11_->data;
								((Block*) _tmp12_)->x = x;
								_tmp13_ = b;
								_tmp14_ = _tmp13_->data;
								((Block*) _tmp14_)->y = y;
								_tmp15_ = b;
								_tmp16_ = _tmp15_->next;
								b = _tmp16_;
							}
						}
					}
				}
			}
		}
	}
}

static void
game_remove_shape (Game* self)
{
	Shape* _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->shape;
	if (_tmp0_ == NULL) {
		return;
	}
	_g_object_unref0 (self->shape);
	self->shape = NULL;
	g_signal_emit (self, game_signals[GAME_SHAPE_REMOVED_SIGNAL], 0);
}

gint
game_get_width (Game* self)
{
	gint result;
	Block** _tmp0_;
	gint _tmp0__length1;
	gint _tmp0__length2;
	gint _tmp1_;
	g_return_val_if_fail (self != NULL, -1);
	_tmp0_ = self->blocks;
	_tmp0__length1 = self->blocks_length1;
	_tmp0__length2 = self->blocks_length2;
	_tmp1_ = _tmp0__length1;
	result = _tmp1_;
	return result;
}

gint
game_get_height (Game* self)
{
	gint result;
	Block** _tmp0_;
	gint _tmp0__length1;
	gint _tmp0__length2;
	gint _tmp1_;
	g_return_val_if_fail (self != NULL, -1);
	_tmp0_ = self->blocks;
	_tmp0__length1 = self->blocks_length1;
	_tmp0__length2 = self->blocks_length2;
	_tmp1_ = _tmp0__length2;
	result = _tmp1_;
	return result;
}

gint
game_get_level (Game* self)
{
	gint result;
	g_return_val_if_fail (self != NULL, -1);
	result = (self->difficulty + 1) + (self->n_lines_destroyed / 10);
	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;
	g_return_if_fail (self != NULL);
	self->priv->_paused = value;
	if (self->priv->has_started) {
		_tmp0_ = !self->game_over;
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		game_setup_drop_timer (self);
	}
	g_signal_emit (self, game_signals[GAME_PAUSE_CHANGED_SIGNAL], 0);
	g_object_notify_by_pspec ((GObject *) self, game_properties[GAME_PAUSED_PROPERTY]);
}

gint
game_get_shadow_y (Game* self)
{
	gint result;
	Shape* _tmp0_;
	gint d = 0;
	Game* g = NULL;
	Game* _tmp1_;
	Shape* _tmp4_;
	g_return_val_if_fail (self != NULL, -1);
	_tmp0_ = self->shape;
	if (_tmp0_ == NULL) {
		result = 0;
		return result;
	}
	d = 0;
	_tmp1_ = game_copy (self);
	g = _tmp1_;
	while (TRUE) {
		Game* _tmp2_;
		gint _tmp3_;
		_tmp2_ = g;
		if (!game_move_shape (_tmp2_, 0, 1, 0)) {
			break;
		}
		_tmp3_ = d;
		d = _tmp3_ + 1;
	}
	_tmp4_ = self->shape;
	result = _tmp4_->y + d;
	_g_object_unref0 (g);
	return result;
}

static void
g_cclosure_user_marshal_VOID__POINTER_INT_POINTER (GClosure * closure,
                                                   GValue * return_value,
                                                   guint n_param_values,
                                                   const GValue * param_values,
                                                   gpointer invocation_hint,
                                                   gpointer marshal_data)
{
	typedef void (*GMarshalFunc_VOID__POINTER_INT_POINTER) (gpointer data1, gpointer arg_1, gint arg_2, gpointer arg_3, gpointer data2);
	register GMarshalFunc_VOID__POINTER_INT_POINTER callback;
	register GCClosure * cc;
	register gpointer data1;
	register gpointer data2;
	cc = (GCClosure *) closure;
	g_return_if_fail (n_param_values == 4);
	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__POINTER_INT_POINTER) (marshal_data ? marshal_data : cc->callback);
	callback (data1, g_value_get_pointer (param_values + 1), g_value_get_int (param_values + 2), g_value_get_pointer (param_values + 3), data2);
}

static void
game_class_init (GameClass * klass,
                 gpointer klass_data)
{
	game_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &Game_private_offset);
	G_OBJECT_CLASS (klass)->get_property = _vala_game_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_game_set_property;
	G_OBJECT_CLASS (klass)->finalize = game_finalize;
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_WIDTH_PROPERTY, game_properties[GAME_WIDTH_PROPERTY] = g_param_spec_int ("width", "width", "width", G_MININT, G_MAXINT, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_HEIGHT_PROPERTY, game_properties[GAME_HEIGHT_PROPERTY] = g_param_spec_int ("height", "height", "height", G_MININT, G_MAXINT, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_LEVEL_PROPERTY, game_properties[GAME_LEVEL_PROPERTY] = g_param_spec_int ("level", "level", "level", G_MININT, G_MAXINT, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_PAUSED_PROPERTY, game_properties[GAME_PAUSED_PROPERTY] = g_param_spec_boolean ("paused", "paused", "paused", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAME_SHADOW_Y_PROPERTY, game_properties[GAME_SHADOW_Y_PROPERTY] = g_param_spec_int ("shadow-y", "shadow-y", "shadow-y", G_MININT, G_MAXINT, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	game_signals[GAME_STARTED_SIGNAL] = g_signal_new ("started", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	game_signals[GAME_SHAPE_ADDED_SIGNAL] = g_signal_new ("shape-added", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	game_signals[GAME_SHAPE_HELD_SIGNAL] = g_signal_new ("shape-held", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	game_signals[GAME_SHAPE_MOVED_SIGNAL] = g_signal_new ("shape-moved", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	game_signals[GAME_SHAPE_REMOVED_SIGNAL] = g_signal_new ("shape-removed", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	game_signals[GAME_SHAPE_DROPPED_SIGNAL] = g_signal_new ("shape-dropped", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	game_signals[GAME_SHAPE_ROTATED_SIGNAL] = g_signal_new ("shape-rotated", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	game_signals[GAME_SHAPE_LANDED_SIGNAL] = g_signal_new ("shape-landed", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__POINTER_INT_POINTER, G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_INT, G_TYPE_POINTER);
	game_signals[GAME_PAUSE_CHANGED_SIGNAL] = g_signal_new ("pause-changed", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	game_signals[GAME_COMPLETE_SIGNAL] = g_signal_new ("complete", TYPE_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}

static void
game_instance_init (Game * self,
                    gpointer klass)
{
	gint* _tmp0_;
	self->priv = game_get_instance_private (self);
	self->shape = NULL;
	self->next_shape = NULL;
	self->held_shape = NULL;
	self->n_lines_destroyed = 0;
	self->score = 0;
	self->difficulty = 0;
	self->pick_difficult_blocks = FALSE;
	self->priv->fast_move_direction = 0;
	self->priv->fast_move_timeout = (guint) 0;
	self->priv->fast_forward = FALSE;
	self->priv->drop_timeout = (guint) 0;
	self->priv->has_started = FALSE;
	self->priv->is_hold_used = FALSE;
	self->priv->_paused = FALSE;
	self->game_over = FALSE;
	_tmp0_ = g_new0 (gint, 7);
	_tmp0_[0] = 0;
	_tmp0_[1] = 0;
	_tmp0_[2] = 0;
	_tmp0_[3] = 0;
	_tmp0_[4] = 0;
	_tmp0_[5] = 0;
	_tmp0_[6] = 0;
	self->priv->distshapecount = _tmp0_;
	self->priv->distshapecount_length1 = 7;
	self->priv->_distshapecount_size_ = self->priv->distshapecount_length1;
}

static void
game_finalize (GObject * obj)
{
	Game * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_GAME, Game);
	_g_object_unref0 (self->shape);
	_g_object_unref0 (self->next_shape);
	_g_object_unref0 (self->held_shape);
	self->blocks = (_vala_array_free (self->blocks, self->blocks_length1 * self->blocks_length2, (GDestroyNotify) g_object_unref), NULL);
	self->priv->distshapecount = (g_free (self->priv->distshapecount), NULL);
	G_OBJECT_CLASS (game_parent_class)->finalize (obj);
}

static GType
game_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (GameClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) game_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Game), 0, (GInstanceInitFunc) game_instance_init, NULL };
	GType game_type_id;
	game_type_id = g_type_register_static (G_TYPE_OBJECT, "Game", &g_define_type_info, 0);
	Game_private_offset = g_type_add_instance_private (game_type_id, sizeof (GamePrivate));
	return game_type_id;
}

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

static void
_vala_game_get_property (GObject * object,
                         guint property_id,
                         GValue * value,
                         GParamSpec * pspec)
{
	Game * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_GAME, Game);
	switch (property_id) {
		case GAME_WIDTH_PROPERTY:
		g_value_set_int (value, game_get_width (self));
		break;
		case GAME_HEIGHT_PROPERTY:
		g_value_set_int (value, game_get_height (self));
		break;
		case GAME_LEVEL_PROPERTY:
		g_value_set_int (value, game_get_level (self));
		break;
		case GAME_PAUSED_PROPERTY:
		g_value_set_boolean (value, game_get_paused (self));
		break;
		case GAME_SHADOW_Y_PROPERTY:
		g_value_set_int (value, game_get_shadow_y (self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_game_set_property (GObject * object,
                         guint property_id,
                         const GValue * value,
                         GParamSpec * pspec)
{
	Game * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_GAME, Game);
	switch (property_id) {
		case GAME_PAUSED_PROPERTY:
		game_set_paused (self, g_value_get_boolean (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

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

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

