/* chess-state.c generated by valac 0.56.0, the Vala compiler
 * generated from chess-state.vala, do not modify */

/* -*- Mode: vala; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 *
 * Copyright (C) 2010-2014 Robert Ancell
 * Copyright (C) 2015-2016 Sahil Sareen
 *
 * 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. See http://www.gnu.org/copyleft/gpl.html the full text of the
 * license.
 */

#include "libchess.h"
#include <glib.h>
#include <glib-object.h>
#include <stdlib.h>
#include <string.h>

enum  {
	CHESS_STATE_0_PROPERTY,
	CHESS_STATE_OPPONENT_PROPERTY,
	CHESS_STATE_NUM_PROPERTIES
};
static GParamSpec* chess_state_properties[CHESS_STATE_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))
#define _g_string_free0(var) ((var == NULL) ? NULL : (var = (g_string_free (var, TRUE), NULL)))

struct _ChessStatePrivate {
	gint64 piece_masks[2];
};

static gint ChessState_private_offset;
static gpointer chess_state_parent_class = NULL;

static ChessState* chess_state_new_empty (void);
static ChessState* chess_state_construct_empty (GType object_type);
static gboolean chess_state_decode_piece_type (ChessState* self,
                                        gunichar c,
                                        PieceType* type);
static CheckState chess_state_get_check_state (ChessState* self,
                                        ChessPlayer* player);
static gboolean chess_state_decode_move (ChessState* self,
                                  ChessPlayer* player,
                                  const gchar* move,
                                  gint* r0,
                                  gint* f0,
                                  gint* r1,
                                  gint* f1,
                                  PieceType* promotion_type);
static gboolean chess_state_is_in_checkmate (ChessState* self,
                                      ChessPlayer* player);
static void chess_state_finalize (GObject * obj);
static GType chess_state_get_type_once (void);
static void _vala_chess_state_get_property (GObject * object,
                                     guint property_id,
                                     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);
static gssize _vala_array_length (gpointer array);

VALA_EXTERN const gint64 BIT_BOARD_set_location_masks[64];
VALA_EXTERN const gint64 BIT_BOARD_move_masks[768];
VALA_EXTERN const gint64 BIT_BOARD_over_masks[4096];
VALA_EXTERN const gint64 BIT_BOARD_clear_location_masks[64];

static GType
check_state_get_type_once (void)
{
	static const GEnumValue values[] = {{CHECK_STATE_NONE, "CHECK_STATE_NONE", "none"}, {CHECK_STATE_CHECK, "CHECK_STATE_CHECK", "check"}, {CHECK_STATE_CHECKMATE, "CHECK_STATE_CHECKMATE", "checkmate"}, {0, NULL, NULL}};
	GType check_state_type_id;
	check_state_type_id = g_enum_register_static ("CheckState", values);
	return check_state_type_id;
}

GType
check_state_get_type (void)
{
	static volatile gsize check_state_type_id__once = 0;
	if (g_once_init_enter (&check_state_type_id__once)) {
		GType check_state_type_id;
		check_state_type_id = check_state_get_type_once ();
		g_once_init_leave (&check_state_type_id__once, check_state_type_id);
	}
	return check_state_type_id__once;
}

static inline gpointer
chess_state_get_instance_private (ChessState* self)
{
	return G_STRUCT_MEMBER_P (self, ChessState_private_offset);
}

static ChessState*
chess_state_construct_empty (GType object_type)
{
	ChessState * self = NULL;
	self = (ChessState*) g_object_new (object_type, NULL);
	return self;
}

static ChessState*
chess_state_new_empty (void)
{
	return chess_state_construct_empty (TYPE_CHESS_STATE);
}

static gchar
string_get (const gchar* self,
            glong index)
{
	gchar _tmp0_;
	gchar result;
	g_return_val_if_fail (self != NULL, '\0');
	_tmp0_ = ((gchar*) self)[index];
	result = _tmp0_;
	return result;
}

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

ChessState*
chess_state_construct (GType object_type,
                       const gchar* fen)
{
	ChessState * self = NULL;
	ChessPlayer* _tmp0_;
	ChessPlayer* _tmp1_;
	gchar** fields = NULL;
	gchar** _tmp4_;
	gchar** _tmp5_;
	gint fields_length1;
	gint _fields_size_;
	gchar** ranks = NULL;
	gchar** _tmp6_;
	gint _tmp6__length1;
	const gchar* _tmp7_;
	gchar** _tmp8_;
	gchar** _tmp9_;
	gint ranks_length1;
	gint _ranks_size_;
	gchar** _tmp31_;
	gint _tmp31__length1;
	const gchar* _tmp32_;
	gchar** _tmp39_;
	gint _tmp39__length1;
	const gchar* _tmp40_;
	gchar** _tmp49_;
	gint _tmp49__length1;
	const gchar* _tmp50_;
	gchar** _tmp55_;
	gint _tmp55__length1;
	const gchar* _tmp56_;
	gchar** _tmp57_;
	gint _tmp57__length1;
	const gchar* _tmp58_;
	ChessPlayer* _tmp59_;
	ChessPlayer* _tmp61_;
	g_return_val_if_fail (fen != NULL, NULL);
	self = (ChessState*) g_object_new (object_type, NULL);
	_tmp0_ = chess_player_new (COLOR_WHITE);
	_g_object_unref0 (self->players[COLOR_WHITE]);
	self->players[COLOR_WHITE] = _tmp0_;
	_tmp1_ = chess_player_new (COLOR_BLACK);
	_g_object_unref0 (self->players[COLOR_BLACK]);
	self->players[COLOR_BLACK] = _tmp1_;
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp2_ = FALSE;
			_tmp2_ = TRUE;
			while (TRUE) {
				if (!_tmp2_) {
					gint _tmp3_;
					_tmp3_ = i;
					i = _tmp3_ + 1;
				}
				_tmp2_ = FALSE;
				if (!(i < 64)) {
					break;
				}
				_g_object_unref0 (self->board[i]);
				self->board[i] = NULL;
			}
		}
	}
	_tmp5_ = _tmp4_ = g_strsplit (fen, " ", 0);
	fields = _tmp5_;
	fields_length1 = _vala_array_length (_tmp4_);
	_fields_size_ = fields_length1;
	_tmp6_ = fields;
	_tmp6__length1 = fields_length1;
	_tmp7_ = _tmp6_[0];
	_tmp9_ = _tmp8_ = g_strsplit (_tmp7_, "/", 0);
	ranks = _tmp9_;
	ranks_length1 = _vala_array_length (_tmp8_);
	_ranks_size_ = ranks_length1;
	{
		gint rank = 0;
		rank = 0;
		{
			gboolean _tmp10_ = FALSE;
			_tmp10_ = TRUE;
			while (TRUE) {
				gchar* rank_string = NULL;
				gchar** _tmp12_;
				gint _tmp12__length1;
				const gchar* _tmp13_;
				gchar* _tmp14_;
				if (!_tmp10_) {
					gint _tmp11_;
					_tmp11_ = rank;
					rank = _tmp11_ + 1;
				}
				_tmp10_ = FALSE;
				if (!(rank < 8)) {
					break;
				}
				_tmp12_ = ranks;
				_tmp12__length1 = ranks_length1;
				_tmp13_ = _tmp12_[7 - rank];
				_tmp14_ = g_strdup (_tmp13_);
				rank_string = _tmp14_;
				{
					gint file = 0;
					gint offset = 0;
					file = 0;
					offset = 0;
					{
						gboolean _tmp15_ = FALSE;
						_tmp15_ = TRUE;
						while (TRUE) {
							gboolean _tmp17_ = FALSE;
							gchar c = '\0';
							const gchar* _tmp21_;
							gboolean _tmp22_ = FALSE;
							PieceType type = 0;
							Color _tmp23_ = 0;
							Color color = 0;
							PieceType _tmp24_ = 0;
							gint index = 0;
							ChessPiece* piece = NULL;
							ChessPlayer* _tmp25_;
							ChessPiece* _tmp26_;
							ChessPiece* _tmp27_;
							ChessPiece* _tmp28_;
							gint64 mask = 0LL;
							gint64 _tmp29_;
							gint _tmp30_;
							if (!_tmp15_) {
								gint _tmp16_;
								_tmp16_ = offset;
								offset = _tmp16_ + 1;
							}
							_tmp15_ = FALSE;
							if (file < 8) {
								const gchar* _tmp18_;
								gint _tmp19_;
								gint _tmp20_;
								_tmp18_ = rank_string;
								_tmp19_ = strlen (_tmp18_);
								_tmp20_ = _tmp19_;
								_tmp17_ = offset < _tmp20_;
							} else {
								_tmp17_ = FALSE;
							}
							if (!_tmp17_) {
								break;
							}
							_tmp21_ = rank_string;
							c = string_get (_tmp21_, (glong) offset);
							if (c >= '1') {
								_tmp22_ = c <= '8';
							} else {
								_tmp22_ = FALSE;
							}
							if (_tmp22_) {
								file += (gint) (c - '0');
								continue;
							}
							if (g_ascii_isupper (c)) {
								_tmp23_ = COLOR_WHITE;
							} else {
								_tmp23_ = COLOR_BLACK;
							}
							color = _tmp23_;
							chess_state_decode_piece_type (self, (gunichar) g_ascii_toupper (c), &_tmp24_);
							type = _tmp24_;
							index = chess_state_get_index (self, rank, file);
							_tmp25_ = self->players[color];
							_tmp26_ = chess_piece_new (_tmp25_, type);
							piece = _tmp26_;
							_tmp27_ = piece;
							_tmp28_ = _g_object_ref0 (_tmp27_);
							_g_object_unref0 (self->board[index]);
							self->board[index] = _tmp28_;
							_tmp29_ = BIT_BOARD_set_location_masks[index];
							mask = _tmp29_;
							self->priv->piece_masks[color] |= mask;
							_tmp30_ = file;
							file = _tmp30_ + 1;
							_g_object_unref0 (piece);
						}
					}
				}
				_g_free0 (rank_string);
			}
		}
	}
	_tmp31_ = fields;
	_tmp31__length1 = fields_length1;
	_tmp32_ = _tmp31_[1];
	if (g_strcmp0 (_tmp32_, "w") == 0) {
		ChessPlayer* _tmp33_;
		ChessPlayer* _tmp34_;
		_tmp33_ = self->players[COLOR_WHITE];
		_tmp34_ = _g_object_ref0 (_tmp33_);
		_g_object_unref0 (self->current_player);
		self->current_player = _tmp34_;
	} else {
		gchar** _tmp35_;
		gint _tmp35__length1;
		const gchar* _tmp36_;
		_tmp35_ = fields;
		_tmp35__length1 = fields_length1;
		_tmp36_ = _tmp35_[1];
		if (g_strcmp0 (_tmp36_, "b") == 0) {
			ChessPlayer* _tmp37_;
			ChessPlayer* _tmp38_;
			_tmp37_ = self->players[COLOR_BLACK];
			_tmp38_ = _g_object_ref0 (_tmp37_);
			_g_object_unref0 (self->current_player);
			self->current_player = _tmp38_;
		}
	}
	_tmp39_ = fields;
	_tmp39__length1 = fields_length1;
	_tmp40_ = _tmp39_[2];
	if (g_strcmp0 (_tmp40_, "-") != 0) {
		{
			gint i = 0;
			i = 0;
			{
				gboolean _tmp41_ = FALSE;
				_tmp41_ = TRUE;
				while (TRUE) {
					gchar** _tmp43_;
					gint _tmp43__length1;
					const gchar* _tmp44_;
					gint _tmp45_;
					gint _tmp46_;
					gchar c = '\0';
					gchar** _tmp47_;
					gint _tmp47__length1;
					const gchar* _tmp48_;
					if (!_tmp41_) {
						gint _tmp42_;
						_tmp42_ = i;
						i = _tmp42_ + 1;
					}
					_tmp41_ = FALSE;
					_tmp43_ = fields;
					_tmp43__length1 = fields_length1;
					_tmp44_ = _tmp43_[2];
					_tmp45_ = strlen (_tmp44_);
					_tmp46_ = _tmp45_;
					if (!(i < _tmp46_)) {
						break;
					}
					_tmp47_ = fields;
					_tmp47__length1 = fields_length1;
					_tmp48_ = _tmp47_[2];
					c = string_get (_tmp48_, (glong) i);
					if (c == 'K') {
						self->can_castle_kingside[COLOR_WHITE] = TRUE;
					} else {
						if (c == 'Q') {
							self->can_castle_queenside[COLOR_WHITE] = TRUE;
						} else {
							if (c == 'k') {
								self->can_castle_kingside[COLOR_BLACK] = TRUE;
							} else {
								if (c == 'q') {
									self->can_castle_queenside[COLOR_BLACK] = TRUE;
								}
							}
						}
					}
				}
			}
		}
	}
	_tmp49_ = fields;
	_tmp49__length1 = fields_length1;
	_tmp50_ = _tmp49_[3];
	if (g_strcmp0 (_tmp50_, "-") != 0) {
		gchar** _tmp51_;
		gint _tmp51__length1;
		const gchar* _tmp52_;
		gchar** _tmp53_;
		gint _tmp53__length1;
		const gchar* _tmp54_;
		_tmp51_ = fields;
		_tmp51__length1 = fields_length1;
		_tmp52_ = _tmp51_[3];
		_tmp53_ = fields;
		_tmp53__length1 = fields_length1;
		_tmp54_ = _tmp53_[3];
		self->en_passant_index = chess_state_get_index (self, (gint) (string_get (_tmp52_, (glong) 1) - '1'), (gint) (string_get (_tmp54_, (glong) 0) - 'a'));
	}
	_tmp55_ = fields;
	_tmp55__length1 = fields_length1;
	_tmp56_ = _tmp55_[4];
	self->halfmove_clock = atoi (_tmp56_);
	_tmp57_ = fields;
	_tmp57__length1 = fields_length1;
	_tmp58_ = _tmp57_[5];
	self->number = (atoi (_tmp58_) - 1) * 2;
	_tmp59_ = self->current_player;
	if (_tmp59_->color == COLOR_BLACK) {
		gint _tmp60_;
		_tmp60_ = self->number;
		self->number = _tmp60_ + 1;
	}
	_tmp61_ = self->current_player;
	self->check_state = chess_state_get_check_state (self, _tmp61_);
	ranks = (_vala_array_free (ranks, ranks_length1, (GDestroyNotify) g_free), NULL);
	fields = (_vala_array_free (fields, fields_length1, (GDestroyNotify) g_free), NULL);
	return self;
}

