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

/* -*- Mode: vala; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * Copyright © 2014 Parin Porecha
 * Copyright © 2014 Michael Catanzaro
 *
 * This file is part of GNOME Sudoku.
 *
 * GNOME Sudoku 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.
 *
 * GNOME Sudoku is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with GNOME Sudoku. If not, see <http://www.gnu.org/licenses/>.
 */

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

#define SUDOKU_GAME_TYPE_UNDO_ITEM (sudoku_game_undo_item_get_type ())
typedef struct _SudokuGameUndoItem SudokuGameUndoItem;
enum  {
	SUDOKU_GAME_0_PROPERTY,
	SUDOKU_GAME_PAUSED_PROPERTY,
	SUDOKU_GAME_NUM_PROPERTIES
};
static GParamSpec* sudoku_game_properties[SUDOKU_GAME_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_timer_destroy0(var) ((var == NULL) ? NULL : (var = (g_timer_destroy (var), NULL)))
#define _sudoku_game_undo_item_free0(var) ((var == NULL) ? NULL : (var = (sudoku_game_undo_item_free (var), NULL)))
enum  {
	SUDOKU_GAME_TICK_SIGNAL,
	SUDOKU_GAME_PAUSED_CHANGED_SIGNAL,
	SUDOKU_GAME_CELL_CHANGED_SIGNAL,
	SUDOKU_GAME_NUM_SIGNALS
};
static guint sudoku_game_signals[SUDOKU_GAME_NUM_SIGNALS] = {0};
#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);

struct _SudokuGameUndoItem {
	gint row;
	gint col;
	gint val;
	gboolean* earmarks;
	gint earmarks_length1;
	gint _earmarks_size_;
};

struct _SudokuGamePrivate {
	guint clock_timeout;
	gboolean _paused;
	GeeList* undostack;
	GeeList* redostack;
};

static gint SudokuGame_private_offset;
static gpointer sudoku_game_parent_class = NULL;

static GType sudoku_game_undo_item_get_type (void) G_GNUC_CONST  G_GNUC_UNUSED ;
static SudokuGameUndoItem* sudoku_game_undo_item_dup (const SudokuGameUndoItem* self);
static void sudoku_game_undo_item_free (SudokuGameUndoItem* self);
static void sudoku_game_undo_item_copy (const SudokuGameUndoItem* self,
                                 SudokuGameUndoItem* dest);
static void sudoku_game_undo_item_destroy (SudokuGameUndoItem* self);
static void sudoku_game_apply_stack (SudokuGame* self,
                              GeeList* from,
                              GeeList* to);
static void sudoku_game_add_to_stack (SudokuGame* self,
                               GeeList* stack,
                               gint r,
                               gint c,
                               gint v,
                               gboolean* e,
                               gint e_length1);
static gboolean* _vala_array_dup9 (gboolean* self,
                            gssize length);
static gboolean sudoku_game_timeout_cb (SudokuGame* self);
static gboolean _sudoku_game_timeout_cb_gsource_func (gpointer self);
static void sudoku_game_set_paused (SudokuGame* self,
                             gboolean value);
static void g_cclosure_user_marshal_VOID__INT_INT_INT_INT (GClosure * closure,
                                                    GValue * return_value,
                                                    guint n_param_values,
                                                    const GValue * param_values,
                                                    gpointer invocation_hint,
                                                    gpointer marshal_data);
static gboolean* _vala_array_dup10 (gboolean* self,
                             gssize length);
static void sudoku_game_finalize (GObject * obj);
static GType sudoku_game_get_type_once (void);
static void _vala_sudoku_game_get_property (GObject * object,
                                     guint property_id,
                                     GValue * value,
                                     GParamSpec * pspec);
static void _vala_sudoku_game_set_property (GObject * object,
                                     guint property_id,
                                     const GValue * value,
                                     GParamSpec * pspec);
static inline gpointer _vala_memdup2 (gconstpointer mem,
                        gsize byte_size);

static inline gpointer
sudoku_game_get_instance_private (SudokuGame* self)
{
	return G_STRUCT_MEMBER_P (self, SudokuGame_private_offset);
}

gboolean
sudoku_game_is_undostack_null (SudokuGame* self)
{
	GeeList* _tmp0_;
	gint _tmp1_;
	gint _tmp2_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->undostack;
	_tmp1_ = gee_collection_get_size ((GeeCollection*) _tmp0_);
	_tmp2_ = _tmp1_;
	result = _tmp2_ == 0;
	return result;
}

gboolean
sudoku_game_is_redostack_null (SudokuGame* self)
{
	GeeList* _tmp0_;
	gint _tmp1_;
	gint _tmp2_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->redostack;
	_tmp1_ = gee_collection_get_size ((GeeCollection*) _tmp0_);
	_tmp2_ = _tmp1_;
	result = _tmp2_ == 0;
	return result;
}

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

SudokuGame*
sudoku_game_construct (GType object_type,
                       SudokuBoard* board)
{
	SudokuGame * self = NULL;
	SudokuBoard* _tmp0_;
	GTimer* _tmp1_;
	GeeArrayList* _tmp2_;
	GeeArrayList* _tmp3_;
	g_return_val_if_fail (board != NULL, NULL);
	self = (SudokuGame*) g_object_new (object_type, NULL);
	_tmp0_ = _g_object_ref0 (board);
	_g_object_unref0 (self->board);
	self->board = _tmp0_;
	self->mode = GAME_MODE_PLAY;
	_tmp1_ = g_timer_new ();
	_g_timer_destroy0 (self->timer);
	self->timer = _tmp1_;
	_tmp2_ = gee_array_list_new (SUDOKU_GAME_TYPE_UNDO_ITEM, (GBoxedCopyFunc) sudoku_game_undo_item_dup, (GDestroyNotify) sudoku_game_undo_item_free, NULL, NULL, NULL);
	_g_object_unref0 (self->priv->undostack);
	self->priv->undostack = (GeeList*) _tmp2_;
	_tmp3_ = gee_array_list_new (SUDOKU_GAME_TYPE_UNDO_ITEM, (GBoxedCopyFunc) sudoku_game_undo_item_dup, (GDestroyNotify) sudoku_game_undo_item_free, NULL, NULL, NULL);
	_g_object_unref0 (self->priv->redostack);
	self->priv->redostack = (GeeList*) _tmp3_;
	return self;
}

SudokuGame*
sudoku_game_new (SudokuBoard* board)
{
	return sudoku_game_construct (TYPE_SUDOKU_GAME, board);
}

void
sudoku_game_enable_earmark (SudokuGame* self,
                            gint row,
                            gint col,
                            gint k_no)
{
	gint old_val = 0;
	SudokuBoard* _tmp0_;
	gboolean* old_earmarks = NULL;
	SudokuBoard* _tmp1_;
	gint _tmp2_ = 0;
	gboolean* _tmp3_;
	gint old_earmarks_length1;
	gint _old_earmarks_size_;
	SudokuBoard* _tmp4_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->board;
	old_val = sudoku_board_get (_tmp0_, row, col);
	_tmp1_ = self->board;
	_tmp3_ = sudoku_board_get_earmarks (_tmp1_, row, col, &_tmp2_);
	old_earmarks = _tmp3_;
	old_earmarks_length1 = _tmp2_;
	_old_earmarks_size_ = old_earmarks_length1;
	sudoku_game_update_undo (self, row, col, old_val, old_earmarks, (gint) old_earmarks_length1);
	_tmp4_ = self->board;
	sudoku_board_enable_earmark (_tmp4_, row, col, k_no);
	old_earmarks = (g_free (old_earmarks), NULL);
}

void
sudoku_game_disable_earmark (SudokuGame* self,
                             gint row,
                             gint col,
                             gint k_no)
{
	gint old_val = 0;
	SudokuBoard* _tmp0_;
	gboolean* old_earmarks = NULL;
	SudokuBoard* _tmp1_;
	gint _tmp2_ = 0;
	gboolean* _tmp3_;
	gint old_earmarks_length1;
	gint _old_earmarks_size_;
	SudokuBoard* _tmp4_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->board;
	old_val = sudoku_board_get (_tmp0_, row, col);
	_tmp1_ = self->board;
	_tmp3_ = sudoku_board_get_earmarks (_tmp1_, row, col, &_tmp2_);
	old_earmarks = _tmp3_;
	old_earmarks_length1 = _tmp2_;
	_old_earmarks_size_ = old_earmarks_length1;
	sudoku_game_update_undo (self, row, col, old_val, old_earmarks, (gint) old_earmarks_length1);
	_tmp4_ = self->board;
	sudoku_board_disable_earmark (_tmp4_, row, col, k_no);
	old_earmarks = (g_free (old_earmarks), NULL);
}

void
sudoku_game_insert (SudokuGame* self,
                    gint row,
                    gint col,
                    gint val)
{
	gint old_val = 0;
	SudokuBoard* _tmp0_;
	gboolean* old_earmarks = NULL;
	SudokuBoard* _tmp1_;
	gint _tmp2_ = 0;
	gboolean* _tmp3_;
	gint old_earmarks_length1;
	gint _old_earmarks_size_;
	gboolean* _tmp4_;
	gint _tmp4__length1;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->board;
	old_val = sudoku_board_get (_tmp0_, row, col);
	_tmp1_ = self->board;
	_tmp3_ = sudoku_board_get_earmarks (_tmp1_, row, col, &_tmp2_);
	old_earmarks = _tmp3_;
	old_earmarks_length1 = _tmp2_;
	_old_earmarks_size_ = old_earmarks_length1;
	_tmp4_ = old_earmarks;
	_tmp4__length1 = old_earmarks_length1;
	sudoku_game_update_undo (self, row, col, old_val, _tmp4_, (gint) _tmp4__length1);
	if (self->mode == GAME_MODE_CREATE) {
		SudokuBoard* _tmp5_;
		SudokuBoard* _tmp6_;
		gboolean* _tmp7_;
		gint _tmp7__length1;
		gint _tmp7__length2;
		_tmp5_ = self->board;
		sudoku_board_insert (_tmp5_, row, col, val, TRUE);
		_tmp6_ = self->board;
		_tmp7_ = _tmp6_->is_fixed;
		_tmp7__length1 = _tmp6_->is_fixed_length1;
		_tmp7__length2 = _tmp6_->is_fixed_length2;
		_tmp7_[(row * _tmp7__length2) + col] = TRUE;
	} else {
		SudokuBoard* _tmp8_;
		_tmp8_ = self->board;
		sudoku_board_insert (_tmp8_, row, col, val, FALSE);
	}
	g_signal_emit (self, sudoku_game_signals[SUDOKU_GAME_CELL_CHANGED_SIGNAL], 0, row, col, old_val, val);
	old_earmarks = (g_free (old_earmarks), NULL);
}

void
sudoku_game_remove (SudokuGame* self,
                    gint row,
                    gint col)
{
	gint old_val = 0;
	SudokuBoard* _tmp0_;
	gboolean* old_earmarks = NULL;
	SudokuBoard* _tmp1_;
	gint _tmp2_ = 0;
	gboolean* _tmp3_;
	gint old_earmarks_length1;
	gint _old_earmarks_size_;
	gboolean* _tmp4_;
	gint _tmp4__length1;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->board;
	old_val = sudoku_board_get (_tmp0_, row, col);
	_tmp1_ = self->board;
	_tmp3_ = sudoku_board_get_earmarks (_tmp1_, row, col, &_tmp2_);
	old_earmarks = _tmp3_;
	old_earmarks_length1 = _tmp2_;
	_old_earmarks_size_ = old_earmarks_length1;
	_tmp4_ = old_earmarks;
	_tmp4__length1 = old_earmarks_length1;
	sudoku_game_update_undo (self, row, col, old_val, _tmp4_, (gint) _tmp4__length1);
	if (self->mode == GAME_MODE_CREATE) {
		SudokuBoard* _tmp5_;
		SudokuBoard* _tmp6_;
		gboolean* _tmp7_;
		gint _tmp7__length1;
		gint _tmp7__length2;
		_tmp5_ = self->board;
		sudoku_board_remove (_tmp5_, row, col, TRUE);
		_tmp6_ = self->board;
		_tmp7_ = _tmp6_->is_fixed;
		_tmp7__length1 = _tmp6_->is_fixed_length1;
		_tmp7__length2 = _tmp6_->is_fixed_length2;
		_tmp7_[(row * _tmp7__length2) + col] = FALSE;
	} else {
		SudokuBoard* _tmp8_;
		_tmp8_ = self->board;
		sudoku_board_remove (_tmp8_, row, col, FALSE);
	}
	g_signal_emit (self, sudoku_game_signals[SUDOKU_GAME_CELL_CHANGED_SIGNAL], 0, row, col, old_val, 0);
	old_earmarks = (g_free (old_earmarks), NULL);
}

gboolean
sudoku_game_is_empty (SudokuGame* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	if (self->mode == GAME_MODE_CREATE) {
		SudokuBoard* _tmp0_;
		gint _tmp1_;
		gint _tmp2_;
		_tmp0_ = self->board;
		_tmp1_ = sudoku_board_get_filled (_tmp0_);
		_tmp2_ = _tmp1_;
		result = _tmp2_ == 0;
		return result;
	} else {
		SudokuBoard* _tmp3_;
		_tmp3_ = self->board;
		result = sudoku_board_is_empty (_tmp3_);
		return result;
	}
}

void
sudoku_game_undo (SudokuGame* self)
{
	GeeList* _tmp0_;
	GeeList* _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->undostack;
	_tmp1_ = self->priv->redostack;
	sudoku_game_apply_stack (self, _tmp0_, _tmp1_);
}

void
sudoku_game_redo (SudokuGame* self)
{
	GeeList* _tmp0_;
	GeeList* _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->redostack;
	_tmp1_ = self->priv->undostack;
	sudoku_game_apply_stack (self, _tmp0_, _tmp1_);
}

void
sudoku_game_reset (SudokuGame* self)
{
	SudokuBoard* _tmp0_;
	GTimer* _tmp1_;
	GeeList* _tmp2_;
	GeeList* _tmp3_;
	SudokuBoard* _tmp25_;
	GeeSet* _tmp26_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->board;
	sudoku_board_set_previous_played_time (_tmp0_, (gdouble) 0);
	_tmp1_ = self->timer;
	g_timer_start (_tmp1_);
	_tmp2_ = self->priv->undostack;
	gee_collection_clear ((GeeCollection*) _tmp2_);
	_tmp3_ = self->priv->redostack;
	gee_collection_clear ((GeeCollection*) _tmp3_);
	{
		gint l1 = 0;
		l1 = 0;
		{
			gboolean _tmp4_ = FALSE;
			_tmp4_ = TRUE;
			while (TRUE) {
				SudokuBoard* _tmp6_;
				gint _tmp7_;
				gint _tmp8_;
				if (!_tmp4_) {
					gint _tmp5_;
					_tmp5_ = l1;
					l1 = _tmp5_ + 1;
				}
				_tmp4_ = FALSE;
				_tmp6_ = self->board;
				_tmp7_ = sudoku_board_get_rows (_tmp6_);
				_tmp8_ = _tmp7_;
				if (!(l1 < _tmp8_)) {
					break;
				}
				{
					gint l2 = 0;
					l2 = 0;
					{
						gboolean _tmp9_ = FALSE;
						_tmp9_ = TRUE;
						while (TRUE) {
							SudokuBoard* _tmp11_;
							gint _tmp12_;
							gint _tmp13_;
							gboolean _tmp14_ = FALSE;
							SudokuBoard* _tmp18_;
							SudokuBoard* _tmp19_;
							gboolean* _tmp20_;
							gint _tmp20__length1;
							gint _tmp20__length2;
							gboolean _tmp21_;
							SudokuBoard* _tmp22_;
							gboolean* _tmp23_;
							gint _tmp23__length1;
							gint _tmp23__length2;
							SudokuBoard* _tmp24_;
							if (!_tmp9_) {
								gint _tmp10_;
								_tmp10_ = l2;
								l2 = _tmp10_ + 1;
							}
							_tmp9_ = FALSE;
							_tmp11_ = self->board;
							_tmp12_ = sudoku_board_get_cols (_tmp11_);
							_tmp13_ = _tmp12_;
							if (!(l2 < _tmp13_)) {
								break;
							}
							if (self->mode == GAME_MODE_PLAY) {
								SudokuBoard* _tmp15_;
								gboolean* _tmp16_;
								gint _tmp16__length1;
								gint _tmp16__length2;
								gboolean _tmp17_;
								_tmp15_ = self->board;
								_tmp16_ = _tmp15_->is_fixed;
								_tmp16__length1 = _tmp15_->is_fixed_length1;
								_tmp16__length2 = _tmp15_->is_fixed_length2;
								_tmp17_ = _tmp16_[(l1 * _tmp16__length2) + l2];
								_tmp14_ = _tmp17_;
							} else {
								_tmp14_ = FALSE;
							}
							if (_tmp14_) {
								continue;
							}
							_tmp18_ = self->board;
							_tmp19_ = self->board;
							_tmp20_ = _tmp19_->is_fixed;
							_tmp20__length1 = _tmp19_->is_fixed_length1;
							_tmp20__length2 = _tmp19_->is_fixed_length2;
							_tmp21_ = _tmp20_[(l1 * _tmp20__length2) + l2];
							sudoku_board_remove (_tmp18_, l1, l2, _tmp21_);
							_tmp22_ = self->board;
							_tmp23_ = _tmp22_->is_fixed;
							_tmp23__length1 = _tmp22_->is_fixed_length1;
							_tmp23__length2 = _tmp22_->is_fixed_length2;
							_tmp23_[(l1 * _tmp23__length2) + l2] = FALSE;
							_tmp24_ = self->board;
							g_signal_emit (self, sudoku_game_signals[SUDOKU_GAME_CELL_CHANGED_SIGNAL], 0, l1, l2, sudoku_board_get (_tmp24_, l1, l2), 0);
						}
					}
				}
			}
		}
	}
	_tmp25_ = self->board;
	_tmp26_ = _tmp25_->broken_coords;
	gee_collection_clear ((GeeCollection*) _tmp26_);
}

void
sudoku_game_cell_changed_cb (SudokuGame* self,
                             gint row,
                             gint col,
                             gint old_val,
                             gint new_val)
{
	g_return_if_fail (self != NULL);
	g_signal_emit (self, sudoku_game_signals[SUDOKU_GAME_CELL_CHANGED_SIGNAL], 0, row, col, old_val, new_val);
}

void
sudoku_game_update_undo (SudokuGame* self,
                         gint row,
                         gint col,
                         gint old_val,
                         gboolean* old_earmarks,
                         gint old_earmarks_length1)
{
	GeeList* _tmp0_;
	GeeList* _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->undostack;
	sudoku_game_add_to_stack (self, _tmp0_, row, col, old_val, old_earmarks, (gint) old_earmarks_length1);
	_tmp1_ = self->priv->redostack;
	gee_collection_clear ((GeeCollection*) _tmp1_);
}

static gboolean*
_vala_array_dup9 (gboolean* self,
                  gssize length)
{
	if (length > 0) {
		return _vala_memdup2 (self, length * sizeof (gboolean));
	}
	return NULL;
}

static void
sudoku_game_add_to_stack (SudokuGame* self,
                          GeeList* stack,
                          gint r,
                          gint c,
                          gint v,
                          gboolean* e,
                          gint e_length1)
{
	SudokuGameUndoItem step = {0};
	gboolean* _tmp0_;
	gint _tmp0__length1;
	SudokuGameUndoItem _tmp1_ = {0};
	SudokuGameUndoItem _tmp2_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (stack != NULL);
	_tmp0_ = (e != NULL) ? _vala_array_dup9 (e, e_length1) : e;
	_tmp0__length1 = e_length1;
	_tmp1_.row = r;
	_tmp1_.col = c;
	_tmp1_.val = v;
	_tmp1_.earmarks = (g_free (_tmp1_.earmarks), NULL);
	_tmp1_.earmarks = _tmp0_;
	_tmp1_.earmarks_length1 = _tmp0__length1;
	_tmp1_._earmarks_size_ = _tmp1_.earmarks_length1;
	step = _tmp1_;
	_tmp2_ = step;
	gee_collection_add ((GeeCollection*) stack, &_tmp2_);
	sudoku_game_undo_item_destroy (&step);
}

static void
sudoku_game_apply_stack (SudokuGame* self,
                         GeeList* from,
                         GeeList* to)
{
	gint _tmp0_;
	gint _tmp1_;
	SudokuGameUndoItem* top = NULL;
	gint _tmp2_;
	gint _tmp3_;
	gpointer _tmp4_;
	gint old_val = 0;
	SudokuBoard* _tmp5_;
	SudokuGameUndoItem* _tmp6_;
	SudokuGameUndoItem* _tmp7_;
	gboolean* old_earmarks = NULL;
	SudokuBoard* _tmp8_;
	SudokuGameUndoItem* _tmp9_;
	SudokuGameUndoItem* _tmp10_;
	gint _tmp11_ = 0;
	gboolean* _tmp12_;
	gint old_earmarks_length1;
	gint _old_earmarks_size_;
	SudokuGameUndoItem* _tmp13_;
	SudokuGameUndoItem* _tmp14_;
	gboolean* _tmp15_;
	gint _tmp15__length1;
	SudokuGameUndoItem* _tmp31_;
	SudokuGameUndoItem* _tmp62_;
	SudokuGameUndoItem* _tmp63_;
	SudokuGameUndoItem* _tmp64_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (from != NULL);
	g_return_if_fail (to != NULL);
	_tmp0_ = gee_collection_get_size ((GeeCollection*) from);
	_tmp1_ = _tmp0_;
	if (_tmp1_ == 0) {
		return;
	}
	_tmp2_ = gee_collection_get_size ((GeeCollection*) from);
	_tmp3_ = _tmp2_;
	_tmp4_ = gee_list_remove_at (from, _tmp3_ - 1);
	top = (SudokuGameUndoItem*) _tmp4_;
	_tmp5_ = self->board;
	_tmp6_ = top;
	_tmp7_ = top;
	old_val = sudoku_board_get (_tmp5_, (*_tmp6_).row, (*_tmp7_).col);
	_tmp8_ = self->board;
	_tmp9_ = top;
	_tmp10_ = top;
	_tmp12_ = sudoku_board_get_earmarks (_tmp8_, (*_tmp9_).row, (*_tmp10_).col, &_tmp11_);
	old_earmarks = _tmp12_;
	old_earmarks_length1 = _tmp11_;
	_old_earmarks_size_ = old_earmarks_length1;
	_tmp13_ = top;
	_tmp14_ = top;
	_tmp15_ = old_earmarks;
	_tmp15__length1 = old_earmarks_length1;
	sudoku_game_add_to_stack (self, to, (*_tmp13_).row, (*_tmp14_).col, old_val, _tmp15_, (gint) _tmp15__length1);
	if (self->mode == GAME_MODE_CREATE) {
		SudokuBoard* _tmp16_;
		SudokuGameUndoItem* _tmp17_;
		SudokuGameUndoItem* _tmp18_;
		SudokuBoard* _tmp19_;
		gboolean* _tmp20_;
		gint _tmp20__length1;
		gint _tmp20__length2;
		SudokuGameUndoItem* _tmp21_;
		SudokuGameUndoItem* _tmp22_;
		gboolean _tmp23_;
		SudokuBoard* _tmp24_;
		gboolean* _tmp25_;
		gint _tmp25__length1;
		gint _tmp25__length2;
		SudokuGameUndoItem* _tmp26_;
		SudokuGameUndoItem* _tmp27_;
		_tmp16_ = self->board;
		_tmp17_ = top;
		_tmp18_ = top;
		_tmp19_ = self->board;
		_tmp20_ = _tmp19_->is_fixed;
		_tmp20__length1 = _tmp19_->is_fixed_length1;
		_tmp20__length2 = _tmp19_->is_fixed_length2;
		_tmp21_ = top;
		_tmp22_ = top;
		_tmp23_ = _tmp20_[((*_tmp21_).row * _tmp20__length2) + (*_tmp22_).col];
		sudoku_board_remove (_tmp16_, (*_tmp17_).row, (*_tmp18_).col, _tmp23_);
		_tmp24_ = self->board;
		_tmp25_ = _tmp24_->is_fixed;
		_tmp25__length1 = _tmp24_->is_fixed_length1;
		_tmp25__length2 = _tmp24_->is_fixed_length2;
		_tmp26_ = top;
		_tmp27_ = top;
		_tmp25_[((*_tmp26_).row * _tmp25__length2) + (*_tmp27_).col] = FALSE;
	} else {
		SudokuBoard* _tmp28_;
		SudokuGameUndoItem* _tmp29_;
		SudokuGameUndoItem* _tmp30_;
		_tmp28_ = self->board;
		_tmp29_ = top;
		_tmp30_ = top;
		sudoku_board_remove (_tmp28_, (*_tmp29_).row, (*_tmp30_).col, FALSE);
	}
	_tmp31_ = top;
	if ((*_tmp31_).val != 0) {
		if (self->mode == GAME_MODE_CREATE) {
			SudokuBoard* _tmp32_;
			SudokuGameUndoItem* _tmp33_;
			SudokuGameUndoItem* _tmp34_;
			SudokuGameUndoItem* _tmp35_;
			SudokuBoard* _tmp36_;
			gboolean* _tmp37_;
			gint _tmp37__length1;
			gint _tmp37__length2;
			SudokuGameUndoItem* _tmp38_;
			SudokuGameUndoItem* _tmp39_;
			gboolean _tmp40_;
			SudokuBoard* _tmp41_;
			gboolean* _tmp42_;
			gint _tmp42__length1;
			gint _tmp42__length2;
			SudokuGameUndoItem* _tmp43_;
			SudokuGameUndoItem* _tmp44_;
			_tmp32_ = self->board;
			_tmp33_ = top;
			_tmp34_ = top;
			_tmp35_ = top;
			_tmp36_ = self->board;
			_tmp37_ = _tmp36_->is_fixed;
			_tmp37__length1 = _tmp36_->is_fixed_length1;
			_tmp37__length2 = _tmp36_->is_fixed_length2;
			_tmp38_ = top;
			_tmp39_ = top;
			_tmp40_ = _tmp37_[((*_tmp38_).row * _tmp37__length2) + (*_tmp39_).col];
			sudoku_board_insert (_tmp32_, (*_tmp33_).row, (*_tmp34_).col, (*_tmp35_).val, _tmp40_);
			_tmp41_ = self->board;
			_tmp42_ = _tmp41_->is_fixed;
			_tmp42__length1 = _tmp41_->is_fixed_length1;
			_tmp42__length2 = _tmp41_->is_fixed_length2;
			_tmp43_ = top;
			_tmp44_ = top;
			_tmp42_[((*_tmp43_).row * _tmp42__length2) + (*_tmp44_).col] = TRUE;
		} else {
			SudokuBoard* _tmp45_;
			SudokuGameUndoItem* _tmp46_;
			SudokuGameUndoItem* _tmp47_;
			SudokuGameUndoItem* _tmp48_;
			_tmp45_ = self->board;
			_tmp46_ = top;
			_tmp47_ = top;
			_tmp48_ = top;
			sudoku_board_insert (_tmp45_, (*_tmp46_).row, (*_tmp47_).col, (*_tmp48_).val, FALSE);
		}
	}
	{
		gint i = 0;
		i = 1;
		{
			gboolean _tmp49_ = FALSE;
			_tmp49_ = TRUE;
			while (TRUE) {
				SudokuGameUndoItem* _tmp51_;
				gboolean* _tmp52_;
				gint _tmp52__length1;
				SudokuGameUndoItem* _tmp53_;
				gboolean* _tmp54_;
				gint _tmp54__length1;
				gboolean _tmp55_;
				if (!_tmp49_) {
					gint _tmp50_;
					_tmp50_ = i;
					i = _tmp50_ + 1;
				}
				_tmp49_ = FALSE;
				_tmp51_ = top;
				_tmp52_ = (*_tmp51_).earmarks;
				_tmp52__length1 = (*_tmp51_).earmarks_length1;
				if (!(i <= _tmp52__length1)) {
					break;
				}
				_tmp53_ = top;
				_tmp54_ = (*_tmp53_).earmarks;
				_tmp54__length1 = (*_tmp53_).earmarks_length1;
				_tmp55_ = _tmp54_[i - 1];
				if (_tmp55_) {
					SudokuBoard* _tmp56_;
					SudokuGameUndoItem* _tmp57_;
					SudokuGameUndoItem* _tmp58_;
					_tmp56_ = self->board;
					_tmp57_ = top;
					_tmp58_ = top;
					sudoku_board_enable_earmark (_tmp56_, (*_tmp57_).row, (*_tmp58_).col, i);
				} else {
					SudokuBoard* _tmp59_;
					SudokuGameUndoItem* _tmp60_;
					SudokuGameUndoItem* _tmp61_;
					_tmp59_ = self->board;
					_tmp60_ = top;
					_tmp61_ = top;
					sudoku_board_disable_earmark (_tmp59_, (*_tmp60_).row, (*_tmp61_).col, i);
				}
			}
		}
	}
	_tmp62_ = top;
	_tmp63_ = top;
	_tmp64_ = top;
	g_signal_emit (self, sudoku_game_signals[SUDOKU_GAME_CELL_CHANGED_SIGNAL], 0, (*_tmp62_).row, (*_tmp63_).col, old_val, (*_tmp64_).val);
	old_earmarks = (g_free (old_earmarks), NULL);
	_sudoku_game_undo_item_free0 (top);
}

gdouble
sudoku_game_get_total_time_played (SudokuGame* self)
{
	SudokuBoard* _tmp0_;
	gdouble _tmp1_;
	gdouble _tmp2_;
	GTimer* _tmp3_;
	gdouble result;
	g_return_val_if_fail (self != NULL, 0.0);
	_tmp0_ = self->board;
	_tmp1_ = sudoku_board_get_previous_played_time (_tmp0_);
	_tmp2_ = _tmp1_;
	_tmp3_ = self->timer;
	result = _tmp2_ + g_timer_elapsed (_tmp3_, NULL);
	return result;
}

static gboolean
_sudoku_game_timeout_cb_gsource_func (gpointer self)
{
	gboolean result;
	result = sudoku_game_timeout_cb ((SudokuGame*) self);
	return result;
}

static gboolean
sudoku_game_timeout_cb (SudokuGame* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	self->priv->clock_timeout = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, (guint) 1, _sudoku_game_timeout_cb_gsource_func, g_object_ref (self), g_object_unref);
	g_source_set_name_by_id (self->priv->clock_timeout, "[gnome-sudoku] timeout_cb");
	g_signal_emit (self, sudoku_game_signals[SUDOKU_GAME_TICK_SIGNAL], 0);
	result = FALSE;
	return result;
}

