/* computer-player.c generated by valac 0.38.1.9-3e35a, the Vala compiler
 * generated from computer-player.vala, do not modify */

/* -*- Mode: vala; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 *
 * Copyright (C) 2010-2013 Robert Ancell
 *
 * This file is part of Iagno.
 *
 * Iagno 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.
 *
 * Iagno 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 Iagno. If not, see <http://www.gnu.org/licenses/>.
 */

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


#define TYPE_COMPUTER_PLAYER (computer_player_get_type ())
#define COMPUTER_PLAYER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_COMPUTER_PLAYER, ComputerPlayer))
#define COMPUTER_PLAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_COMPUTER_PLAYER, ComputerPlayerClass))
#define IS_COMPUTER_PLAYER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_COMPUTER_PLAYER))
#define IS_COMPUTER_PLAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_COMPUTER_PLAYER))
#define COMPUTER_PLAYER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_COMPUTER_PLAYER, ComputerPlayerClass))

typedef struct _ComputerPlayer ComputerPlayer;
typedef struct _ComputerPlayerClass ComputerPlayerClass;
typedef struct _ComputerPlayerPrivate ComputerPlayerPrivate;

#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;
enum  {
	COMPUTER_PLAYER_DUMMY_PROPERTY,
	COMPUTER_PLAYER_LAST_PROPERTY
};
static GParamSpec* computer_player_properties[COMPUTER_PLAYER_LAST_PROPERTY];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))
typedef struct _Block1Data Block1Data;
#define _g_thread_unref0(var) ((var == NULL) ? NULL : (var = (g_thread_unref (var), NULL)))
#define _g_timer_destroy0(var) ((var == NULL) ? NULL : (var = (g_timer_destroy (var), NULL)))
typedef struct _ComputerPlayerMoveAsyncData ComputerPlayerMoveAsyncData;

#define COMPUTER_PLAYER_TYPE_POSSIBLE_MOVE (computer_player_possible_move_get_type ())
typedef struct _ComputerPlayerPossibleMove ComputerPlayerPossibleMove;
#define _computer_player_possible_move_free0(var) ((var == NULL) ? NULL : (var = (computer_player_possible_move_free (var), NULL)))
#define __g_list_free__computer_player_possible_move_free0_0(var) ((var == NULL) ? NULL : (var = (_g_list_free__computer_player_possible_move_free0_ (var), NULL)))

#define TYPE_PLAYER (player_get_type ())
#define _g_list_free0(var) ((var == NULL) ? NULL : (var = (g_list_free (var), NULL)))
#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);

struct _ComputerPlayer {
	GObject parent_instance;
	ComputerPlayerPrivate * priv;
};

struct _ComputerPlayerClass {
	GObjectClass parent_class;
};

struct _ComputerPlayerPrivate {
	Game* game;
	gint difficulty_level;
	guint pending_move_id;
	gboolean _move_pending;
	GRecMutex _move_pending_mutex;
};

struct _Block1Data {
	int _ref_count_;
	ComputerPlayer* self;
	gint x;
	gint y;
	gpointer _async_data_;
};

struct _ComputerPlayerMoveAsyncData {
	int _state_;
	GObject* _source_object_;
	GAsyncResult* _res_;
	GTask* _async_result;
	GAsyncReadyCallback _callback_;
	gboolean _task_complete_;
	ComputerPlayer* self;
	gdouble delay_seconds;
	Block1Data* _data1_;
	GTimer* timer;
	GTimer* _tmp0_;
	gboolean _tmp1_;
	gboolean _tmp2_;
	GTimer* _tmp3_;
	GThread* _tmp4_;
	GThread* _tmp5_;
	GTimer* _tmp6_;
	gboolean _tmp7_;
	gboolean _tmp8_;
	GTimer* _tmp9_;
	gdouble _tmp10_;
	gdouble _tmp11_;
	gdouble _tmp12_;
	GTimer* _tmp13_;
	gdouble _tmp14_;
	guint _tmp15_;
};

struct _ComputerPlayerPossibleMove {
	gint x;
	gint y;
	gint n_tiles;
};

typedef enum  {
	PLAYER_NONE,
	PLAYER_DARK,
	PLAYER_LIGHT
} Player;


static gpointer computer_player_parent_class = NULL;

GType computer_player_get_type (void) G_GNUC_CONST;
GType game_get_type (void) G_GNUC_CONST;
#define COMPUTER_PLAYER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_COMPUTER_PLAYER, ComputerPlayerPrivate))
#define COMPUTER_PLAYER_POSITIVE_INFINITY 10000
#define COMPUTER_PLAYER_NEGATIVE_INFINITY -10000
ComputerPlayer* computer_player_new (Game* game, gint difficulty_level);
ComputerPlayer* computer_player_construct (GType object_type, Game* game, gint difficulty_level);
static void computer_player_complete_move (ComputerPlayer* self, gint x, gint y);
gint game_place_tile (Game* self, gint x, gint y, gboolean apply);
gchar* game_to_string (Game* self);
void computer_player_move (ComputerPlayer* self);
static void computer_player_run_search (ComputerPlayer* self, gint* x, gint* y);
static void computer_player_move_async_data_free (gpointer _data);
static void computer_player_move_async_async_ready_wrapper (GObject *source_object, GAsyncResult *res, void *user_data);
void computer_player_move_async (ComputerPlayer* self, gdouble delay_seconds, GAsyncReadyCallback _callback_, gpointer _user_data_);
void computer_player_move_finish (ComputerPlayer* self, GAsyncResult* _res_);
static gboolean computer_player_move_async_co (ComputerPlayerMoveAsyncData* _data_);
static Block1Data* block1_data_ref (Block1Data* _data1_);
static void block1_data_unref (void * _userdata_);
static gboolean computer_player_get_move_pending (ComputerPlayer* self);
static gboolean _computer_player_move_async_co_gsource_func (gpointer self);
static void* __lambda4_ (Block1Data* _data1_);
static void computer_player_set_move_pending (ComputerPlayer* self, gboolean value);
static gpointer ___lambda4__gthread_func (gpointer self);
static gboolean __lambda5_ (Block1Data* _data1_);
static gboolean ___lambda5__gsource_func (gpointer self);
void computer_player_cancel_move (ComputerPlayer* self);
gboolean game_get_current_player_can_move (Game* self);
gint game_get_size (Game* self);
gint game_get_n_tiles (Game* self);
gint game_get_initial_number_of_tiles (Game* self);
static void computer_player_random_select (Game* g, gint* move_x, gint* move_y);
Game* game_new_copy (Game* game);
Game* game_construct_copy (GType object_type, Game* game);
static GType computer_player_possible_move_get_type (void) G_GNUC_CONST G_GNUC_UNUSED;
static ComputerPlayerPossibleMove* computer_player_possible_move_dup (const ComputerPlayerPossibleMove* self);
static void computer_player_possible_move_free (ComputerPlayerPossibleMove* self);
static void computer_player_get_possible_moves_sorted (ComputerPlayer* self, Game* g, GList* * moves);
static gint computer_player_search (ComputerPlayer* self, Game* g, gint depth, gint a, gint b);
void game_undo (Game* self, gint count);
static void _computer_player_possible_move_free0_ (gpointer var);
static inline void _g_list_free__computer_player_possible_move_free0_ (GList* self);
gboolean game_get_is_complete (Game* self);
gint game_get_n_current_tiles (Game* self);
gint game_get_n_opponent_tiles (Game* self);
static gint computer_player_calculate_heuristic (ComputerPlayer* self, Game* g);
void game_pass (Game* self);
static void computer_player_possible_move_init (ComputerPlayerPossibleMove *self, gint x, gint y, gint n_tiles);
static gint computer_player_compare_move (ComputerPlayerPossibleMove* a, ComputerPlayerPossibleMove* b);
static gint _computer_player_compare_move_gcompare_func (gconstpointer a, gconstpointer b);
static gint computer_player_eval_heuristic (Game* g);
static gint computer_player_around (Game* g);
GType player_get_type (void) G_GNUC_CONST;
Player game_get_owner (Game* self, gint x, gint y);
Player game_get_current_color (Game* self);
static gint computer_player_is_empty (Game* g, gint x, gint y);
gboolean game_is_valid_location (Game* self, gint x, gint y);
gboolean game_can_place (Game* self, gint x, gint y, Player color);
static void computer_player_finalize (GObject * obj);
static void _vala_computer_player_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec);
static void _vala_computer_player_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec);
static void _vala_clear_GMutex (GMutex * mutex);
static void _vala_clear_GRecMutex (GRecMutex * mutex);
static void _vala_clear_GRWLock (GRWLock * mutex);
static void _vala_clear_GCond (GCond * mutex);