ChessState*
chess_state_new (const gchar* fen)
{
	return chess_state_construct (TYPE_CHESS_STATE, fen);
}

ChessState*
chess_state_copy (ChessState* self)
{
	ChessState* state = NULL;
	ChessState* _tmp0_;
	ChessState* _tmp1_;
	ChessState* _tmp2_;
	ChessPlayer* _tmp3_;
	ChessPlayer* _tmp4_;
	ChessState* _tmp5_;
	ChessPlayer* _tmp6_;
	ChessPlayer* _tmp7_;
	ChessState* _tmp8_;
	ChessPlayer* _tmp9_;
	ChessPlayer* _tmp10_;
	ChessState* _tmp11_;
	gboolean _tmp12_;
	ChessState* _tmp13_;
	gboolean _tmp14_;
	ChessState* _tmp15_;
	gboolean _tmp16_;
	ChessState* _tmp17_;
	gboolean _tmp18_;
	ChessState* _tmp19_;
	ChessState* _tmp20_;
	ChessMove* _tmp21_;
	ChessState* _tmp30_;
	gint64 _tmp31_;
	ChessState* _tmp32_;
	gint64 _tmp33_;
	ChessState* _tmp34_;
	ChessState* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = chess_state_new_empty ();
	state = _tmp0_;
	_tmp1_ = state;
	_tmp1_->number = self->number;
	_tmp2_ = state;
	_tmp3_ = self->players[COLOR_WHITE];
	_tmp4_ = _g_object_ref0 (_tmp3_);
	_g_object_unref0 (_tmp2_->players[COLOR_WHITE]);
	_tmp2_->players[COLOR_WHITE] = _tmp4_;
	_tmp5_ = state;
	_tmp6_ = self->players[COLOR_BLACK];
	_tmp7_ = _g_object_ref0 (_tmp6_);
	_g_object_unref0 (_tmp5_->players[COLOR_BLACK]);
	_tmp5_->players[COLOR_BLACK] = _tmp7_;
	_tmp8_ = state;
	_tmp9_ = self->current_player;
	_tmp10_ = _g_object_ref0 (_tmp9_);
	_g_object_unref0 (_tmp8_->current_player);
	_tmp8_->current_player = _tmp10_;
	_tmp11_ = state;
	_tmp12_ = self->can_castle_kingside[COLOR_WHITE];
	_tmp11_->can_castle_kingside[COLOR_WHITE] = _tmp12_;
	_tmp13_ = state;
	_tmp14_ = self->can_castle_queenside[COLOR_WHITE];
	_tmp13_->can_castle_queenside[COLOR_WHITE] = _tmp14_;
	_tmp15_ = state;
	_tmp16_ = self->can_castle_kingside[COLOR_BLACK];
	_tmp15_->can_castle_kingside[COLOR_BLACK] = _tmp16_;
	_tmp17_ = state;
	_tmp18_ = self->can_castle_queenside[COLOR_BLACK];
	_tmp17_->can_castle_queenside[COLOR_BLACK] = _tmp18_;
	_tmp19_ = state;
	_tmp19_->en_passant_index = self->en_passant_index;
	_tmp20_ = state;
	_tmp20_->check_state = self->check_state;
	_tmp21_ = self->last_move;
	if (_tmp21_ != NULL) {
		ChessState* _tmp22_;
		ChessMove* _tmp23_;
		ChessMove* _tmp24_;
		_tmp22_ = state;
		_tmp23_ = self->last_move;
		_tmp24_ = chess_move_copy (_tmp23_);
		_g_object_unref0 (_tmp22_->last_move);
		_tmp22_->last_move = _tmp24_;
	}
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp25_ = FALSE;
			_tmp25_ = TRUE;
			while (TRUE) {
				ChessState* _tmp27_;
				ChessPiece* _tmp28_;
				ChessPiece* _tmp29_;
				if (!_tmp25_) {
					gint _tmp26_;
					_tmp26_ = i;
					i = _tmp26_ + 1;
				}
				_tmp25_ = FALSE;
				if (!(i < 64)) {
					break;
				}
				_tmp27_ = state;
				_tmp28_ = self->board[i];
				_tmp29_ = _g_object_ref0 (_tmp28_);
				_g_object_unref0 (_tmp27_->board[i]);
				_tmp27_->board[i] = _tmp29_;
			}
		}
	}
	_tmp30_ = state;
	_tmp31_ = self->priv->piece_masks[COLOR_WHITE];
	_tmp30_->priv->piece_masks[COLOR_WHITE] = _tmp31_;
	_tmp32_ = state;
	_tmp33_ = self->priv->piece_masks[COLOR_BLACK];
	_tmp32_->priv->piece_masks[COLOR_BLACK] = _tmp33_;
	_tmp34_ = state;
	_tmp34_->halfmove_clock = self->halfmove_clock;
	result = state;
	return result;
}

gboolean
chess_state_equals (ChessState* self,
                    ChessState* state)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean _tmp2_ = FALSE;
	gboolean _tmp3_ = FALSE;
	gboolean _tmp4_ = FALSE;
	gboolean _tmp5_ = FALSE;
	gboolean _tmp6_ = FALSE;
	gint64 _tmp7_;
	gint64 _tmp8_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (state != NULL, FALSE);
	_tmp7_ = self->priv->piece_masks[COLOR_WHITE];
	_tmp8_ = state->priv->piece_masks[COLOR_WHITE];
	if (_tmp7_ != _tmp8_) {
		_tmp6_ = TRUE;
	} else {
		gint64 _tmp9_;
		gint64 _tmp10_;
		_tmp9_ = self->priv->piece_masks[COLOR_BLACK];
		_tmp10_ = state->priv->piece_masks[COLOR_BLACK];
		_tmp6_ = _tmp9_ != _tmp10_;
	}
	if (_tmp6_) {
		_tmp5_ = TRUE;
	} else {
		ChessPlayer* _tmp11_;
		ChessPlayer* _tmp12_;
		_tmp11_ = self->current_player;
		_tmp12_ = state->current_player;
		_tmp5_ = _tmp11_->color != _tmp12_->color;
	}
	if (_tmp5_) {
		_tmp4_ = TRUE;
	} else {
		gboolean _tmp13_;
		gboolean _tmp14_;
		_tmp13_ = self->can_castle_kingside[COLOR_WHITE];
		_tmp14_ = state->can_castle_kingside[COLOR_WHITE];
		_tmp4_ = _tmp13_ != _tmp14_;
	}
	if (_tmp4_) {
		_tmp3_ = TRUE;
	} else {
		gboolean _tmp15_;
		gboolean _tmp16_;
		_tmp15_ = self->can_castle_queenside[COLOR_WHITE];
		_tmp16_ = state->can_castle_queenside[COLOR_WHITE];
		_tmp3_ = _tmp15_ != _tmp16_;
	}
	if (_tmp3_) {
		_tmp2_ = TRUE;
	} else {
		gboolean _tmp17_;
		gboolean _tmp18_;
		_tmp17_ = self->can_castle_kingside[COLOR_BLACK];
		_tmp18_ = state->can_castle_kingside[COLOR_BLACK];
		_tmp2_ = _tmp17_ != _tmp18_;
	}
	if (_tmp2_) {
		_tmp1_ = TRUE;
	} else {
		gboolean _tmp19_;
		gboolean _tmp20_;
		_tmp19_ = self->can_castle_queenside[COLOR_BLACK];
		_tmp20_ = state->can_castle_queenside[COLOR_BLACK];
		_tmp1_ = _tmp19_ != _tmp20_;
	}
	if (_tmp1_) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = self->en_passant_index != state->en_passant_index;
	}
	if (_tmp0_) {
		result = FALSE;
		return result;
	}
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp21_ = FALSE;
			_tmp21_ = TRUE;
			while (TRUE) {
				gboolean _tmp23_ = FALSE;
				ChessPiece* _tmp24_;
				if (!_tmp21_) {
					gint _tmp22_;
					_tmp22_ = i;
					i = _tmp22_ + 1;
				}
				_tmp21_ = FALSE;
				if (!(i < 64)) {
					break;
				}
				_tmp24_ = self->board[i];
				if (_tmp24_ != NULL) {
					ChessPiece* _tmp25_;
					ChessPiece* _tmp26_;
					_tmp25_ = self->board[i];
					_tmp26_ = state->board[i];
					_tmp23_ = _tmp25_->type != _tmp26_->type;
				} else {
					_tmp23_ = FALSE;
				}
				if (_tmp23_) {
					result = FALSE;
					return result;
				}
			}
		}
	}
	result = TRUE;
	return result;
}