void
sudoku_game_start_clock (SudokuGame* self)
{
	GTimer* _tmp0_;
	GTimer* _tmp2_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->timer;
	if (_tmp0_ == NULL) {
		GTimer* _tmp1_;
		_tmp1_ = g_timer_new ();
		_g_timer_destroy0 (self->timer);
		self->timer = _tmp1_;
	}
	_tmp2_ = self->timer;
	g_timer_start (_tmp2_);
	sudoku_game_timeout_cb (self);
}

void
sudoku_game_stop_clock (SudokuGame* self)
{
	GTimer* _tmp0_;
	GTimer* _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->timer;
	_vala_return_if_fail (_tmp0_ != NULL, "timer != null");
	if (self->priv->clock_timeout != ((guint) 0)) {
		g_source_remove (self->priv->clock_timeout);
	}
	self->priv->clock_timeout = (guint) 0;
	sudoku_game_set_paused (self, TRUE);
	_tmp1_ = self->timer;
	g_timer_stop (_tmp1_);
	g_signal_emit (self, sudoku_game_signals[SUDOKU_GAME_TICK_SIGNAL], 0);
}

void
sudoku_game_resume_clock (SudokuGame* self)
{
	GTimer* _tmp0_;
	GTimer* _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->timer;
	_vala_return_if_fail ((_tmp0_ != NULL) && (self->priv->clock_timeout == ((guint) 0)), "timer != null && clock_timeout == 0");
	_tmp1_ = self->timer;
	g_timer_continue (_tmp1_);
	sudoku_game_set_paused (self, FALSE);
	sudoku_game_timeout_cb (self);
}

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