static const gint COMPUTER_PLAYER_heuristic[64] = {65, -3, 6, 4, 4, 6, -3, 65, -3, -29, 3, 1, 1, 3, -29, -3, 6, 3, 5, 3, 3, 5, 3, 6, 4, 1, 3, 1, 1, 3, 1, 4, 4, 1, 3, 1, 1, 3, 1, 4, 6, 3, 5, 3, 3, 5, 3, 6, -3, -29, 3, 1, 1, 3, -29, -3, 65, -3, 6, 4, 4, 6, -3, 65};

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


ComputerPlayer* computer_player_construct (GType object_type, Game* game, gint difficulty_level) {
	ComputerPlayer * self = NULL;
	Game* _tmp0_;
	Game* _tmp1_;
	gint _tmp2_;
	g_return_val_if_fail (game != NULL, NULL);
	self = (ComputerPlayer*) g_object_new (object_type, NULL);
	_tmp0_ = game;
	_tmp1_ = _g_object_ref0 (_tmp0_);
	_g_object_unref0 (self->priv->game);
	self->priv->game = _tmp1_;
	_tmp2_ = difficulty_level;
	self->priv->difficulty_level = _tmp2_;
	return self;
}


ComputerPlayer* computer_player_new (Game* game, gint difficulty_level) {
	return computer_player_construct (TYPE_COMPUTER_PLAYER, game, difficulty_level);
}


static void computer_player_complete_move (ComputerPlayer* self, gint x, gint y) {
	Game* _tmp0_;
	gint _tmp1_;
	gint _tmp2_;
	gint _tmp3_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->game;
	_tmp1_ = x;
	_tmp2_ = y;
	_tmp3_ = game_place_tile (_tmp0_, _tmp1_, _tmp2_, TRUE);
	if (_tmp3_ == 0) {
		gint _tmp4_;
		gint _tmp5_;
		Game* _tmp6_;
		gchar* _tmp7_;
		gchar* _tmp8_;
		_tmp4_ = x;
		_tmp5_ = y;
		_tmp6_ = self->priv->game;
		_tmp7_ = game_to_string (_tmp6_);
		_tmp8_ = _tmp7_;
		g_critical ("computer-player.vala:95: Computer chose an invalid move: %d,%d\n%s", _tmp4_, _tmp5_, _tmp8_);
		_g_free0 (_tmp8_);
		g_assert_not_reached ();
	}
}


void computer_player_move (ComputerPlayer* self) {
	gint x = 0;
	gint y = 0;
	gint _tmp0_;
	gint _tmp1_;
	g_return_if_fail (self != NULL);
	x = 0;
	y = 0;
	computer_player_run_search (self, &x, &y);
	_tmp0_ = x;
	_tmp1_ = y;
	computer_player_complete_move (self, _tmp0_, _tmp1_);
}


static void computer_player_move_async_data_free (gpointer _data) {
	ComputerPlayerMoveAsyncData* _data_;
	_data_ = _data;
	_g_object_unref0 (_data_->self);
	g_slice_free (ComputerPlayerMoveAsyncData, _data_);
}


static void computer_player_move_async_async_ready_wrapper (GObject *source_object, GAsyncResult *res, void *user_data) {
	ComputerPlayerMoveAsyncData* _task_data_;
	_task_data_ = g_task_get_task_data (G_TASK (res));
	if (_task_data_->_callback_ != NULL) {
		_task_data_->_callback_ (source_object, res, user_data);
	}
	_task_data_->_task_complete_ = TRUE;
}


void computer_player_move_async (ComputerPlayer* self, gdouble delay_seconds, GAsyncReadyCallback _callback_, gpointer _user_data_) {
	ComputerPlayerMoveAsyncData* _data_;
	ComputerPlayer* _tmp0_;
	gdouble _tmp1_;
	_data_ = g_slice_new0 (ComputerPlayerMoveAsyncData);
	_data_->_callback_ = _callback_;
	_data_->_async_result = g_task_new (G_OBJECT (self), NULL, computer_player_move_async_async_ready_wrapper, _user_data_);
	if (_callback_ == NULL) {
		_data_->_task_complete_ = TRUE;
	}
	g_task_set_task_data (_data_->_async_result, _data_, computer_player_move_async_data_free);
	_tmp0_ = _g_object_ref0 (self);
	_data_->self = _tmp0_;
	_tmp1_ = delay_seconds;
	_data_->delay_seconds = _tmp1_;
	computer_player_move_async_co (_data_);
}


void computer_player_move_finish (ComputerPlayer* self, GAsyncResult* _res_) {
	ComputerPlayerMoveAsyncData* _data_;
	_data_ = g_task_propagate_pointer (G_TASK (_res_), NULL);
}


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


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


static gboolean _computer_player_move_async_co_gsource_func (gpointer self) {
	gboolean result;
	result = computer_player_move_async_co (self);
	return result;
}


static void* __lambda4_ (Block1Data* _data1_) {
	ComputerPlayer* self;
	void* result = NULL;
	self = _data1_->self;
	computer_player_set_move_pending (self, TRUE);
	computer_player_run_search (self, &_data1_->x, &_data1_->y);
	computer_player_move_async_co (_data1_->_async_data_);
	result = NULL;
	return result;
}


static gpointer ___lambda4__gthread_func (gpointer self) {
	gpointer result;
	result = __lambda4_ (self);
	block1_data_unref (self);
	return result;
}


static gboolean __lambda5_ (Block1Data* _data1_) {
	ComputerPlayer* self;
	gboolean result = FALSE;
	gint _tmp0_;
	gint _tmp1_;
	self = _data1_->self;
	_tmp0_ = _data1_->x;
	_tmp1_ = _data1_->y;
	computer_player_complete_move (self, _tmp0_, _tmp1_);
	result = G_SOURCE_REMOVE;
	return result;
}


static gboolean ___lambda5__gsource_func (gpointer self) {
	gboolean result;
	result = __lambda5_ (self);
	return result;
}