gchar*
chess_state_get_fen (ChessState* self)
{
	GString* value = NULL;
	GString* _tmp0_;
	GString* _tmp16_;
	ChessPlayer* _tmp17_;
	GString* _tmp20_;
	gboolean _tmp21_;
	gboolean _tmp23_;
	gboolean _tmp25_;
	gboolean _tmp27_;
	gboolean _tmp29_;
	gboolean _tmp30_;
	gboolean _tmp31_;
	gboolean _tmp32_;
	GString* _tmp34_;
	GString* _tmp37_;
	GString* _tmp38_;
	GString* _tmp39_;
	ChessPlayer* _tmp40_;
	GString* _tmp43_;
	const gchar* _tmp44_;
	gchar* _tmp45_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = g_string_new ("");
	value = _tmp0_;
	{
		gint rank = 0;
		rank = 7;
		{
			gboolean _tmp1_ = FALSE;
			_tmp1_ = TRUE;
			while (TRUE) {
				gint skip_count = 0;
				if (!_tmp1_) {
					gint _tmp2_;
					_tmp2_ = rank;
					rank = _tmp2_ - 1;
				}
				_tmp1_ = FALSE;
				if (!(rank >= 0)) {
					break;
				}
				skip_count = 0;
				{
					gint file = 0;
					file = 0;
					{
						gboolean _tmp3_ = FALSE;
						_tmp3_ = TRUE;
						while (TRUE) {
							ChessPiece* p = NULL;
							ChessPiece* _tmp5_;
							ChessPiece* _tmp6_;
							ChessPiece* _tmp7_;
							if (!_tmp3_) {
								gint _tmp4_;
								_tmp4_ = file;
								file = _tmp4_ + 1;
							}
							_tmp3_ = FALSE;
							if (!(file < 8)) {
								break;
							}
							_tmp5_ = self->board[chess_state_get_index (self, rank, file)];
							_tmp6_ = _g_object_ref0 (_tmp5_);
							p = _tmp6_;
							_tmp7_ = p;
							if (_tmp7_ == NULL) {
								gint _tmp8_;
								_tmp8_ = skip_count;
								skip_count = _tmp8_ + 1;
							} else {
								GString* _tmp10_;
								ChessPiece* _tmp11_;
								gunichar _tmp12_;
								gunichar _tmp13_;
								if (skip_count > 0) {
									GString* _tmp9_;
									_tmp9_ = value;
									g_string_append_printf (_tmp9_, "%d", skip_count);
									skip_count = 0;
								}
								_tmp10_ = value;
								_tmp11_ = p;
								_tmp12_ = chess_piece_get_symbol (_tmp11_);
								_tmp13_ = _tmp12_;
								g_string_append_printf (_tmp10_, "%c", (gint) _tmp13_);
							}
							_g_object_unref0 (p);
						}
					}
				}
				if (skip_count > 0) {
					GString* _tmp14_;
					_tmp14_ = value;
					g_string_append_printf (_tmp14_, "%d", skip_count);
				}
				if (rank != 0) {
					GString* _tmp15_;
					_tmp15_ = value;
					g_string_append_c (_tmp15_, '/');
				}
			}
		}
	}
	_tmp16_ = value;
	g_string_append_c (_tmp16_, ' ');
	_tmp17_ = self->current_player;
	if (_tmp17_->color == COLOR_WHITE) {
		GString* _tmp18_;
		_tmp18_ = value;
		g_string_append_c (_tmp18_, 'w');
	} else {
		GString* _tmp19_;
		_tmp19_ = value;
		g_string_append_c (_tmp19_, 'b');
	}
	_tmp20_ = value;
	g_string_append_c (_tmp20_, ' ');
	_tmp21_ = self->can_castle_kingside[COLOR_WHITE];
	if (_tmp21_) {
		GString* _tmp22_;
		_tmp22_ = value;
		g_string_append_c (_tmp22_, 'K');
	}
	_tmp23_ = self->can_castle_queenside[COLOR_WHITE];
	if (_tmp23_) {
		GString* _tmp24_;
		_tmp24_ = value;
		g_string_append_c (_tmp24_, 'Q');
	}
	_tmp25_ = self->can_castle_kingside[COLOR_BLACK];
	if (_tmp25_) {
		GString* _tmp26_;
		_tmp26_ = value;
		g_string_append_c (_tmp26_, 'k');
	}
	_tmp27_ = self->can_castle_queenside[COLOR_BLACK];
	if (_tmp27_) {
		GString* _tmp28_;
		_tmp28_ = value;
		g_string_append_c (_tmp28_, 'q');
	}
	_tmp29_ = self->can_castle_kingside[COLOR_WHITE];
	_tmp30_ = self->can_castle_queenside[COLOR_WHITE];
	_tmp31_ = self->can_castle_kingside[COLOR_BLACK];
	_tmp32_ = self->can_castle_queenside[COLOR_BLACK];
	if (!(((_tmp29_ | _tmp30_) | _tmp31_) | _tmp32_)) {
		GString* _tmp33_;
		_tmp33_ = value;
		g_string_append_c (_tmp33_, '-');
	}
	_tmp34_ = value;
	g_string_append_c (_tmp34_, ' ');
	if (self->en_passant_index >= 0) {
		GString* _tmp35_;
		_tmp35_ = value;
		g_string_append_printf (_tmp35_, "%c%d", 'a' + chess_state_get_file (self, self->en_passant_index), chess_state_get_rank (self, self->en_passant_index) + 1);
	} else {
		GString* _tmp36_;
		_tmp36_ = value;
		g_string_append_c (_tmp36_, '-');
	}
	_tmp37_ = value;
	g_string_append_c (_tmp37_, ' ');
	_tmp38_ = value;
	g_string_append_printf (_tmp38_, "%d", self->halfmove_clock);
	_tmp39_ = value;
	g_string_append_c (_tmp39_, ' ');
	_tmp40_ = self->current_player;
	if (_tmp40_->color == COLOR_WHITE) {
		GString* _tmp41_;
		_tmp41_ = value;
		g_string_append_printf (_tmp41_, "%d", self->number / 2);
	} else {
		GString* _tmp42_;
		_tmp42_ = value;
		g_string_append_printf (_tmp42_, "%d", (self->number / 2) + 1);
	}
	_tmp43_ = value;
	_tmp44_ = _tmp43_->str;
	_tmp45_ = g_strdup (_tmp44_);
	result = _tmp45_;
	_g_string_free0 (value);
	return result;
}

gint
chess_state_get_index (ChessState* self,
                       gint rank,
                       gint file)
{
	gint result;
	g_return_val_if_fail (self != NULL, 0);
	result = (rank * 8) + file;
	return result;
}

gint
chess_state_get_rank (ChessState* self,
                      gint index)
{
	gint result;
	g_return_val_if_fail (self != NULL, 0);
	result = index / 8;
	return result;
}

gint
chess_state_get_file (ChessState* self,
                      gint index)
{
	gint result;
	g_return_val_if_fail (self != NULL, 0);
	result = index % 8;
	return result;
}

gboolean
chess_state_move (ChessState* self,
                  const gchar* move,
                  gboolean apply)
{
	gint r0 = 0;
	gint f0 = 0;
	gint r1 = 0;
	gint f1 = 0;
	PieceType promotion_type = 0;
	ChessPlayer* _tmp0_;
	gint _tmp1_ = 0;
	gint _tmp2_ = 0;
	gint _tmp3_ = 0;
	gint _tmp4_ = 0;
	PieceType _tmp5_ = 0;
	gboolean _tmp6_;
	ChessPlayer* _tmp7_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (move != NULL, FALSE);
	_tmp0_ = self->current_player;
	_tmp6_ = chess_state_decode_move (self, _tmp0_, move, &_tmp1_, &_tmp2_, &_tmp3_, &_tmp4_, &_tmp5_);
	r0 = _tmp1_;
	f0 = _tmp2_;
	r1 = _tmp3_;
	f1 = _tmp4_;
	promotion_type = _tmp5_;
	if (!_tmp6_) {
		result = FALSE;
		return result;
	}
	_tmp7_ = self->current_player;
	if (!chess_state_move_with_coords (self, _tmp7_, r0, f0, r1, f1, promotion_type, apply, TRUE)) {
		result = FALSE;
		return result;
	}
	result = TRUE;
	return result;
}