static void
sudoku_game_set_paused (SudokuGame* self,
                        gboolean value)
{
	g_return_if_fail (self != NULL);
	self->priv->_paused = value;
	g_signal_emit (self, sudoku_game_signals[SUDOKU_GAME_PAUSED_CHANGED_SIGNAL], 0);
	g_object_notify_by_pspec ((GObject *) self, sudoku_game_properties[SUDOKU_GAME_PAUSED_PROPERTY]);
}

static void
g_cclosure_user_marshal_VOID__INT_INT_INT_INT (GClosure * closure,
                                               GValue * return_value,
                                               guint n_param_values,
                                               const GValue * param_values,
                                               gpointer invocation_hint,
                                               gpointer marshal_data)
{
	typedef void (*GMarshalFunc_VOID__INT_INT_INT_INT) (gpointer data1, gint arg_1, gint arg_2, gint arg_3, gint arg_4, gpointer data2);
	register GMarshalFunc_VOID__INT_INT_INT_INT callback;
	register GCClosure * cc;
	register gpointer data1;
	register gpointer data2;
	cc = (GCClosure *) closure;
	g_return_if_fail (n_param_values == 5);
	if (G_CCLOSURE_SWAP_DATA (closure)) {
		data1 = closure->data;
		data2 = param_values->data[0].v_pointer;
	} else {
		data1 = param_values->data[0].v_pointer;
		data2 = closure->data;
	}
	callback = (GMarshalFunc_VOID__INT_INT_INT_INT) (marshal_data ? marshal_data : cc->callback);
	callback (data1, g_value_get_int (param_values + 1), g_value_get_int (param_values + 2), g_value_get_int (param_values + 3), g_value_get_int (param_values + 4), data2);
}