static gboolean computer_player_move_async_co (ComputerPlayerMoveAsyncData* _data_) {
	switch (_data_->_state_) {
		case 0:
		goto _state_0;
		case 1:
		goto _state_1;
		case 2:
		goto _state_2;
		case 3:
		goto _state_3;
		default:
		g_assert_not_reached ();
	}
	_state_0:
	_data_->_data1_ = g_slice_new0 (Block1Data);
	_data_->_data1_->_ref_count_ = 1;
	_data_->_data1_->self = g_object_ref (_data_->self);
	_data_->_data1_->_async_data_ = _data_;
	_data_->_tmp0_ = g_timer_new ();
	_data_->timer = _data_->_tmp0_;
	_data_->_data1_->x = 0;
	_data_->_data1_->y = 0;
	while (TRUE) {
		_data_->_tmp1_ = computer_player_get_move_pending (_data_->self);
		_data_->_tmp2_ = _data_->_tmp1_;
		if (!_data_->_tmp2_) {
			break;
		}
		g_timeout_add_full (G_PRIORITY_DEFAULT, (guint) 200, _computer_player_move_async_co_gsource_func, _data_, NULL);
		_data_->_state_ = 1;
		return FALSE;
		_state_1:
		;
	}
	_data_->_tmp3_ = _data_->timer;
	g_timer_start (_data_->_tmp3_);
	_data_->_tmp4_ = g_thread_new ("AI thread", ___lambda4__gthread_func, block1_data_ref (_data_->_data1_));
	_data_->_tmp5_ = _data_->_tmp4_;
	_g_thread_unref0 (_data_->_tmp5_);
	_data_->_state_ = 2;
	return FALSE;
	_state_2:
	;
	_data_->_tmp6_ = _data_->timer;
	g_timer_stop (_data_->_tmp6_);
	_data_->_tmp7_ = computer_player_get_move_pending (_data_->self);
	_data_->_tmp8_ = _data_->_tmp7_;
	if (!_data_->_tmp8_) {
		_g_timer_destroy0 (_data_->timer);
		block1_data_unref (_data_->_data1_);
		_data_->_data1_ = NULL;
		g_task_return_pointer (_data_->_async_result, _data_, NULL);
		if (_data_->_state_ != 0) {
			while (_data_->_task_complete_ != TRUE) {
				g_main_context_iteration (g_task_get_context (_data_->_async_result), TRUE);
			}
		}
		g_object_unref (_data_->_async_result);
		return FALSE;
	}
	_data_->_tmp9_ = _data_->timer;
	_data_->_tmp10_ = g_timer_elapsed (_data_->_tmp9_, NULL);
	_data_->_tmp11_ = _data_->delay_seconds;
	if (_data_->_tmp10_ < _data_->_tmp11_) {
		_data_->_tmp12_ = _data_->delay_seconds;
		_data_->_tmp13_ = _data_->timer;
		_data_->_tmp14_ = g_timer_elapsed (_data_->_tmp13_, NULL);
		_data_->_tmp15_ = g_timeout_add_full (G_PRIORITY_DEFAULT, (guint) ((_data_->_tmp12_ - _data_->_tmp14_) * 1000), _computer_player_move_async_co_gsource_func, _data_, NULL);
		_data_->self->priv->pending_move_id = _data_->_tmp15_;
		_data_->_state_ = 3;
		return FALSE;
		_state_3:
		;
	}
	_data_->self->priv->pending_move_id = (guint) 0;
	computer_player_set_move_pending (_data_->self, FALSE);
	g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, ___lambda5__gsource_func, block1_data_ref (_data_->_data1_), block1_data_unref);
	_g_timer_destroy0 (_data_->timer);
	block1_data_unref (_data_->_data1_);
	_data_->_data1_ = NULL;
	g_task_return_pointer (_data_->_async_result, _data_, NULL);
	if (_data_->_state_ != 0) {
		while (_data_->_task_complete_ != TRUE) {
			g_main_context_iteration (g_task_get_context (_data_->_async_result), TRUE);
		}
	}
	g_object_unref (_data_->_async_result);
	return FALSE;
}


void computer_player_cancel_move (ComputerPlayer* self) {
	gboolean _tmp0_;
	gboolean _tmp1_;
	guint _tmp2_;
	g_return_if_fail (self != NULL);
	_tmp0_ = computer_player_get_move_pending (self);
	_tmp1_ = _tmp0_;
	if (!_tmp1_) {
		return;
	}
	_tmp2_ = self->priv->pending_move_id;
	if (_tmp2_ != ((guint) 0)) {
		guint _tmp3_;
		_tmp3_ = self->priv->pending_move_id;
		g_source_remove (_tmp3_);
		self->priv->pending_move_id = (guint) 0;
	}
	computer_player_set_move_pending (self, FALSE);
}


static gpointer _computer_player_possible_move_dup0 (gpointer self) {
	return self ? computer_player_possible_move_dup (self) : NULL;
}


static void _computer_player_possible_move_free0_ (gpointer var) {
	(var == NULL) ? NULL : (var = (computer_player_possible_move_free (var), NULL));
}


static inline void _g_list_free__computer_player_possible_move_free0_ (GList* self) {
	g_list_free_full (self, (GDestroyNotify) _computer_player_possible_move_free0_);
}