gboolean
chess_state_move_with_coords (ChessState* self,
                              ChessPlayer* player,
                              gint r0,
                              gint f0,
                              gint r1,
                              gint f1,
                              PieceType promotion_type,
                              gboolean apply,
                              gboolean test_check)
{
	gint start = 0;
	gint end = 0;
	Color color = 0;
	Color _tmp0_ = 0;
	Color opponent_color = 0;
	ChessPiece* piece = NULL;
	ChessPiece* _tmp1_;
	ChessPiece* _tmp2_;
	gboolean _tmp3_ = FALSE;
	ChessPiece* _tmp4_;
	gint64 end_mask = 0LL;
	gint64 _tmp7_;
	gint64 move_mask = 0LL;
	ChessPiece* _tmp8_;
	gint64 _tmp9_;
	gint64 over_mask = 0LL;
	gint64 _tmp10_;
	gint64 _tmp11_;
	gint64 _tmp12_;
	ChessPiece* victim = NULL;
	ChessPiece* _tmp13_;
	ChessPiece* _tmp14_;
	gint victim_index = 0;
	gboolean _tmp15_ = FALSE;
	ChessPiece* _tmp16_;
	gint rook_start = 0;
	gint rook_end = 0;
	gboolean is_promotion = FALSE;
	gboolean en_passant = FALSE;
	gboolean ambiguous_rank = FALSE;
	gboolean ambiguous_file = FALSE;
	ChessPiece* _tmp19_;
	gboolean _tmp45_ = FALSE;
	gint64 old_white_mask = 0LL;
	gint64 _tmp57_;
	gint64 old_black_mask = 0LL;
	gint64 _tmp58_;
	gboolean old_white_can_castle_kingside = FALSE;
	gboolean _tmp59_;
	gboolean old_white_can_castle_queenside = FALSE;
	gboolean _tmp60_;
	gboolean old_black_can_castle_kingside = FALSE;
	gboolean _tmp61_;
	gboolean old_black_can_castle_queenside = FALSE;
	gboolean _tmp62_;
	gint old_en_passant_index = 0;
	gint old_halfmove_clock = 0;
	gint64 _tmp63_;
	gint64 _tmp64_;
	ChessPiece* _tmp65_;
	gint64 _tmp71_;
	ChessPiece* _tmp78_;
	gboolean _tmp85_ = FALSE;
	ChessPiece* _tmp86_;
	gboolean _tmp87_ = FALSE;
	ChessPiece* _tmp88_;
	gboolean _result_ = FALSE;
	gboolean _tmp91_ = FALSE;
	gboolean _tmp92_ = FALSE;
	ChessPlayer* _tmp102_ = NULL;
	ChessPlayer* _tmp105_;
	ChessPlayer* _tmp106_;
	ChessMove* _tmp107_;
	ChessMove* _tmp108_;
	ChessMove* _tmp109_;
	ChessPiece* _tmp110_;
	ChessPiece* _tmp111_;
	ChessMove* _tmp115_;
	ChessPiece* _tmp116_;
	ChessPiece* _tmp117_;
	ChessMove* _tmp121_;
	ChessMove* _tmp122_;
	ChessMove* _tmp123_;
	ChessMove* _tmp124_;
	ChessMove* _tmp125_;
	ChessMove* _tmp126_;
	ChessMove* _tmp127_;
	ChessMove* _tmp128_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (player != NULL, FALSE);
	start = chess_state_get_index (self, r0, f0);
	end = chess_state_get_index (self, r1, f1);
	color = player->color;
	if (color == COLOR_WHITE) {
		_tmp0_ = COLOR_BLACK;
	} else {
		_tmp0_ = COLOR_WHITE;
	}
	opponent_color = _tmp0_;
	_tmp1_ = self->board[start];
	_tmp2_ = _g_object_ref0 (_tmp1_);
	piece = _tmp2_;
	_tmp4_ = piece;
	if (_tmp4_ == NULL) {
		_tmp3_ = TRUE;
	} else {
		ChessPiece* _tmp5_;
		ChessPlayer* _tmp6_;
		_tmp5_ = piece;
		_tmp6_ = _tmp5_->player;
		_tmp3_ = _tmp6_ != player;
	}
	if (_tmp3_) {
		result = FALSE;
		_g_object_unref0 (piece);
		return result;
	}
	_tmp7_ = BIT_BOARD_set_location_masks[end];
	end_mask = _tmp7_;
	_tmp8_ = piece;
	_tmp9_ = BIT_BOARD_move_masks[(((color * 64) * 6) + (_tmp8_->type * 64)) + start];
	move_mask = _tmp9_;
	if ((end_mask & move_mask) == ((gint64) 0)) {
		result = FALSE;
		_g_object_unref0 (piece);
		return result;
	}
	_tmp10_ = BIT_BOARD_over_masks[(start * 64) + end];
	over_mask = _tmp10_;
	_tmp11_ = self->priv->piece_masks[COLOR_WHITE];
	_tmp12_ = self->priv->piece_masks[COLOR_BLACK];
	if ((over_mask & (_tmp11_ | _tmp12_)) != ((gint64) 0)) {
		result = FALSE;
		_g_object_unref0 (piece);
		return result;
	}
	_tmp13_ = self->board[end];
	_tmp14_ = _g_object_ref0 (_tmp13_);
	victim = _tmp14_;
	victim_index = end;
	_tmp16_ = victim;
	if (_tmp16_ != NULL) {
		ChessPiece* _tmp17_;
		ChessPlayer* _tmp18_;
		_tmp17_ = victim;
		_tmp18_ = _tmp17_->player;
		_tmp15_ = _tmp18_ == player;
	} else {
		_tmp15_ = FALSE;
	}
	if (_tmp15_) {
		result = FALSE;
		_g_object_unref0 (victim);
		_g_object_unref0 (piece);
		return result;
	}
	rook_start = -1;
	rook_end = -1;
	is_promotion = FALSE;
	en_passant = FALSE;
	ambiguous_rank = FALSE;
	ambiguous_file = FALSE;
	_tmp19_ = piece;
	switch (_tmp19_->type) {
		case PIECE_TYPE_PAWN:
		{
			gboolean _tmp20_ = FALSE;
			ChessPiece* _tmp21_;
			gboolean _tmp27_ = FALSE;
			ChessPiece* _tmp28_;
			_tmp21_ = victim;
			if (_tmp21_ == NULL) {
				_tmp20_ = end == self->en_passant_index;
			} else {
				_tmp20_ = FALSE;
			}
			if (_tmp20_) {
				gint _tmp22_ = 0;
				ChessPiece* _tmp23_;
				ChessPiece* _tmp24_;
				en_passant = TRUE;
				if (r1 == 2) {
					_tmp22_ = 3;
				} else {
					_tmp22_ = 4;
				}
				victim_index = chess_state_get_index (self, _tmp22_, f1);
				_tmp23_ = self->board[victim_index];
				_tmp24_ = _g_object_ref0 (_tmp23_);
				_g_object_unref0 (victim);
				victim = _tmp24_;
			}
			if (f0 != f1) {
				ChessPiece* _tmp25_;
				_tmp25_ = victim;
				if (_tmp25_ == NULL) {
					result = FALSE;
					_g_object_unref0 (victim);
					_g_object_unref0 (piece);
					return result;
				}
			} else {
				ChessPiece* _tmp26_;
				_tmp26_ = victim;
				if (_tmp26_ != NULL) {
					result = FALSE;
					_g_object_unref0 (victim);
					_g_object_unref0 (piece);
					return result;
				}
			}
			if (r1 == 0) {
				_tmp27_ = TRUE;
			} else {
				_tmp27_ = r1 == 7;
			}
			is_promotion = _tmp27_;
			_tmp28_ = victim;
			if (_tmp28_ != NULL) {
				ambiguous_file = TRUE;
			}
			break;
		}
		case PIECE_TYPE_KING:
		{
			if (abs (f0 - f1) > 1) {
				gint _tmp29_ = 0;
				gint _tmp30_ = 0;
				ChessPiece* rook = NULL;
				ChessPiece* _tmp33_;
				ChessPiece* _tmp34_;
				gboolean _tmp35_ = FALSE;
				gboolean _tmp36_ = FALSE;
				ChessPiece* _tmp37_;
				gint64 rook_over_mask = 0LL;
				gint64 _tmp42_;
				gint64 _tmp43_;
				gint64 _tmp44_;
				if (f1 > f0) {
					_tmp29_ = 7;
				} else {
					_tmp29_ = 0;
				}
				rook_start = chess_state_get_index (self, r0, _tmp29_);
				if (f1 > f0) {
					_tmp30_ = f1 - 1;
				} else {
					_tmp30_ = f1 + 1;
				}
				rook_end = chess_state_get_index (self, r0, _tmp30_);
				if (f1 > f0) {
					gboolean _tmp31_;
					_tmp31_ = self->can_castle_kingside[color];
					if (!_tmp31_) {
						result = FALSE;
						_g_object_unref0 (victim);
						_g_object_unref0 (piece);
						return result;
					}
				} else {
					gboolean _tmp32_;
					_tmp32_ = self->can_castle_queenside[color];
					if (!_tmp32_) {
						result = FALSE;
						_g_object_unref0 (victim);
						_g_object_unref0 (piece);
						return result;
					}
				}
				_tmp33_ = self->board[rook_start];
				_tmp34_ = _g_object_ref0 (_tmp33_);
				rook = _tmp34_;
				_tmp37_ = rook;
				if (_tmp37_ == NULL) {
					_tmp36_ = TRUE;
				} else {
					ChessPiece* _tmp38_;
					_tmp38_ = rook;
					_tmp36_ = _tmp38_->type != PIECE_TYPE_ROOK;
				}
				if (_tmp36_) {
					_tmp35_ = TRUE;
				} else {
					ChessPiece* _tmp39_;
					Color _tmp40_;
					Color _tmp41_;
					_tmp39_ = rook;
					_tmp40_ = chess_piece_get_color (_tmp39_);
					_tmp41_ = _tmp40_;
					_tmp35_ = _tmp41_ != color;
				}
				if (_tmp35_) {
					result = FALSE;
					_g_object_unref0 (rook);
					_g_object_unref0 (victim);
					_g_object_unref0 (piece);
					return result;
				}
				_tmp42_ = BIT_BOARD_over_masks[(rook_start * 64) + rook_end];
				rook_over_mask = _tmp42_;
				_tmp43_ = self->priv->piece_masks[COLOR_WHITE];
				_tmp44_ = self->priv->piece_masks[COLOR_BLACK];
				if ((rook_over_mask & (_tmp43_ | _tmp44_)) != ((gint64) 0)) {
					result = FALSE;
					_g_object_unref0 (rook);
					_g_object_unref0 (victim);
					_g_object_unref0 (piece);
					return result;
				}
				if (self->check_state == CHECK_STATE_CHECK) {
					result = FALSE;
					_g_object_unref0 (rook);
					_g_object_unref0 (victim);
					_g_object_unref0 (piece);
					return result;
				}
				if (!chess_state_move_with_coords (self, player, r0, f0, chess_state_get_rank (self, rook_end), chess_state_get_file (self, rook_end), PIECE_TYPE_QUEEN, FALSE, TRUE)) {
					result = FALSE;
					_g_object_unref0 (rook);
					_g_object_unref0 (victim);
					_g_object_unref0 (piece);
					return result;
				}
				_g_object_unref0 (rook);
			}
			break;
		}
		default:
		{
			break;
		}
	}
	if (!apply) {
		_tmp45_ = !test_check;
	} else {
		_tmp45_ = FALSE;
	}
	if (_tmp45_) {
		result = TRUE;
		_g_object_unref0 (victim);
		_g_object_unref0 (piece);
		return result;
	}
	if (apply) {
		{
			gint i = 0;
			i = 0;
			{
				gboolean _tmp46_ = FALSE;
				_tmp46_ = TRUE;
				while (TRUE) {
					ChessPiece* p = NULL;
					ChessPiece* _tmp48_;
					ChessPiece* _tmp49_;
					gboolean _tmp50_ = FALSE;
					gboolean _tmp51_ = FALSE;
					ChessPiece* _tmp52_;
					gint r = 0;
					gint f = 0;
					if (!_tmp46_) {
						gint _tmp47_;
						_tmp47_ = i;
						i = _tmp47_ + 1;
					}
					_tmp46_ = FALSE;
					if (!(i < 64)) {
						break;
					}
					if (i == start) {
						continue;
					}
					_tmp48_ = self->board[i];
					_tmp49_ = _g_object_ref0 (_tmp48_);
					p = _tmp49_;
					_tmp52_ = p;
					if (_tmp52_ == NULL) {
						_tmp51_ = TRUE;
					} else {
						ChessPiece* _tmp53_;
						ChessPlayer* _tmp54_;
						_tmp53_ = p;
						_tmp54_ = _tmp53_->player;
						_tmp51_ = _tmp54_ != player;
					}
					if (_tmp51_) {
						_tmp50_ = TRUE;
					} else {
						ChessPiece* _tmp55_;
						ChessPiece* _tmp56_;
						_tmp55_ = p;
						_tmp56_ = piece;
						_tmp50_ = _tmp55_->type != _tmp56_->type;
					}
					if (_tmp50_) {
						_g_object_unref0 (p);
						continue;
					}
					r = chess_state_get_rank (self, i);
					f = chess_state_get_file (self, i);
					if (chess_state_move_with_coords (self, player, r, f, r1, f1, PIECE_TYPE_QUEEN, FALSE, TRUE)) {
						if (r != r0) {
							ambiguous_rank = TRUE;
						}
						if (f != f0) {
							ambiguous_file = TRUE;
						}
					}
					_g_object_unref0 (p);
				}
			}
		}
	}
	_tmp57_ = self->priv->piece_masks[COLOR_WHITE];
	old_white_mask = _tmp57_;
	_tmp58_ = self->priv->piece_masks[COLOR_BLACK];
	old_black_mask = _tmp58_;
	_tmp59_ = self->can_castle_kingside[COLOR_WHITE];
	old_white_can_castle_kingside = _tmp59_;
	_tmp60_ = self->can_castle_queenside[COLOR_WHITE];
	old_white_can_castle_queenside = _tmp60_;
	_tmp61_ = self->can_castle_kingside[COLOR_BLACK];
	old_black_can_castle_kingside = _tmp61_;
	_tmp62_ = self->can_castle_queenside[COLOR_BLACK];
	old_black_can_castle_queenside = _tmp62_;
	old_en_passant_index = self->en_passant_index;
	old_halfmove_clock = self->halfmove_clock;
	_g_object_unref0 (self->board[start]);
	self->board[start] = NULL;
	_tmp63_ = BIT_BOARD_clear_location_masks[start];
	self->priv->piece_masks[COLOR_WHITE] &= _tmp63_;
	_tmp64_ = BIT_BOARD_clear_location_masks[start];
	self->priv->piece_masks[COLOR_BLACK] &= _tmp64_;
	_tmp65_ = victim;
	if (_tmp65_ != NULL) {
		gint64 _tmp66_;
		gint64 _tmp67_;
		_g_object_unref0 (self->board[victim_index]);
		self->board[victim_index] = NULL;
		_tmp66_ = BIT_BOARD_clear_location_masks[victim_index];
		self->priv->piece_masks[COLOR_WHITE] &= _tmp66_;
		_tmp67_ = BIT_BOARD_clear_location_masks[victim_index];
		self->priv->piece_masks[COLOR_BLACK] &= _tmp67_;
	}
	if (is_promotion) {
		ChessPiece* _tmp68_;
		_tmp68_ = chess_piece_new (player, promotion_type);
		_g_object_unref0 (self->board[end]);
		self->board[end] = _tmp68_;
	} else {
		ChessPiece* _tmp69_;
		ChessPiece* _tmp70_;
		_tmp69_ = piece;
		_tmp70_ = _g_object_ref0 (_tmp69_);
		_g_object_unref0 (self->board[end]);
		self->board[end] = _tmp70_;
	}
	self->priv->piece_masks[color] |= end_mask;
	_tmp71_ = BIT_BOARD_clear_location_masks[end];
	self->priv->piece_masks[opponent_color] &= _tmp71_;
	if (rook_start >= 0) {
		ChessPiece* rook = NULL;
		ChessPiece* _tmp72_;
		ChessPiece* _tmp73_;
		gint64 _tmp74_;
		ChessPiece* _tmp75_;
		ChessPiece* _tmp76_;
		gint64 _tmp77_;
		_tmp72_ = self->board[rook_start];
		_tmp73_ = _g_object_ref0 (_tmp72_);
		rook = _tmp73_;
		_g_object_unref0 (self->board[rook_start]);
		self->board[rook_start] = NULL;
		_tmp74_ = BIT_BOARD_clear_location_masks[rook_start];
		self->priv->piece_masks[color] &= _tmp74_;
		_tmp75_ = rook;
		_tmp76_ = _g_object_ref0 (_tmp75_);
		_g_object_unref0 (self->board[rook_end]);
		self->board[rook_end] = _tmp76_;
		_tmp77_ = BIT_BOARD_set_location_masks[rook_end];
		self->priv->piece_masks[color] |= _tmp77_;
		_g_object_unref0 (rook);
	}
	_tmp78_ = piece;
	if (_tmp78_->type == PIECE_TYPE_KING) {
		self->can_castle_kingside[color] = FALSE;
		self->can_castle_queenside[color] = FALSE;
	} else {
		ChessPiece* _tmp79_;
		_tmp79_ = piece;
		if (_tmp79_->type == PIECE_TYPE_ROOK) {
			gint _tmp80_ = 0;
			gint base_rank = 0;
			if (color == COLOR_WHITE) {
				_tmp80_ = 0;
			} else {
				_tmp80_ = 7;
			}
			base_rank = _tmp80_;
			if (r0 == base_rank) {
				if (f0 == 0) {
					self->can_castle_queenside[color] = FALSE;
				} else {
					if (f0 == 7) {
						self->can_castle_kingside[color] = FALSE;
					}
				}
			}
		} else {
			gboolean _tmp81_ = FALSE;
			ChessPiece* _tmp82_;
			_tmp82_ = victim;
			if (_tmp82_ != NULL) {
				ChessPiece* _tmp83_;
				_tmp83_ = victim;
				_tmp81_ = _tmp83_->type == PIECE_TYPE_ROOK;
			} else {
				_tmp81_ = FALSE;
			}
			if (_tmp81_) {
				gint _tmp84_ = 0;
				gint base_rank = 0;
				if (opponent_color == COLOR_WHITE) {
					_tmp84_ = 0;
				} else {
					_tmp84_ = 7;
				}
				base_rank = _tmp84_;
				if (r1 == base_rank) {
					if (f1 == 0) {
						self->can_castle_queenside[opponent_color] = FALSE;
					} else {
						if (f1 == 7) {
							self->can_castle_kingside[opponent_color] = FALSE;
						}
					}
				}
			}
		}
	}
	_tmp86_ = piece;
	if (_tmp86_->type == PIECE_TYPE_PAWN) {
		_tmp85_ = over_mask != ((gint64) 0);
	} else {
		_tmp85_ = FALSE;
	}
	if (_tmp85_) {
		self->en_passant_index = chess_state_get_index (self, (r0 + r1) / 2, f0);
	} else {
		self->en_passant_index = -1;
	}
	_tmp88_ = piece;
	if (_tmp88_->type == PIECE_TYPE_PAWN) {
		_tmp87_ = TRUE;
	} else {
		ChessPiece* _tmp89_;
		_tmp89_ = victim;
		_tmp87_ = _tmp89_ != NULL;
	}
	if (_tmp87_) {
		self->halfmove_clock = 0;
	} else {
		gint _tmp90_;
		_tmp90_ = self->halfmove_clock;
		self->halfmove_clock = _tmp90_ + 1;
	}
	_result_ = TRUE;
	if (test_check) {
		_tmp91_ = chess_state_is_in_check (self, player);
	} else {
		_tmp91_ = FALSE;
	}
	if (_tmp91_) {
		_result_ = FALSE;
	}
	if (!apply) {
		_tmp92_ = TRUE;
	} else {
		_tmp92_ = !_result_;
	}
	if (_tmp92_) {
		ChessPiece* _tmp93_;
		ChessPiece* _tmp94_;
		ChessPiece* _tmp95_;
		_tmp93_ = piece;
		_tmp94_ = _g_object_ref0 (_tmp93_);
		_g_object_unref0 (self->board[start]);
		self->board[start] = _tmp94_;
		_g_object_unref0 (self->board[end]);
		self->board[end] = NULL;
		_tmp95_ = victim;
		if (_tmp95_ != NULL) {
			ChessPiece* _tmp96_;
			ChessPiece* _tmp97_;
			_tmp96_ = victim;
			_tmp97_ = _g_object_ref0 (_tmp96_);
			_g_object_unref0 (self->board[victim_index]);
			self->board[victim_index] = _tmp97_;
		}
		if (rook_start >= 0) {
			ChessPiece* rook = NULL;
			ChessPiece* _tmp98_;
			ChessPiece* _tmp99_;
			ChessPiece* _tmp100_;
			ChessPiece* _tmp101_;
			_tmp98_ = self->board[rook_end];
			_tmp99_ = _g_object_ref0 (_tmp98_);
			rook = _tmp99_;
			_tmp100_ = rook;
			_tmp101_ = _g_object_ref0 (_tmp100_);
			_g_object_unref0 (self->board[rook_start]);
			self->board[rook_start] = _tmp101_;
			_g_object_unref0 (self->board[rook_end]);
			self->board[rook_end] = NULL;
			_g_object_unref0 (rook);
		}
		self->priv->piece_masks[COLOR_WHITE] = old_white_mask;
		self->priv->piece_masks[COLOR_BLACK] = old_black_mask;
		self->can_castle_kingside[COLOR_WHITE] = old_white_can_castle_kingside;
		self->can_castle_queenside[COLOR_WHITE] = old_white_can_castle_queenside;
		self->can_castle_kingside[COLOR_BLACK] = old_black_can_castle_kingside;
		self->can_castle_queenside[COLOR_BLACK] = old_black_can_castle_queenside;
		self->en_passant_index = old_en_passant_index;
		self->halfmove_clock = old_halfmove_clock;
		result = _result_;
		_g_object_unref0 (victim);
		_g_object_unref0 (piece);
		return result;
	}
	if (color == COLOR_WHITE) {
		ChessPlayer* _tmp103_;
		_tmp103_ = self->players[COLOR_BLACK];
		_tmp102_ = _tmp103_;
	} else {
		ChessPlayer* _tmp104_;
		_tmp104_ = self->players[COLOR_WHITE];
		_tmp102_ = _tmp104_;
	}
	_tmp105_ = _g_object_ref0 (_tmp102_);
	_g_object_unref0 (self->current_player);
	self->current_player = _tmp105_;
	_tmp106_ = self->current_player;
	self->check_state = chess_state_get_check_state (self, _tmp106_);
	_tmp107_ = chess_move_new ();
	_g_object_unref0 (self->last_move);
	self->last_move = _tmp107_;
	_tmp108_ = self->last_move;
	_tmp108_->number = self->number;
	_tmp109_ = self->last_move;
	_tmp110_ = piece;
	_tmp111_ = _g_object_ref0 (_tmp110_);
	_g_object_unref0 (_tmp109_->piece);
	_tmp109_->piece = _tmp111_;
	if (is_promotion) {
		ChessMove* _tmp112_;
		ChessPiece* _tmp113_;
		ChessPiece* _tmp114_;
		_tmp112_ = self->last_move;
		_tmp113_ = self->board[end];
		_tmp114_ = _g_object_ref0 (_tmp113_);
		_g_object_unref0 (_tmp112_->promotion_piece);
		_tmp112_->promotion_piece = _tmp114_;
	}
	_tmp115_ = self->last_move;
	_tmp116_ = victim;
	_tmp117_ = _g_object_ref0 (_tmp116_);
	_g_object_unref0 (_tmp115_->victim);
	_tmp115_->victim = _tmp117_;
	if (rook_end >= 0) {
		ChessMove* _tmp118_;
		ChessPiece* _tmp119_;
		ChessPiece* _tmp120_;
		_tmp118_ = self->last_move;
		_tmp119_ = self->board[rook_end];
		_tmp120_ = _g_object_ref0 (_tmp119_);
		_g_object_unref0 (_tmp118_->castling_rook);
		_tmp118_->castling_rook = _tmp120_;
	}
	_tmp121_ = self->last_move;
	_tmp121_->r0 = r0;
	_tmp122_ = self->last_move;
	_tmp122_->f0 = f0;
	_tmp123_ = self->last_move;
	_tmp123_->r1 = r1;
	_tmp124_ = self->last_move;
	_tmp124_->f1 = f1;
	_tmp125_ = self->last_move;
	_tmp125_->ambiguous_rank = ambiguous_rank;
	_tmp126_ = self->last_move;
	_tmp126_->ambiguous_file = ambiguous_file;
	_tmp127_ = self->last_move;
	_tmp127_->en_passant = en_passant;
	_tmp128_ = self->last_move;
	_tmp128_->check_state = self->check_state;
	result = TRUE;
	_g_object_unref0 (victim);
	_g_object_unref0 (piece);
	return result;
}

