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


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


#define TYPE_STRATEGY (strategy_get_type ())

#define TYPE_POSSIBLE_MOVE (possible_move_get_type ())
typedef struct _PossibleMove PossibleMove;

#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;
#define _game_unref0(var) ((var == NULL) ? NULL : (var = (game_unref (var), NULL)))
#define _possible_move_free0(var) ((var == NULL) ? NULL : (var = (possible_move_free (var), NULL)))
#define __g_list_free__possible_move_free0_0(var) ((var == NULL) ? NULL : (var = (_g_list_free__possible_move_free0_ (var), NULL)))
typedef struct _GamePrivate GamePrivate;

#define TYPE_PLAYER (player_get_type ())
#define _g_list_free0(var) ((var == NULL) ? NULL : (var = (g_list_free (var), NULL)))
typedef struct _ParamSpecComputerPlayer ParamSpecComputerPlayer;

typedef enum  {
	STRATEGY_PERFECT,
	STRATEGY_VICTORY,
	STRATEGY_BEST
} Strategy;

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

struct _ComputerPlayer {
	GTypeInstance parent_instance;
	volatile int ref_count;
	ComputerPlayerPrivate * priv;
};

struct _ComputerPlayerClass {
	GTypeClass parent_class;
	void (*finalize) (ComputerPlayer *self);
};

struct _ComputerPlayerPrivate {
	Game* game;
	gint level;
};

typedef enum  {
	PLAYER_NONE,
	PLAYER_LIGHT,
	PLAYER_DARK
} Player;

struct _Game {
	GTypeInstance parent_instance;
	volatile int ref_count;
	GamePrivate * priv;
	Player* tiles;
	gint tiles_length1;
	gint tiles_length2;
	Player current_color;
};

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

struct _ParamSpecComputerPlayer {
	GParamSpec parent_instance;
};


static gpointer computer_player_parent_class = NULL;