static void computer_player_run_search (ComputerPlayer* self, gint* x, gint* y) {
	Game* _tmp0_;
	gboolean _tmp1_;
	gboolean _tmp2_;
	gint _tmp3_ = 0;
	Game* _tmp4_;
	gint _tmp5_;
	gint _tmp6_;
	Game* _tmp7_;
	gint _tmp8_;
	gint _tmp9_;
	Game* _tmp10_;
	gint _tmp11_;
	gint _tmp12_;
	Game* g = NULL;
	Game* _tmp16_;
	Game* _tmp17_;
	gint depth = 0;
	gint _tmp18_;
	gint a = 0;
	GList* moves = NULL;
	Game* _tmp19_;
	GList* _tmp20_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->game;
	_tmp1_ = game_get_current_player_can_move (_tmp0_);
	_tmp2_ = _tmp1_;
	_vala_return_if_fail (_tmp2_, "game.current_player_can_move");
	_tmp4_ = self->priv->game;
	_tmp5_ = game_get_size (_tmp4_);
	_tmp6_ = _tmp5_;
	if (_tmp6_ < 6) {
		_tmp3_ = 2;
	} else {
		_tmp3_ = 4;
	}
	_tmp7_ = self->priv->game;
	_tmp8_ = game_get_n_tiles (_tmp7_);
	_tmp9_ = _tmp8_;
	_tmp10_ = self->priv->game;
	_tmp11_ = game_get_initial_number_of_tiles (_tmp10_);
	_tmp12_ = _tmp11_;
	if (_tmp9_ < (_tmp12_ + _tmp3_)) {
		Game* _tmp13_;
		gint _tmp14_ = 0;
		gint _tmp15_ = 0;
		_tmp13_ = self->priv->game;
		computer_player_random_select (_tmp13_, &_tmp14_, &_tmp15_);
		*x = _tmp14_;
		*y = _tmp15_;
		return;
	}
	_tmp16_ = self->priv->game;
	_tmp17_ = game_new_copy (_tmp16_);
	g = _tmp17_;
	_tmp18_ = self->priv->difficulty_level;
	depth = _tmp18_ * 2;
	a = COMPUTER_PLAYER_NEGATIVE_INFINITY - 1;
	moves = NULL;
	_tmp19_ = g;
	computer_player_get_possible_moves_sorted (self, _tmp19_, &moves);
	_tmp20_ = moves;
	{
		GList* move_collection = NULL;
		GList* move_it = NULL;
		move_collection = _tmp20_;
		for (move_it = move_collection; move_it != NULL; move_it = move_it->next) {
			ComputerPlayerPossibleMove* _tmp21_;
			ComputerPlayerPossibleMove* move = NULL;
			_tmp21_ = _computer_player_possible_move_dup0 ((ComputerPlayerPossibleMove*) move_it->data);
			move = _tmp21_;
			{
				Game* _tmp22_;
				ComputerPlayerPossibleMove* _tmp23_;
				gint _tmp24_;
				ComputerPlayerPossibleMove* _tmp25_;
				gint _tmp26_;
				gint _tmp27_;
				gint a_new = 0;
				Game* _tmp38_;
				gint _tmp39_;
				gint _tmp40_;
				gint _tmp41_;
				gint _tmp42_;
				gint _tmp43_;
				Game* _tmp49_;
				_tmp22_ = g;
				_tmp23_ = move;
				_tmp24_ = (*_tmp23_).x;
				_tmp25_ = move;
				_tmp26_ = (*_tmp25_).y;
				_tmp27_ = game_place_tile (_tmp22_, _tmp24_, _tmp26_, TRUE);
				if (_tmp27_ == 0) {
					gint _tmp28_;
					ComputerPlayerPossibleMove* _tmp29_;
					gint _tmp30_;
					ComputerPlayerPossibleMove* _tmp31_;
					gint _tmp32_;
					ComputerPlayerPossibleMove* _tmp33_;
					gint _tmp34_;
					Game* _tmp35_;
					gchar* _tmp36_;
					gchar* _tmp37_;
					_tmp28_ = depth;
					_tmp29_ = move;
					_tmp30_ = (*_tmp29_).x;
					_tmp31_ = move;
					_tmp32_ = (*_tmp31_).y;
					_tmp33_ = move;
					_tmp34_ = (*_tmp33_).n_tiles;
					_tmp35_ = g;
					_tmp36_ = game_to_string (_tmp35_);
					_tmp37_ = _tmp36_;
					g_critical ("computer-player.vala:201: Computer marked move (depth %d, %d,%d, %d fl" \
"ips) as valid, but is invalid when checking.\n" \
"%s", _tmp28_, _tmp30_, _tmp32_, _tmp34_, _tmp37_);
					_g_free0 (_tmp37_);
					g_assert_not_reached ();
				}
				_tmp38_ = g;
				_tmp39_ = depth;
				_tmp40_ = a;
				_tmp41_ = computer_player_search (self, _tmp38_, _tmp39_, COMPUTER_PLAYER_NEGATIVE_INFINITY, -_tmp40_);
				a_new = -1 * _tmp41_;
				_tmp42_ = a_new;
				_tmp43_ = a;
				if (_tmp42_ > _tmp43_) {
					gint _tmp44_;
					ComputerPlayerPossibleMove* _tmp45_;
					gint _tmp46_;
					ComputerPlayerPossibleMove* _tmp47_;
					gint _tmp48_;
					_tmp44_ = a_new;
					a = _tmp44_;
					_tmp45_ = move;
					_tmp46_ = (*_tmp45_).x;
					*x = _tmp46_;
					_tmp47_ = move;
					_tmp48_ = (*_tmp47_).y;
					*y = _tmp48_;
				}
				_tmp49_ = g;
				game_undo (_tmp49_, 1);
				_computer_player_possible_move_free0 (move);
			}
		}
	}
	__g_list_free__computer_player_possible_move_free0_0 (moves);
	_g_object_unref0 (g);
}