ChessResult
chess_state_get_result (ChessState* self,
                        ChessRule* rule)
{
	ChessRule _vala_rule = 0;
	ChessPlayer* _tmp1_;
	gboolean _tmp2_ = FALSE;
	gboolean _tmp3_ = FALSE;
	ChessMove* _tmp4_;
	ChessResult result;
	g_return_val_if_fail (self != NULL, 0);
	_vala_rule = CHESS_RULE_CHECKMATE;
	if (self->check_state == CHECK_STATE_CHECKMATE) {
		ChessPlayer* _tmp0_;
		_tmp0_ = self->current_player;
		if (_tmp0_->color == COLOR_WHITE) {
			_vala_rule = CHESS_RULE_CHECKMATE;
			result = CHESS_RESULT_BLACK_WON;
			if (rule) {
				*rule = _vala_rule;
			}
			return result;
		} else {
			_vala_rule = CHESS_RULE_CHECKMATE;
			result = CHESS_RESULT_WHITE_WON;
			if (rule) {
				*rule = _vala_rule;
			}
			return result;
		}
	}
	_tmp1_ = self->current_player;
	if (!chess_state_can_move (self, _tmp1_)) {
		_vala_rule = CHESS_RULE_STALEMATE;
		result = CHESS_RESULT_DRAW;
		if (rule) {
			*rule = _vala_rule;
		}
		return result;
	}
	_tmp4_ = self->last_move;
	if (_tmp4_ != NULL) {
		ChessMove* _tmp5_;
		ChessPiece* _tmp6_;
		_tmp5_ = self->last_move;
		_tmp6_ = _tmp5_->victim;
		_tmp3_ = _tmp6_ != NULL;
	} else {
		_tmp3_ = FALSE;
	}
	if (_tmp3_) {
		_tmp2_ = !chess_state_have_sufficient_material (self);
	} else {
		_tmp2_ = FALSE;
	}
	if (_tmp2_) {
		_vala_rule = CHESS_RULE_INSUFFICIENT_MATERIAL;
		result = CHESS_RESULT_DRAW;
		if (rule) {
			*rule = _vala_rule;
		}
		return result;
	}
	result = CHESS_RESULT_IN_PROGRESS;
	if (rule) {
		*rule = _vala_rule;
	}
	return result;
}