GType strategy_get_type (void) G_GNUC_CONST;
GType possible_move_get_type (void) G_GNUC_CONST;
PossibleMove* possible_move_dup (const PossibleMove* self);
void possible_move_free (PossibleMove* self);
gpointer computer_player_ref (gpointer instance);
void computer_player_unref (gpointer instance);
GParamSpec* param_spec_computer_player (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
void value_set_computer_player (GValue* value, gpointer v_object);
void value_take_computer_player (GValue* value, gpointer v_object);
gpointer value_get_computer_player (const GValue* value);
GType computer_player_get_type (void) G_GNUC_CONST;
gpointer game_ref (gpointer instance);
void game_unref (gpointer instance);
GParamSpec* param_spec_game (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
void value_set_game (GValue* value, gpointer v_object);
void value_take_game (GValue* value, gpointer v_object);
gpointer value_get_game (const GValue* value);
GType game_get_type (void) G_GNUC_CONST;
#define COMPUTER_PLAYER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_COMPUTER_PLAYER, ComputerPlayerPrivate))
enum  {
	COMPUTER_PLAYER_DUMMY_PROPERTY
};
ComputerPlayer* computer_player_new (Game* game, gint level);
ComputerPlayer* computer_player_construct (GType object_type, Game* game, gint level);
void computer_player_move (ComputerPlayer* self);
gint game_get_n_tiles (Game* self);
static void computer_player_random_select (ComputerPlayer* self, gint* move_x, gint* move_y);
gint game_place_tile (Game* self, gint x, gint y);
static gint computer_player_search (ComputerPlayer* self, Game* g, Strategy strategy, gint depth, gint a, gint b, gint p, gint* move_x, gint* move_y);
Game* game_new_copy (Game* game);
Game* game_construct_copy (GType object_type, Game* game);
gboolean game_get_is_complete (Game* self);
static gint computer_player_calculate_heuristic (ComputerPlayer* self, Game* g, Strategy strategy);
static gint computer_player_compare_move (PossibleMove* a, PossibleMove* b);
static gint _computer_player_compare_move_gcompare_func (gconstpointer a, gconstpointer b);
void game_undo (Game* self, gint count);
void game_pass (Game* self);
static void _possible_move_free0_ (gpointer var);
static void _g_list_free__possible_move_free0_ (GList* self);
gint game_get_n_dark_tiles (Game* self);
gint game_get_n_light_tiles (Game* self);
GType player_get_type (void) G_GNUC_CONST;
static gint computer_player_around (ComputerPlayer* self);
static gint computer_player_eval_heuristic (ComputerPlayer* self);
Player game_get_owner (Game* self, gint x, gint y);
static gint computer_player_is_empty (ComputerPlayer* self, gint x, gint y);
gboolean game_can_place (Game* self, gint x, gint y);
static void computer_player_finalize (ComputerPlayer* obj);

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

GType strategy_get_type (void) {
	static volatile gsize strategy_type_id__volatile = 0;
	if (g_once_init_enter (&strategy_type_id__volatile)) {
		static const GEnumValue values[] = {{STRATEGY_PERFECT, "STRATEGY_PERFECT", "perfect"}, {STRATEGY_VICTORY, "STRATEGY_VICTORY", "victory"}, {STRATEGY_BEST, "STRATEGY_BEST", "best"}, {0, NULL, NULL}};
		GType strategy_type_id;
		strategy_type_id = g_enum_register_static ("Strategy", values);
		g_once_init_leave (&strategy_type_id__volatile, strategy_type_id);
	}
	return strategy_type_id__volatile;
}


PossibleMove* possible_move_dup (const PossibleMove* self) {
	PossibleMove* dup;
	dup = g_new0 (PossibleMove, 1);
	memcpy (dup, self, sizeof (PossibleMove));
	return dup;
}


void possible_move_free (PossibleMove* self) {
	g_free (self);
}


GType possible_move_get_type (void) {
	static volatile gsize possible_move_type_id__volatile = 0;
	if (g_once_init_enter (&possible_move_type_id__volatile)) {
		GType possible_move_type_id;
		possible_move_type_id = g_boxed_type_register_static ("PossibleMove", (GBoxedCopyFunc) possible_move_dup, (GBoxedFreeFunc) possible_move_free);
		g_once_init_leave (&possible_move_type_id__volatile, possible_move_type_id);
	}
	return possible_move_type_id__volatile;
}


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


ComputerPlayer* computer_player_construct (GType object_type, Game* game, gint level) {
	ComputerPlayer* self = NULL;
	Game* _tmp0_;
	Game* _tmp1_;
	gint _tmp2_;
	g_return_val_if_fail (game != NULL, NULL);
	self = (ComputerPlayer*) g_type_create_instance (object_type);
	_tmp0_ = game;
	_tmp1_ = _game_ref0 (_tmp0_);
	_game_unref0 (self->priv->game);
	self->priv->game = _tmp1_;
	_tmp2_ = level;
	self->priv->level = _tmp2_;
	return self;
}


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


void computer_player_move (ComputerPlayer* self) {
	Game* _tmp0_;
	gint _tmp1_;
	gint _tmp2_;
	Game* _tmp8_;
	gint _tmp9_;
	gint _tmp10_;
	gint depth;
	Strategy strategy;
	gint _tmp11_;
	gint _tmp12_;
	gint x;
	gint y;
	Game* _tmp16_;
	Game* _tmp17_;
	Game* _tmp18_;
	Strategy _tmp19_;
	gint _tmp20_;
	gint _tmp21_;
	gint _tmp22_;
	Game* _tmp23_;
	gint _tmp24_;
	gint _tmp25_;
	gint _tmp26_ = 0;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->game;
	_tmp1_ = game_get_n_tiles (_tmp0_);
	_tmp2_ = _tmp1_;
	if (_tmp2_ < 8) {
		gint x = 0;
		gint y = 0;
		gint _tmp3_ = 0;
		gint _tmp4_ = 0;
		Game* _tmp5_;
		gint _tmp6_;
		gint _tmp7_;
		computer_player_random_select (self, &_tmp3_, &_tmp4_);
		x = _tmp3_;
		y = _tmp4_;
		_tmp5_ = self->priv->game;
		_tmp6_ = x;
		_tmp7_ = y;
		game_place_tile (_tmp5_, _tmp6_, _tmp7_);
		return;
	}
	_tmp8_ = self->priv->game;
	_tmp9_ = game_get_n_tiles (_tmp8_);
	_tmp10_ = _tmp9_;
	depth = 64 - _tmp10_;
	strategy = STRATEGY_BEST;
	_tmp11_ = depth;
	_tmp12_ = self->priv->level;
	if (_tmp11_ <= (17 - ((3 - _tmp12_) * 2))) {
		strategy = STRATEGY_PERFECT;
	} else {
		gint _tmp13_;
		gint _tmp14_;
		_tmp13_ = depth;
		_tmp14_ = self->priv->level;
		if (_tmp13_ <= (19 - ((3 - _tmp14_) * 2))) {
			strategy = STRATEGY_VICTORY;
		} else {
			gint _tmp15_;
			_tmp15_ = self->priv->level;
			depth = 7 - ((3 - _tmp15_) * 2);
		}
	}
	x = 0;
	y = 0;
	_tmp16_ = self->priv->game;
	_tmp17_ = game_new_copy (_tmp16_);
	_tmp18_ = _tmp17_;
	_tmp19_ = strategy;
	_tmp20_ = depth;
	_tmp21_ = G_MININT;
	_tmp22_ = G_MAXINT;
	computer_player_search (self, _tmp18_, _tmp19_, _tmp20_, _tmp21_, _tmp22_, 1, &x, &y);
	_game_unref0 (_tmp18_);
	_tmp23_ = self->priv->game;
	_tmp24_ = x;
	_tmp25_ = y;
	_tmp26_ = game_place_tile (_tmp23_, _tmp24_, _tmp25_);
	if (_tmp26_ == 0) {
		gint _tmp27_;
		gint _tmp28_;
		_tmp27_ = x;
		_tmp28_ = y;
		g_warning ("computer-player.vala:73: Computer chose an invalid move: %d,%d", _tmp27_, _tmp28_);
	}
}


static gpointer _possible_move_dup0 (gpointer self) {
	return self ? possible_move_dup (self) : NULL;
}


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


static void _possible_move_free0_ (gpointer var) {
	(var == NULL) ? NULL : (var = (possible_move_free (var), NULL));
}


static void _g_list_free__possible_move_free0_ (GList* self) {
	g_list_foreach (self, (GFunc) _possible_move_free0_, NULL);
	g_list_free (self);
}


static gint computer_player_search (ComputerPlayer* self, Game* g, Strategy strategy, gint depth, gint a, gint b, gint p, gint* move_x, gint* move_y) {
	gint result = 0;
	gboolean _tmp0_ = FALSE;
	gint _tmp1_;
	gboolean _tmp5_;
	GList* moves;
	GList* _tmp28_;
	GList* _tmp31_;
	gint _tmp81_;
	g_return_val_if_fail (self != NULL, 0);
	g_return_val_if_fail (g != NULL, 0);
	_tmp1_ = depth;
	if (_tmp1_ == 0) {
		_tmp0_ = TRUE;
	} else {
		Game* _tmp2_;
		gboolean _tmp3_;
		gboolean _tmp4_;
		_tmp2_ = g;
		_tmp3_ = game_get_is_complete (_tmp2_);
		_tmp4_ = _tmp3_;
		_tmp0_ = _tmp4_;
	}
	_tmp5_ = _tmp0_;
	if (_tmp5_) {
		Game* _tmp6_;
		Strategy _tmp7_;
		gint _tmp8_ = 0;
		_tmp6_ = g;
		_tmp7_ = strategy;
		_tmp8_ = computer_player_calculate_heuristic (self, _tmp6_, _tmp7_);
		result = _tmp8_;
		return result;
	}
	moves = NULL;
	{
		gint x;
		x = 0;
		{
			gboolean _tmp9_;
			_tmp9_ = TRUE;
			while (TRUE) {
				gboolean _tmp10_;
				gint _tmp12_;
				_tmp10_ = _tmp9_;
				if (!_tmp10_) {
					gint _tmp11_;
					_tmp11_ = x;
					x = _tmp11_ + 1;
				}
				_tmp9_ = FALSE;
				_tmp12_ = x;
				if (!(_tmp12_ < 8)) {
					break;
				}
				{
					gint y;
					y = 0;
					{
						gboolean _tmp13_;
						_tmp13_ = TRUE;
						while (TRUE) {
							gboolean _tmp14_;
							gint _tmp16_;
							Game* _tmp17_;
							gint _tmp18_;
							gint _tmp19_;
							gint _tmp20_ = 0;
							gint n_tiles;
							gint _tmp21_;
							_tmp14_ = _tmp13_;
							if (!_tmp14_) {
								gint _tmp15_;
								_tmp15_ = y;
								y = _tmp15_ + 1;
							}
							_tmp13_ = FALSE;
							_tmp16_ = y;
							if (!(_tmp16_ < 8)) {
								break;
							}
							_tmp17_ = g;
							_tmp18_ = x;
							_tmp19_ = y;
							_tmp20_ = game_place_tile (_tmp17_, _tmp18_, _tmp19_);
							n_tiles = _tmp20_;
							_tmp21_ = n_tiles;
							if (_tmp21_ > 0) {
								PossibleMove move = {0};
								gint _tmp22_;
								gint _tmp23_;
								gint _tmp24_;
								PossibleMove _tmp25_;
								PossibleMove* _tmp26_;
								Game* _tmp27_;
								memset (&move, 0, sizeof (PossibleMove));
								_tmp22_ = x;
								move.x = _tmp22_;
								_tmp23_ = y;
								move.y = _tmp23_;
								_tmp24_ = n_tiles;
								move.n_tiles = _tmp24_;
								_tmp25_ = move;
								_tmp26_ = _possible_move_dup0 (&_tmp25_);
								moves = g_list_insert_sorted (moves, _tmp26_, _computer_player_compare_move_gcompare_func);
								_tmp27_ = g;
								game_undo (_tmp27_, 1);
							}
						}
					}
				}
			}
		}
	}
	_tmp28_ = moves;
	if (_tmp28_ == NULL) {
		PossibleMove move = {0};
		PossibleMove _tmp29_;
		PossibleMove* _tmp30_;
		memset (&move, 0, sizeof (PossibleMove));
		move.x = 0;
		move.y = 0;
		move.n_tiles = 0;
		_tmp29_ = move;
		_tmp30_ = _possible_move_dup0 (&_tmp29_);
		moves = g_list_append (moves, _tmp30_);
	}
	_tmp31_ = moves;
	{
		GList* move_collection = NULL;
		GList* move_it = NULL;
		move_collection = _tmp31_;
		for (move_it = move_collection; move_it != NULL; move_it = move_it->next) {
			PossibleMove* _tmp32_;
			PossibleMove* move = NULL;
			_tmp32_ = _possible_move_dup0 ((PossibleMove*) move_it->data);
			move = _tmp32_;
			{
				PossibleMove* _tmp33_;
				gint _tmp34_;
				gint _tmp49_;
				Game* _tmp78_;
				gint _tmp79_;
				gint _tmp80_;
				_tmp33_ = move;
				_tmp34_ = (*_tmp33_).n_tiles;
				if (_tmp34_ == 0) {
					Game* _tmp35_;
					_tmp35_ = g;
					game_pass (_tmp35_);
				} else {
					Game* _tmp36_;
					PossibleMove* _tmp37_;
					gint _tmp38_;
					PossibleMove* _tmp39_;
					gint _tmp40_;
					gint _tmp41_ = 0;
					_tmp36_ = g;
					_tmp37_ = move;
					_tmp38_ = (*_tmp37_).x;
					_tmp39_ = move;
					_tmp40_ = (*_tmp39_).y;
					_tmp41_ = game_place_tile (_tmp36_, _tmp38_, _tmp40_);
					if (_tmp41_ == 0) {
						gint _tmp42_;
						PossibleMove* _tmp43_;
						gint _tmp44_;
						PossibleMove* _tmp45_;
						gint _tmp46_;
						PossibleMove* _tmp47_;
						gint _tmp48_;
						_tmp42_ = depth;
						_tmp43_ = move;
						_tmp44_ = (*_tmp43_).x;
						_tmp45_ = move;
						_tmp46_ = (*_tmp45_).y;
						_tmp47_ = move;
						_tmp48_ = (*_tmp47_).n_tiles;
						g_warning ("computer-player.vala:119: Computer marked move (depth %d, %d,%d, %d fl" \
"ips) as valid, but is invalid when checking", _tmp42_, _tmp44_, _tmp46_, _tmp48_);
						_possible_move_free0 (move);
						continue;
					}
				}
				_tmp49_ = p;
				if (_tmp49_ > 0) {
					gint next_x_move;
					gint next_y_move;
					Game* _tmp50_;
					Strategy _tmp51_;
					gint _tmp52_;
					gint _tmp53_;
					gint _tmp54_;
					gint _tmp55_;
					gint _tmp56_ = 0;
					gint a_new;
					gint _tmp57_;
					gint _tmp58_;
					next_x_move = 0;
					next_y_move = 0;
					_tmp50_ = g;
					_tmp51_ = strategy;
					_tmp52_ = depth;
					_tmp53_ = a;
					_tmp54_ = b;
					_tmp55_ = p;
					_tmp56_ = computer_player_search (self, _tmp50_, _tmp51_, _tmp52_ - 1, _tmp53_, _tmp54_, -_tmp55_, &next_x_move, &next_y_move);
					a_new = _tmp56_;
					_tmp57_ = a_new;
					_tmp58_ = a;
					if (_tmp57_ > _tmp58_) {
						gint _tmp59_;
						PossibleMove* _tmp60_;
						gint _tmp61_;
						PossibleMove* _tmp62_;
						gint _tmp63_;
						_tmp59_ = a_new;
						a = _tmp59_;
						_tmp60_ = move;
						_tmp61_ = (*_tmp60_).x;
						*move_x = _tmp61_;
						_tmp62_ = move;
						_tmp63_ = (*_tmp62_).y;
						*move_y = _tmp63_;
					}
				} else {
					gint next_x_move;
					gint next_y_move;
					Game* _tmp64_;
					Strategy _tmp65_;
					gint _tmp66_;
					gint _tmp67_;
					gint _tmp68_;
					gint _tmp69_;
					gint _tmp70_ = 0;
					gint b_new;
					gint _tmp71_;
					gint _tmp72_;
					next_x_move = 0;
					next_y_move = 0;
					_tmp64_ = g;
					_tmp65_ = strategy;
					_tmp66_ = depth;
					_tmp67_ = a;
					_tmp68_ = b;
					_tmp69_ = p;
					_tmp70_ = computer_player_search (self, _tmp64_, _tmp65_, _tmp66_ - 1, _tmp67_, _tmp68_, -_tmp69_, &next_x_move, &next_y_move);
					b_new = _tmp70_;
					_tmp71_ = b_new;
					_tmp72_ = b;
					if (_tmp71_ < _tmp72_) {
						gint _tmp73_;
						PossibleMove* _tmp74_;
						gint _tmp75_;
						PossibleMove* _tmp76_;
						gint _tmp77_;
						_tmp73_ = b_new;
						b = _tmp73_;
						_tmp74_ = move;
						_tmp75_ = (*_tmp74_).x;
						*move_x = _tmp75_;
						_tmp76_ = move;
						_tmp77_ = (*_tmp76_).y;
						*move_y = _tmp77_;
					}
				}
				_tmp78_ = g;
				game_undo (_tmp78_, 1);
				_tmp79_ = b;
				_tmp80_ = a;
				if (_tmp79_ <= _tmp80_) {
					_possible_move_free0 (move);
					break;
				}
				_possible_move_free0 (move);
			}
		}
	}
	_tmp81_ = p;
	if (_tmp81_ > 0) {
		gint _tmp82_;
		_tmp82_ = a;
		result = _tmp82_;
		__g_list_free__possible_move_free0_0 (moves);
		return result;
	} else {
		gint _tmp83_;
		_tmp83_ = b;
		result = _tmp83_;
		__g_list_free__possible_move_free0_0 (moves);
		return result;
	}
	__g_list_free__possible_move_free0_0 (moves);
}


static gint computer_player_compare_move (PossibleMove* a, PossibleMove* b) {
	gint result = 0;
	PossibleMove* _tmp0_;
	gint _tmp1_;
	PossibleMove* _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, Strategy strategy) {
	gint result = 0;
	Game* _tmp0_;
	gint _tmp1_;
	gint _tmp2_;
	Game* _tmp3_;
	gint _tmp4_;
	gint _tmp5_;
	gint tile_difference;
	Game* _tmp6_;
	Player _tmp7_;
	Strategy _tmp9_;
	g_return_val_if_fail (self != NULL, 0);
	g_return_val_if_fail (g != NULL, 0);
	_tmp0_ = g;
	_tmp1_ = game_get_n_dark_tiles (_tmp0_);
	_tmp2_ = _tmp1_;
	_tmp3_ = g;
	_tmp4_ = game_get_n_light_tiles (_tmp3_);
	_tmp5_ = _tmp4_;
	tile_difference = _tmp2_ - _tmp5_;
	_tmp6_ = g;
	_tmp7_ = _tmp6_->current_color;
	if (_tmp7_ == PLAYER_DARK) {
		gint _tmp8_;
		_tmp8_ = tile_difference;
		tile_difference = -_tmp8_;
	}
	_tmp9_ = strategy;
	switch (_tmp9_) {
		case STRATEGY_PERFECT:
		{
			result = tile_difference;
			return result;
		}
		case STRATEGY_VICTORY:
		{
			gint _tmp10_;
			gint _tmp11_ = 0;
			_tmp10_ = tile_difference;
			_tmp11_ = CLAMP (_tmp10_, -1, 1);
			result = _tmp11_;
			return result;
		}
		default:
		{
			gint _tmp12_;
			gint _tmp13_ = 0;
			gint _tmp14_ = 0;
			_tmp12_ = tile_difference;
			_tmp13_ = computer_player_around (self);
			_tmp14_ = computer_player_eval_heuristic (self);
			result = (_tmp12_ + _tmp13_) + _tmp14_;
			return result;
		}
	}
}


static gint computer_player_eval_heuristic (ComputerPlayer* self) {
	gint result = 0;
	gint count;
	g_return_val_if_fail (self != NULL, 0);
	count = 0;
	{
		gint x;
		x = 0;
		{
			gboolean _tmp0_;
			_tmp0_ = TRUE;
			while (TRUE) {
				gboolean _tmp1_;
				gint _tmp3_;
				_tmp1_ = _tmp0_;
				if (!_tmp1_) {
					gint _tmp2_;
					_tmp2_ = x;
					x = _tmp2_ + 1;
				}
				_tmp0_ = FALSE;
				_tmp3_ = x;
				if (!(_tmp3_ < 8)) {
					break;
				}
				{
					gint y;
					y = 0;
					{
						gboolean _tmp4_;
						_tmp4_ = TRUE;
						while (TRUE) {
							gboolean _tmp5_;
							gint _tmp7_;
							gint _tmp8_;
							gint _tmp9_;
							gint _tmp10_;
							gint h;
							Game* _tmp11_;
							gint _tmp12_;
							gint _tmp13_;
							Player _tmp14_ = 0;
							Game* _tmp15_;
							Player _tmp16_;
							gint _tmp18_;
							gint _tmp19_;
							_tmp5_ = _tmp4_;
							if (!_tmp5_) {
								gint _tmp6_;
								_tmp6_ = y;
								y = _tmp6_ + 1;
							}
							_tmp4_ = FALSE;
							_tmp7_ = y;
							if (!(_tmp7_ < 8)) {
								break;
							}
							_tmp8_ = y;
							_tmp9_ = x;
							_tmp10_ = COMPUTER_PLAYER_heuristic[(_tmp8_ * 8) + _tmp9_];
							h = _tmp10_;
							_tmp11_ = self->priv->game;
							_tmp12_ = x;
							_tmp13_ = y;
							_tmp14_ = game_get_owner (_tmp11_, _tmp12_, _tmp13_);
							_tmp15_ = self->priv->game;
							_tmp16_ = _tmp15_->current_color;
							if (_tmp14_ != _tmp16_) {
								gint _tmp17_;
								_tmp17_ = h;
								h = -_tmp17_;
							}
							_tmp18_ = count;
							_tmp19_ = h;
							count = _tmp18_ + _tmp19_;
						}
					}
				}
			}
		}
	}
	result = count;
	return result;
}


static gint computer_player_around (ComputerPlayer* self) {
	gint result = 0;
	gint count;
	g_return_val_if_fail (self != NULL, 0);
	count = 0;
	{
		gint x;
		x = 0;
		{
			gboolean _tmp0_;
			_tmp0_ = TRUE;
			while (TRUE) {
				gboolean _tmp1_;
				gint _tmp3_;
				_tmp1_ = _tmp0_;
				if (!_tmp1_) {
					gint _tmp2_;
					_tmp2_ = x;
					x = _tmp2_ + 1;
				}
				_tmp0_ = FALSE;
				_tmp3_ = x;
				if (!(_tmp3_ < 8)) {
					break;
				}
				{
					gint y;
					y = 0;
					{
						gboolean _tmp4_;
						_tmp4_ = TRUE;
						while (TRUE) {
							gboolean _tmp5_;
							gint _tmp7_;
							gint a;
							gint _tmp8_;
							gint _tmp9_;
							gint _tmp10_;
							gint _tmp11_ = 0;
							gint _tmp12_;
							gint _tmp13_;
							gint _tmp14_;
							gint _tmp15_ = 0;
							gint _tmp16_;
							gint _tmp17_;
							gint _tmp18_;
							gint _tmp19_ = 0;
							gint _tmp20_;
							gint _tmp21_;
							gint _tmp22_;
							gint _tmp23_ = 0;
							gint _tmp24_;
							gint _tmp25_;
							gint _tmp26_;
							gint _tmp27_ = 0;
							gint _tmp28_;
							gint _tmp29_;
							gint _tmp30_;
							gint _tmp31_ = 0;
							gint _tmp32_;
							gint _tmp33_;
							gint _tmp34_;
							gint _tmp35_ = 0;
							gint _tmp36_;
							gint _tmp37_;
							gint _tmp38_;
							gint _tmp39_ = 0;
							gint _tmp40_;
							Game* _tmp41_;
							gint _tmp42_;
							gint _tmp43_;
							Player _tmp44_ = 0;
							Game* _tmp45_;
							Player _tmp46_;
							gint _tmp48_;
							gint _tmp49_;
							_tmp5_ = _tmp4_;
							if (!_tmp5_) {
								gint _tmp6_;
								_tmp6_ = y;
								y = _tmp6_ + 1;
							}
							_tmp4_ = FALSE;
							_tmp7_ = y;
							if (!(_tmp7_ < 8)) {
								break;
							}
							a = 0;
							_tmp8_ = a;
							_tmp9_ = x;
							_tmp10_ = y;
							_tmp11_ = computer_player_is_empty (self, _tmp9_ + 1, _tmp10_);
							a = _tmp8_ + _tmp11_;
							_tmp12_ = a;
							_tmp13_ = x;
							_tmp14_ = y;
							_tmp15_ = computer_player_is_empty (self, _tmp13_ + 1, _tmp14_ + 1);
							a = _tmp12_ + _tmp15_;
							_tmp16_ = a;
							_tmp17_ = x;
							_tmp18_ = y;
							_tmp19_ = computer_player_is_empty (self, _tmp17_, _tmp18_ + 1);
							a = _tmp16_ + _tmp19_;
							_tmp20_ = a;
							_tmp21_ = x;
							_tmp22_ = y;
							_tmp23_ = computer_player_is_empty (self, _tmp21_ - 1, _tmp22_ + 1);
							a = _tmp20_ + _tmp23_;
							_tmp24_ = a;
							_tmp25_ = x;
							_tmp26_ = y;
							_tmp27_ = computer_player_is_empty (self, _tmp25_ - 1, _tmp26_);
							a = _tmp24_ + _tmp27_;
							_tmp28_ = a;
							_tmp29_ = x;
							_tmp30_ = y;
							_tmp31_ = computer_player_is_empty (self, _tmp29_ - 1, _tmp30_ - 1);
							a = _tmp28_ + _tmp31_;
							_tmp32_ = a;
							_tmp33_ = x;
							_tmp34_ = y;
							_tmp35_ = computer_player_is_empty (self, _tmp33_, _tmp34_ - 1);
							a = _tmp32_ + _tmp35_;
							_tmp36_ = a;
							_tmp37_ = x;
							_tmp38_ = y;
							_tmp39_ = computer_player_is_empty (self, _tmp37_ + 1, _tmp38_ - 1);
							a = _tmp36_ + _tmp39_;
							_tmp40_ = a;
							if (_tmp40_ == 0) {
								a = 2;
							}
							_tmp41_ = self->priv->game;
							_tmp42_ = x;
							_tmp43_ = y;
							_tmp44_ = game_get_owner (_tmp41_, _tmp42_, _tmp43_);
							_tmp45_ = self->priv->game;
							_tmp46_ = _tmp45_->current_color;
							if (_tmp44_ != _tmp46_) {
								gint _tmp47_;
								_tmp47_ = a;
								a = -_tmp47_;
							}
							_tmp48_ = count;
							_tmp49_ = a;
							count = _tmp48_ + _tmp49_;
						}
					}
				}
			}
		}
	}
	result = count;
	return result;
}


static gint computer_player_is_empty (ComputerPlayer* self, gint x, gint y) {
	gint result = 0;
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean _tmp2_ = FALSE;
	gboolean _tmp3_ = FALSE;
	gint _tmp4_;
	gboolean _tmp6_;
	gboolean _tmp8_;
	gboolean _tmp10_;
	gboolean _tmp15_;
	g_return_val_if_fail (self != NULL, 0);
	_tmp4_ = x;
	if (_tmp4_ < 0) {
		_tmp3_ = TRUE;
	} else {
		gint _tmp5_;
		_tmp5_ = x;
		_tmp3_ = _tmp5_ >= 8;
	}
	_tmp6_ = _tmp3_;
	if (_tmp6_) {
		_tmp2_ = TRUE;
	} else {
		gint _tmp7_;
		_tmp7_ = y;
		_tmp2_ = _tmp7_ < 0;
	}
	_tmp8_ = _tmp2_;
	if (_tmp8_) {
		_tmp1_ = TRUE;
	} else {
		gint _tmp9_;
		_tmp9_ = y;
		_tmp1_ = _tmp9_ >= 8;
	}
	_tmp10_ = _tmp1_;
	if (_tmp10_) {
		_tmp0_ = TRUE;
	} else {
		Game* _tmp11_;
		gint _tmp12_;
		gint _tmp13_;
		Player _tmp14_ = 0;
		_tmp11_ = self->priv->game;
		_tmp12_ = x;
		_tmp13_ = y;
		_tmp14_ = game_get_owner (_tmp11_, _tmp12_, _tmp13_);
		_tmp0_ = _tmp14_ != PLAYER_NONE;
	}
	_tmp15_ = _tmp0_;
	if (_tmp15_) {
		result = 0;
		return result;
	}
	result = 1;
	return result;
}


static void computer_player_random_select (ComputerPlayer* self, gint* move_x, gint* move_y) {
	gint _vala_move_x = 0;
	gint _vala_move_y = 0;
	GList* moves;
	GList* _tmp14_;
	g_return_if_fail (self != NULL);
	moves = NULL;
	{
		gint x;
		x = 0;
		{
			gboolean _tmp0_;
			_tmp0_ = TRUE;
			while (TRUE) {
				gboolean _tmp1_;
				gint _tmp3_;
				_tmp1_ = _tmp0_;
				if (!_tmp1_) {
					gint _tmp2_;
					_tmp2_ = x;
					x = _tmp2_ + 1;
				}
				_tmp0_ = FALSE;
				_tmp3_ = x;
				if (!(_tmp3_ < 8)) {
					break;
				}
				{
					gint y;
					y = 0;
					{
						gboolean _tmp4_;
						_tmp4_ = TRUE;
						while (TRUE) {
							gboolean _tmp5_;
							gint _tmp7_;
							Game* _tmp8_;
							gint _tmp9_;
							gint _tmp10_;
							gboolean _tmp11_ = FALSE;
							_tmp5_ = _tmp4_;
							if (!_tmp5_) {
								gint _tmp6_;
								_tmp6_ = y;
								y = _tmp6_ + 1;
							}
							_tmp4_ = FALSE;
							_tmp7_ = y;
							if (!(_tmp7_ < 8)) {
								break;
							}
							_tmp8_ = self->priv->game;
							_tmp9_ = x;
							_tmp10_ = y;
							_tmp11_ = game_can_place (_tmp8_, _tmp9_, _tmp10_);
							if (_tmp11_) {
								gint _tmp12_;
								gint _tmp13_;
								_tmp12_ = x;
								_tmp13_ = y;
								moves = g_list_append (moves, GINT_TO_POINTER ((_tmp12_ * 8) + _tmp13_));
							}
						}
					}
				}
			}
		}
	}
	_tmp14_ = moves;
	if (_tmp14_ != NULL) {
		GList* _tmp15_;
		guint _tmp16_ = 0U;
		gint32 _tmp17_ = 0;
		gint32 i;
		GList* _tmp18_;
		gint32 _tmp19_;
		gconstpointer _tmp20_ = NULL;
		gint xy;
		gint _tmp21_;
		gint _tmp22_;
		_tmp15_ = moves;
		_tmp16_ = g_list_length (_tmp15_);
		_tmp17_ = g_random_int_range ((gint32) 0, (gint32) ((gint) _tmp16_));
		i = _tmp17_;
		_tmp18_ = moves;
		_tmp19_ = i;
		_tmp20_ = g_list_nth_data (_tmp18_, (guint) _tmp19_);
		xy = GPOINTER_TO_INT (_tmp20_);
		_tmp21_ = xy;
		_vala_move_x = _tmp21_ / 8;
		_tmp22_ = xy;
		_vala_move_y = _tmp22_ % 8;
	} else {
		gint _tmp23_;
		_vala_move_y = 0;
		_tmp23_ = _vala_move_y;
		_vala_move_x = _tmp23_;
	}
	_g_list_free0 (moves);
	if (move_x) {
		*move_x = _vala_move_x;
	}
	if (move_y) {
		*move_y = _vala_move_y;
	}
}


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


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


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


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


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


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


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


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


void value_set_computer_player (GValue* value, gpointer v_object) {
	ComputerPlayer* old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_COMPUTER_PLAYER));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_COMPUTER_PLAYER));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
		computer_player_ref (value->data[0].v_pointer);
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		computer_player_unref (old);
	}
}