static gint computer_player_search (ComputerPlayer* self, Game* g, gint depth, gint a, gint b) {
	gint result = 0;
	gint _tmp0_;
	gint _tmp1_;
	Game* _tmp2_;
	gboolean _tmp3_;
	gboolean _tmp4_;
	gboolean _tmp18_;
	gboolean _tmp19_;
	gint _tmp20_;
	Game* _tmp23_;
	gboolean _tmp24_;
	gboolean _tmp25_;
	gint _tmp66_;
	g_return_val_if_fail (self != NULL, 0);
	g_return_val_if_fail (g != NULL, 0);
	_tmp0_ = a;
	_tmp1_ = b;
	_vala_return_val_if_fail (_tmp0_ <= _tmp1_, "a <= b", 0);
	_tmp2_ = g;
	_tmp3_ = game_get_is_complete (_tmp2_);
	_tmp4_ = _tmp3_;
	if (_tmp4_) {
		gint _tmp5_ = 0;
		Game* _tmp6_;
		gint _tmp7_;
		gint _tmp8_;
		Game* _tmp9_;
		gint _tmp10_;
		gint _tmp11_;
		_tmp6_ = g;
		_tmp7_ = game_get_n_current_tiles (_tmp6_);
		_tmp8_ = _tmp7_;
		_tmp9_ = g;
		_tmp10_ = game_get_n_opponent_tiles (_tmp9_);
		_tmp11_ = _tmp10_;
		if (_tmp8_ > _tmp11_) {
			Game* _tmp12_;
			gint _tmp13_;
			gint _tmp14_;
			_tmp12_ = g;
			_tmp13_ = game_get_n_opponent_tiles (_tmp12_);
			_tmp14_ = _tmp13_;
			_tmp5_ = COMPUTER_PLAYER_POSITIVE_INFINITY - _tmp14_;
		} else {
			Game* _tmp15_;
			gint _tmp16_;
			gint _tmp17_;
			_tmp15_ = g;
			_tmp16_ = game_get_n_current_tiles (_tmp15_);
			_tmp17_ = _tmp16_;
			_tmp5_ = COMPUTER_PLAYER_NEGATIVE_INFINITY + _tmp17_;
		}
		result = _tmp5_;
		return result;
	}
	_tmp18_ = computer_player_get_move_pending (self);
	_tmp19_ = _tmp18_;
	if (!_tmp19_) {
		result = 0;
		return result;
	}
	_tmp20_ = depth;
	if (_tmp20_ == 0) {
		Game* _tmp21_;
		gint _tmp22_;
		_tmp21_ = g;
		_tmp22_ = computer_player_calculate_heuristic (self, _tmp21_);
		result = _tmp22_;
		return result;
	}
	_tmp23_ = g;
	_tmp24_ = game_get_current_player_can_move (_tmp23_);
	_tmp25_ = _tmp24_;
	if (_tmp25_) {
		GList* moves = NULL;
		Game* _tmp26_;
		GList* _tmp27_;
		moves = NULL;
		_tmp26_ = g;
		computer_player_get_possible_moves_sorted (self, _tmp26_, &moves);
		_tmp27_ = moves;
		{
			GList* move_collection = NULL;
			GList* move_it = NULL;
			move_collection = _tmp27_;
			for (move_it = move_collection; move_it != NULL; move_it = move_it->next) {
				ComputerPlayerPossibleMove* _tmp28_;
				ComputerPlayerPossibleMove* move = NULL;
				_tmp28_ = _computer_player_possible_move_dup0 ((ComputerPlayerPossibleMove*) move_it->data);
				move = _tmp28_;
				{
					Game* _tmp29_;
					ComputerPlayerPossibleMove* _tmp30_;
					gint _tmp31_;
					ComputerPlayerPossibleMove* _tmp32_;
					gint _tmp33_;
					gint _tmp34_;
					gint a_new = 0;
					Game* _tmp45_;
					gint _tmp46_;
					gint _tmp47_;
					gint _tmp48_;
					gint _tmp49_;
					gint _tmp50_;
					gint _tmp51_;
					Game* _tmp53_;
					gint _tmp54_;
					gint _tmp55_;
					_tmp29_ = g;
					_tmp30_ = move;
					_tmp31_ = (*_tmp30_).x;
					_tmp32_ = move;
					_tmp33_ = (*_tmp32_).y;
					_tmp34_ = game_place_tile (_tmp29_, _tmp31_, _tmp33_, TRUE);
					if (_tmp34_ == 0) {
						gint _tmp35_;
						ComputerPlayerPossibleMove* _tmp36_;
						gint _tmp37_;
						ComputerPlayerPossibleMove* _tmp38_;
						gint _tmp39_;
						ComputerPlayerPossibleMove* _tmp40_;
						gint _tmp41_;
						Game* _tmp42_;
						gchar* _tmp43_;
						gchar* _tmp44_;
						_tmp35_ = depth;
						_tmp36_ = move;
						_tmp37_ = (*_tmp36_).x;
						_tmp38_ = move;
						_tmp39_ = (*_tmp38_).y;
						_tmp40_ = move;
						_tmp41_ = (*_tmp40_).n_tiles;
						_tmp42_ = g;
						_tmp43_ = game_to_string (_tmp42_);
						_tmp44_ = _tmp43_;
						g_critical ("computer-player.vala:243: Computer marked move (depth %d, %d,%d, %d fl" \
"ips) as valid, but is invalid when checking.\n" \
"%s", _tmp35_, _tmp37_, _tmp39_, _tmp41_, _tmp44_);
						_g_free0 (_tmp44_);
						g_assert_not_reached ();
					}
					_tmp45_ = g;
					_tmp46_ = depth;
					_tmp47_ = b;
					_tmp48_ = a;
					_tmp49_ = computer_player_search (self, _tmp45_, _tmp46_ - 1, -_tmp47_, -_tmp48_);
					a_new = -1 * _tmp49_;
					_tmp50_ = a_new;
					_tmp51_ = a;
					if (_tmp50_ > _tmp51_) {
						gint _tmp52_;
						_tmp52_ = a_new;
						a = _tmp52_;
					}
					_tmp53_ = g;
					game_undo (_tmp53_, 1);
					_tmp54_ = b;
					_tmp55_ = a;
					if (_tmp54_ <= _tmp55_) {
						_computer_player_possible_move_free0 (move);
						break;
					}
					_computer_player_possible_move_free0 (move);
				}
			}
		}
		__g_list_free__computer_player_possible_move_free0_0 (moves);
	} else {
		Game* _tmp56_;
		gint a_new = 0;
		Game* _tmp57_;
		gint _tmp58_;
		gint _tmp59_;
		gint _tmp60_;
		gint _tmp61_;
		gint _tmp62_;
		gint _tmp63_;
		Game* _tmp65_;
		_tmp56_ = g;
		game_pass (_tmp56_);
		_tmp57_ = g;
		_tmp58_ = depth;
		_tmp59_ = b;
		_tmp60_ = a;
		_tmp61_ = computer_player_search (self, _tmp57_, _tmp58_ - 1, -_tmp59_, -_tmp60_);
		a_new = -1 * _tmp61_;
		_tmp62_ = a_new;
		_tmp63_ = a;
		if (_tmp62_ > _tmp63_) {
			gint _tmp64_;
			_tmp64_ = a_new;
			a = _tmp64_;
		}
		_tmp65_ = g;
		game_undo (_tmp65_, 1);
	}
	_tmp66_ = a;
	result = _tmp66_;
	return result;
}


static gint _computer_player_compare_move_gcompare_func (gconstpointer a, gconstpointer b) {
	gint result;
	result = computer_player_compare_move ((ComputerPlayerPossibleMove*) a, (ComputerPlayerPossibleMove*) b);
	return result;
}


static void computer_player_get_possible_moves_sorted (ComputerPlayer* self, Game* g, GList* * moves) {
	g_return_if_fail (self != NULL);
	g_return_if_fail (g != NULL);
	{
		gint x = 0;
		x = 0;
		{
			gboolean _tmp0_ = FALSE;
			_tmp0_ = TRUE;
			while (TRUE) {
				gint _tmp2_;
				Game* _tmp3_;
				gint _tmp4_;
				gint _tmp5_;
				if (!_tmp0_) {
					gint _tmp1_;
					_tmp1_ = x;
					x = _tmp1_ + 1;
				}
				_tmp0_ = FALSE;
				_tmp2_ = x;
				_tmp3_ = g;
				_tmp4_ = game_get_size (_tmp3_);
				_tmp5_ = _tmp4_;
				if (!(_tmp2_ < _tmp5_)) {
					break;
				}
				{
					gint y = 0;
					y = 0;
					{
						gboolean _tmp6_ = FALSE;
						_tmp6_ = TRUE;
						while (TRUE) {
							gint _tmp8_;
							Game* _tmp9_;
							gint _tmp10_;
							gint _tmp11_;
							gint n_tiles = 0;
							Game* _tmp12_;
							gint _tmp13_;
							gint _tmp14_;
							gint _tmp15_;
							gint _tmp16_;
							ComputerPlayerPossibleMove move = {0};
							gint _tmp17_;
							gint _tmp18_;
							gint _tmp19_;
							ComputerPlayerPossibleMove _tmp20_;
							ComputerPlayerPossibleMove* _tmp21_;
							if (!_tmp6_) {
								gint _tmp7_;
								_tmp7_ = y;
								y = _tmp7_ + 1;
							}
							_tmp6_ = FALSE;
							_tmp8_ = y;
							_tmp9_ = g;
							_tmp10_ = game_get_size (_tmp9_);
							_tmp11_ = _tmp10_;
							if (!(_tmp8_ < _tmp11_)) {
								break;
							}
							_tmp12_ = g;
							_tmp13_ = x;
							_tmp14_ = y;
							_tmp15_ = game_place_tile (_tmp12_, _tmp13_, _tmp14_, FALSE);
							n_tiles = _tmp15_;
							_tmp16_ = n_tiles;
							if (_tmp16_ <= 0) {
								continue;
							}
							_tmp17_ = x;
							_tmp18_ = y;
							_tmp19_ = n_tiles;
							computer_player_possible_move_init (&move, _tmp17_, _tmp18_, _tmp19_);
							_tmp20_ = move;
							_tmp21_ = _computer_player_possible_move_dup0 (&_tmp20_);
							*moves = g_list_insert_sorted (*moves, _tmp21_, _computer_player_compare_move_gcompare_func);
						}
					}
				}
			}
		}
	}
}


static gint computer_player_compare_move (ComputerPlayerPossibleMove* a, ComputerPlayerPossibleMove* b) {
	gint result = 0;
	ComputerPlayerPossibleMove* _tmp0_;
	gint _tmp1_;
	ComputerPlayerPossibleMove* _tmp2_;
	gint _tmp3_;
	_tmp0_ = b;
	_tmp1_ = (*_tmp0_).n_tiles;
	_tmp2_ = a;
	_tmp3_ = (*_tmp2_).n_tiles;
	result = _tmp1_ - _tmp3_;
	return result;
}