static gboolean*
_vala_array_dup10 (gboolean* self,
                   gssize length)
{
	if (length > 0) {
		return _vala_memdup2 (self, length * sizeof (gboolean));
	}
	return NULL;
}

static void
sudoku_game_undo_item_copy (const SudokuGameUndoItem* self,
                            SudokuGameUndoItem* dest)
{
	gboolean* _tmp0_;
	gint _tmp0__length1;
	gboolean* _tmp1_;
	gint _tmp1__length1;
	(*dest).row = (*self).row;
	(*dest).col = (*self).col;
	(*dest).val = (*self).val;
	_tmp0_ = (*self).earmarks;
	_tmp0__length1 = (*self).earmarks_length1;
	_tmp1_ = (_tmp0_ != NULL) ? _vala_array_dup10 (_tmp0_, _tmp0__length1) : _tmp0_;
	_tmp1__length1 = _tmp0__length1;
	(*dest).earmarks = (g_free ((*dest).earmarks), NULL);
	(*dest).earmarks = _tmp1_;
	(*dest).earmarks_length1 = _tmp1__length1;
	(*dest)._earmarks_size_ = (*dest).earmarks_length1;
}

static void
sudoku_game_undo_item_destroy (SudokuGameUndoItem* self)
{
	(*self).earmarks = (g_free ((*self).earmarks), NULL);
}