void value_take_computer_player (GValue* value, gpointer v_object) {
	ComputerPlayer* old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_COMPUTER_PLAYER));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_COMPUTER_PLAYER));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		computer_player_unref (old);
	}
}


static void computer_player_class_init (ComputerPlayerClass * klass) {
	computer_player_parent_class = g_type_class_peek_parent (klass);
	COMPUTER_PLAYER_CLASS (klass)->finalize = computer_player_finalize;
	g_type_class_add_private (klass, sizeof (ComputerPlayerPrivate));
}


static void computer_player_instance_init (ComputerPlayer * self) {
	self->priv = COMPUTER_PLAYER_GET_PRIVATE (self);
	self->ref_count = 1;
}


static void computer_player_finalize (ComputerPlayer* obj) {
	ComputerPlayer * self;
	self = COMPUTER_PLAYER (obj);
	_game_unref0 (self->priv->game);
}


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 GTypeValueTable g_define_type_value_table = { value_computer_player_init, value_computer_player_free_value, value_computer_player_copy_value, value_computer_player_peek_pointer, "p", value_computer_player_collect_value, "p", value_computer_player_lcopy_value };
		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, &g_define_type_value_table };
		static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };
		GType computer_player_type_id;
		computer_player_type_id = g_type_register_fundamental (g_type_fundamental_next (), "ComputerPlayer", &g_define_type_info, &g_define_type_fundamental_info, 0);
		g_once_init_leave (&computer_player_type_id__volatile, computer_player_type_id);
	}
	return computer_player_type_id__volatile;
}


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


void computer_player_unref (gpointer instance) {
	ComputerPlayer* self;
	self = instance;
	if (g_atomic_int_dec_and_test (&self->ref_count)) {
		COMPUTER_PLAYER_GET_CLASS (self)->finalize (self);
		g_type_free_instance ((GTypeInstance *) self);
	}
}