static gint computer_player_calculate_heuristic (ComputerPlayer* self, Game* g) {
	gint result = 0;
	gint tile_difference = 0;
	Game* _tmp0_;
	gint _tmp1_;
	gint _tmp2_;
	Game* _tmp3_;
	gint _tmp4_;
	gint _tmp5_;
	gint _tmp6_;
	Game* _tmp8_;
	gint _tmp9_;
	gint _tmp10_;
	gint _tmp11_;
	Game* _tmp12_;
	gint _tmp13_;
	Game* _tmp14_;
	gint _tmp15_;
	g_return_val_if_fail (self != NULL, 0);
	g_return_val_if_fail (g != NULL, 0);
	_tmp0_ = g;
	_tmp1_ = game_get_n_current_tiles (_tmp0_);
	_tmp2_ = _tmp1_;
	_tmp3_ = g;
	_tmp4_ = game_get_n_opponent_tiles (_tmp3_);
	_tmp5_ = _tmp4_;
	tile_difference = _tmp2_ - _tmp5_;
	_tmp6_ = self->priv->difficulty_level;
	if (_tmp6_ == 1) {
		gint _tmp7_;
		_tmp7_ = tile_difference;
		result = -_tmp7_;
		return result;
	}
	_tmp8_ = g;
	_tmp9_ = game_get_n_tiles (_tmp8_);
	_tmp10_ = _tmp9_;
	if (_tmp10_ >= 54) {
		result = tile_difference;
		return result;
	}
	_tmp11_ = tile_difference;
	_tmp12_ = g;
	_tmp13_ = computer_player_eval_heuristic (_tmp12_);
	_tmp14_ = g;
	_tmp15_ = computer_player_around (_tmp14_);
	result = (_tmp11_ + _tmp13_) + _tmp15_;
	return result;
}


static gint computer_player_eval_heuristic (Game* g) {
	gint result = 0;
	gint count = 0;
	Game* _tmp0_;
	gint _tmp1_;
	gint _tmp2_;
	g_return_val_if_fail (g != NULL, 0);
	count = 0;
	_tmp0_ = g;
	_tmp1_ = game_get_size (_tmp0_);
	_tmp2_ = _tmp1_;
	if (_tmp2_ != 8) {
		result = 0;
		return result;
	}
	{
		gint x = 0;
		x = 0;
		{
			gboolean _tmp3_ = FALSE;
			_tmp3_ = TRUE;
			while (TRUE) {
				gint _tmp5_;
				Game* _tmp6_;
				gint _tmp7_;
				gint _tmp8_;
				if (!_tmp3_) {
					gint _tmp4_;
					_tmp4_ = x;
					x = _tmp4_ + 1;
				}
				_tmp3_ = FALSE;
				_tmp5_ = x;
				_tmp6_ = g;
				_tmp7_ = game_get_size (_tmp6_);
				_tmp8_ = _tmp7_;
				if (!(_tmp5_ < _tmp8_)) {
					break;
				}
				{
					gint y = 0;
					y = 0;
					{
						gboolean _tmp9_ = FALSE;
						_tmp9_ = TRUE;
						while (TRUE) {
							gint _tmp11_;
							Game* _tmp12_;
							gint _tmp13_;
							gint _tmp14_;
							gint h = 0;
							gint _tmp15_;
							Game* _tmp16_;
							gint _tmp17_;
							gint _tmp18_;
							gint _tmp19_;
							gint _tmp20_;
							Game* _tmp21_;
							gint _tmp22_;
							gint _tmp23_;
							Player _tmp24_;
							Game* _tmp25_;
							Player _tmp26_;
							Player _tmp27_;
							gint _tmp29_;
							gint _tmp30_;
							if (!_tmp9_) {
								gint _tmp10_;
								_tmp10_ = y;
								y = _tmp10_ + 1;
							}
							_tmp9_ = FALSE;
							_tmp11_ = y;
							_tmp12_ = g;
							_tmp13_ = game_get_size (_tmp12_);
							_tmp14_ = _tmp13_;
							if (!(_tmp11_ < _tmp14_)) {
								break;
							}
							_tmp15_ = y;
							_tmp16_ = g;
							_tmp17_ = game_get_size (_tmp16_);
							_tmp18_ = _tmp17_;
							_tmp19_ = x;
							_tmp20_ = COMPUTER_PLAYER_heuristic[(_tmp15_ * _tmp18_) + _tmp19_];
							h = _tmp20_;
							_tmp21_ = g;
							_tmp22_ = x;
							_tmp23_ = y;
							_tmp24_ = game_get_owner (_tmp21_, _tmp22_, _tmp23_);
							_tmp25_ = g;
							_tmp26_ = game_get_current_color (_tmp25_);
							_tmp27_ = _tmp26_;
							if (_tmp24_ != _tmp27_) {
								gint _tmp28_;
								_tmp28_ = h;
								h = -_tmp28_;
							}
							_tmp29_ = count;
							_tmp30_ = h;
							count = _tmp29_ + _tmp30_;
						}
					}
				}
			}
		}
	}
	result = count;
	return result;
}