static SudokuGameUndoItem*
sudoku_game_undo_item_dup (const SudokuGameUndoItem* self)
{
	SudokuGameUndoItem* dup;
	dup = g_new0 (SudokuGameUndoItem, 1);
	sudoku_game_undo_item_copy (self, dup);
	return dup;
}

static void
sudoku_game_undo_item_free (SudokuGameUndoItem* self)
{
	sudoku_game_undo_item_destroy (self);
	g_free (self);
}

static GType
sudoku_game_undo_item_get_type_once (void)
{
	GType sudoku_game_undo_item_type_id;
	sudoku_game_undo_item_type_id = g_boxed_type_register_static ("SudokuGameUndoItem", (GBoxedCopyFunc) sudoku_game_undo_item_dup, (GBoxedFreeFunc) sudoku_game_undo_item_free);
	return sudoku_game_undo_item_type_id;
}

static GType
sudoku_game_undo_item_get_type (void)
{
	static volatile gsize sudoku_game_undo_item_type_id__once = 0;
	if (g_once_init_enter (&sudoku_game_undo_item_type_id__once)) {
		GType sudoku_game_undo_item_type_id;
		sudoku_game_undo_item_type_id = sudoku_game_undo_item_get_type_once ();
		g_once_init_leave (&sudoku_game_undo_item_type_id__once, sudoku_game_undo_item_type_id);
	}
	return sudoku_game_undo_item_type_id__once;
}