static CheckState
chess_state_get_check_state (ChessState* self,
                             ChessPlayer* player)
{
	CheckState result;
	g_return_val_if_fail (self != NULL, 0);
	g_return_val_if_fail (player != NULL, 0);
	if (chess_state_is_in_check (self, player)) {
		if (chess_state_is_in_checkmate (self, player)) {
			result = CHECK_STATE_CHECKMATE;
			return result;
		} else {
			result = CHECK_STATE_CHECK;
			return result;
		}
	}
	result = CHECK_STATE_NONE;
	return result;
}

gboolean
chess_state_is_in_check (ChessState* self,
                         ChessPlayer* player)
{
	ChessPlayer* _tmp0_ = NULL;
	ChessPlayer* opponent = NULL;
	ChessPlayer* _tmp3_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (player != NULL, FALSE);
	if (player->color == COLOR_WHITE) {
		ChessPlayer* _tmp1_;
		_tmp1_ = self->players[COLOR_BLACK];
		_tmp0_ = _tmp1_;
	} else {
		ChessPlayer* _tmp2_;
		_tmp2_ = self->players[COLOR_WHITE];
		_tmp0_ = _tmp2_;
	}
	_tmp3_ = _g_object_ref0 (_tmp0_);
	opponent = _tmp3_;
	{
		gint king_index = 0;
		king_index = 0;
		{
			gboolean _tmp4_ = FALSE;
			_tmp4_ = TRUE;
			while (TRUE) {
				ChessPiece* p = NULL;
				ChessPiece* _tmp6_;
				ChessPiece* _tmp7_;
				gboolean _tmp8_ = FALSE;
				gboolean _tmp9_ = FALSE;
				ChessPiece* _tmp10_;
				if (!_tmp4_) {
					gint _tmp5_;
					_tmp5_ = king_index;
					king_index = _tmp5_ + 1;
				}
				_tmp4_ = FALSE;
				if (!(king_index < 64)) {
					break;
				}
				_tmp6_ = self->board[king_index];
				_tmp7_ = _g_object_ref0 (_tmp6_);
				p = _tmp7_;
				_tmp10_ = p;
				if (_tmp10_ != NULL) {
					ChessPiece* _tmp11_;
					ChessPlayer* _tmp12_;
					_tmp11_ = p;
					_tmp12_ = _tmp11_->player;
					_tmp9_ = _tmp12_ == player;
				} else {
					_tmp9_ = FALSE;
				}
				if (_tmp9_) {
					ChessPiece* _tmp13_;
					_tmp13_ = p;
					_tmp8_ = _tmp13_->type == PIECE_TYPE_KING;
				} else {
					_tmp8_ = FALSE;
				}
				if (_tmp8_) {
					{
						gint start = 0;
						start = 0;
						{
							gboolean _tmp14_ = FALSE;
							_tmp14_ = TRUE;
							while (TRUE) {
								ChessPlayer* _tmp16_;
								if (!_tmp14_) {
									gint _tmp15_;
									_tmp15_ = start;
									start = _tmp15_ + 1;
								}
								_tmp14_ = FALSE;
								if (!(start < 64)) {
									break;
								}
								_tmp16_ = opponent;
								if (chess_state_move_with_coords (self, _tmp16_, chess_state_get_rank (self, start), chess_state_get_file (self, start), chess_state_get_rank (self, king_index), chess_state_get_file (self, king_index), PIECE_TYPE_QUEEN, FALSE, FALSE)) {
									result = TRUE;
									_g_object_unref0 (p);
									_g_object_unref0 (opponent);
									return result;
								}
							}
						}
					}
				}
				_g_object_unref0 (p);
			}
		}
	}
	result = FALSE;
	_g_object_unref0 (opponent);
	return result;
}

static gboolean
chess_state_is_in_checkmate (ChessState* self,
                             ChessPlayer* player)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (player != NULL, FALSE);
	{
		gint piece_index = 0;
		piece_index = 0;
		{
			gboolean _tmp0_ = FALSE;
			_tmp0_ = TRUE;
			while (TRUE) {
				ChessPiece* p = NULL;
				ChessPiece* _tmp2_;
				ChessPiece* _tmp3_;
				gboolean _tmp4_ = FALSE;
				ChessPiece* _tmp5_;
				if (!_tmp0_) {
					gint _tmp1_;
					_tmp1_ = piece_index;
					piece_index = _tmp1_ + 1;
				}
				_tmp0_ = FALSE;
				if (!(piece_index < 64)) {
					break;
				}
				_tmp2_ = self->board[piece_index];
				_tmp3_ = _g_object_ref0 (_tmp2_);
				p = _tmp3_;
				_tmp5_ = p;
				if (_tmp5_ != NULL) {
					ChessPiece* _tmp6_;
					ChessPlayer* _tmp7_;
					_tmp6_ = p;
					_tmp7_ = _tmp6_->player;
					_tmp4_ = _tmp7_ == player;
				} else {
					_tmp4_ = FALSE;
				}
				if (_tmp4_) {
					{
						gint end = 0;
						end = 0;
						{
							gboolean _tmp8_ = FALSE;
							_tmp8_ = TRUE;
							while (TRUE) {
								if (!_tmp8_) {
									gint _tmp9_;
									_tmp9_ = end;
									end = _tmp9_ + 1;
								}
								_tmp8_ = FALSE;
								if (!(end < 64)) {
									break;
								}
								if (chess_state_move_with_coords (self, player, chess_state_get_rank (self, piece_index), chess_state_get_file (self, piece_index), chess_state_get_rank (self, end), chess_state_get_file (self, end), PIECE_TYPE_QUEEN, FALSE, TRUE)) {
									result = FALSE;
									_g_object_unref0 (p);
									return result;
								}
							}
						}
					}
				}
				_g_object_unref0 (p);
			}
		}
	}
	result = TRUE;
	return result;
}

gboolean
chess_state_can_move (ChessState* self,
                      ChessPlayer* player)
{
	gboolean have_pieces = FALSE;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (player != NULL, FALSE);
	have_pieces = FALSE;
	{
		gint start = 0;
		start = 0;
		{
			gboolean _tmp0_ = FALSE;
			_tmp0_ = TRUE;
			while (TRUE) {
				ChessPiece* p = NULL;
				ChessPiece* _tmp2_;
				ChessPiece* _tmp3_;
				gboolean _tmp4_ = FALSE;
				ChessPiece* _tmp5_;
				if (!_tmp0_) {
					gint _tmp1_;
					_tmp1_ = start;
					start = _tmp1_ + 1;
				}
				_tmp0_ = FALSE;
				if (!(start < 64)) {
					break;
				}
				_tmp2_ = self->board[start];
				_tmp3_ = _g_object_ref0 (_tmp2_);
				p = _tmp3_;
				_tmp5_ = p;
				if (_tmp5_ != NULL) {
					ChessPiece* _tmp6_;
					ChessPlayer* _tmp7_;
					_tmp6_ = p;
					_tmp7_ = _tmp6_->player;
					_tmp4_ = _tmp7_ == player;
				} else {
					_tmp4_ = FALSE;
				}
				if (_tmp4_) {
					have_pieces = TRUE;
					{
						gint end = 0;
						end = 0;
						{
							gboolean _tmp8_ = FALSE;
							_tmp8_ = TRUE;
							while (TRUE) {
								if (!_tmp8_) {
									gint _tmp9_;
									_tmp9_ = end;
									end = _tmp9_ + 1;
								}
								_tmp8_ = FALSE;
								if (!(end < 64)) {
									break;
								}
								if (chess_state_move_with_coords (self, player, chess_state_get_rank (self, start), chess_state_get_file (self, start), chess_state_get_rank (self, end), chess_state_get_file (self, end), PIECE_TYPE_QUEEN, FALSE, TRUE)) {
									result = TRUE;
									_g_object_unref0 (p);
									return result;
								}
							}
						}
					}
				}
				_g_object_unref0 (p);
			}
		}
	}
	if (have_pieces) {
		result = FALSE;
		return result;
	} else {
		result = TRUE;
		return result;
	}
}