static gint computer_player_around (Game* g) {
	gint result = 0;
	gint count = 0;
	g_return_val_if_fail (g != NULL, 0);
	count = 0;
	{
		gint x = 0;
		x = 0;
		{
			gboolean _tmp0_ = FALSE;
			_tmp0_ = TRUE;
			while (TRUE) {
				gint _tmp2_;
				Game* _tmp3_;
				gint _tmp4_;
				gint _tmp5_;
				if (!_tmp0_) {
					gint _tmp1_;
					_tmp1_ = x;
					x = _tmp1_ + 1;
				}
				_tmp0_ = FALSE;
				_tmp2_ = x;
				_tmp3_ = g;
				_tmp4_ = game_get_size (_tmp3_);
				_tmp5_ = _tmp4_;
				if (!(_tmp2_ < _tmp5_)) {
					break;
				}
				{
					gint y = 0;
					y = 0;
					{
						gboolean _tmp6_ = FALSE;
						_tmp6_ = TRUE;
						while (TRUE) {
							gint _tmp8_;
							Game* _tmp9_;
							gint _tmp10_;
							gint _tmp11_;
							gint a = 0;
							gint _tmp12_;
							Game* _tmp13_;
							gint _tmp14_;
							gint _tmp15_;
							gint _tmp16_;
							gint _tmp17_;
							Game* _tmp18_;
							gint _tmp19_;
							gint _tmp20_;
							gint _tmp21_;
							gint _tmp22_;
							Game* _tmp23_;
							gint _tmp24_;
							gint _tmp25_;
							gint _tmp26_;
							gint _tmp27_;
							Game* _tmp28_;
							gint _tmp29_;
							gint _tmp30_;
							gint _tmp31_;
							gint _tmp32_;
							Game* _tmp33_;
							gint _tmp34_;
							gint _tmp35_;
							gint _tmp36_;
							gint _tmp37_;
							Game* _tmp38_;
							gint _tmp39_;
							gint _tmp40_;
							gint _tmp41_;
							gint _tmp42_;
							Game* _tmp43_;
							gint _tmp44_;
							gint _tmp45_;
							gint _tmp46_;
							gint _tmp47_;
							Game* _tmp48_;
							gint _tmp49_;
							gint _tmp50_;
							gint _tmp51_;
							gint _tmp52_;
							gint _tmp53_ = 0;
							Game* _tmp54_;
							gint _tmp55_;
							gint _tmp56_;
							Player _tmp57_;
							Game* _tmp58_;
							Player _tmp59_;
							Player _tmp60_;
							gint _tmp63_;
							if (!_tmp6_) {
								gint _tmp7_;
								_tmp7_ = y;
								y = _tmp7_ + 1;
							}
							_tmp6_ = FALSE;
							_tmp8_ = y;
							_tmp9_ = g;
							_tmp10_ = game_get_size (_tmp9_);
							_tmp11_ = _tmp10_;
							if (!(_tmp8_ < _tmp11_)) {
								break;
							}
							a = 0;
							_tmp12_ = a;
							_tmp13_ = g;
							_tmp14_ = x;
							_tmp15_ = y;
							_tmp16_ = computer_player_is_empty (_tmp13_, _tmp14_ + 1, _tmp15_);
							a = _tmp12_ - _tmp16_;
							_tmp17_ = a;
							_tmp18_ = g;
							_tmp19_ = x;
							_tmp20_ = y;
							_tmp21_ = computer_player_is_empty (_tmp18_, _tmp19_ + 1, _tmp20_ + 1);
							a = _tmp17_ - _tmp21_;
							_tmp22_ = a;
							_tmp23_ = g;
							_tmp24_ = x;
							_tmp25_ = y;
							_tmp26_ = computer_player_is_empty (_tmp23_, _tmp24_, _tmp25_ + 1);
							a = _tmp22_ - _tmp26_;
							_tmp27_ = a;
							_tmp28_ = g;
							_tmp29_ = x;
							_tmp30_ = y;
							_tmp31_ = computer_player_is_empty (_tmp28_, _tmp29_ - 1, _tmp30_ + 1);
							a = _tmp27_ - _tmp31_;
							_tmp32_ = a;
							_tmp33_ = g;
							_tmp34_ = x;
							_tmp35_ = y;
							_tmp36_ = computer_player_is_empty (_tmp33_, _tmp34_ - 1, _tmp35_);
							a = _tmp32_ - _tmp36_;
							_tmp37_ = a;
							_tmp38_ = g;
							_tmp39_ = x;
							_tmp40_ = y;
							_tmp41_ = computer_player_is_empty (_tmp38_, _tmp39_ - 1, _tmp40_ - 1);
							a = _tmp37_ - _tmp41_;
							_tmp42_ = a;
							_tmp43_ = g;
							_tmp44_ = x;
							_tmp45_ = y;
							_tmp46_ = computer_player_is_empty (_tmp43_, _tmp44_, _tmp45_ - 1);
							a = _tmp42_ - _tmp46_;
							_tmp47_ = a;
							_tmp48_ = g;
							_tmp49_ = x;
							_tmp50_ = y;
							_tmp51_ = computer_player_is_empty (_tmp48_, _tmp49_ + 1, _tmp50_ - 1);
							a = _tmp47_ - _tmp51_;
							_tmp52_ = a;
							if (_tmp52_ == 0) {
								a = 2;
							}
							_tmp54_ = g;
							_tmp55_ = x;
							_tmp56_ = y;
							_tmp57_ = game_get_owner (_tmp54_, _tmp55_, _tmp56_);
							_tmp58_ = g;
							_tmp59_ = game_get_current_color (_tmp58_);
							_tmp60_ = _tmp59_;
							if (_tmp57_ == _tmp60_) {
								gint _tmp61_;
								_tmp61_ = a;
								_tmp53_ = _tmp61_;
							} else {
								gint _tmp62_;
								_tmp62_ = a;
								_tmp53_ = -_tmp62_;
							}
							_tmp63_ = count;
							count = _tmp63_ + _tmp53_;
						}
					}
				}
			}
		}
	}
	result = count;
	return result;
}


static gint computer_player_is_empty (Game* g, gint x, gint y) {
	gint result = 0;
	gboolean _tmp0_ = FALSE;
	Game* _tmp1_;
	gint _tmp2_;
	gint _tmp3_;
	gboolean _tmp4_;
	g_return_val_if_fail (g != NULL, 0);
	_tmp1_ = g;
	_tmp2_ = x;
	_tmp3_ = y;
	_tmp4_ = game_is_valid_location (_tmp1_, _tmp2_, _tmp3_);
	if (_tmp4_) {
		Game* _tmp5_;
		gint _tmp6_;
		gint _tmp7_;
		Player _tmp8_;
		_tmp5_ = g;
		_tmp6_ = x;
		_tmp7_ = y;
		_tmp8_ = game_get_owner (_tmp5_, _tmp6_, _tmp7_);
		_tmp0_ = _tmp8_ == PLAYER_NONE;
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		result = 1;
		return result;
	}
	result = 0;
	return result;
}


static void computer_player_random_select (Game* g, gint* move_x, gint* move_y) {
	gint _vala_move_x = 0;
	gint _vala_move_y = 0;
	GList* moves = NULL;
	GList* _tmp24_;
	gint32 i = 0;
	GList* _tmp25_;
	guint _tmp26_;
	gint32 _tmp27_;
	gint xy = 0;
	GList* _tmp28_;
	gconstpointer _tmp29_;
	Game* _tmp30_;
	gint _tmp31_;
	gint _tmp32_;
	Game* _tmp33_;
	gint _tmp34_;
	gint _tmp35_;
	g_return_if_fail (g != NULL);
	moves = NULL;
	{
		gint x = 0;
		x = 0;
		{
			gboolean _tmp0_ = FALSE;
			_tmp0_ = TRUE;
			while (TRUE) {
				gint _tmp2_;
				Game* _tmp3_;
				gint _tmp4_;
				gint _tmp5_;
				if (!_tmp0_) {
					gint _tmp1_;
					_tmp1_ = x;
					x = _tmp1_ + 1;
				}
				_tmp0_ = FALSE;
				_tmp2_ = x;
				_tmp3_ = g;
				_tmp4_ = game_get_size (_tmp3_);
				_tmp5_ = _tmp4_;
				if (!(_tmp2_ < _tmp5_)) {
					break;
				}
				{
					gint y = 0;
					y = 0;
					{
						gboolean _tmp6_ = FALSE;
						_tmp6_ = TRUE;
						while (TRUE) {
							gint _tmp8_;
							Game* _tmp9_;
							gint _tmp10_;
							gint _tmp11_;
							Game* _tmp12_;
							gint _tmp13_;
							gint _tmp14_;
							Game* _tmp15_;
							Player _tmp16_;
							Player _tmp17_;
							gboolean _tmp18_;
							if (!_tmp6_) {
								gint _tmp7_;
								_tmp7_ = y;
								y = _tmp7_ + 1;
							}
							_tmp6_ = FALSE;
							_tmp8_ = y;
							_tmp9_ = g;
							_tmp10_ = game_get_size (_tmp9_);
							_tmp11_ = _tmp10_;
							if (!(_tmp8_ < _tmp11_)) {
								break;
							}
							_tmp12_ = g;
							_tmp13_ = x;
							_tmp14_ = y;
							_tmp15_ = g;
							_tmp16_ = game_get_current_color (_tmp15_);
							_tmp17_ = _tmp16_;
							_tmp18_ = game_can_place (_tmp12_, _tmp13_, _tmp14_, _tmp17_);
							if (_tmp18_) {
								gint _tmp19_;
								Game* _tmp20_;
								gint _tmp21_;
								gint _tmp22_;
								gint _tmp23_;
								_tmp19_ = x;
								_tmp20_ = g;
								_tmp21_ = game_get_size (_tmp20_);
								_tmp22_ = _tmp21_;
								_tmp23_ = y;
								moves = g_list_append (moves, (gpointer) ((gintptr) ((_tmp19_ * _tmp22_) + _tmp23_)));
							}
						}
					}
				}
			}
		}
	}
	_tmp24_ = moves;
	if (_tmp24_ == NULL) {
		g_assert_not_reached ();
	}
	_tmp25_ = moves;
	_tmp26_ = g_list_length (_tmp25_);
	_tmp27_ = g_random_int_range ((gint32) 0, (gint32) ((gint) _tmp26_));
	i = _tmp27_;
	_tmp28_ = moves;
	_tmp29_ = g_list_nth_data (_tmp28_, (guint) i);
	xy = (gint) ((gintptr) _tmp29_);
	_tmp30_ = g;
	_tmp31_ = game_get_size (_tmp30_);
	_tmp32_ = _tmp31_;
	_vala_move_x = xy / _tmp32_;
	_tmp33_ = g;
	_tmp34_ = game_get_size (_tmp33_);
	_tmp35_ = _tmp34_;
	_vala_move_y = xy % _tmp35_;
	_g_list_free0 (moves);
	if (move_x) {
		*move_x = _vala_move_x;
	}
	if (move_y) {
		*move_y = _vala_move_y;
	}
}