static void
sudoku_game_class_init (SudokuGameClass * klass,
                        gpointer klass_data)
{
	sudoku_game_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &SudokuGame_private_offset);
	G_OBJECT_CLASS (klass)->get_property = _vala_sudoku_game_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_sudoku_game_set_property;
	G_OBJECT_CLASS (klass)->finalize = sudoku_game_finalize;
	g_object_class_install_property (G_OBJECT_CLASS (klass), SUDOKU_GAME_PAUSED_PROPERTY, sudoku_game_properties[SUDOKU_GAME_PAUSED_PROPERTY] = g_param_spec_boolean ("paused", "paused", "paused", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	sudoku_game_signals[SUDOKU_GAME_TICK_SIGNAL] = g_signal_new ("tick", TYPE_SUDOKU_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	sudoku_game_signals[SUDOKU_GAME_PAUSED_CHANGED_SIGNAL] = g_signal_new ("paused-changed", TYPE_SUDOKU_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	sudoku_game_signals[SUDOKU_GAME_CELL_CHANGED_SIGNAL] = g_signal_new ("cell-changed", TYPE_SUDOKU_GAME, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__INT_INT_INT_INT, G_TYPE_NONE, 4, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
}

static void
sudoku_game_instance_init (SudokuGame * self,
                           gpointer klass)
{
	self->priv = sudoku_game_get_instance_private (self);
	self->priv->_paused = FALSE;
}

static void
sudoku_game_finalize (GObject * obj)
{
	SudokuGame * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_SUDOKU_GAME, SudokuGame);
	_g_object_unref0 (self->board);
	_g_timer_destroy0 (self->timer);
	_g_object_unref0 (self->priv->undostack);
	_g_object_unref0 (self->priv->redostack);
	G_OBJECT_CLASS (sudoku_game_parent_class)->finalize (obj);
}

static GType
sudoku_game_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (SudokuGameClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) sudoku_game_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (SudokuGame), 0, (GInstanceInitFunc) sudoku_game_instance_init, NULL };
	GType sudoku_game_type_id;
	sudoku_game_type_id = g_type_register_static (G_TYPE_OBJECT, "SudokuGame", &g_define_type_info, 0);
	SudokuGame_private_offset = g_type_add_instance_private (sudoku_game_type_id, sizeof (SudokuGamePrivate));
	return sudoku_game_type_id;
}

GType
sudoku_game_get_type (void)
{
	static volatile gsize sudoku_game_type_id__once = 0;
	if (g_once_init_enter (&sudoku_game_type_id__once)) {
		GType sudoku_game_type_id;
		sudoku_game_type_id = sudoku_game_get_type_once ();
		g_once_init_leave (&sudoku_game_type_id__once, sudoku_game_type_id);
	}
	return sudoku_game_type_id__once;
}

static void
_vala_sudoku_game_get_property (GObject * object,
                                guint property_id,
                                GValue * value,
                                GParamSpec * pspec)
{
	SudokuGame * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_SUDOKU_GAME, SudokuGame);
	switch (property_id) {
		case SUDOKU_GAME_PAUSED_PROPERTY:
		g_value_set_boolean (value, sudoku_game_get_paused (self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_sudoku_game_set_property (GObject * object,
                                guint property_id,
                                const GValue * value,
                                GParamSpec * pspec)
{
	SudokuGame * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_SUDOKU_GAME, SudokuGame);
	switch (property_id) {
		case SUDOKU_GAME_PAUSED_PROPERTY:
		sudoku_game_set_paused (self, g_value_get_boolean (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static GType
game_mode_get_type_once (void)
{
	static const GEnumValue values[] = {{GAME_MODE_PLAY, "GAME_MODE_PLAY", "play"}, {GAME_MODE_CREATE, "GAME_MODE_CREATE", "create"}, {0, NULL, NULL}};
	GType game_mode_type_id;
	game_mode_type_id = g_enum_register_static ("GameMode", values);
	return game_mode_type_id;
}

GType
game_mode_get_type (void)
{
	static volatile gsize game_mode_type_id__once = 0;
	if (g_once_init_enter (&game_mode_type_id__once)) {
		GType game_mode_type_id;
		game_mode_type_id = game_mode_get_type_once ();
		g_once_init_leave (&game_mode_type_id__once, game_mode_type_id);
	}
	return game_mode_type_id__once;
}

static inline gpointer
_vala_memdup2 (gconstpointer mem,
               gsize byte_size)
{
	gpointer new_mem;
	if (mem && byte_size != 0) {
		new_mem = g_malloc (byte_size);
		memcpy (new_mem, mem, byte_size);
	} else {
		new_mem = NULL;
	}
	return new_mem;
}