gboolean
chess_state_have_sufficient_material (ChessState* self)
{
	gint white_knight_count = 0;
	gint white_bishop_count = 0;
	gboolean white_bishop_on_white_square = FALSE;
	gboolean white_bishop_on_black_square = FALSE;
	gint black_knight_count = 0;
	gint black_bishop_count = 0;
	gboolean black_bishop_on_white_square = FALSE;
	gboolean black_bishop_on_black_square = FALSE;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	white_knight_count = 0;
	white_bishop_count = 0;
	white_bishop_on_white_square = FALSE;
	white_bishop_on_black_square = FALSE;
	black_knight_count = 0;
	black_bishop_count = 0;
	black_bishop_on_white_square = FALSE;
	black_bishop_on_black_square = FALSE;
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp0_ = FALSE;
			_tmp0_ = TRUE;
			while (TRUE) {
				ChessPiece* p = NULL;
				ChessPiece* _tmp2_;
				ChessPiece* _tmp3_;
				ChessPiece* _tmp4_;
				gboolean _tmp5_ = FALSE;
				gboolean _tmp6_ = FALSE;
				ChessPiece* _tmp7_;
				ChessPiece* _tmp10_;
				ChessPiece* _tmp16_;
				gboolean _tmp22_ = FALSE;
				gboolean _tmp23_ = FALSE;
				gboolean _tmp24_ = FALSE;
				gboolean _tmp25_ = FALSE;
				gboolean _tmp26_ = FALSE;
				gboolean _tmp27_ = FALSE;
				gboolean _tmp28_ = FALSE;
				gboolean _tmp29_ = FALSE;
				gboolean _tmp30_ = FALSE;
				gboolean _tmp31_ = FALSE;
				if (!_tmp0_) {
					gint _tmp1_;
					_tmp1_ = i;
					i = _tmp1_ + 1;
				}
				_tmp0_ = FALSE;
				if (!(i < 64)) {
					break;
				}
				_tmp2_ = self->board[i];
				_tmp3_ = _g_object_ref0 (_tmp2_);
				p = _tmp3_;
				_tmp4_ = p;
				if (_tmp4_ == NULL) {
					_g_object_unref0 (p);
					continue;
				}
				_tmp7_ = p;
				if (_tmp7_->type == PIECE_TYPE_PAWN) {
					_tmp6_ = TRUE;
				} else {
					ChessPiece* _tmp8_;
					_tmp8_ = p;
					_tmp6_ = _tmp8_->type == PIECE_TYPE_ROOK;
				}
				if (_tmp6_) {
					_tmp5_ = TRUE;
				} else {
					ChessPiece* _tmp9_;
					_tmp9_ = p;
					_tmp5_ = _tmp9_->type == PIECE_TYPE_QUEEN;
				}
				if (_tmp5_) {
					result = TRUE;
					_g_object_unref0 (p);
					return result;
				}
				_tmp10_ = p;
				if (_tmp10_->type == PIECE_TYPE_KNIGHT) {
					ChessPiece* _tmp11_;
					Color _tmp12_;
					Color _tmp13_;
					_tmp11_ = p;
					_tmp12_ = chess_piece_get_color (_tmp11_);
					_tmp13_ = _tmp12_;
					if (_tmp13_ == COLOR_WHITE) {
						gint _tmp14_;
						_tmp14_ = white_knight_count;
						white_knight_count = _tmp14_ + 1;
					} else {
						gint _tmp15_;
						_tmp15_ = black_knight_count;
						black_knight_count = _tmp15_ + 1;
					}
				}
				_tmp16_ = p;
				if (_tmp16_->type == PIECE_TYPE_BISHOP) {
					Color color = 0;
					ChessPiece* _tmp17_;
					Color _tmp18_;
					Color _tmp19_;
					color = COLOR_BLACK;
					if (((i + (i / 8)) % 2) != 0) {
						color = COLOR_WHITE;
					}
					_tmp17_ = p;
					_tmp18_ = chess_piece_get_color (_tmp17_);
					_tmp19_ = _tmp18_;
					if (_tmp19_ == COLOR_WHITE) {
						gint _tmp20_;
						if (color == COLOR_WHITE) {
							white_bishop_on_white_square = TRUE;
						} else {
							white_bishop_on_black_square = TRUE;
						}
						_tmp20_ = white_bishop_count;
						white_bishop_count = _tmp20_ + 1;
					} else {
						gint _tmp21_;
						if (color == COLOR_WHITE) {
							black_bishop_on_white_square = TRUE;
						} else {
							black_bishop_on_black_square = TRUE;
						}
						_tmp21_ = black_bishop_count;
						black_bishop_count = _tmp21_ + 1;
					}
				}
				if (white_knight_count > 1) {
					_tmp22_ = TRUE;
				} else {
					_tmp22_ = black_knight_count > 1;
				}
				if (_tmp22_) {
					result = TRUE;
					_g_object_unref0 (p);
					return result;
				}
				if (white_bishop_count > 0) {
					_tmp23_ = white_knight_count > 0;
				} else {
					_tmp23_ = FALSE;
				}
				if (_tmp23_) {
					result = TRUE;
					_g_object_unref0 (p);
					return result;
				}
				if (black_bishop_count > 0) {
					_tmp24_ = black_knight_count > 0;
				} else {
					_tmp24_ = FALSE;
				}
				if (_tmp24_) {
					result = TRUE;
					_g_object_unref0 (p);
					return result;
				}
				if (white_bishop_on_white_square) {
					_tmp25_ = white_bishop_on_black_square;
				} else {
					_tmp25_ = FALSE;
				}
				if (_tmp25_) {
					result = TRUE;
					_g_object_unref0 (p);
					return result;
				}
				if (black_bishop_on_white_square) {
					_tmp26_ = black_bishop_on_black_square;
				} else {
					_tmp26_ = FALSE;
				}
				if (_tmp26_) {
					result = TRUE;
					_g_object_unref0 (p);
					return result;
				}
				if (white_bishop_count > 0) {
					_tmp28_ = TRUE;
				} else {
					_tmp28_ = white_knight_count > 0;
				}
				if (_tmp28_) {
					_tmp27_ = black_knight_count > 0;
				} else {
					_tmp27_ = FALSE;
				}
				if (_tmp27_) {
					result = TRUE;
					_g_object_unref0 (p);
					return result;
				}
				if (black_bishop_count > 0) {
					_tmp30_ = TRUE;
				} else {
					_tmp30_ = black_knight_count > 0;
				}
				if (_tmp30_) {
					_tmp29_ = white_knight_count > 0;
				} else {
					_tmp29_ = FALSE;
				}
				if (_tmp29_) {
					result = TRUE;
					_g_object_unref0 (p);
					return result;
				}
				if (white_bishop_count > 0) {
					_tmp31_ = black_bishop_count > 0;
				} else {
					_tmp31_ = FALSE;
				}
				if (_tmp31_) {
					gboolean _tmp32_ = FALSE;
					if (white_bishop_on_white_square) {
						_tmp32_ = black_bishop_on_black_square;
					} else {
						_tmp32_ = FALSE;
					}
					if (_tmp32_) {
						result = TRUE;
						_g_object_unref0 (p);
						return result;
					} else {
						gboolean _tmp33_ = FALSE;
						if (white_bishop_on_black_square) {
							_tmp33_ = black_bishop_on_white_square;
						} else {
							_tmp33_ = FALSE;
						}
						if (_tmp33_) {
							result = TRUE;
							_g_object_unref0 (p);
							return result;
						}
					}
				}
				_g_object_unref0 (p);
			}
		}
	}
	result = FALSE;
	return result;
}

static gboolean
chess_state_decode_piece_type (ChessState* self,
                               gunichar c,
                               PieceType* type)
{
	PieceType _vala_type = 0;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_vala_type = PIECE_TYPE_PAWN;
	switch (c) {
		case 'P':
		{
			_vala_type = PIECE_TYPE_PAWN;
			result = TRUE;
			if (type) {
				*type = _vala_type;
			}
			return result;
		}
		case 'R':
		{
			_vala_type = PIECE_TYPE_ROOK;
			result = TRUE;
			if (type) {
				*type = _vala_type;
			}
			return result;
		}
		case 'N':
		{
			_vala_type = PIECE_TYPE_KNIGHT;
			result = TRUE;
			if (type) {
				*type = _vala_type;
			}
			return result;
		}
		case 'B':
		{
			_vala_type = PIECE_TYPE_BISHOP;
			result = TRUE;
			if (type) {
				*type = _vala_type;
			}
			return result;
		}
		case 'Q':
		{
			_vala_type = PIECE_TYPE_QUEEN;
			result = TRUE;
			if (type) {
				*type = _vala_type;
			}
			return result;
		}
		case 'K':
		{
			_vala_type = PIECE_TYPE_KING;
			result = TRUE;
			if (type) {
				*type = _vala_type;
			}
			return result;
		}
		default:
		{
			result = FALSE;
			if (type) {
				*type = _vala_type;
			}
			return result;
		}
	}
}