static gboolean computer_player_get_move_pending (ComputerPlayer* self) {
	gboolean result;
	gboolean _result_ = FALSE;
	gboolean _tmp0_;
	g_return_val_if_fail (self != NULL, FALSE);
	g_rec_mutex_lock (&self->priv->_move_pending_mutex);
	_tmp0_ = self->priv->_move_pending;
	_result_ = _tmp0_;
	g_rec_mutex_unlock (&self->priv->_move_pending_mutex);
	result = _result_;
	return result;
}


static void computer_player_set_move_pending (ComputerPlayer* self, gboolean value) {
	gboolean _tmp0_;
	g_return_if_fail (self != NULL);
	g_rec_mutex_lock (&self->priv->_move_pending_mutex);
	_tmp0_ = value;
	self->priv->_move_pending = _tmp0_;
	g_rec_mutex_unlock (&self->priv->_move_pending_mutex);
}


static void computer_player_possible_move_init (ComputerPlayerPossibleMove *self, gint x, gint y, gint n_tiles) {
	gint _tmp0_;
	gint _tmp1_;
	gint _tmp2_;
	memset (self, 0, sizeof (ComputerPlayerPossibleMove));
	_tmp0_ = x;
	(*self).x = _tmp0_;
	_tmp1_ = y;
	(*self).y = _tmp1_;
	_tmp2_ = n_tiles;
	(*self).n_tiles = _tmp2_;
}


static ComputerPlayerPossibleMove* computer_player_possible_move_dup (const ComputerPlayerPossibleMove* self) {
	ComputerPlayerPossibleMove* dup;
	dup = g_new0 (ComputerPlayerPossibleMove, 1);
	memcpy (dup, self, sizeof (ComputerPlayerPossibleMove));
	return dup;
}


static void computer_player_possible_move_free (ComputerPlayerPossibleMove* self) {
	g_free (self);
}


static GType computer_player_possible_move_get_type (void) {
	static volatile gsize computer_player_possible_move_type_id__volatile = 0;
	if (g_once_init_enter (&computer_player_possible_move_type_id__volatile)) {
		GType computer_player_possible_move_type_id;
		computer_player_possible_move_type_id = g_boxed_type_register_static ("ComputerPlayerPossibleMove", (GBoxedCopyFunc) computer_player_possible_move_dup, (GBoxedFreeFunc) computer_player_possible_move_free);
		g_once_init_leave (&computer_player_possible_move_type_id__volatile, computer_player_possible_move_type_id);
	}
	return computer_player_possible_move_type_id__volatile;
}


static void computer_player_class_init (ComputerPlayerClass * klass) {
	computer_player_parent_class = g_type_class_peek_parent (klass);
	g_type_class_add_private (klass, sizeof (ComputerPlayerPrivate));
	G_OBJECT_CLASS (klass)->get_property = _vala_computer_player_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_computer_player_set_property;
	G_OBJECT_CLASS (klass)->finalize = computer_player_finalize;
}


static void computer_player_instance_init (ComputerPlayer * self) {
	self->priv = COMPUTER_PLAYER_GET_PRIVATE (self);
	self->priv->pending_move_id = (guint) 0;
}


static void computer_player_finalize (GObject * obj) {
	ComputerPlayer * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_COMPUTER_PLAYER, ComputerPlayer);
	_g_object_unref0 (self->priv->game);
	_vala_clear_GRecMutex (&self->priv->_move_pending_mutex);
	G_OBJECT_CLASS (computer_player_parent_class)->finalize (obj);
}


GType computer_player_get_type (void) {
	static volatile gsize computer_player_type_id__volatile = 0;
	if (g_once_init_enter (&computer_player_type_id__volatile)) {
		static const GTypeInfo g_define_type_info = { sizeof (ComputerPlayerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) computer_player_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (ComputerPlayer), 0, (GInstanceInitFunc) computer_player_instance_init, NULL };
		GType computer_player_type_id;
		computer_player_type_id = g_type_register_static (G_TYPE_OBJECT, "ComputerPlayer", &g_define_type_info, 0);
		g_once_init_leave (&computer_player_type_id__volatile, computer_player_type_id);
	}
	return computer_player_type_id__volatile;
}


static void _vala_computer_player_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) {
	ComputerPlayer * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_COMPUTER_PLAYER, ComputerPlayer);
	switch (property_id) {
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}


static void _vala_computer_player_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) {
	ComputerPlayer * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_COMPUTER_PLAYER, ComputerPlayer);
	switch (property_id) {
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}


static void _vala_clear_GMutex (GMutex * mutex) {
	GMutex zero_mutex = { 0 };
	if (memcmp (mutex, &zero_mutex, sizeof (GMutex))) {
		g_mutex_clear (mutex);
		memset (mutex, 0, sizeof (GMutex));
	}
}


static void _vala_clear_GRecMutex (GRecMutex * mutex) {
	GRecMutex zero_mutex = { 0 };
	if (memcmp (mutex, &zero_mutex, sizeof (GRecMutex))) {
		g_rec_mutex_clear (mutex);
		memset (mutex, 0, sizeof (GRecMutex));
	}
}


static void _vala_clear_GRWLock (GRWLock * mutex) {
	GRWLock zero_mutex = { 0 };
	if (memcmp (mutex, &zero_mutex, sizeof (GRWLock))) {
		g_rw_lock_clear (mutex);
		memset (mutex, 0, sizeof (GRWLock));
	}
}


static void _vala_clear_GCond (GCond * mutex) {
	GCond zero_mutex = { 0 };
	if (memcmp (mutex, &zero_mutex, sizeof (GCond))) {
		g_cond_clear (mutex);
		memset (mutex, 0, sizeof (GCond));
	}
}