static gboolean
chess_state_decode_move (ChessState* self,
                         ChessPlayer* player,
                         const gchar* move,
                         gint* r0,
                         gint* f0,
                         gint* r1,
                         gint* f1,
                         PieceType* promotion_type)
{
	gint _vala_r0 = 0;
	gint _vala_f0 = 0;
	gint _vala_r1 = 0;
	gint _vala_f1 = 0;
	PieceType _vala_promotion_type = 0;
	gint i = 0;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (player != NULL, FALSE);
	g_return_val_if_fail (move != NULL, FALSE);
	i = 0;
	_vala_promotion_type = PIECE_TYPE_QUEEN;
	if (g_str_has_prefix (move, "O-O-O")) {
		gint _tmp0_;
		gint _tmp1_;
		if (player->color == COLOR_WHITE) {
			_vala_r1 = 0;
			_vala_r0 = _vala_r1;
		} else {
			_vala_r1 = 7;
			_vala_r0 = _vala_r1;
		}
		_vala_f0 = 4;
		_vala_f1 = 2;
		_tmp0_ = strlen ("O-O-O");
		_tmp1_ = _tmp0_;
		i += (gint) _tmp1_;
	} else {
		if (g_str_has_prefix (move, "O-O")) {
			gint _tmp2_;
			gint _tmp3_;
			if (player->color == COLOR_WHITE) {
				_vala_r1 = 0;
				_vala_r0 = _vala_r1;
			} else {
				_vala_r1 = 7;
				_vala_r0 = _vala_r1;
			}
			_vala_f0 = 4;
			_vala_f1 = 6;
			_tmp2_ = strlen ("O-O");
			_tmp3_ = _tmp2_;
			i += (gint) _tmp3_;
		} else {
			PieceType type = 0;
			PieceType _tmp4_ = 0;
			gboolean _tmp5_;
			gboolean _tmp7_ = FALSE;
			gboolean _tmp9_ = FALSE;
			gboolean _tmp11_ = FALSE;
			gboolean _tmp13_ = FALSE;
			gboolean _tmp15_ = FALSE;
			gboolean _tmp25_ = FALSE;
			gboolean _tmp26_ = FALSE;
			type = PIECE_TYPE_PAWN;
			_tmp5_ = chess_state_decode_piece_type (self, (gunichar) string_get (move, (glong) i), &_tmp4_);
			type = _tmp4_;
			if (_tmp5_) {
				gint _tmp6_;
				_tmp6_ = i;
				i = _tmp6_ + 1;
			}
			_vala_f1 = -1;
			_vala_r1 = _vala_f1;
			_vala_f0 = _vala_r1;
			_vala_r0 = _vala_f0;
			if (string_get (move, (glong) i) >= 'a') {
				_tmp7_ = string_get (move, (glong) i) <= 'h';
			} else {
				_tmp7_ = FALSE;
			}
			if (_tmp7_) {
				gint _tmp8_;
				_vala_f1 = (gint) (string_get (move, (glong) i) - 'a');
				_tmp8_ = i;
				i = _tmp8_ + 1;
			}
			if (string_get (move, (glong) i) >= '1') {
				_tmp9_ = string_get (move, (glong) i) <= '8';
			} else {
				_tmp9_ = FALSE;
			}
			if (_tmp9_) {
				gint _tmp10_;
				_vala_r1 = (gint) (string_get (move, (glong) i) - '1');
				_tmp10_ = i;
				i = _tmp10_ + 1;
			}
			if (string_get (move, (glong) i) == 'x') {
				_tmp11_ = TRUE;
			} else {
				_tmp11_ = string_get (move, (glong) i) == '-';
			}
			if (_tmp11_) {
				gint _tmp12_;
				_tmp12_ = i;
				i = _tmp12_ + 1;
			}
			if (string_get (move, (glong) i) >= 'a') {
				_tmp13_ = string_get (move, (glong) i) <= 'h';
			} else {
				_tmp13_ = FALSE;
			}
			if (_tmp13_) {
				gint _tmp14_;
				_vala_f0 = _vala_f1;
				_vala_f1 = (gint) (string_get (move, (glong) i) - 'a');
				_tmp14_ = i;
				i = _tmp14_ + 1;
			}
			if (string_get (move, (glong) i) >= '1') {
				_tmp15_ = string_get (move, (glong) i) <= '8';
			} else {
				_tmp15_ = FALSE;
			}
			if (_tmp15_) {
				gint _tmp16_;
				_vala_r0 = _vala_r1;
				_vala_r1 = (gint) (string_get (move, (glong) i) - '1');
				_tmp16_ = i;
				i = _tmp16_ + 1;
			}
			if (string_get (move, (glong) i) == '=') {
				gint _tmp17_;
				PieceType _tmp18_ = 0;
				gboolean _tmp19_;
				_tmp17_ = i;
				i = _tmp17_ + 1;
				_tmp19_ = chess_state_decode_piece_type (self, (gunichar) string_get (move, (glong) i), &_tmp18_);
				_vala_promotion_type = _tmp18_;
				if (_tmp19_) {
					gint _tmp20_;
					_tmp20_ = i;
					i = _tmp20_ + 1;
				}
			} else {
				if (string_get (move, (glong) i) != '\0') {
					switch (string_get (move, (glong) i)) {
						case 'q':
						case 'Q':
						{
							gint _tmp21_;
							_vala_promotion_type = PIECE_TYPE_QUEEN;
							_tmp21_ = i;
							i = _tmp21_ + 1;
							break;
						}
						case 'n':
						case 'N':
						{
							gint _tmp22_;
							_vala_promotion_type = PIECE_TYPE_KNIGHT;
							_tmp22_ = i;
							i = _tmp22_ + 1;
							break;
						}
						case 'r':
						case 'R':
						{
							gint _tmp23_;
							_vala_promotion_type = PIECE_TYPE_ROOK;
							_tmp23_ = i;
							i = _tmp23_ + 1;
							break;
						}
						case 'b':
						case 'B':
						{
							gint _tmp24_;
							_vala_promotion_type = PIECE_TYPE_BISHOP;
							_tmp24_ = i;
							i = _tmp24_ + 1;
							break;
						}
						default:
						break;
					}
				}
			}
			if (_vala_r1 < 0) {
				_tmp25_ = TRUE;
			} else {
				_tmp25_ = _vala_f1 < 0;
			}
			if (_tmp25_) {
				g_debug ("chess-state.vala:913: Move %s missing destination", move);
				result = FALSE;
				if (r0) {
					*r0 = _vala_r0;
				}
				if (f0) {
					*f0 = _vala_f0;
				}
				if (r1) {
					*r1 = _vala_r1;
				}
				if (f1) {
					*f1 = _vala_f1;
				}
				if (promotion_type) {
					*promotion_type = _vala_promotion_type;
				}
				return result;
			}
			if (_vala_r0 < 0) {
				_tmp26_ = TRUE;
			} else {
				_tmp26_ = _vala_f0 < 0;
			}
			if (_tmp26_) {
				gint match_rank = 0;
				gint match_file = 0;
				match_rank = -1;
				match_file = -1;
				{
					gint file = 0;
					file = 0;
					{
						gboolean _tmp27_ = FALSE;
						_tmp27_ = TRUE;
						while (TRUE) {
							gboolean _tmp29_ = FALSE;
							if (!_tmp27_) {
								gint _tmp28_;
								_tmp28_ = file;
								file = _tmp28_ + 1;
							}
							_tmp27_ = FALSE;
							if (!(file < 8)) {
								break;
							}
							if (_vala_f0 >= 0) {
								_tmp29_ = file != _vala_f0;
							} else {
								_tmp29_ = FALSE;
							}
							if (_tmp29_) {
								continue;
							}
							{
								gint rank = 0;
								rank = 0;
								{
									gboolean _tmp30_ = FALSE;
									_tmp30_ = TRUE;
									while (TRUE) {
										gboolean _tmp32_ = FALSE;
										ChessPiece* piece = NULL;
										ChessPiece* _tmp33_;
										ChessPiece* _tmp34_;
										gboolean _tmp35_ = FALSE;
										gboolean _tmp36_ = FALSE;
										ChessPiece* _tmp37_;
										if (!_tmp30_) {
											gint _tmp31_;
											_tmp31_ = rank;
											rank = _tmp31_ + 1;
										}
										_tmp30_ = FALSE;
										if (!(rank < 8)) {
											break;
										}
										if (_vala_r0 >= 0) {
											_tmp32_ = rank != _vala_r0;
										} else {
											_tmp32_ = FALSE;
										}
										if (_tmp32_) {
											continue;
										}
										_tmp33_ = self->board[chess_state_get_index (self, rank, file)];
										_tmp34_ = _g_object_ref0 (_tmp33_);
										piece = _tmp34_;
										_tmp37_ = piece;
										if (_tmp37_ == NULL) {
											_tmp36_ = TRUE;
										} else {
											ChessPiece* _tmp38_;
											_tmp38_ = piece;
											_tmp36_ = _tmp38_->type != type;
										}
										if (_tmp36_) {
											_tmp35_ = TRUE;
										} else {
											ChessPiece* _tmp39_;
											ChessPlayer* _tmp40_;
											_tmp39_ = piece;
											_tmp40_ = _tmp39_->player;
											_tmp35_ = _tmp40_ != player;
										}
										if (_tmp35_) {
											_g_object_unref0 (piece);
											continue;
										}
										if (!chess_state_move_with_coords (self, player, rank, file, _vala_r1, _vala_f1, PIECE_TYPE_QUEEN, FALSE, TRUE)) {
											_g_object_unref0 (piece);
											continue;
										}
										if (match_rank >= 0) {
											g_debug ("chess-state.vala:944: Move %s is ambiguous", move);
											result = FALSE;
											_g_object_unref0 (piece);
											if (r0) {
												*r0 = _vala_r0;
											}
											if (f0) {
												*f0 = _vala_f0;
											}
											if (r1) {
												*r1 = _vala_r1;
											}
											if (f1) {
												*f1 = _vala_f1;
											}
											if (promotion_type) {
												*promotion_type = _vala_promotion_type;
											}
											return result;
										}
										match_rank = rank;
										match_file = file;
										_g_object_unref0 (piece);
									}
								}
							}
						}
					}
				}
				if (match_rank < 0) {
					g_debug ("chess-state.vala:955: Move %s has no matches", move);
					result = FALSE;
					if (r0) {
						*r0 = _vala_r0;
					}
					if (f0) {
						*f0 = _vala_f0;
					}
					if (r1) {
						*r1 = _vala_r1;
					}
					if (f1) {
						*f1 = _vala_f1;
					}
					if (promotion_type) {
						*promotion_type = _vala_promotion_type;
					}
					return result;
				}
				_vala_r0 = match_rank;
				_vala_f0 = match_file;
			}
		}
	}
	if (string_get (move, (glong) i) == '+') {
		gint _tmp41_;
		_tmp41_ = i;
		i = _tmp41_ + 1;
	} else {
		if (string_get (move, (glong) i) == '#') {
			gint _tmp42_;
			_tmp42_ = i;
			i = _tmp42_ + 1;
		}
	}
	if (string_get (move, (glong) i) != '\0') {
		g_debug ("chess-state.vala:971: Move %s has unexpected characters", move);
		result = FALSE;
		if (r0) {
			*r0 = _vala_r0;
		}
		if (f0) {
			*f0 = _vala_f0;
		}
		if (r1) {
			*r1 = _vala_r1;
		}
		if (f1) {
			*f1 = _vala_f1;
		}
		if (promotion_type) {
			*promotion_type = _vala_promotion_type;
		}
		return result;
	}
	result = TRUE;
	if (r0) {
		*r0 = _vala_r0;
	}
	if (f0) {
		*f0 = _vala_f0;
	}
	if (r1) {
		*r1 = _vala_r1;
	}
	if (f1) {
		*f1 = _vala_f1;
	}
	if (promotion_type) {
		*promotion_type = _vala_promotion_type;
	}
	return result;
}

ChessPlayer*
chess_state_get_opponent (ChessState* self)
{
	ChessPlayer* result;
	ChessPlayer* _tmp0_ = NULL;
	ChessPlayer* _tmp1_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp1_ = self->current_player;
	if (_tmp1_->color == COLOR_WHITE) {
		ChessPlayer* _tmp2_;
		_tmp2_ = self->players[COLOR_BLACK];
		_tmp0_ = _tmp2_;
	} else {
		ChessPlayer* _tmp3_;
		_tmp3_ = self->players[COLOR_WHITE];
		_tmp0_ = _tmp3_;
	}
	result = _tmp0_;
	return result;
}

static void
chess_state_class_init (ChessStateClass * klass,
                        gpointer klass_data)
{
	chess_state_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &ChessState_private_offset);
	G_OBJECT_CLASS (klass)->get_property = _vala_chess_state_get_property;
	G_OBJECT_CLASS (klass)->finalize = chess_state_finalize;
	g_object_class_install_property (G_OBJECT_CLASS (klass), CHESS_STATE_OPPONENT_PROPERTY, chess_state_properties[CHESS_STATE_OPPONENT_PROPERTY] = g_param_spec_object ("opponent", "opponent", "opponent", TYPE_CHESS_PLAYER, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
}

static void
chess_state_instance_init (ChessState * self,
                           gpointer klass)
{
	self->priv = chess_state_get_instance_private (self);
	self->number = 0;
	self->en_passant_index = -1;
	self->last_move = NULL;
}

static void
chess_state_finalize (GObject * obj)
{
	ChessState * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_CHESS_STATE, ChessState);
	_vala_array_destroy (self->players, 2, (GDestroyNotify) g_object_unref);
	_g_object_unref0 (self->current_player);
	_vala_array_destroy (self->board, 64, (GDestroyNotify) g_object_unref);
	_g_object_unref0 (self->last_move);
	G_OBJECT_CLASS (chess_state_parent_class)->finalize (obj);
}

static GType
chess_state_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (ChessStateClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) chess_state_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (ChessState), 0, (GInstanceInitFunc) chess_state_instance_init, NULL };
	GType chess_state_type_id;
	chess_state_type_id = g_type_register_static (G_TYPE_OBJECT, "ChessState", &g_define_type_info, 0);
	ChessState_private_offset = g_type_add_instance_private (chess_state_type_id, sizeof (ChessStatePrivate));
	return chess_state_type_id;
}

GType
chess_state_get_type (void)
{
	static volatile gsize chess_state_type_id__once = 0;
	if (g_once_init_enter (&chess_state_type_id__once)) {
		GType chess_state_type_id;
		chess_state_type_id = chess_state_get_type_once ();
		g_once_init_leave (&chess_state_type_id__once, chess_state_type_id);
	}
	return chess_state_type_id__once;
}

static void
_vala_chess_state_get_property (GObject * object,
                                guint property_id,
                                GValue * value,
                                GParamSpec * pspec)
{
	ChessState * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_CHESS_STATE, ChessState);
	switch (property_id) {
		case CHESS_STATE_OPPONENT_PROPERTY:
		g_value_set_object (value, chess_state_get_opponent (self));
		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);
}

static gssize
_vala_array_length (gpointer array)
{
	gssize length;
	length = 0;
	if (array) {
		while (((gpointer*) array)[length]) {
			length++;
		}
	}
	return length;
}

