[four-in-a-row: 1/72] Partial Vala translation. (Sorry I just remembered to commit all this)



commit 7fd41c6bc4edaa8e93fbe60286b13205bf89b05d
Author: Jacob Humphrey <Jacob Ryan Humphrey gmail com>
Date:   Fri Nov 2 20:07:02 2018 -0500

    Partial Vala translation. (Sorry I just remembered to commit all this)

 build/config.h           |   51 ++
 build/src/ai.c           | 1918 ++++++++++++++++++++++++++++++++++++++++++++++
 build/src/ai.h           |   64 ++
 src/Makefile.am          |   11 +-
 src/games-controls2.vala |    0
 src/gfx.c                |  202 +----
 src/gfx2.vala            |  176 +++++
 src/main.c               |  195 +----
 src/main.h               |   15 +-
 src/main2.vala           |  189 +++++
 src/prefs.c              |  832 ++++++++++++++------
 src/prefs.h              |    4 +
 src/prefs.vala           |  220 ++++++
 src/temp.vapi            |   88 +++
 src/theme.h              |    6 +-
 15 files changed, 3359 insertions(+), 612 deletions(-)
---
diff --git a/build/config.h b/build/config.h
new file mode 100644
index 0000000..3fbd6a6
--- /dev/null
+++ b/build/config.h
@@ -0,0 +1,51 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+#define ENABLE_NLS 1
+
+/* The gettext package name */
+#define GETTEXT_PACKAGE "four-in-a-row"
+
+/* Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the
+   CoreFoundation framework. */
+/* #undef HAVE_CFLOCALECOPYCURRENT */
+
+/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in
+   the CoreFoundation framework. */
+/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+#define HAVE_DCGETTEXT 1
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+#define HAVE_GETTEXT 1
+
+/* Define if you have the iconv() function and it works. */
+/* #undef HAVE_ICONV */
+
+/* Name of package */
+#define PACKAGE "four-in-a-row"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "https://bugzilla.gnome.org/";
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "Four-in-a-Row"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "Four-in-a-Row 3.28.0"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "four-in-a-row"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL "https://wiki.gnome.org/Apps/Four-in-a-row";
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "3.28.0"
+
+/* Version number of package */
+#define VERSION "3.28.0"
diff --git a/build/src/ai.c b/build/src/ai.c
new file mode 100644
index 0000000..7642789
--- /dev/null
+++ b/build/src/ai.c
@@ -0,0 +1,1918 @@
+/* ai.c generated by valac 0.40.10, the Vala compiler
+ * generated from ai.vala, do not modify */
+
+/* -*- Mode: vala; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * Copyright © 2014 Nikhar Agrawal
+ *
+ * This file is part of Four-in-a-row.
+ *
+ * Four-in-a-row 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Four-in-a-row 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 Four-in-a-row.  If not, see <http://www.gnu.org/licenses/>. */
+/* Here NEG_INF is supposed to be the lowest possible int value. int.MIN
+MAX_HEURIST_VALUE is the maximum value that the heuristic functions can return.
+It is returned when AI wins. -1*MAX_HEURIST_VALUE is returned when Human wins
+MAX_HEURIST_VALUE < NEG_INF/plies */
+
+
+#include <glib.h>
+#include <glib-object.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ai.h"
+#include <stdio.h>
+#include <gobject/gvaluecollector.h>
+
+
+#define TYPE_PLAYER (player_get_type ())
+
+#define TYPE_DIFFICULTY (difficulty_get_type ())
+#define _decision_tree_unref0(var) ((var == NULL) ? NULL : (var = (decision_tree_unref (var), NULL)))
+#define _g_free0(var) (var = (g_free (var), NULL))
+typedef struct _ParamSpecDecisionTree ParamSpecDecisionTree;
+#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);
+
+typedef enum  {
+       PLAYER_NONE,
+       PLAYER_HUMAN,
+       PLAYER_AI
+} Player;
+
+typedef enum  {
+       DIFFICULTY_EASY,
+       DIFFICULTY_MEDIUM,
+       DIFFICULTY_HARD
+} Difficulty;
+
+struct _DecisionTreePrivate {
+       Player* board;
+       gint board_length1;
+       gint board_length2;
+       gint plies;
+       Player last_moving_player;
+       gint next_move_in_column;
+       Difficulty level;
+};
+
+struct _ParamSpecDecisionTree {
+       GParamSpec parent_instance;
+};
+
+
+static gpointer decision_tree_parent_class = NULL;
+
+#define NEG_INF -100000
+#define MAX_HEURIST_VALUE 10000
+#define BOARD_ROWS 6
+#define BOARD_COLUMNS 7
+GType player_get_type (void) G_GNUC_CONST;
+GType difficulty_get_type (void) G_GNUC_CONST;
+gint playgame (const gchar* moves_until_now);
+#define DECISION_TREE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_DECISION_TREE, 
DecisionTreePrivate))
+static gint decision_tree_negamax (DecisionTree* self,
+                            gint height,
+                            gint alpha,
+                            gint beta);
+static gboolean decision_tree_board_full (DecisionTree* self);
+static gint decision_tree_heurist (DecisionTree* self);
+static gboolean decision_tree_move (DecisionTree* self,
+                             gint column);
+static gboolean decision_tree_victory (DecisionTree* self,
+                                gint column);
+static void decision_tree_unmove (DecisionTree* self,
+                           gint column);
+static gboolean decision_tree_vertical_win (DecisionTree* self,
+                                     gint i,
+                                     gint j);
+static gboolean decision_tree_horizontal_win (DecisionTree* self,
+                                       gint i,
+                                       gint j);
+static gboolean decision_tree_forward_diagonal_win (DecisionTree* self,
+                                             gint i,
+                                             gint j);
+static gboolean decision_tree_backward_diagonal_win (DecisionTree* self,
+                                              gint i,
+                                              gint j);
+static gint decision_tree_immediate_win (DecisionTree* self,
+                                  Player p);
+static void decision_tree_set_level (DecisionTree* self,
+                              const gchar* vstr);
+static gint decision_tree_heurist_easy (DecisionTree* self);
+static gint decision_tree_heurist_medium (DecisionTree* self);
+static gint decision_tree_heurist_hard (DecisionTree* self);
+static gint decision_tree_count_3_in_a_row (DecisionTree* self,
+                                     Player p);
+static gboolean decision_tree_all_adjacent_empty (DecisionTree* self,
+                                           gint i,
+                                           gint j);
+static void decision_tree_finalize (DecisionTree * obj);
+
+
+GType
+player_get_type (void)
+{
+       static volatile gsize player_type_id__volatile = 0;
+       if (g_once_init_enter (&player_type_id__volatile)) {
+               static const GEnumValue values[] = {{PLAYER_NONE, "PLAYER_NONE", "none"}, {PLAYER_HUMAN, 
"PLAYER_HUMAN", "human"}, {PLAYER_AI, "PLAYER_AI", "ai"}, {0, NULL, NULL}};
+               GType player_type_id;
+               player_type_id = g_enum_register_static ("Player", values);
+               g_once_init_leave (&player_type_id__volatile, player_type_id);
+       }
+       return player_type_id__volatile;
+}
+
+
+GType
+difficulty_get_type (void)
+{
+       static volatile gsize difficulty_type_id__volatile = 0;
+       if (g_once_init_enter (&difficulty_type_id__volatile)) {
+               static const GEnumValue values[] = {{DIFFICULTY_EASY, "DIFFICULTY_EASY", "easy"}, 
{DIFFICULTY_MEDIUM, "DIFFICULTY_MEDIUM", "medium"}, {DIFFICULTY_HARD, "DIFFICULTY_HARD", "hard"}, {0, NULL, 
NULL}};
+               GType difficulty_type_id;
+               difficulty_type_id = g_enum_register_static ("Difficulty", values);
+               g_once_init_leave (&difficulty_type_id__volatile, difficulty_type_id);
+       }
+       return difficulty_type_id__volatile;
+}
+
+
+gint
+playgame (const gchar* moves_until_now)
+{
+       gint result = 0;
+       DecisionTree* t = NULL;
+       DecisionTree* _tmp0_;
+       g_return_val_if_fail (moves_until_now != NULL, 0);
+       _tmp0_ = decision_tree_new ();
+       t = _tmp0_;
+       result = decision_tree_playgame (t, moves_until_now);
+       _decision_tree_unref0 (t);
+       return result;
+}
+
+
+DecisionTree*
+decision_tree_construct (GType object_type)
+{
+       DecisionTree* self = NULL;
+       self = (DecisionTree*) g_type_create_instance (object_type);
+       {
+               gint i = 0;
+               i = 0;
+               {
+                       gboolean _tmp0_ = FALSE;
+                       _tmp0_ = TRUE;
+                       while (TRUE) {
+                               gint _tmp2_;
+                               if (!_tmp0_) {
+                                       gint _tmp1_;
+                                       _tmp1_ = i;
+                                       i = _tmp1_ + 1;
+                               }
+                               _tmp0_ = FALSE;
+                               _tmp2_ = i;
+                               if (!(_tmp2_ < BOARD_ROWS)) {
+                                       break;
+                               }
+                               {
+                                       gint j = 0;
+                                       j = 0;
+                                       {
+                                               gboolean _tmp3_ = FALSE;
+                                               _tmp3_ = TRUE;
+                                               while (TRUE) {
+                                                       gint _tmp5_;
+                                                       Player* _tmp6_;
+                                                       gint _tmp6__length1;
+                                                       gint _tmp6__length2;
+                                                       gint _tmp7_;
+                                                       gint _tmp8_;
+                                                       Player _tmp9_;
+                                                       if (!_tmp3_) {
+                                                               gint _tmp4_;
+                                                               _tmp4_ = j;
+                                                               j = _tmp4_ + 1;
+                                                       }
+                                                       _tmp3_ = FALSE;
+                                                       _tmp5_ = j;
+                                                       if (!(_tmp5_ < BOARD_COLUMNS)) {
+                                                               break;
+                                                       }
+                                                       _tmp6_ = self->priv->board;
+                                                       _tmp6__length1 = self->priv->board_length1;
+                                                       _tmp6__length2 = self->priv->board_length2;
+                                                       _tmp7_ = i;
+                                                       _tmp8_ = j;
+                                                       _tmp6_[(_tmp7_ * _tmp6__length2) + _tmp8_] = 
PLAYER_NONE;
+                                                       _tmp9_ = _tmp6_[(_tmp7_ * _tmp6__length2) + _tmp8_];
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       return self;
+}
+
+
+DecisionTree*
+decision_tree_new (void)
+{
+       return decision_tree_construct (TYPE_DECISION_TREE);
+}
+
+
+void
+decision_tree_print_board (DecisionTree* self)
+{
+       FILE* _tmp12_;
+       g_return_if_fail (self != NULL);
+       {
+               gint i = 0;
+               i = 0;
+               {
+                       gboolean _tmp0_ = FALSE;
+                       _tmp0_ = TRUE;
+                       while (TRUE) {
+                               gint _tmp2_;
+                               FILE* _tmp11_;
+                               if (!_tmp0_) {
+                                       gint _tmp1_;
+                                       _tmp1_ = i;
+                                       i = _tmp1_ + 1;
+                               }
+                               _tmp0_ = FALSE;
+                               _tmp2_ = i;
+                               if (!(_tmp2_ < BOARD_ROWS)) {
+                                       break;
+                               }
+                               {
+                                       gint j = 0;
+                                       j = 0;
+                                       {
+                                               gboolean _tmp3_ = FALSE;
+                                               _tmp3_ = TRUE;
+                                               while (TRUE) {
+                                                       gint _tmp5_;
+                                                       FILE* _tmp6_;
+                                                       Player* _tmp7_;
+                                                       gint _tmp7__length1;
+                                                       gint _tmp7__length2;
+                                                       gint _tmp8_;
+                                                       gint _tmp9_;
+                                                       Player _tmp10_;
+                                                       if (!_tmp3_) {
+                                                               gint _tmp4_;
+                                                               _tmp4_ = j;
+                                                               j = _tmp4_ + 1;
+                                                       }
+                                                       _tmp3_ = FALSE;
+                                                       _tmp5_ = j;
+                                                       if (!(_tmp5_ < BOARD_COLUMNS)) {
+                                                               break;
+                                                       }
+                                                       _tmp6_ = stdout;
+                                                       _tmp7_ = self->priv->board;
+                                                       _tmp7__length1 = self->priv->board_length1;
+                                                       _tmp7__length2 = self->priv->board_length2;
+                                                       _tmp8_ = i;
+                                                       _tmp9_ = j;
+                                                       _tmp10_ = _tmp7_[(_tmp8_ * _tmp7__length2) + _tmp9_];
+                                                       fprintf (_tmp6_, "%d\t", (gint) _tmp10_);
+                                               }
+                                       }
+                               }
+                               _tmp11_ = stdout;
+                               fprintf (_tmp11_, "\n");
+                       }
+               }
+       }
+       _tmp12_ = stdout;
+       fprintf (_tmp12_, "\n");
+}
+
+
+static gint
+decision_tree_negamax (DecisionTree* self,
+                       gint height,
+                       gint alpha,
+                       gint beta)
+{
+       gint result = 0;
+       gboolean _tmp0_ = FALSE;
+       gint max = 0;
+       gint next = 0;
+       gint _tmp16_;
+       g_return_val_if_fail (self != NULL, 0);
+       if (height == 0) {
+               _tmp0_ = TRUE;
+       } else {
+               _tmp0_ = decision_tree_board_full (self);
+       }
+       if (_tmp0_) {
+               Player _tmp1_;
+               _tmp1_ = self->priv->last_moving_player;
+               if (_tmp1_ == PLAYER_HUMAN) {
+                       result = decision_tree_heurist (self);
+                       return result;
+               } else {
+                       Player _tmp2_;
+                       _tmp2_ = self->priv->last_moving_player;
+                       if (_tmp2_ == PLAYER_AI) {
+                               result = -1 * decision_tree_heurist (self);
+                               return result;
+                       } else {
+                               result = 0;
+                               return result;
+                       }
+               }
+       }
+       max = NEG_INF;
+       next = -1;
+       {
+               gint column = 0;
+               column = 0;
+               {
+                       gboolean _tmp3_ = FALSE;
+                       _tmp3_ = TRUE;
+                       while (TRUE) {
+                               gint _tmp5_;
+                               gint _tmp6_;
+                               gint _tmp7_ = 0;
+                               gint _tmp8_;
+                               gint temp = 0;
+                               gint _tmp9_;
+                               gint _tmp10_;
+                               gint _tmp11_;
+                               gint _tmp14_;
+                               if (!_tmp3_) {
+                                       gint _tmp4_;
+                                       _tmp4_ = column;
+                                       column = _tmp4_ + 1;
+                               }
+                               _tmp3_ = FALSE;
+                               _tmp5_ = column;
+                               if (!(_tmp5_ < BOARD_COLUMNS)) {
+                                       break;
+                               }
+                               _tmp6_ = column;
+                               if (!decision_tree_move (self, _tmp6_)) {
+                                       continue;
+                               }
+                               _tmp8_ = column;
+                               if (decision_tree_victory (self, _tmp8_)) {
+                                       _tmp7_ = MAX_HEURIST_VALUE * height;
+                               } else {
+                                       _tmp7_ = -1 * decision_tree_negamax (self, height - 1, -1 * beta, -1 
* alpha);
+                               }
+                               temp = _tmp7_;
+                               _tmp9_ = column;
+                               decision_tree_unmove (self, _tmp9_);
+                               _tmp10_ = temp;
+                               _tmp11_ = max;
+                               if (_tmp10_ > _tmp11_) {
+                                       gint _tmp12_;
+                                       gint _tmp13_;
+                                       _tmp12_ = column;
+                                       next = _tmp12_;
+                                       _tmp13_ = temp;
+                                       max = _tmp13_;
+                               }
+                               _tmp14_ = temp;
+                               if (_tmp14_ > alpha) {
+                                       gint _tmp15_;
+                                       _tmp15_ = temp;
+                                       alpha = _tmp15_;
+                               }
+                               if (alpha >= beta) {
+                                       break;
+                               }
+                       }
+               }
+       }
+       _tmp16_ = self->priv->plies;
+       if (height == _tmp16_) {
+               gint _tmp17_;
+               _tmp17_ = next;
+               self->priv->next_move_in_column = _tmp17_;
+       }
+       result = max;
+       return result;
+}
+
+
+static gboolean
+decision_tree_victory (DecisionTree* self,
+                       gint column)
+{
+       gboolean result = FALSE;
+       gint row = 0;
+       gboolean _tmp7_ = FALSE;
+       gboolean _tmp8_ = FALSE;
+       gboolean _tmp9_ = FALSE;
+       gint _tmp10_;
+       g_return_val_if_fail (self != NULL, FALSE);
+       {
+               gboolean _tmp0_ = FALSE;
+               row = 0;
+               _tmp0_ = TRUE;
+               while (TRUE) {
+                       gboolean _tmp2_ = FALSE;
+                       gint _tmp3_;
+                       if (!_tmp0_) {
+                               gint _tmp1_;
+                               _tmp1_ = row;
+                               row = _tmp1_ + 1;
+                       }
+                       _tmp0_ = FALSE;
+                       _tmp3_ = row;
+                       if (_tmp3_ < BOARD_ROWS) {
+                               Player* _tmp4_;
+                               gint _tmp4__length1;
+                               gint _tmp4__length2;
+                               gint _tmp5_;
+                               Player _tmp6_;
+                               _tmp4_ = self->priv->board;
+                               _tmp4__length1 = self->priv->board_length1;
+                               _tmp4__length2 = self->priv->board_length2;
+                               _tmp5_ = row;
+                               _tmp6_ = _tmp4_[(_tmp5_ * _tmp4__length2) + column];
+                               _tmp2_ = _tmp6_ == PLAYER_NONE;
+                       } else {
+                               _tmp2_ = FALSE;
+                       }
+                       if (!_tmp2_) {
+                               break;
+                       }
+               }
+       }
+       _tmp10_ = row;
+       if (decision_tree_vertical_win (self, _tmp10_, column)) {
+               _tmp9_ = TRUE;
+       } else {
+               gint _tmp11_;
+               _tmp11_ = row;
+               _tmp9_ = decision_tree_horizontal_win (self, _tmp11_, column);
+       }
+       if (_tmp9_) {
+               _tmp8_ = TRUE;
+       } else {
+               gint _tmp12_;
+               _tmp12_ = row;
+               _tmp8_ = decision_tree_forward_diagonal_win (self, _tmp12_, column);
+       }
+       if (_tmp8_) {
+               _tmp7_ = TRUE;
+       } else {
+               gint _tmp13_;
+               _tmp13_ = row;
+               _tmp7_ = decision_tree_backward_diagonal_win (self, _tmp13_, column);
+       }
+       result = _tmp7_;
+       return result;
+}
+
+
+static gboolean
+decision_tree_forward_diagonal_win (DecisionTree* self,
+                                    gint i,
+                                    gint j)
+{
+       gboolean result = FALSE;
+       gint count = 0;
+       gint _tmp26_;
+       g_return_val_if_fail (self != NULL, FALSE);
+       count = 0;
+       {
+               gint k = 0;
+               gint l = 0;
+               k = i;
+               l = j;
+               {
+                       gboolean _tmp0_ = FALSE;
+                       _tmp0_ = TRUE;
+                       while (TRUE) {
+                               gboolean _tmp4_ = FALSE;
+                               gboolean _tmp5_ = FALSE;
+                               gint _tmp6_;
+                               if (!_tmp0_) {
+                                       gint _tmp1_;
+                                       gint _tmp2_;
+                                       gint _tmp3_;
+                                       _tmp1_ = k;
+                                       k = _tmp1_ - 1;
+                                       _tmp2_ = l;
+                                       l = _tmp2_ + 1;
+                                       _tmp3_ = count;
+                                       count = _tmp3_ + 1;
+                               }
+                               _tmp0_ = FALSE;
+                               _tmp6_ = k;
+                               if (_tmp6_ >= 0) {
+                                       gint _tmp7_;
+                                       _tmp7_ = l;
+                                       _tmp5_ = _tmp7_ < BOARD_COLUMNS;
+                               } else {
+                                       _tmp5_ = FALSE;
+                               }
+                               if (_tmp5_) {
+                                       Player* _tmp8_;
+                                       gint _tmp8__length1;
+                                       gint _tmp8__length2;
+                                       gint _tmp9_;
+                                       gint _tmp10_;
+                                       Player _tmp11_;
+                                       Player _tmp12_;
+                                       _tmp8_ = self->priv->board;
+                                       _tmp8__length1 = self->priv->board_length1;
+                                       _tmp8__length2 = self->priv->board_length2;
+                                       _tmp9_ = k;
+                                       _tmp10_ = l;
+                                       _tmp11_ = _tmp8_[(_tmp9_ * _tmp8__length2) + _tmp10_];
+                                       _tmp12_ = self->priv->last_moving_player;
+                                       _tmp4_ = _tmp11_ == _tmp12_;
+                               } else {
+                                       _tmp4_ = FALSE;
+                               }
+                               if (!_tmp4_) {
+                                       break;
+                               }
+                       }
+               }
+       }
+       {
+               gint k = 0;
+               gint l = 0;
+               k = i + 1;
+               l = j - 1;
+               {
+                       gboolean _tmp13_ = FALSE;
+                       _tmp13_ = TRUE;
+                       while (TRUE) {
+                               gboolean _tmp17_ = FALSE;
+                               gboolean _tmp18_ = FALSE;
+                               gint _tmp19_;
+                               if (!_tmp13_) {
+                                       gint _tmp14_;
+                                       gint _tmp15_;
+                                       gint _tmp16_;
+                                       _tmp14_ = k;
+                                       k = _tmp14_ + 1;
+                                       _tmp15_ = l;
+                                       l = _tmp15_ - 1;
+                                       _tmp16_ = count;
+                                       count = _tmp16_ + 1;
+                               }
+                               _tmp13_ = FALSE;
+                               _tmp19_ = k;
+                               if (_tmp19_ < BOARD_ROWS) {
+                                       gint _tmp20_;
+                                       _tmp20_ = l;
+                                       _tmp18_ = _tmp20_ >= 0;
+                               } else {
+                                       _tmp18_ = FALSE;
+                               }
+                               if (_tmp18_) {
+                                       Player* _tmp21_;
+                                       gint _tmp21__length1;
+                                       gint _tmp21__length2;
+                                       gint _tmp22_;
+                                       gint _tmp23_;
+                                       Player _tmp24_;
+                                       Player _tmp25_;
+                                       _tmp21_ = self->priv->board;
+                                       _tmp21__length1 = self->priv->board_length1;
+                                       _tmp21__length2 = self->priv->board_length2;
+                                       _tmp22_ = k;
+                                       _tmp23_ = l;
+                                       _tmp24_ = _tmp21_[(_tmp22_ * _tmp21__length2) + _tmp23_];
+                                       _tmp25_ = self->priv->last_moving_player;
+                                       _tmp17_ = _tmp24_ == _tmp25_;
+                               } else {
+                                       _tmp17_ = FALSE;
+                               }
+                               if (!_tmp17_) {
+                                       break;
+                               }
+                       }
+               }
+       }
+       _tmp26_ = count;
+       result = _tmp26_ >= 4;
+       return result;
+}
+
+
+static gboolean
+decision_tree_backward_diagonal_win (DecisionTree* self,
+                                     gint i,
+                                     gint j)
+{
+       gboolean result = FALSE;
+       gint count = 0;
+       gint _tmp26_;
+       g_return_val_if_fail (self != NULL, FALSE);
+       count = 0;
+       {
+               gint k = 0;
+               gint l = 0;
+               k = i;
+               l = j;
+               {
+                       gboolean _tmp0_ = FALSE;
+                       _tmp0_ = TRUE;
+                       while (TRUE) {
+                               gboolean _tmp4_ = FALSE;
+                               gboolean _tmp5_ = FALSE;
+                               gint _tmp6_;
+                               if (!_tmp0_) {
+                                       gint _tmp1_;
+                                       gint _tmp2_;
+                                       gint _tmp3_;
+                                       _tmp1_ = k;
+                                       k = _tmp1_ - 1;
+                                       _tmp2_ = l;
+                                       l = _tmp2_ - 1;
+                                       _tmp3_ = count;
+                                       count = _tmp3_ + 1;
+                               }
+                               _tmp0_ = FALSE;
+                               _tmp6_ = k;
+                               if (_tmp6_ >= 0) {
+                                       gint _tmp7_;
+                                       _tmp7_ = l;
+                                       _tmp5_ = _tmp7_ >= 0;
+                               } else {
+                                       _tmp5_ = FALSE;
+                               }
+                               if (_tmp5_) {
+                                       Player* _tmp8_;
+                                       gint _tmp8__length1;
+                                       gint _tmp8__length2;
+                                       gint _tmp9_;
+                                       gint _tmp10_;
+                                       Player _tmp11_;
+                                       Player _tmp12_;
+                                       _tmp8_ = self->priv->board;
+                                       _tmp8__length1 = self->priv->board_length1;
+                                       _tmp8__length2 = self->priv->board_length2;
+                                       _tmp9_ = k;
+                                       _tmp10_ = l;
+                                       _tmp11_ = _tmp8_[(_tmp9_ * _tmp8__length2) + _tmp10_];
+                                       _tmp12_ = self->priv->last_moving_player;
+                                       _tmp4_ = _tmp11_ == _tmp12_;
+                               } else {
+                                       _tmp4_ = FALSE;
+                               }
+                               if (!_tmp4_) {
+                                       break;
+                               }
+                       }
+               }
+       }
+       {
+               gint k = 0;
+               gint l = 0;
+               k = i + 1;
+               l = j + 1;
+               {
+                       gboolean _tmp13_ = FALSE;
+                       _tmp13_ = TRUE;
+                       while (TRUE) {
+                               gboolean _tmp17_ = FALSE;
+                               gboolean _tmp18_ = FALSE;
+                               gint _tmp19_;
+                               if (!_tmp13_) {
+                                       gint _tmp14_;
+                                       gint _tmp15_;
+                                       gint _tmp16_;
+                                       _tmp14_ = k;
+                                       k = _tmp14_ + 1;
+                                       _tmp15_ = l;
+                                       l = _tmp15_ + 1;
+                                       _tmp16_ = count;
+                                       count = _tmp16_ + 1;
+                               }
+                               _tmp13_ = FALSE;
+                               _tmp19_ = k;
+                               if (_tmp19_ < BOARD_ROWS) {
+                                       gint _tmp20_;
+                                       _tmp20_ = l;
+                                       _tmp18_ = _tmp20_ < BOARD_COLUMNS;
+                               } else {
+                                       _tmp18_ = FALSE;
+                               }
+                               if (_tmp18_) {
+                                       Player* _tmp21_;
+                                       gint _tmp21__length1;
+                                       gint _tmp21__length2;
+                                       gint _tmp22_;
+                                       gint _tmp23_;
+                                       Player _tmp24_;
+                                       Player _tmp25_;
+                                       _tmp21_ = self->priv->board;
+                                       _tmp21__length1 = self->priv->board_length1;
+                                       _tmp21__length2 = self->priv->board_length2;
+                                       _tmp22_ = k;
+                                       _tmp23_ = l;
+                                       _tmp24_ = _tmp21_[(_tmp22_ * _tmp21__length2) + _tmp23_];
+                                       _tmp25_ = self->priv->last_moving_player;
+                                       _tmp17_ = _tmp24_ == _tmp25_;
+                               } else {
+                                       _tmp17_ = FALSE;
+                               }
+                               if (!_tmp17_) {
+                                       break;
+                               }
+                       }
+               }
+       }
+       _tmp26_ = count;
+       result = _tmp26_ >= 4;
+       return result;
+}
+
+
+static gboolean
+decision_tree_horizontal_win (DecisionTree* self,
+                              gint i,
+                              gint j)
+{
+       gboolean result = FALSE;
+       gint count = 0;
+       gint _tmp18_;
+       g_return_val_if_fail (self != NULL, FALSE);
+       count = 0;
+       {
+               gint k = 0;
+               k = j;
+               {
+                       gboolean _tmp0_ = FALSE;
+                       _tmp0_ = TRUE;
+                       while (TRUE) {
+                               gboolean _tmp3_ = FALSE;
+                               gint _tmp4_;
+                               if (!_tmp0_) {
+                                       gint _tmp1_;
+                                       gint _tmp2_;
+                                       _tmp1_ = k;
+                                       k = _tmp1_ - 1;
+                                       _tmp2_ = count;
+                                       count = _tmp2_ + 1;
+                               }
+                               _tmp0_ = FALSE;
+                               _tmp4_ = k;
+                               if (_tmp4_ >= 0) {
+                                       Player* _tmp5_;
+                                       gint _tmp5__length1;
+                                       gint _tmp5__length2;
+                                       gint _tmp6_;
+                                       Player _tmp7_;
+                                       Player _tmp8_;
+                                       _tmp5_ = self->priv->board;
+                                       _tmp5__length1 = self->priv->board_length1;
+                                       _tmp5__length2 = self->priv->board_length2;
+                                       _tmp6_ = k;
+                                       _tmp7_ = _tmp5_[(i * _tmp5__length2) + _tmp6_];
+                                       _tmp8_ = self->priv->last_moving_player;
+                                       _tmp3_ = _tmp7_ == _tmp8_;
+                               } else {
+                                       _tmp3_ = FALSE;
+                               }
+                               if (!_tmp3_) {
+                                       break;
+                               }
+                       }
+               }
+       }
+       {
+               gint k = 0;
+               k = j + 1;
+               {
+                       gboolean _tmp9_ = FALSE;
+                       _tmp9_ = TRUE;
+                       while (TRUE) {
+                               gboolean _tmp12_ = FALSE;
+                               gint _tmp13_;
+                               if (!_tmp9_) {
+                                       gint _tmp10_;
+                                       gint _tmp11_;
+                                       _tmp10_ = k;
+                                       k = _tmp10_ + 1;
+                                       _tmp11_ = count;
+                                       count = _tmp11_ + 1;
+                               }
+                               _tmp9_ = FALSE;
+                               _tmp13_ = k;
+                               if (_tmp13_ < BOARD_COLUMNS) {
+                                       Player* _tmp14_;
+                                       gint _tmp14__length1;
+                                       gint _tmp14__length2;
+                                       gint _tmp15_;
+                                       Player _tmp16_;
+                                       Player _tmp17_;
+                                       _tmp14_ = self->priv->board;
+                                       _tmp14__length1 = self->priv->board_length1;
+                                       _tmp14__length2 = self->priv->board_length2;
+                                       _tmp15_ = k;
+                                       _tmp16_ = _tmp14_[(i * _tmp14__length2) + _tmp15_];
+                                       _tmp17_ = self->priv->last_moving_player;
+                                       _tmp12_ = _tmp16_ == _tmp17_;
+                               } else {
+                                       _tmp12_ = FALSE;
+                               }
+                               if (!_tmp12_) {
+                                       break;
+                               }
+                       }
+               }
+       }
+       _tmp18_ = count;
+       result = _tmp18_ >= 4;
+       return result;
+}
+
+
+static gboolean
+decision_tree_vertical_win (DecisionTree* self,
+                            gint i,
+                            gint j)
+{
+       gboolean result = FALSE;
+       gint count = 0;
+       gint _tmp9_;
+       g_return_val_if_fail (self != NULL, FALSE);
+       count = 0;
+       {
+               gint k = 0;
+               k = i;
+               {
+                       gboolean _tmp0_ = FALSE;
+                       _tmp0_ = TRUE;
+                       while (TRUE) {
+                               gboolean _tmp3_ = FALSE;
+                               gint _tmp4_;
+                               if (!_tmp0_) {
+                                       gint _tmp1_;
+                                       gint _tmp2_;
+                                       _tmp1_ = k;
+                                       k = _tmp1_ + 1;
+                                       _tmp2_ = count;
+                                       count = _tmp2_ + 1;
+                               }
+                               _tmp0_ = FALSE;
+                               _tmp4_ = k;
+                               if (_tmp4_ < BOARD_ROWS) {
+                                       Player* _tmp5_;
+                                       gint _tmp5__length1;
+                                       gint _tmp5__length2;
+                                       gint _tmp6_;
+                                       Player _tmp7_;
+                                       Player _tmp8_;
+                                       _tmp5_ = self->priv->board;
+                                       _tmp5__length1 = self->priv->board_length1;
+                                       _tmp5__length2 = self->priv->board_length2;
+                                       _tmp6_ = k;
+                                       _tmp7_ = _tmp5_[(_tmp6_ * _tmp5__length2) + j];
+                                       _tmp8_ = self->priv->last_moving_player;
+                                       _tmp3_ = _tmp7_ == _tmp8_;
+                               } else {
+                                       _tmp3_ = FALSE;
+                               }
+                               if (!_tmp3_) {
+                                       break;
+                               }
+                       }
+               }
+       }
+       _tmp9_ = count;
+       result = _tmp9_ >= 4;
+       return result;
+}
+
+
+static gboolean
+decision_tree_board_full (DecisionTree* self)
+{
+       gboolean result = FALSE;
+       g_return_val_if_fail (self != NULL, FALSE);
+       {
+               gint i = 0;
+               i = 0;
+               {
+                       gboolean _tmp0_ = FALSE;
+                       _tmp0_ = TRUE;
+                       while (TRUE) {
+                               gint _tmp2_;
+                               Player* _tmp3_;
+                               gint _tmp3__length1;
+                               gint _tmp3__length2;
+                               gint _tmp4_;
+                               Player _tmp5_;
+                               if (!_tmp0_) {
+                                       gint _tmp1_;
+                                       _tmp1_ = i;
+                                       i = _tmp1_ + 1;
+                               }
+                               _tmp0_ = FALSE;
+                               _tmp2_ = i;
+                               if (!(_tmp2_ < BOARD_COLUMNS)) {
+                                       break;
+                               }
+                               _tmp3_ = self->priv->board;
+                               _tmp3__length1 = self->priv->board_length1;
+                               _tmp3__length2 = self->priv->board_length2;
+                               _tmp4_ = i;
+                               _tmp5_ = _tmp3_[(0 * _tmp3__length2) + _tmp4_];
+                               if (_tmp5_ == PLAYER_NONE) {
+                                       result = FALSE;
+                                       return result;
+                               }
+                       }
+               }
+       }
+       result = TRUE;
+       return result;
+}
+
+
+static gboolean
+decision_tree_move (DecisionTree* self,
+                    gint column)
+{
+       gboolean result = FALSE;
+       gint row = 0;
+       gint _tmp7_;
+       Player _tmp8_ = 0;
+       Player _tmp9_;
+       Player player = 0;
+       Player* _tmp10_;
+       gint _tmp10__length1;
+       gint _tmp10__length2;
+       gint _tmp11_;
+       Player _tmp12_;
+       Player _tmp13_;
+       Player _tmp14_;
+       g_return_val_if_fail (self != NULL, FALSE);
+       {
+               gboolean _tmp0_ = FALSE;
+               row = BOARD_ROWS - 1;
+               _tmp0_ = TRUE;
+               while (TRUE) {
+                       gboolean _tmp2_ = FALSE;
+                       gint _tmp3_;
+                       if (!_tmp0_) {
+                               gint _tmp1_;
+                               _tmp1_ = row;
+                               row = _tmp1_ - 1;
+                       }
+                       _tmp0_ = FALSE;
+                       _tmp3_ = row;
+                       if (_tmp3_ >= 0) {
+                               Player* _tmp4_;
+                               gint _tmp4__length1;
+                               gint _tmp4__length2;
+                               gint _tmp5_;
+                               Player _tmp6_;
+                               _tmp4_ = self->priv->board;
+                               _tmp4__length1 = self->priv->board_length1;
+                               _tmp4__length2 = self->priv->board_length2;
+                               _tmp5_ = row;
+                               _tmp6_ = _tmp4_[(_tmp5_ * _tmp4__length2) + column];
+                               _tmp2_ = _tmp6_ != PLAYER_NONE;
+                       } else {
+                               _tmp2_ = FALSE;
+                       }
+                       if (!_tmp2_) {
+                               break;
+                       }
+               }
+       }
+       _tmp7_ = row;
+       if (_tmp7_ < 0) {
+               result = FALSE;
+               return result;
+       }
+       _tmp9_ = self->priv->last_moving_player;
+       if (_tmp9_ != PLAYER_AI) {
+               _tmp8_ = PLAYER_AI;
+       } else {
+               _tmp8_ = PLAYER_HUMAN;
+       }
+       player = _tmp8_;
+       _tmp10_ = self->priv->board;
+       _tmp10__length1 = self->priv->board_length1;
+       _tmp10__length2 = self->priv->board_length2;
+       _tmp11_ = row;
+       _tmp12_ = player;
+       _tmp10_[(_tmp11_ * _tmp10__length2) + column] = _tmp12_;
+       _tmp13_ = _tmp10_[(_tmp11_ * _tmp10__length2) + column];
+       _tmp14_ = player;
+       self->priv->last_moving_player = _tmp14_;
+       result = TRUE;
+       return result;
+}
+
+
+static void
+decision_tree_unmove (DecisionTree* self,
+                      gint column)
+{
+       Player _tmp0_;
+       gint row = 0;
+       Player* _tmp8_;
+       gint _tmp8__length1;
+       gint _tmp8__length2;
+       gint _tmp9_;
+       Player _tmp10_;
+       Player _tmp11_ = 0;
+       Player _tmp12_;
+       g_return_if_fail (self != NULL);
+       _tmp0_ = self->priv->last_moving_player;
+       _vala_return_if_fail (_tmp0_ != PLAYER_NONE, "last_moving_player != Player.NONE");
+       {
+               gboolean _tmp1_ = FALSE;
+               row = 0;
+               _tmp1_ = TRUE;
+               while (TRUE) {
+                       gboolean _tmp3_ = FALSE;
+                       gint _tmp4_;
+                       if (!_tmp1_) {
+                               gint _tmp2_;
+                               _tmp2_ = row;
+                               row = _tmp2_ + 1;
+                       }
+                       _tmp1_ = FALSE;
+                       _tmp4_ = row;
+                       if (_tmp4_ < BOARD_ROWS) {
+                               Player* _tmp5_;
+                               gint _tmp5__length1;
+                               gint _tmp5__length2;
+                               gint _tmp6_;
+                               Player _tmp7_;
+                               _tmp5_ = self->priv->board;
+                               _tmp5__length1 = self->priv->board_length1;
+                               _tmp5__length2 = self->priv->board_length2;
+                               _tmp6_ = row;
+                               _tmp7_ = _tmp5_[(_tmp6_ * _tmp5__length2) + column];
+                               _tmp3_ = _tmp7_ == PLAYER_NONE;
+                       } else {
+                               _tmp3_ = FALSE;
+                       }
+                       if (!_tmp3_) {
+                               break;
+                       }
+               }
+       }
+       _tmp8_ = self->priv->board;
+       _tmp8__length1 = self->priv->board_length1;
+       _tmp8__length2 = self->priv->board_length2;
+       _tmp9_ = row;
+       _tmp8_[(_tmp9_ * _tmp8__length2) + column] = PLAYER_NONE;
+       _tmp10_ = _tmp8_[(_tmp9_ * _tmp8__length2) + column];
+       _tmp12_ = self->priv->last_moving_player;
+       if (_tmp12_ == PLAYER_AI) {
+               _tmp11_ = PLAYER_HUMAN;
+       } else {
+               _tmp11_ = PLAYER_AI;
+       }
+       self->priv->last_moving_player = _tmp11_;
+}
+
+
+static gchar
+string_get (const gchar* self,
+            glong index)
+{
+       gchar result = '\0';
+       gchar _tmp0_;
+       g_return_val_if_fail (self != NULL, '\0');
+       _tmp0_ = ((gchar*) self)[index];
+       result = _tmp0_;
+       return result;
+}
+
+
+void
+decision_tree_update_board (DecisionTree* self,
+                            const gchar* vstr)
+{
+       gint _tmp0_;
+       gint _tmp1_;
+       Player _tmp2_ = 0;
+       gint _tmp3_;
+       gint _tmp4_;
+       Player move = 0;
+       g_return_if_fail (self != NULL);
+       g_return_if_fail (vstr != NULL);
+       self->priv->next_move_in_column = -1;
+       _tmp0_ = strlen (vstr);
+       _tmp1_ = _tmp0_;
+       if (_tmp1_ == 2) {
+               return;
+       }
+       _tmp3_ = strlen (vstr);
+       _tmp4_ = _tmp3_;
+       if ((_tmp4_ % 2) == 0) {
+               _tmp2_ = PLAYER_AI;
+       } else {
+               _tmp2_ = PLAYER_HUMAN;
+       }
+       move = _tmp2_;
+       {
+               gint i = 0;
+               i = 1;
+               {
+                       gboolean _tmp5_ = FALSE;
+                       _tmp5_ = TRUE;
+                       while (TRUE) {
+                               gint _tmp7_;
+                               gint _tmp8_;
+                               gint _tmp9_;
+                               gint column = 0;
+                               gint _tmp10_;
+                               gchar* _tmp11_;
+                               gchar* _tmp12_;
+                               gint _tmp13_;
+                               gint row = 0;
+                               Player* _tmp22_;
+                               gint _tmp22__length1;
+                               gint _tmp22__length2;
+                               gint _tmp23_;
+                               gint _tmp24_;
+                               Player _tmp25_;
+                               Player _tmp26_;
+                               Player _tmp27_ = 0;
+                               Player _tmp28_;
+                               if (!_tmp5_) {
+                                       gint _tmp6_;
+                                       _tmp6_ = i;
+                                       i = _tmp6_ + 1;
+                               }
+                               _tmp5_ = FALSE;
+                               _tmp7_ = i;
+                               _tmp8_ = strlen (vstr);
+                               _tmp9_ = _tmp8_;
+                               if (!(_tmp7_ < (_tmp9_ - 1))) {
+                                       break;
+                               }
+                               _tmp10_ = i;
+                               _tmp11_ = g_strdup_printf ("%c", string_get (vstr, (glong) _tmp10_));
+                               _tmp12_ = _tmp11_;
+                               _tmp13_ = atoi (_tmp12_) - 1;
+                               _g_free0 (_tmp12_);
+                               column = _tmp13_;
+                               {
+                                       gboolean _tmp14_ = FALSE;
+                                       row = BOARD_ROWS - 1;
+                                       _tmp14_ = TRUE;
+                                       while (TRUE) {
+                                               gboolean _tmp16_ = FALSE;
+                                               gint _tmp17_;
+                                               if (!_tmp14_) {
+                                                       gint _tmp15_;
+                                                       _tmp15_ = row;
+                                                       row = _tmp15_ - 1;
+                                               }
+                                               _tmp14_ = FALSE;
+                                               _tmp17_ = row;
+                                               if (_tmp17_ >= 0) {
+                                                       Player* _tmp18_;
+                                                       gint _tmp18__length1;
+                                                       gint _tmp18__length2;
+                                                       gint _tmp19_;
+                                                       gint _tmp20_;
+                                                       Player _tmp21_;
+                                                       _tmp18_ = self->priv->board;
+                                                       _tmp18__length1 = self->priv->board_length1;
+                                                       _tmp18__length2 = self->priv->board_length2;
+                                                       _tmp19_ = row;
+                                                       _tmp20_ = column;
+                                                       _tmp21_ = _tmp18_[(_tmp19_ * _tmp18__length2) + 
_tmp20_];
+                                                       _tmp16_ = _tmp21_ != PLAYER_NONE;
+                                               } else {
+                                                       _tmp16_ = FALSE;
+                                               }
+                                               if (!_tmp16_) {
+                                                       break;
+                                               }
+                                       }
+                               }
+                               _tmp22_ = self->priv->board;
+                               _tmp22__length1 = self->priv->board_length1;
+                               _tmp22__length2 = self->priv->board_length2;
+                               _tmp23_ = row;
+                               _tmp24_ = column;
+                               _tmp25_ = move;
+                               _tmp22_[(_tmp23_ * _tmp22__length2) + _tmp24_] = _tmp25_;
+                               _tmp26_ = _tmp22_[(_tmp23_ * _tmp22__length2) + _tmp24_];
+                               _tmp28_ = move;
+                               if (_tmp28_ == PLAYER_HUMAN) {
+                                       _tmp27_ = PLAYER_AI;
+                               } else {
+                                       _tmp27_ = PLAYER_HUMAN;
+                               }
+                               move = _tmp27_;
+                       }
+               }
+       }
+       self->priv->last_moving_player = PLAYER_HUMAN;
+}
+
+
+static gint
+decision_tree_immediate_win (DecisionTree* self,
+                             Player p)
+{
+       gint result = 0;
+       Player old_last_moving_player = 0;
+       Player _tmp0_;
+       Player _tmp1_ = 0;
+       gboolean player_wins = FALSE;
+       gint i = 0;
+       Player _tmp9_;
+       gint _tmp10_ = 0;
+       gboolean _tmp11_;
+       g_return_val_if_fail (self != NULL, 0);
+       _tmp0_ = self->priv->last_moving_player;
+       old_last_moving_player = _tmp0_;
+       if (p == PLAYER_AI) {
+               _tmp1_ = PLAYER_HUMAN;
+       } else {
+               _tmp1_ = PLAYER_AI;
+       }
+       self->priv->last_moving_player = _tmp1_;
+       player_wins = FALSE;
+       {
+               gboolean _tmp2_ = FALSE;
+               i = 0;
+               _tmp2_ = TRUE;
+               while (TRUE) {
+                       gint _tmp4_;
+                       gint _tmp5_;
+                       gint _tmp6_;
+                       gint _tmp7_;
+                       gboolean _tmp8_;
+                       if (!_tmp2_) {
+                               gint _tmp3_;
+                               _tmp3_ = i;
+                               i = _tmp3_ + 1;
+                       }
+                       _tmp2_ = FALSE;
+                       _tmp4_ = i;
+                       if (!(_tmp4_ < BOARD_COLUMNS)) {
+                               break;
+                       }
+                       _tmp5_ = i;
+                       if (!decision_tree_move (self, _tmp5_)) {
+                               continue;
+                       }
+                       _tmp6_ = i;
+                       player_wins = decision_tree_victory (self, _tmp6_);
+                       _tmp7_ = i;
+                       decision_tree_unmove (self, _tmp7_);
+                       _tmp8_ = player_wins;
+                       if (_tmp8_) {
+                               break;
+                       }
+               }
+       }
+       _tmp9_ = old_last_moving_player;
+       self->priv->last_moving_player = _tmp9_;
+       _tmp11_ = player_wins;
+       if (_tmp11_) {
+               gint _tmp12_;
+               _tmp12_ = i;
+               _tmp10_ = _tmp12_;
+       } else {
+               _tmp10_ = -1;
+       }
+       result = _tmp10_;
+       return result;
+}
+
+
+gint
+decision_tree_playgame (DecisionTree* self,
+                        const gchar* vstr)
+{
+       gint result = 0;
+       gint temp = 0;
+       gint _tmp0_;
+       gint _tmp2_;
+       gint _tmp4_;
+       gint _tmp5_;
+       g_return_val_if_fail (self != NULL, 0);
+       g_return_val_if_fail (vstr != NULL, 0);
+       decision_tree_set_level (self, vstr);
+       decision_tree_update_board (self, vstr);
+       temp = decision_tree_immediate_win (self, PLAYER_AI);
+       _tmp0_ = temp;
+       if (_tmp0_ != -1) {
+               gint _tmp1_;
+               _tmp1_ = temp;
+               result = _tmp1_ + 1;
+               return result;
+       }
+       temp = decision_tree_immediate_win (self, PLAYER_HUMAN);
+       _tmp2_ = temp;
+       if (_tmp2_ != -1) {
+               gint _tmp3_;
+               _tmp3_ = temp;
+               result = _tmp3_ + 1;
+               return result;
+       }
+       _tmp4_ = self->priv->plies;
+       decision_tree_negamax (self, _tmp4_, NEG_INF, -1 * NEG_INF);
+       _tmp5_ = self->priv->next_move_in_column;
+       result = _tmp5_ + 1;
+       return result;
+}
+
+
+static gint
+decision_tree_heurist (DecisionTree* self)
+{
+       gint result = 0;
+       Difficulty _tmp0_;
+       g_return_val_if_fail (self != NULL, 0);
+       _tmp0_ = self->priv->level;
+       if (_tmp0_ == DIFFICULTY_EASY) {
+               result = decision_tree_heurist_easy (self);
+               return result;
+       } else {
+               Difficulty _tmp1_;
+               _tmp1_ = self->priv->level;
+               if (_tmp1_ == DIFFICULTY_MEDIUM) {
+                       result = decision_tree_heurist_medium (self);
+                       return result;
+               } else {
+                       result = decision_tree_heurist_hard (self);
+                       return result;
+               }
+       }
+}
+
+
+static gint
+decision_tree_heurist_easy (DecisionTree* self)
+{
+       gint result = 0;
+       g_return_val_if_fail (self != NULL, 0);
+       result = -1 * decision_tree_heurist_hard (self);
+       return result;
+}
+
+
+static gint
+decision_tree_heurist_medium (DecisionTree* self)
+{
+       gint result = 0;
+       g_return_val_if_fail (self != NULL, 0);
+       result = (gint) g_random_int_range ((gint32) 1, (gint32) 49);
+       return result;
+}
+
+
+static gint
+decision_tree_heurist_hard (DecisionTree* self)
+{
+       gint result = 0;
+       gint count = 0;
+       gint32 _tmp0_ = 0;
+       gint _tmp1_;
+       g_return_val_if_fail (self != NULL, 0);
+       count = decision_tree_count_3_in_a_row (self, PLAYER_AI) - decision_tree_count_3_in_a_row (self, 
PLAYER_HUMAN);
+       _tmp1_ = count;
+       if (_tmp1_ == 0) {
+               _tmp0_ = g_random_int_range ((gint32) 1, (gint32) 49);
+       } else {
+               gint _tmp2_;
+               _tmp2_ = count;
+               _tmp0_ = (gint32) (_tmp2_ * 100);
+       }
+       result = (gint) _tmp0_;
+       return result;
+}
+
+
+static gint
+decision_tree_count_3_in_a_row (DecisionTree* self,
+                                Player p)
+{
+       gint result = 0;
+       gint count = 0;
+       Player old_last_moving_player = 0;
+       Player _tmp0_;
+       Player _tmp23_;
+       g_return_val_if_fail (self != NULL, 0);
+       count = 0;
+       _tmp0_ = self->priv->last_moving_player;
+       old_last_moving_player = _tmp0_;
+       self->priv->last_moving_player = p;
+       {
+               gint j = 0;
+               j = 0;
+               {
+                       gboolean _tmp1_ = FALSE;
+                       _tmp1_ = TRUE;
+                       while (TRUE) {
+                               gint _tmp3_;
+                               if (!_tmp1_) {
+                                       gint _tmp2_;
+                                       _tmp2_ = j;
+                                       j = _tmp2_ + 1;
+                               }
+                               _tmp1_ = FALSE;
+                               _tmp3_ = j;
+                               if (!(_tmp3_ < BOARD_COLUMNS)) {
+                                       break;
+                               }
+                               {
+                                       gint i = 0;
+                                       i = 0;
+                                       {
+                                               gboolean _tmp4_ = FALSE;
+                                               _tmp4_ = TRUE;
+                                               while (TRUE) {
+                                                       gint _tmp6_;
+                                                       Player* _tmp7_;
+                                                       gint _tmp7__length1;
+                                                       gint _tmp7__length2;
+                                                       gint _tmp8_;
+                                                       gint _tmp9_;
+                                                       Player _tmp10_;
+                                                       gint _tmp11_;
+                                                       gint _tmp12_;
+                                                       Player* _tmp13_;
+                                                       gint _tmp13__length1;
+                                                       gint _tmp13__length2;
+                                                       gint _tmp14_;
+                                                       gint _tmp15_;
+                                                       Player _tmp16_;
+                                                       gint _tmp17_;
+                                                       Player* _tmp19_;
+                                                       gint _tmp19__length1;
+                                                       gint _tmp19__length2;
+                                                       gint _tmp20_;
+                                                       gint _tmp21_;
+                                                       Player _tmp22_;
+                                                       if (!_tmp4_) {
+                                                               gint _tmp5_;
+                                                               _tmp5_ = i;
+                                                               i = _tmp5_ + 1;
+                                                       }
+                                                       _tmp4_ = FALSE;
+                                                       _tmp6_ = i;
+                                                       if (!(_tmp6_ < BOARD_ROWS)) {
+                                                               break;
+                                                       }
+                                                       _tmp7_ = self->priv->board;
+                                                       _tmp7__length1 = self->priv->board_length1;
+                                                       _tmp7__length2 = self->priv->board_length2;
+                                                       _tmp8_ = i;
+                                                       _tmp9_ = j;
+                                                       _tmp10_ = _tmp7_[(_tmp8_ * _tmp7__length2) + _tmp9_];
+                                                       if (_tmp10_ != PLAYER_NONE) {
+                                                               break;
+                                                       }
+                                                       _tmp11_ = i;
+                                                       _tmp12_ = j;
+                                                       if (decision_tree_all_adjacent_empty (self, _tmp11_, 
_tmp12_)) {
+                                                               continue;
+                                                       }
+                                                       _tmp13_ = self->priv->board;
+                                                       _tmp13__length1 = self->priv->board_length1;
+                                                       _tmp13__length2 = self->priv->board_length2;
+                                                       _tmp14_ = i;
+                                                       _tmp15_ = j;
+                                                       _tmp13_[(_tmp14_ * _tmp13__length2) + _tmp15_] = p;
+                                                       _tmp16_ = _tmp13_[(_tmp14_ * _tmp13__length2) + 
_tmp15_];
+                                                       _tmp17_ = j;
+                                                       if (decision_tree_victory (self, _tmp17_)) {
+                                                               gint _tmp18_;
+                                                               _tmp18_ = count;
+                                                               count = _tmp18_ + 1;
+                                                       }
+                                                       _tmp19_ = self->priv->board;
+                                                       _tmp19__length1 = self->priv->board_length1;
+                                                       _tmp19__length2 = self->priv->board_length2;
+                                                       _tmp20_ = i;
+                                                       _tmp21_ = j;
+                                                       _tmp19_[(_tmp20_ * _tmp19__length2) + _tmp21_] = 
PLAYER_NONE;
+                                                       _tmp22_ = _tmp19_[(_tmp20_ * _tmp19__length2) + 
_tmp21_];
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       _tmp23_ = old_last_moving_player;
+       self->priv->last_moving_player = _tmp23_;
+       result = count;
+       return result;
+}
+
+
+static gboolean
+decision_tree_all_adjacent_empty (DecisionTree* self,
+                                  gint i,
+                                  gint j)
+{
+       gboolean result = FALSE;
+       g_return_val_if_fail (self != NULL, FALSE);
+       {
+               gint k = 0;
+               k = -1;
+               {
+                       gboolean _tmp0_ = FALSE;
+                       _tmp0_ = TRUE;
+                       while (TRUE) {
+                               gint _tmp2_;
+                               if (!_tmp0_) {
+                                       gint _tmp1_;
+                                       _tmp1_ = k;
+                                       k = _tmp1_ + 1;
+                               }
+                               _tmp0_ = FALSE;
+                               _tmp2_ = k;
+                               if (!(_tmp2_ <= 1)) {
+                                       break;
+                               }
+                               {
+                                       gint l = 0;
+                                       l = -1;
+                                       {
+                                               gboolean _tmp3_ = FALSE;
+                                               _tmp3_ = TRUE;
+                                               while (TRUE) {
+                                                       gint _tmp5_;
+                                                       gboolean _tmp6_ = FALSE;
+                                                       gint _tmp7_;
+                                                       gboolean _tmp9_ = FALSE;
+                                                       gboolean _tmp10_ = FALSE;
+                                                       gboolean _tmp11_ = FALSE;
+                                                       gboolean _tmp12_ = FALSE;
+                                                       gint _tmp13_;
+                                                       if (!_tmp3_) {
+                                                               gint _tmp4_;
+                                                               _tmp4_ = l;
+                                                               l = _tmp4_ + 1;
+                                                       }
+                                                       _tmp3_ = FALSE;
+                                                       _tmp5_ = l;
+                                                       if (!(_tmp5_ <= 1)) {
+                                                               break;
+                                                       }
+                                                       _tmp7_ = k;
+                                                       if (_tmp7_ == 0) {
+                                                               gint _tmp8_;
+                                                               _tmp8_ = l;
+                                                               _tmp6_ = _tmp8_ == 0;
+                                                       } else {
+                                                               _tmp6_ = FALSE;
+                                                       }
+                                                       if (_tmp6_) {
+                                                               continue;
+                                                       }
+                                                       _tmp13_ = k;
+                                                       if ((i + _tmp13_) >= 0) {
+                                                               gint _tmp14_;
+                                                               _tmp14_ = k;
+                                                               _tmp12_ = (i + _tmp14_) < BOARD_ROWS;
+                                                       } else {
+                                                               _tmp12_ = FALSE;
+                                                       }
+                                                       if (_tmp12_) {
+                                                               gint _tmp15_;
+                                                               _tmp15_ = l;
+                                                               _tmp11_ = (j + _tmp15_) >= 0;
+                                                       } else {
+                                                               _tmp11_ = FALSE;
+                                                       }
+                                                       if (_tmp11_) {
+                                                               gint _tmp16_;
+                                                               _tmp16_ = l;
+                                                               _tmp10_ = (j + _tmp16_) < BOARD_COLUMNS;
+                                                       } else {
+                                                               _tmp10_ = FALSE;
+                                                       }
+                                                       if (_tmp10_) {
+                                                               Player* _tmp17_;
+                                                               gint _tmp17__length1;
+                                                               gint _tmp17__length2;
+                                                               gint _tmp18_;
+                                                               gint _tmp19_;
+                                                               Player _tmp20_;
+                                                               _tmp17_ = self->priv->board;
+                                                               _tmp17__length1 = self->priv->board_length1;
+                                                               _tmp17__length2 = self->priv->board_length2;
+                                                               _tmp18_ = k;
+                                                               _tmp19_ = l;
+                                                               _tmp20_ = _tmp17_[((i + _tmp18_) * 
_tmp17__length2) + (j + _tmp19_)];
+                                                               _tmp9_ = _tmp20_ != PLAYER_NONE;
+                                                       } else {
+                                                               _tmp9_ = FALSE;
+                                                       }
+                                                       if (_tmp9_) {
+                                                               result = FALSE;
+                                                               return result;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       result = TRUE;
+       return result;
+}
+
+
+static void
+decision_tree_set_level (DecisionTree* self,
+                         const gchar* vstr)
+{
+       g_return_if_fail (self != NULL);
+       g_return_if_fail (vstr != NULL);
+       if (string_get (vstr, (glong) 0) == 'a') {
+               self->priv->level = DIFFICULTY_EASY;
+               self->priv->plies = 4;
+       } else {
+               if (string_get (vstr, (glong) 0) == 'b') {
+                       self->priv->level = DIFFICULTY_MEDIUM;
+                       self->priv->plies = 7;
+               } else {
+                       self->priv->level = DIFFICULTY_HARD;
+                       self->priv->plies = 7;
+               }
+       }
+}
+
+
+gint
+decision_tree_playandcheck (DecisionTree* self,
+                            const gchar* vstr)
+{
+       gint result = 0;
+       gint temp = 0;
+       gint _tmp0_;
+       gint _tmp1_;
+       gint _tmp3_;
+       gint _tmp4_;
+       g_return_val_if_fail (self != NULL, 0);
+       g_return_val_if_fail (vstr != NULL, 0);
+       decision_tree_set_level (self, vstr);
+       decision_tree_update_board (self, vstr);
+       temp = decision_tree_immediate_win (self, PLAYER_AI);
+       _tmp0_ = temp;
+       if (_tmp0_ != -1) {
+               result = 1000;
+               return result;
+       }
+       temp = decision_tree_immediate_win (self, PLAYER_HUMAN);
+       _tmp1_ = temp;
+       if (_tmp1_ != -1) {
+               gint _tmp2_;
+               _tmp2_ = temp;
+               result = _tmp2_ + 1;
+               return result;
+       }
+       _tmp3_ = self->priv->plies;
+       decision_tree_negamax (self, _tmp3_, NEG_INF, -1 * NEG_INF);
+       _tmp4_ = self->priv->next_move_in_column;
+       result = _tmp4_ + 1;
+       return result;
+}
+
+
+static void
+value_decision_tree_init (GValue* value)
+{
+       value->data[0].v_pointer = NULL;
+}
+
+
+static void
+value_decision_tree_free_value (GValue* value)
+{
+       if (value->data[0].v_pointer) {
+               decision_tree_unref (value->data[0].v_pointer);
+       }
+}
+
+
+static void
+value_decision_tree_copy_value (const GValue* src_value,
+                                GValue* dest_value)
+{
+       if (src_value->data[0].v_pointer) {
+               dest_value->data[0].v_pointer = decision_tree_ref (src_value->data[0].v_pointer);
+       } else {
+               dest_value->data[0].v_pointer = NULL;
+       }
+}
+
+
+static gpointer
+value_decision_tree_peek_pointer (const GValue* value)
+{
+       return value->data[0].v_pointer;
+}
+
+
+static gchar*
+value_decision_tree_collect_value (GValue* value,
+                                   guint n_collect_values,
+                                   GTypeCValue* collect_values,
+                                   guint collect_flags)
+{
+       if (collect_values[0].v_pointer) {
+               DecisionTree * object;
+               object = collect_values[0].v_pointer;
+               if (object->parent_instance.g_class == NULL) {
+                       return g_strconcat ("invalid unclassed object pointer for value type `", 
G_VALUE_TYPE_NAME (value), "'", NULL);
+               } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) {
+                       return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE 
(object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
+               }
+               value->data[0].v_pointer = decision_tree_ref (object);
+       } else {
+               value->data[0].v_pointer = NULL;
+       }
+       return NULL;
+}
+
+
+static gchar*
+value_decision_tree_lcopy_value (const GValue* value,
+                                 guint n_collect_values,
+                                 GTypeCValue* collect_values,
+                                 guint collect_flags)
+{
+       DecisionTree ** object_p;
+       object_p = collect_values[0].v_pointer;
+       if (!object_p) {
+               return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
+       }
+       if (!value->data[0].v_pointer) {
+               *object_p = NULL;
+       } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
+               *object_p = value->data[0].v_pointer;
+       } else {
+               *object_p = decision_tree_ref (value->data[0].v_pointer);
+       }
+       return NULL;
+}
+
+
+GParamSpec*
+param_spec_decision_tree (const gchar* name,
+                          const gchar* nick,
+                          const gchar* blurb,
+                          GType object_type,
+                          GParamFlags flags)
+{
+       ParamSpecDecisionTree* spec;
+       g_return_val_if_fail (g_type_is_a (object_type, TYPE_DECISION_TREE), NULL);
+       spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
+       G_PARAM_SPEC (spec)->value_type = object_type;
+       return G_PARAM_SPEC (spec);
+}
+
+
+gpointer
+value_get_decision_tree (const GValue* value)
+{
+       g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_DECISION_TREE), NULL);
+       return value->data[0].v_pointer;
+}
+
+
+void
+value_set_decision_tree (GValue* value,
+                         gpointer v_object)
+{
+       DecisionTree * old;
+       g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_DECISION_TREE));
+       old = value->data[0].v_pointer;
+       if (v_object) {
+               g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_DECISION_TREE));
+               g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE 
(value)));
+               value->data[0].v_pointer = v_object;
+               decision_tree_ref (value->data[0].v_pointer);
+       } else {
+               value->data[0].v_pointer = NULL;
+       }
+       if (old) {
+               decision_tree_unref (old);
+       }
+}
+
+
+void
+value_take_decision_tree (GValue* value,
+                          gpointer v_object)
+{
+       DecisionTree * old;
+       g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_DECISION_TREE));
+       old = value->data[0].v_pointer;
+       if (v_object) {
+               g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_DECISION_TREE));
+               g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE 
(value)));
+               value->data[0].v_pointer = v_object;
+       } else {
+               value->data[0].v_pointer = NULL;
+       }
+       if (old) {
+               decision_tree_unref (old);
+       }
+}
+
+
+static void
+decision_tree_class_init (DecisionTreeClass * klass)
+{
+       decision_tree_parent_class = g_type_class_peek_parent (klass);
+       ((DecisionTreeClass *) klass)->finalize = decision_tree_finalize;
+       g_type_class_add_private (klass, sizeof (DecisionTreePrivate));
+}
+
+
+static void
+decision_tree_instance_init (DecisionTree * self)
+{
+       Player* _tmp0_;
+       self->priv = DECISION_TREE_GET_PRIVATE (self);
+       _tmp0_ = g_new0 (Player, BOARD_ROWS * BOARD_COLUMNS);
+       self->priv->board = _tmp0_;
+       self->priv->board_length1 = BOARD_ROWS;
+       self->priv->board_length2 = BOARD_COLUMNS;
+       self->priv->plies = 8;
+       self->priv->last_moving_player = PLAYER_NONE;
+       self->priv->next_move_in_column = -1;
+       self->ref_count = 1;
+}
+
+
+static void
+decision_tree_finalize (DecisionTree * obj)
+{
+       DecisionTree * self;
+       self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_DECISION_TREE, DecisionTree);
+       g_signal_handlers_destroy (self);
+       self->priv->board = (g_free (self->priv->board), NULL);
+}
+
+
+GType
+decision_tree_get_type (void)
+{
+       static volatile gsize decision_tree_type_id__volatile = 0;
+       if (g_once_init_enter (&decision_tree_type_id__volatile)) {
+               static const GTypeValueTable g_define_type_value_table = { value_decision_tree_init, 
value_decision_tree_free_value, value_decision_tree_copy_value, value_decision_tree_peek_pointer, "p", 
value_decision_tree_collect_value, "p", value_decision_tree_lcopy_value };
+               static const GTypeInfo g_define_type_info = { sizeof (DecisionTreeClass), (GBaseInitFunc) 
NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) decision_tree_class_init, (GClassFinalizeFunc) NULL, NULL, 
sizeof (DecisionTree), 0, (GInstanceInitFunc) decision_tree_instance_init, &g_define_type_value_table };
+               static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | 
G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };
+               GType decision_tree_type_id;
+               decision_tree_type_id = g_type_register_fundamental (g_type_fundamental_next (), 
"DecisionTree", &g_define_type_info, &g_define_type_fundamental_info, 0);
+               g_once_init_leave (&decision_tree_type_id__volatile, decision_tree_type_id);
+       }
+       return decision_tree_type_id__volatile;
+}
+
+
+gpointer
+decision_tree_ref (gpointer instance)
+{
+       DecisionTree * self;
+       self = instance;
+       g_atomic_int_inc (&self->ref_count);
+       return instance;
+}
+
+
+void
+decision_tree_unref (gpointer instance)
+{
+       DecisionTree * self;
+       self = instance;
+       if (g_atomic_int_dec_and_test (&self->ref_count)) {
+               DECISION_TREE_GET_CLASS (self)->finalize (self);
+               g_type_free_instance ((GTypeInstance *) self);
+       }
+}
+
+
+
diff --git a/build/src/ai.h b/build/src/ai.h
new file mode 100644
index 0000000..fb14904
--- /dev/null
+++ b/build/src/ai.h
@@ -0,0 +1,64 @@
+/* ai.h generated by valac 0.40.10, the Vala compiler, do not modify */
+
+
+#ifndef __AI_H__
+#define __AI_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <stdlib.h>
+#include <string.h>
+
+G_BEGIN_DECLS
+
+
+#define TYPE_DECISION_TREE (decision_tree_get_type ())
+#define DECISION_TREE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_DECISION_TREE, DecisionTree))
+#define DECISION_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_DECISION_TREE, DecisionTreeClass))
+#define IS_DECISION_TREE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_DECISION_TREE))
+#define IS_DECISION_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_DECISION_TREE))
+#define DECISION_TREE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_DECISION_TREE, 
DecisionTreeClass))
+
+typedef struct _DecisionTree DecisionTree;
+typedef struct _DecisionTreeClass DecisionTreeClass;
+typedef struct _DecisionTreePrivate DecisionTreePrivate;
+
+struct _DecisionTree {
+       GTypeInstance parent_instance;
+       volatile int ref_count;
+       DecisionTreePrivate * priv;
+};
+
+struct _DecisionTreeClass {
+       GTypeClass parent_class;
+       void (*finalize) (DecisionTree *self);
+};
+
+
+gpointer decision_tree_ref (gpointer instance);
+void decision_tree_unref (gpointer instance);
+GParamSpec* param_spec_decision_tree (const gchar* name,
+                                      const gchar* nick,
+                                      const gchar* blurb,
+                                      GType object_type,
+                                      GParamFlags flags);
+void value_set_decision_tree (GValue* value,
+                              gpointer v_object);
+void value_take_decision_tree (GValue* value,
+                               gpointer v_object);
+gpointer value_get_decision_tree (const GValue* value);
+GType decision_tree_get_type (void) G_GNUC_CONST;
+DecisionTree* decision_tree_new (void);
+DecisionTree* decision_tree_construct (GType object_type);
+void decision_tree_print_board (DecisionTree* self);
+void decision_tree_update_board (DecisionTree* self,
+                                 const gchar* vstr);
+gint decision_tree_playgame (DecisionTree* self,
+                             const gchar* vstr);
+gint decision_tree_playandcheck (DecisionTree* self,
+                                 const gchar* vstr);
+
+
+G_END_DECLS
+
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 64047cf..e8031e0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,14 +7,17 @@ four_in_a_row_SOURCES = main.h     \
                 gfx.h      \
                 gfx.c      \
                 prefs.h    \
-                prefs.c    \
                 theme.c    \
                 theme.h    \
                 games-controls.c \
                 games-controls.h \
+                games-controls2.vala \
                 rules.h \
                 $(ai_C) \
-                $(ai_HEADER)
+                main2.vala \
+                $(ai_HEADER)\
+               prefs.vala \
+               gfx2.vala
 
 four_in_a_row_CPPFLAGS = \
        -I$(top_srcdir)
@@ -29,6 +32,10 @@ four_in_a_row_CFLAGS = \
 four_in_a_row_LDADD = \
        $(FOUR_IN_A_ROW_LIBS)
 
+four_in_a_row_VALAFLAGS = --pkg gtk+-3.0 \
+                         --vapidir . \
+                         --pkg temp
+
 ai_VALA = ai.vala
 
 ai_HEADER = ai.h
diff --git a/src/games-controls2.vala b/src/games-controls2.vala
new file mode 100644
index 0000000..e69de29
diff --git a/src/gfx.c b/src/gfx.c
index 7a5d9ee..57aae4f 100644
--- a/src/gfx.c
+++ b/src/gfx.c
@@ -41,17 +41,17 @@ extern gint gboard[7][7];
 extern GtkWidget *window;
 extern GtkWidget *drawarea;
 
-static gint boardsize = 0;
-static gint tilesize = 0;
-static gint offset[6];
+gint boardsize = 0;
+gint tilesize = 0;
+gint offset[6];
 
 /* unscaled pixbufs */
-static GdkPixbuf *pb_tileset_raw = NULL;
-static GdkPixbuf *pb_bground_raw = NULL;
+GdkPixbuf *pb_tileset_raw = NULL;
+GdkPixbuf *pb_bground_raw = NULL;
 
 /* scaled pixbufs */
-static GdkPixbuf *pb_tileset = NULL;
-static GdkPixbuf *pb_bground = NULL;
+GdkPixbuf *pb_tileset = NULL;
+GdkPixbuf *pb_bground = NULL;
 
 void
 gfx_free (void)
@@ -74,182 +74,6 @@ gfx_free (void)
   }
 }
 
-gint
-gfx_get_column (gint xpos)
-{
-  /* Derive column from pixel position */
-  gint c = xpos / tilesize;
-  if (c > 6)
-    c = 6;
-  if (c < 0)
-    c = 0;
-
-  return c;
-}
-
-static void
-gfx_paint_tile (cairo_t *cr, gint r, gint c)
-{
-  gint x = c * tilesize;
-  gint y = r * tilesize;
-  gint tile = gboard[r][c];
-  gint os = 0;
-
-  if (tile == TILE_CLEAR && r != 0)
-    return;
-
-  switch (tile) {
-  case TILE_PLAYER1:
-    if (r == 0)
-      os = offset[TILE_PLAYER1_CURSOR];
-    else
-      os = offset[TILE_PLAYER1];
-    break;
-  case TILE_PLAYER2:
-    if (r == 0)
-      os = offset[TILE_PLAYER2_CURSOR];
-    else
-      os = offset[TILE_PLAYER2];
-    break;
-  case TILE_CLEAR:
-    if (r == 0)
-      os = offset[TILE_CLEAR_CURSOR];
-    else
-      os = offset[TILE_CLEAR];
-    break;
-  }
-
-  cairo_save (cr);
-  gdk_cairo_set_source_pixbuf (cr, pb_tileset, x - os, y);
-  cairo_rectangle (cr, x, y, tilesize, tilesize);
-  cairo_clip (cr);
-  cairo_paint (cr);
-  cairo_restore (cr);
-}
-
-void
-gfx_draw_tile (gint r, gint c)
-{
-  gtk_widget_queue_draw_area (drawarea,
-                              c * tilesize, r * tilesize,
-                              tilesize, tilesize);
-}
-
-void
-gfx_draw_all (void)
-{
-  gtk_widget_queue_draw_area (drawarea, 0, 0, boardsize, boardsize);
-}
-
-
-
-void
-gfx_refresh_pixmaps (void)
-{
-  /* scale the pixbufs */
-  if (pb_tileset)
-    g_object_unref (pb_tileset);
-  if (pb_bground)
-    g_object_unref (pb_bground);
-
-  pb_tileset = gdk_pixbuf_scale_simple (pb_tileset_raw,
-                                       tilesize * 6, tilesize,
-                                       GDK_INTERP_BILINEAR);
-  pb_bground = gdk_pixbuf_scale_simple (pb_bground_raw,
-                                       boardsize, boardsize,
-                                       GDK_INTERP_BILINEAR);
-}
-
-static void
-gfx_draw_grid (cairo_t *cr)
-{
-  static const double dashes[] = { 4., 4. };
-  gint i;
-  GdkRGBA color;
-
-  gdk_rgba_parse (&color, theme[p.theme_id].grid_color);
-  gdk_cairo_set_source_rgba (cr, &color);
-  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-  cairo_set_line_width (cr, 1);
-  cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
-  cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
-  cairo_set_dash (cr, dashes, G_N_ELEMENTS (dashes), 0);
-
-  /* draw the grid on the background pixmap */
-  for (i = 1; i < 7; i++) {
-    cairo_move_to (cr, i * tilesize + .5, 0);
-    cairo_line_to (cr, i * tilesize + .5, boardsize);
-    cairo_move_to (cr, 0, i * tilesize + .5);
-    cairo_line_to (cr, boardsize, i * tilesize + .5);
-  }
-  cairo_stroke (cr);
-
-  /* Draw separator line at the top */
-  cairo_set_dash (cr, NULL, 0, 0);
-  cairo_move_to (cr, 0, tilesize + .5);
-  cairo_line_to (cr, boardsize, tilesize + .5);
-
-  cairo_stroke (cr);
-}
-
-void
-gfx_resize (GtkWidget * w)
-{
-  int width, height;
-
-  width = gtk_widget_get_allocated_width (w);
-  height = gtk_widget_get_allocated_height (w);
-
-  boardsize = MIN (width, height);
-  tilesize = boardsize / 7;
-
-  offset[TILE_PLAYER1] = 0;
-  offset[TILE_PLAYER2] = tilesize;
-  offset[TILE_CLEAR] = tilesize * 2;
-  offset[TILE_CLEAR_CURSOR] = tilesize * 3;
-  offset[TILE_PLAYER1_CURSOR] = tilesize * 4;
-  offset[TILE_PLAYER2_CURSOR] = tilesize * 5;
-
-  gfx_refresh_pixmaps ();
-  gfx_draw_all ();
-}
-
-void
-gfx_expose (cairo_t *cr)
-{
-  gint r, c;
-
-  /* draw the background */
-  cairo_save (cr);
-  gdk_cairo_set_source_pixbuf (cr, pb_bground, 0, 0);
-  cairo_rectangle (cr, 0, 0, boardsize, boardsize);
-  cairo_paint (cr);
-  cairo_restore (cr);
-
-  for (r = 0; r < 7; r++) {
-    for (c = 0; c < 7; c++) {
-      gfx_paint_tile (cr, r, c);
-    }
-  }
-
-  gfx_draw_grid (cr);
-}
-
-static void
-gfx_load_error (const gchar * fname)
-{
-  GtkWidget *dialog;
-
-  dialog = gtk_message_dialog_new (GTK_WINDOW (window),
-                                  GTK_DIALOG_MODAL,
-                                  GTK_MESSAGE_WARNING,
-                                  GTK_BUTTONS_CLOSE,
-                                  _("Unable to load image:\n%s"), fname);
-
-  gtk_dialog_run (GTK_DIALOG (dialog));
-  gtk_widget_destroy (dialog);
-}
-
 gboolean
 gfx_load_pixmaps (void)
 {
@@ -327,15 +151,3 @@ gfx_load_pixmaps (void)
 
   return TRUE;
 }
-
-gboolean
-gfx_change_theme (void)
-{
-  if (!gfx_load_pixmaps ())
-    return FALSE;
-
-  gfx_refresh_pixmaps ();
-  gfx_draw_all ();
-
-  return TRUE;
-}
diff --git a/src/gfx2.vala b/src/gfx2.vala
new file mode 100644
index 0000000..07c9c18
--- /dev/null
+++ b/src/gfx2.vala
@@ -0,0 +1,176 @@
+//using GETTTEXT_PACKAGE_CONTENT;
+static const string GETTEXT_PACKAGE2 = Config.GETTEXT_PACKAGE;
+extern int boardsize;
+extern int tilesize;
+extern int offset[6];
+extern Gtk.Widget drawarea;
+extern Gdk.Pixbuf? pb_bground;
+extern Gdk.Pixbuf? pb_tileset;
+extern Gdk.Pixbuf? pb_tileset_raw;
+extern Gdk.Pixbuf? pb_bground_raw;
+extern Theme theme[];
+extern int[,] gboard;
+
+int gboard_length2 = 7;
+
+namespace Gfx{
+    public int get_column (int xpos) {
+        /* Derive column from pixel position */
+        int c = xpos / tilesize;
+        if (c > 6)
+            c = 6;
+        if (c < 0)
+            c = 0;
+
+        return c;
+    }
+
+    public void draw_tile (int r, int c) {
+           drawarea.queue_draw_area(c*tilesize, r*tilesize, tilesize, tilesize);
+    }
+
+    public void draw_all () {
+        drawarea.queue_draw_area(0, 0, boardsize, boardsize);
+    }
+
+    bool change_theme () {
+        if (!gfx_load_pixmaps ())
+            return false;
+
+        gfx_refresh_pixmaps ();
+        draw_all ();
+        return true;
+    }
+
+    void resize (Gtk.Widget w) {
+        int width, height;
+
+        width = w.get_allocated_width ();
+        height = w.get_allocated_height ();
+
+        boardsize = int.min (width, height);
+        tilesize = boardsize / 7;
+
+        offset[Tile.PLAYER1] = 0;
+        offset[Tile.PLAYER2] = tilesize;
+        offset[Tile.CLEAR] = tilesize * 2;
+        offset[Tile.CLEAR_CURSOR] = tilesize * 3;
+        offset[Tile.PLAYER1_CURSOR] = tilesize * 4;
+        offset[Tile.PLAYER2_CURSOR] = tilesize * 5;
+
+        gfx_refresh_pixmaps ();
+        draw_all ();
+    }
+
+    void expose (Cairo.Context cr) {
+        int r, c;
+
+        /* draw the background */
+        cr.save();
+        Gdk.cairo_set_source_pixbuf(cr, pb_bground, 0, 0);
+        cr.rectangle(0, 0, boardsize, boardsize);
+        cr.paint();
+        cr.restore();
+
+        for (r = 0; r < 7; r++) {
+            for (c = 0; c < 7; c++) {
+                gfx_paint_tile (cr, r, c);
+            }
+        }
+
+        draw_grid (cr);
+    }
+
+    void draw_grid (Cairo.Context cr) {
+        const double dashes[] = { 4.0, 4.0 };
+        int i;
+        Gdk.RGBA color = Gdk.RGBA();
+
+        color.parse(theme[p.theme_id].grid_color);
+        Gdk.cairo_set_source_rgba (cr, color);
+        cr.set_operator (Cairo.Operator.SOURCE);
+        cr.set_line_width (1);
+        cr.set_line_cap (Cairo.LineCap.BUTT);
+        cr.set_line_join (Cairo.LineJoin.MITER);
+        cr.set_dash (dashes, 0);
+
+        /* draw the grid on the background pixmap */
+        for (i = 1; i < 7; i++) {
+            cr.move_to (i * tilesize + 0.5, 0);
+            cr.line_to (i * tilesize + 0.5, boardsize);
+            cr.move_to (0, i * tilesize + 0.5);
+            cr.line_to (boardsize, i * tilesize + 0.5);
+        }
+        cr.stroke();
+
+        /* Draw separator line at the top */
+        cr.set_dash(null, 0);
+        cr.move_to(0, tilesize+0.5);
+        cr.line_to(boardsize, tilesize +0.5);
+
+        cr.stroke();
+    }
+
+    void load_error (string fname) {
+        Gtk.MessageDialog dialog;
+
+        dialog = new Gtk.MessageDialog(window, Gtk.DialogFlags.MODAL,
+            Gtk.MessageType.WARNING, Gtk.ButtonsType.CLOSE,
+        dgettext(Config.GETTEXT_PACKAGE, "Unable to load image:\n%s"), fname);
+
+        dialog.run();
+        dialog.destroy();
+    }
+
+    void paint_tile (Cairo.Context cr, int r, int c) {
+        int x = c * tilesize;
+        int y = r * tilesize;
+        int tile = gboard[r,c];
+        int os = 0;
+
+        if (tile == Tile.CLEAR && r != 0)
+            return;
+
+        switch (tile) {
+        case Tile.PLAYER1:
+            if (r == 0)
+                os = offset[Tile.PLAYER1_CURSOR];
+            else
+                os = offset[Tile.PLAYER1];
+            break;
+        case Tile.PLAYER2:
+            if (r == 0)
+                os = offset[Tile.PLAYER2_CURSOR];
+            else
+                os = offset[Tile.PLAYER2];
+            break;
+        case Tile.CLEAR:
+            if (r == 0)
+                os = offset[Tile.CLEAR_CURSOR];
+            else
+                os = offset[Tile.CLEAR];
+            break;
+        }
+
+
+        cr.save();
+        //gdk_cairo_set_source_pixbuf (cr, pb_tileset, x - os, y);
+        cr.rectangle (x, y, tilesize, tilesize);
+
+        cr.clip();
+        cr.paint();
+        cr.restore();
+    }
+
+    void refresh_pixmaps () {
+        /* scale the pixbufs */
+        if (pb_tileset != null)
+            pb_tileset.unref();
+        if (pb_bground != null)
+            g_object_unref (pb_bground);
+
+        pb_tileset = pb_tileset_raw.scale_simple (tilesize * 6, tilesize, Gdk.InterpType.BILINEAR);
+        pb_bground = pb_bground_raw.scale_simple (boardsize, boardsize, Gdk.InterpType.BILINEAR);
+    }
+
+}
diff --git a/src/main.c b/src/main.c
index c6a3f71..6eab827 100644
--- a/src/main.c
+++ b/src/main.c
@@ -69,143 +69,26 @@ gint column;
 gint column_moveto;
 gint row;
 gint row_dropto;
-gint timeout;
+extern gint timeout;
 
 gint gboard[7][7];
 gchar vstr[SIZE_VSTR];
 gchar vlevel[] = "0abc";
 struct board *vboard;
 
-typedef enum {
-  ANIM_NONE,
-  ANIM_MOVE,
-  ANIM_DROP,
-  ANIM_BLINK,
-  ANIM_HINT
-} AnimID;
-
 AnimID anim;
 
-gint blink_r1, blink_c1;
-gint blink_r2, blink_c2;
-gint blink_t;
-gint blink_n;
-gboolean blink_on;
+extern gint blink_r1, blink_c1;
+extern gint blink_r2, blink_c2;
+extern gint blink_t;
+extern gint blink_n;
+extern gboolean blink_on;
 
 
 static void game_process_move (gint c);
 static void process_move2 (gint c);
 static void process_move3 (gint c);
 
-
-
-
-
-static void
-clear_board (void)
-{
-  gint r, c, i;
-
-  for (r = 0; r < 7; r++) {
-    for (c = 0; c < 7; c++) {
-      gboard[r][c] = TILE_CLEAR;
-    }
-  }
-
-  for (i = 0; i < SIZE_VSTR; i++)
-    vstr[i] = '\0';
-
-  vstr[0] = vlevel[LEVEL_WEAK];
-  vstr[1] = '0';
-  moves = 0;
-}
-
-
-
-static gint
-first_empty_row (gint c)
-{
-  gint r = 1;
-
-  while (r < 7 && gboard[r][c] == TILE_CLEAR)
-    r++;
-  return r - 1;
-}
-
-static gint
-get_n_human_players (void)
-{
-  if (p.level[PLAYER1] != LEVEL_HUMAN && p.level[PLAYER2] != LEVEL_HUMAN)
-    return 0;
-  if (p.level[PLAYER1] != LEVEL_HUMAN || p.level[PLAYER2] != LEVEL_HUMAN)
-    return 1;
-  return 2;
-}
-
-
-
-static gboolean
-is_player_human (void)
-{
-  return player == PLAYER1 ? p.level[PLAYER1] == LEVEL_HUMAN
-                           : p.level[PLAYER2] == LEVEL_HUMAN;
-}
-
-
-
-static void
-drop_marble (gint r, gint c)
-{
-  gint tile;
-  tile = player == PLAYER1 ? TILE_PLAYER1 : TILE_PLAYER2;
-
-  gboard[r][c] = tile;
-  gfx_draw_tile (r, c);
-
-  column = column_moveto = c;
-  row = row_dropto = r;
-}
-
-
-
-static void
-drop (void)
-{
-  gint tile;
-  tile = player == PLAYER1 ? TILE_PLAYER1 : TILE_PLAYER2;
-
-  gboard[row][column] = TILE_CLEAR;
-  gfx_draw_tile (row, column);
-
-  row++;
-  gboard[row][column] = tile;
-  gfx_draw_tile (row, column);
-}
-
-
-
-static void
-move (gint c)
-{
-  gboard[0][column] = TILE_CLEAR;
-  gfx_draw_tile (0, column);
-
-  column = c;
-  gboard[0][c] = player == PLAYER1 ? TILE_PLAYER1 : TILE_PLAYER2;
-
-  gfx_draw_tile (0, c);
-}
-
-static void
-move_cursor (gint c)
-{
-  move (c);
-  column = column_moveto = c;
-  row = row_dropto = 0;
-}
-
-
-
 static void
 draw_line (gint r1, gint c1, gint r2, gint c2, gint tile)
 {
@@ -238,7 +121,7 @@ draw_line (gint r1, gint c1, gint r2, gint c2, gint tile)
 
 
 
-static gboolean
+gboolean
 on_animate (gint c)
 {
   if (anim == ANIM_NONE)
@@ -291,40 +174,14 @@ on_animate (gint c)
 
 
 
-static void
-blink_tile (gint r, gint c, gint t, gint n)
-{
-  if (timeout)
-    return;
-  blink_r1 = r;
-  blink_c1 = c;
-  blink_r2 = r;
-  blink_c2 = c;
-  blink_t = t;
-  blink_n = n;
-  blink_on = FALSE;
-  anim = ANIM_BLINK;
-  timeout = g_timeout_add (SPEED_BLINK, (GSourceFunc) on_animate, NULL);
-}
 
 
 
-static void
-swap_player (void)
-{
-  player = (player == PLAYER1) ? PLAYER2 : PLAYER1;
-  move_cursor (3);
-  prompt_player ();
-}
 
 
 
-void
-set_status_message (const gchar * message)
-{
-  if (message)
-    gtk_header_bar_set_title (GTK_HEADER_BAR (headerbar), message);
-}
+
+
 
 static void
 stop_anim (void)
@@ -392,13 +249,7 @@ game_reset (void)
 
 
 
-static void
-game_free (void)
-{
-  gfx_free ();
-}
-
-
+static void game_free (void);
 
 static void
 play_sound (SoundID id)
@@ -948,17 +799,10 @@ check_game_state (void)
 }
 
 static gint
-next_move (gint c)
-{
-  process_move (c);
-  return FALSE;
-}
+next_move (gint c);
 
 static void
-game_process_move (gint c)
-{
-  process_move (c);
-}
+game_process_move (gint c);
 
 void
 process_move (gint c)
@@ -1165,27 +1009,16 @@ create_app (GApplication *app, gpointer user_data)
 }
 
 static void
-activate (GApplication *app, gpointer user_data)
-{
-  if (!gtk_widget_is_visible (window)) {
-    gtk_widget_show_all (window);
-    gfx_refresh_pixmaps ();
-    gfx_draw_all ();
-    scorebox_update ();       /* update visible player descriptions */
-    prompt_player ();
-    game_reset ();
-  }
-}
+activate (GApplication *app, gpointer user_data);
 
 int
-main (int argc, char *argv[])
+main2 (int argc, char *argv[])
 {
   GOptionContext *context;
   gboolean retval;
   GError *error = NULL;
   gint app_retval;
 
-  setlocale (LC_ALL, "");
   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
   textdomain (GETTEXT_PACKAGE);
diff --git a/src/main.h b/src/main.h
index fbed0b7..ac918bf 100644
--- a/src/main.h
+++ b/src/main.h
@@ -1,5 +1,6 @@
 /* main.h */
-
+#ifndef MAIN_H
+#define MAIN_H
 
 #define APPNAME "gnect"
 #define APPNAME_LONG N_("Four-in-a-row")
@@ -15,6 +16,8 @@
 
 #define MAIN_PAGE              0
 
+#include <gtk/gtk.h>
+
 typedef enum {
   MOVE_LEFT,
   MOVE_RIGHT,
@@ -49,6 +52,14 @@ typedef enum {
   LEVEL_STRONG
 } LevelID;
 
+typedef enum {
+  ANIM_NONE,
+  ANIM_MOVE,
+  ANIM_DROP,
+  ANIM_BLINK,
+  ANIM_HINT
+} AnimID;
+
 extern PlayerID who_starts;
 
 gboolean player_active;
@@ -60,3 +71,5 @@ void on_dialog_close (GtkWidget * w, int response_id, gpointer data);
 void scorebox_update (void);
 void scorebox_reset (void);
 void set_status_message (const gchar * message);
+
+#endif
diff --git a/src/main2.vala b/src/main2.vala
new file mode 100644
index 0000000..4d3ed15
--- /dev/null
+++ b/src/main2.vala
@@ -0,0 +1,189 @@
+using Intl;
+//using temp;
+
+extern int main2(int argc, char** argv);
+extern Gtk.Window window;
+extern bool gameover;
+extern bool player_active;
+extern PlayerID player;
+extern PlayerID winner;
+extern PlayerID who_starts;
+extern int score[3];
+extern AnimID anim;
+extern char vstr[];
+extern char vlevel[];
+extern int moves;
+extern const int SIZE_VSTR;
+const int SPEED_BLINK = 150;
+extern int column;
+extern int column_moveto;
+extern int row;
+extern int row_dropto;
+extern Gtk.HeaderBar headerbar;
+
+int blink_r1 = 0;
+int blink_c1 = 0;
+int blink_r2 = 0;
+int blink_c2 = 0;
+int blink_t = 0;
+int blink_n = 0;
+bool blink_on = false;
+uint timeout = 0;
+
+
+public int main(string[] argv) {
+    setlocale();
+
+    var application = new Gtk.Application("org.gnome.four-in-a-row", 0);
+
+    return main2(argv.length, argv);
+}
+
+public void activate() {
+    if (!window.is_visible()) {
+        window.show_all();
+        gfx_refresh_pixmaps();
+        Gfx.draw_all ();
+        scorebox_update ();       /* update visible player descriptions */
+        prompt_player ();
+        game_reset ();
+    }
+}
+
+public int next_move(int c) {
+    process_move(c);
+    return 0;
+}
+
+public void game_process_move(int c) {
+    process_move(c);
+}
+
+public void game_free() {
+    gfx_free();
+}
+
+public void game_init ()
+{
+    //Random.set_seed ((uint) Linux.timegm(null));
+
+    anim = AnimID.NONE;
+    gameover = true;
+    player_active = false;
+    player = PlayerID.PLAYER1;
+    winner = PlayerID.NOBODY;
+    score[PlayerID.PLAYER1] = 0;
+    score[PlayerID.PLAYER2] = 0;
+    score[PlayerID.NOBODY] = 0;
+
+    who_starts = PlayerID.PLAYER2;     /* This gets reversed immediately. */
+
+    clear_board ();
+}
+
+void clear_board () {
+  int r, c, i;
+
+  for (r = 0; r < 7; r++) {
+    for (c = 0; c < 7; c++) {
+      gboard[r, c] = Tile.CLEAR;
+    }
+  }
+
+  for (i = 0; i < SIZE_VSTR; i++)
+    vstr[i] = '\0';
+
+  vstr[0] = vlevel[Level.WEAK];
+  vstr[1] = '0';
+  moves = 0;
+}
+
+static int first_empty_row (int c) {
+  int r = 1;
+
+  while (r < 7 && gboard[r, c] == Tile.CLEAR)
+    r++;
+  return r - 1;
+}
+
+static int get_n_human_players () {
+  if (p.level[PlayerID.PLAYER1] != Level.HUMAN && p.level[PlayerID.PLAYER2] != Level.HUMAN)
+    return 0;
+  if (p.level[PlayerID.PLAYER1] != Level.HUMAN || p.level[PlayerID.PLAYER2] != Level.HUMAN)
+    return 1;
+  return 2;
+}
+
+static bool is_player_human ()
+{
+  return player == PLAYER1 ? p.level[PlayerID.PLAYER1] == Level.HUMAN
+                           : p.level[PlayerID.PLAYER2] == Level.HUMAN;
+}
+
+static void drop_marble (int r, int c)
+{
+  int tile;
+  tile = player == PlayerID.PLAYER1 ? Tile.PLAYER1 : Tile.PLAYER2;
+
+  gboard[r, c] = tile;
+  Gfx.draw_tile (r, c);
+
+  column = column_moveto = c;
+  row = row_dropto = r;
+}
+
+static void drop () {
+  int tile;
+  tile = player == PLAYER1 ? Tile.PLAYER1 : Tile.PLAYER2;
+
+  gboard[row, column] = Tile.CLEAR;
+  Gfx.draw_tile (row, column);
+
+  row++;
+  gboard[row, column] = tile;
+  Gfx.draw_tile (row, column);
+}
+
+static void move (int c) {
+  gboard[0, column] = Tile.CLEAR;
+  Gfx.draw_tile (0, column);
+
+  column = c;
+  gboard[0, c] = player == PlayerID.PLAYER1 ? Tile.PLAYER1 : Tile.PLAYER2;
+
+  Gfx.draw_tile (0, c);
+}
+
+static void move_cursor (int c)
+{
+  move (c);
+  column = column_moveto = c;
+  row = row_dropto = 0;
+}
+
+void swap_player ()
+{
+  player = (player == PlayerID.PLAYER1) ? PlayerID.PLAYER2 : PlayerID.PLAYER1;
+  move_cursor (3);
+  prompt_player ();
+}
+
+
+void set_status_message (string message)
+{
+    headerbar.set_title(message);
+}
+
+static void blink_tile (int r, int c, int t, int n) {
+  if (timeout != 0)
+    return;
+  blink_r1 = r;
+  blink_c1 = c;
+  blink_r2 = r;
+  blink_c2 = c;
+  blink_t = t;
+  blink_n = n;
+  blink_on = false;
+  anim = AnimID.BLINK;
+  timeout = Timeout.add (SPEED_BLINK, on_animate);
+}
diff --git a/src/prefs.c b/src/prefs.c
index dc1e883..0078a49 100644
--- a/src/prefs.c
+++ b/src/prefs.c
@@ -1,272 +1,640 @@
-/* -*- mode:C; indent-tabs-mode:t; tab-width:8; c-basic-offset:8; -*- */
-
-/* prefs.c
- *
- * Four-in-a-row for GNOME
- * (C) 2000 - 2004
- * Authors: Timothy Musson <trmusson ihug co nz>
- *
- * This game 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 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
+/* prefs.c generated by valac 0.40.10, the Vala compiler
+ * generated from prefs.vala, do not modify */
 
+/*public const int DEFAULT_THEME_ID = 0;*/
 
 
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <stdlib.h>
+#include <string.h>
 #include <config.h>
+#include <prefs.h>
+#include <gdk/gdk.h>
+#include <main.h>
+#include <glib/gi18n-lib.h>
+#include <float.h>
+#include <math.h>
 
-#include <glib/gi18n.h>
-#include <gtk/gtk.h>
-#include <gdk/gdkkeysyms.h>
+#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
+#define _g_free0(var) (var = (g_free (var), NULL))
 
-#include "main.h"
-#include "theme.h"
-#include "prefs.h"
-#include "gfx.h"
-#include "games-controls.h"
 
-#define DEFAULT_THEME_ID       0
-#define DEFAULT_KEY_LEFT       GDK_KEY_Left
-#define DEFAULT_KEY_RIGHT      GDK_KEY_Right
-#define DEFAULT_KEY_DROP       GDK_KEY_Down
+extern gint n_themes;
+extern GSettings* settings;
+extern GtkDialog* prefsbox;
+GtkDialog* prefsbox = NULL;
+extern GtkComboBox* combobox;
+GtkComboBox* combobox = NULL;
+extern GtkComboBoxText* combobox_theme;
+GtkComboBoxText* combobox_theme = NULL;
+extern GtkCheckButton* checkbutton_sound;
+GtkCheckButton* checkbutton_sound = NULL;
+extern Prefs p;
+Prefs p = {0};
+extern PlayerID who_starts;
+extern GtkWindow* window;
+
+#define GETTEXT_PACKAGE_CONTENT GETTEXT_PACKAGE
+#define DEFAULT_KEY_LEFT ((guint) GDK_KEY_Left)
+#define DEFAULT_KEY_RIGHT ((guint) GDK_KEY_Right)
+#define DEFAULT_KEY_DROP ((guint) GDK_KEY_Down)
+#define DEFAULT_THEME_ID 0
+gint sane_theme_id (gint val);
+gint sane_player_level (gint val);
+void on_select_theme (GtkComboBox* combo);
+void on_toggle_sound (GtkToggleButton* t);
+void prefs_init (void);
+void settings_changed_cb (const gchar* key);
+static void _settings_changed_cb_g_settings_changed (GSettings* _sender,
+                                              const gchar* key,
+                                              gpointer self);
+gboolean gfx_change_theme (void);
+void on_select_opponent (GtkComboBox* w);
+void prefsbox_open (void);
+static void _on_select_opponent_gtk_combo_box_changed (GtkComboBox* _sender,
+                                                gpointer self);
+static void _on_select_theme_gtk_combo_box_changed (GtkComboBox* _sender,
+                                             gpointer self);
+static void _on_toggle_sound_gtk_toggle_button_toggled (GtkToggleButton* _sender,
+                                                 gpointer self);
+
+
+gint
+sane_theme_id (gint val)
+{
+       gint result = 0;
+       gboolean _tmp0_ = FALSE;
+       if (val < 0) {
+               _tmp0_ = TRUE;
+       } else {
+               gint _tmp1_;
+               _tmp1_ = n_themes;
+               _tmp0_ = val >= _tmp1_;
+       }
+       if (_tmp0_) {
+               result = DEFAULT_THEME_ID;
+               return result;
+       }
+       result = val;
+       return result;
+}
 
-Prefs p;
 
-extern GSettings *settings;
-extern GtkWidget *window;
-extern Theme theme[];
-extern gint n_themes;
+gint
+sane_player_level (gint val)
+{
+       gint result = 0;
+       if (val < ((gint) LEVEL_HUMAN)) {
+               result = (gint) LEVEL_HUMAN;
+               return result;
+       }
+       if (val > ((gint) LEVEL_STRONG)) {
+               result = (gint) LEVEL_STRONG;
+               return result;
+       }
+       result = val;
+       return result;
+}
 
-static GtkWidget *prefsbox = NULL;
-static GtkWidget *combobox;
-static GtkWidget *combobox_theme;
-static GtkWidget *checkbutton_sound;
 
-static gint
-sane_theme_id (gint val)
+void
+on_select_theme (GtkComboBox* combo)
 {
-  if (val < 0 || val >= n_themes)
-    return DEFAULT_THEME_ID;
-  return val;
+       gint id = 0;
+       GSettings* _tmp0_;
+       g_return_if_fail (combo != NULL);
+       id = gtk_combo_box_get_active (combo);
+       _tmp0_ = settings;
+       g_settings_set_int (_tmp0_, "theme-id", id);
 }
 
-static gint
-sane_player_level (gint val)
+
+void
+on_toggle_sound (GtkToggleButton* t)
 {
-  if (val < LEVEL_HUMAN)
-    return LEVEL_HUMAN;
-  if (val > LEVEL_STRONG)
-    return LEVEL_STRONG;
-  return val;
+       GSettings* _tmp0_;
+       g_return_if_fail (t != NULL);
+       p.do_sound = gtk_toggle_button_get_active (t);
+       _tmp0_ = settings;
+       g_settings_set_boolean (_tmp0_, "sound", gtk_toggle_button_get_active (t));
 }
 
+
 static void
-settings_changed_cb (GSettings *settings,
-                     const char *key,
-                     gpointer user_data)
+_settings_changed_cb_g_settings_changed (GSettings* _sender,
+                                         const gchar* key,
+                                         gpointer self)
 {
-  if (strcmp (key, "sound") == 0) {
-    p.do_sound = g_settings_get_boolean (settings, "sound");
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton_sound),
-                                  p.do_sound);
-  } else if (strcmp (key, "key-left") == 0) {
-    p.keypress[MOVE_LEFT] = g_settings_get_int (settings, "key-left");
-  } else if (strcmp (key, "key-right") == 0) {
-    p.keypress[MOVE_RIGHT] = g_settings_get_int (settings, "key-right");
-  } else if (strcmp (key, "key-drop") == 0) {
-    p.keypress[MOVE_DROP] = g_settings_get_int (settings, "key-drop");
-  } else if (strcmp (key, "theme-id") == 0) {
-    gint val;
-
-    val = sane_theme_id (g_settings_get_int (settings, "theme-id"));
-    if (val != p.theme_id) {
-      p.theme_id = val;
-      if (!gfx_change_theme ())
-        return;
-      if (prefsbox == NULL)
-        return;
-      gtk_combo_box_set_active (GTK_COMBO_BOX (combobox_theme), p.theme_id);
-    }
-  }
+       settings_changed_cb (key);
 }
 
-static void
-on_select_theme (GtkComboBox * combo, gpointer data)
+
+void
+prefs_init (void)
 {
-  gint id;
+       GSettings* _tmp0_;
+       LevelID _tmp1_;
+       GSettings* _tmp2_;
+       LevelID _tmp3_;
+       GSettings* _tmp4_;
+       gint _tmp5_;
+       GSettings* _tmp6_;
+       gint _tmp7_;
+       GSettings* _tmp8_;
+       gint _tmp9_;
+       GSettings* _tmp10_;
+       GSettings* _tmp11_;
+       Prefs _tmp12_;
+       LevelID _tmp13_;
+       LevelID _tmp14_;
+       Prefs _tmp15_;
+       LevelID _tmp16_;
+       LevelID _tmp17_;
+       Prefs _tmp18_;
+       gint _tmp19_;
+       _tmp0_ = settings;
+       p.do_sound = g_settings_get_boolean (_tmp0_, "sound");
+       p.level[PLAYER1] = LEVEL_HUMAN;
+       _tmp1_ = p.level[PLAYER1];
+       _tmp2_ = settings;
+       p.level[PLAYER2] = (LevelID) g_settings_get_int (_tmp2_, "opponent");
+       _tmp3_ = p.level[PLAYER2];
+       _tmp4_ = settings;
+       p.keypress[MOVE_LEFT] = g_settings_get_int (_tmp4_, "key-left");
+       _tmp5_ = p.keypress[MOVE_LEFT];
+       _tmp6_ = settings;
+       p.keypress[MOVE_RIGHT] = g_settings_get_int (_tmp6_, "key-right");
+       _tmp7_ = p.keypress[MOVE_RIGHT];
+       _tmp8_ = settings;
+       p.keypress[MOVE_DROP] = g_settings_get_int (_tmp8_, "key-drop");
+       _tmp9_ = p.keypress[MOVE_DROP];
+       _tmp10_ = settings;
+       p.theme_id = g_settings_get_int (_tmp10_, "theme-id");
+       _tmp11_ = settings;
+       g_signal_connect (_tmp11_, "changed", (GCallback) _settings_changed_cb_g_settings_changed, NULL);
+       _tmp12_ = p;
+       _tmp13_ = _tmp12_.level[PLAYER1];
+       p.level[PLAYER1] = (LevelID) sane_player_level ((gint) _tmp13_);
+       _tmp14_ = p.level[PLAYER1];
+       _tmp15_ = p;
+       _tmp16_ = _tmp15_.level[PLAYER2];
+       p.level[PLAYER2] = (LevelID) sane_player_level ((gint) _tmp16_);
+       _tmp17_ = p.level[PLAYER2];
+       _tmp18_ = p;
+       _tmp19_ = _tmp18_.theme_id;
+       p.theme_id = sane_theme_id (_tmp19_);
+}
+
+
+void
+settings_changed_cb (const gchar* key)
+{
+       g_return_if_fail (key != NULL);
+       if (g_strcmp0 (key, "sound") == 0) {
+               GSettings* _tmp0_;
+               GtkCheckButton* _tmp1_;
+               Prefs _tmp2_;
+               gboolean _tmp3_;
+               _tmp0_ = settings;
+               p.do_sound = g_settings_get_boolean (_tmp0_, "sound");
+               _tmp1_ = checkbutton_sound;
+               _tmp2_ = p;
+               _tmp3_ = _tmp2_.do_sound;
+               gtk_toggle_button_set_active (G_TYPE_CHECK_INSTANCE_CAST (_tmp1_, gtk_toggle_button_get_type 
(), GtkToggleButton), _tmp3_);
+       } else {
+               if (g_strcmp0 (key, "key-left") == 0) {
+                       GSettings* _tmp4_;
+                       gint _tmp5_;
+                       _tmp4_ = settings;
+                       p.keypress[MOVE_LEFT] = g_settings_get_int (_tmp4_, "key-left");
+                       _tmp5_ = p.keypress[MOVE_LEFT];
+               } else {
+                       if (g_strcmp0 (key, "key-right") == 0) {
+                               GSettings* _tmp6_;
+                               gint _tmp7_;
+                               _tmp6_ = settings;
+                               p.keypress[MOVE_RIGHT] = g_settings_get_int (_tmp6_, "key-right");
+                               _tmp7_ = p.keypress[MOVE_RIGHT];
+                       } else {
+                               if (g_strcmp0 (key, "key-drop") == 0) {
+                                       GSettings* _tmp8_;
+                                       gint _tmp9_;
+                                       _tmp8_ = settings;
+                                       p.keypress[MOVE_DROP] = g_settings_get_int (_tmp8_, "key-drop");
+                                       _tmp9_ = p.keypress[MOVE_DROP];
+                               } else {
+                                       if (g_strcmp0 (key, "theme-id") == 0) {
+                                               gint val = 0;
+                                               GSettings* _tmp10_;
+                                               gint _tmp11_;
+                                               Prefs _tmp12_;
+                                               gint _tmp13_;
+                                               _tmp10_ = settings;
+                                               val = sane_theme_id (g_settings_get_int (_tmp10_, 
"theme-id"));
+                                               _tmp11_ = val;
+                                               _tmp12_ = p;
+                                               _tmp13_ = _tmp12_.theme_id;
+                                               if (_tmp11_ != _tmp13_) {
+                                                       gint _tmp14_;
+                                                       GtkDialog* _tmp15_;
+                                                       GtkComboBoxText* _tmp16_;
+                                                       Prefs _tmp17_;
+                                                       gint _tmp18_;
+                                                       _tmp14_ = val;
+                                                       p.theme_id = _tmp14_;
+                                                       if (!gfx_change_theme ()) {
+                                                               return;
+                                                       }
+                                                       _tmp15_ = prefsbox;
+                                                       if (_tmp15_ == NULL) {
+                                                               return;
+                                                       }
+                                                       _tmp16_ = combobox_theme;
+                                                       _tmp17_ = p;
+                                                       _tmp18_ = _tmp17_.theme_id;
+                                                       gtk_combo_box_set_active (G_TYPE_CHECK_INSTANCE_CAST 
(_tmp16_, gtk_combo_box_get_type (), GtkComboBox), _tmp18_);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
 
-  id = gtk_combo_box_get_active (combo);
-  g_settings_set_int (settings, "theme-id", id);
+void
+on_select_opponent (GtkComboBox* w)
+{
+       GtkTreeIter iter = {0};
+       gint value = 0;
+       GtkTreeIter _tmp0_ = {0};
+       GtkTreeModel* _tmp1_;
+       GtkTreeIter _tmp2_;
+       LevelID _tmp3_;
+       GSettings* _tmp4_;
+       g_return_if_fail (w != NULL);
+       gtk_combo_box_get_active_iter (w, &_tmp0_);
+       iter = _tmp0_;
+       _tmp1_ = gtk_combo_box_get_model (w);
+       _tmp2_ = iter;
+       gtk_tree_model_get (_tmp1_, &_tmp2_, 1, &value, -1);
+       p.level[PLAYER2] = (LevelID) value;
+       _tmp3_ = p.level[PLAYER2];
+       _tmp4_ = settings;
+       g_settings_set_int (_tmp4_, "opponent", value);
+       scorebox_reset ();
+       who_starts = PLAYER2;
+       game_reset ();
 }
 
+
 static void
-on_toggle_sound (GtkToggleButton * t, gpointer data)
+_on_select_opponent_gtk_combo_box_changed (GtkComboBox* _sender,
+                                           gpointer self)
 {
-  p.do_sound = gtk_toggle_button_get_active (t);
-  g_settings_set_boolean (settings, "sound", gtk_toggle_button_get_active (t));
+       on_select_opponent (_sender);
 }
 
+
 static void
-on_select_opponent (GtkWidget * w, gpointer data)
+_on_select_theme_gtk_combo_box_changed (GtkComboBox* _sender,
+                                        gpointer self)
 {
-  GtkTreeIter iter;
-  gint value;
-
-  if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (w), &iter))
-    return;
-  gtk_tree_model_get (GTK_TREE_MODEL (gtk_combo_box_get_model (GTK_COMBO_BOX (w))), &iter, 1, &value, -1);
-
-  p.level[PLAYER2] = value;
-  g_settings_set_int (settings, "opponent", value);
-  scorebox_reset ();
-  who_starts = PLAYER2;                /* This gets reversed in game_reset. */
-  game_reset ();
+       on_select_theme (_sender);
 }
 
-void
-prefs_init (void)
+
+static void
+_on_toggle_sound_gtk_toggle_button_toggled (GtkToggleButton* _sender,
+                                            gpointer self)
 {
-  p.do_sound = g_settings_get_boolean (settings, "sound");
-  p.level[PLAYER1] = 0;                /* Human. Always human. */
-  p.level[PLAYER2] = g_settings_get_int (settings, "opponent");
-  p.keypress[MOVE_LEFT] = g_settings_get_int (settings, "key-left");
-  p.keypress[MOVE_RIGHT] = g_settings_get_int (settings, "key-right");
-  p.keypress[MOVE_DROP] = g_settings_get_int (settings, "key-drop");
-  p.theme_id = g_settings_get_int (settings, "theme-id");
-
-  g_signal_connect (settings, "changed", G_CALLBACK (settings_changed_cb), NULL);
-
-  p.level[PLAYER1] = sane_player_level (p.level[PLAYER1]);
-  p.level[PLAYER2] = sane_player_level (p.level[PLAYER2]);
-  p.theme_id = sane_theme_id (p.theme_id);
+       on_toggle_sound (_sender);
 }
 
+
 void
 prefsbox_open (void)
 {
-  GtkWidget *notebook;
-  GtkWidget *grid;
-  GtkWidget *controls_list;
-  GtkWidget *label;
-  GtkCellRenderer *renderer;
-  GtkListStore *model;
-  GtkTreeIter iter;
-  gint i;
-
-  if (prefsbox != NULL) {
-    gtk_window_present (GTK_WINDOW (prefsbox));
-    return;
-  }
-
-  prefsbox = gtk_dialog_new_with_buttons (_("Preferences"),
-                                         GTK_WINDOW (window),
-                                         GTK_DIALOG_USE_HEADER_BAR,
-                                         NULL);
-  gtk_container_set_border_width (GTK_CONTAINER (prefsbox), 5);
-  gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (prefsbox))),
-                      2);
-
-  g_signal_connect (G_OBJECT (prefsbox), "destroy",
-                   G_CALLBACK (gtk_widget_destroyed), &prefsbox);
-
-  notebook = gtk_notebook_new ();
-  gtk_container_set_border_width (GTK_CONTAINER (notebook), 5);
-  gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (prefsbox))), notebook, TRUE, TRUE, 
0);
-
-  /* game tab */
-
-  grid = gtk_grid_new ();
-  gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
-  gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
-  gtk_container_set_border_width (GTK_CONTAINER (grid), 12);
-
-  label = gtk_label_new (_("Game"));
-  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), grid, label);
-
-  label = gtk_label_new (_("Opponent:"));
-  gtk_widget_set_hexpand (label, TRUE);
-  gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
-
-  combobox = gtk_combo_box_new ();
-  renderer = gtk_cell_renderer_text_new ();
-  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox), renderer, TRUE);
-  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox), renderer, "text", 0);
-  model = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
-  gtk_combo_box_set_model (GTK_COMBO_BOX (combobox), GTK_TREE_MODEL (model));
-  gtk_list_store_append (model, &iter);
-  gtk_list_store_set (model, &iter, 0, _("Human"), 1, LEVEL_HUMAN, -1);
-  if (p.level[PLAYER2] == LEVEL_HUMAN)
-    gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox), &iter);
-  gtk_list_store_append (model, &iter);
-  gtk_list_store_set (model, &iter, 0, _("Level one"), 1, LEVEL_WEAK, -1);
-  if (p.level[PLAYER2] == LEVEL_WEAK)
-    gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox), &iter);
-  gtk_list_store_append (model, &iter);
-  gtk_list_store_set (model, &iter, 0, _("Level two"), 1, LEVEL_MEDIUM, -1);
-  if (p.level[PLAYER2] == LEVEL_MEDIUM)
-    gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox), &iter);
-  gtk_list_store_append (model, &iter);
-  gtk_list_store_set (model, &iter, 0, _("Level three"), 1, LEVEL_STRONG, -1);
-  if (p.level[PLAYER2] == LEVEL_STRONG)
-    gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox), &iter);
-  g_signal_connect (combobox, "changed", G_CALLBACK (on_select_opponent), NULL);
-  gtk_grid_attach (GTK_GRID (grid), combobox, 1, 0, 1, 1);
-
-  label = gtk_label_new_with_mnemonic (_("_Theme:"));
-  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-  gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
-
-  combobox_theme = gtk_combo_box_text_new ();
-  for (i = 0; i < n_themes; i++) {
-    gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combobox_theme),
-                                   _(theme_get_title (i)));
-  }
-  gtk_label_set_mnemonic_widget (GTK_LABEL (label), combobox_theme);
-  gtk_grid_attach (GTK_GRID (grid), combobox_theme, 1, 1, 1, 1);
-
-  checkbutton_sound =
-    gtk_check_button_new_with_mnemonic (_("E_nable sounds"));
-  gtk_grid_attach (GTK_GRID (grid), checkbutton_sound, 0, 2, 2, 1);
-
-  /* keyboard tab */
-
-  label = gtk_label_new_with_mnemonic (_("Keyboard Controls"));
-
-  controls_list = games_controls_list_new (settings);
-  games_controls_list_add_controls (GAMES_CONTROLS_LIST (controls_list),
-                                   "key-left", _("Move left"), DEFAULT_KEY_LEFT,
-                                    "key-right", _("Move right"), DEFAULT_KEY_RIGHT,
-                                   "key-drop", _("Drop marble"), DEFAULT_KEY_DROP,
-                                    NULL);
-  gtk_container_set_border_width (GTK_CONTAINER (controls_list), 12);
-  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), controls_list, label);
-
-  /* fill in initial values */
-
-  gtk_combo_box_set_active (GTK_COMBO_BOX (combobox_theme), p.theme_id);
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton_sound),
-                               p.do_sound);
-
-  /* connect signals */
-
-  g_signal_connect (prefsbox, "response", G_CALLBACK (on_dialog_close),
-                   &prefsbox);
-
-  g_signal_connect (G_OBJECT (combobox_theme), "changed",
-                   G_CALLBACK (on_select_theme), NULL);
-
-  g_signal_connect (G_OBJECT (checkbutton_sound), "toggled",
-                   G_CALLBACK (on_toggle_sound), NULL);
-
-  gtk_widget_show_all (prefsbox);
+       GtkNotebook* notebook = NULL;
+       GtkGrid* grid = NULL;
+       GtkLabel* label = NULL;
+       GtkCellRendererText* renderer = NULL;
+       GtkListStore* model = NULL;
+       GtkTreeIter iter = {0};
+       GtkDialog* _tmp0_;
+       GtkWindow* _tmp2_;
+       GtkDialog* _tmp3_;
+       GtkDialog* _tmp4_;
+       GtkDialog* _tmp5_;
+       GtkBox* _tmp6_;
+       GtkNotebook* _tmp7_;
+       GtkNotebook* _tmp8_;
+       GtkDialog* _tmp9_;
+       GtkBox* _tmp10_;
+       GtkNotebook* _tmp11_;
+       GtkGrid* _tmp12_;
+       GtkGrid* _tmp13_;
+       GtkGrid* _tmp14_;
+       GtkGrid* _tmp15_;
+       GtkLabel* _tmp16_;
+       GtkNotebook* _tmp17_;
+       GtkGrid* _tmp18_;
+       GtkLabel* _tmp19_;
+       GtkLabel* _tmp20_;
+       GtkLabel* _tmp21_;
+       GtkGrid* _tmp22_;
+       GtkLabel* _tmp23_;
+       GtkComboBox* _tmp24_;
+       GtkCellRendererText* _tmp25_;
+       GtkComboBox* _tmp26_;
+       GtkCellRendererText* _tmp27_;
+       GtkComboBox* _tmp28_;
+       GtkCellRendererText* _tmp29_;
+       GtkListStore* _tmp30_;
+       GtkComboBox* _tmp31_;
+       GtkListStore* _tmp32_;
+       GtkListStore* _tmp33_;
+       GtkTreeIter _tmp34_ = {0};
+       GtkListStore* _tmp35_;
+       GtkTreeIter _tmp36_;
+       Prefs _tmp37_;
+       LevelID _tmp38_;
+       GtkListStore* _tmp41_;
+       GtkTreeIter _tmp42_ = {0};
+       GtkListStore* _tmp43_;
+       GtkTreeIter _tmp44_;
+       Prefs _tmp45_;
+       LevelID _tmp46_;
+       GtkListStore* _tmp49_;
+       GtkTreeIter _tmp50_ = {0};
+       GtkListStore* _tmp51_;
+       GtkTreeIter _tmp52_;
+       Prefs _tmp53_;
+       LevelID _tmp54_;
+       GtkListStore* _tmp57_;
+       GtkTreeIter _tmp58_ = {0};
+       GtkListStore* _tmp59_;
+       GtkTreeIter _tmp60_;
+       Prefs _tmp61_;
+       LevelID _tmp62_;
+       GtkComboBox* _tmp65_;
+       GtkGrid* _tmp66_;
+       GtkComboBox* _tmp67_;
+       GtkLabel* _tmp68_;
+       GtkLabel* _tmp69_;
+       GtkLabel* _tmp70_;
+       GtkGrid* _tmp71_;
+       GtkLabel* _tmp72_;
+       GtkComboBoxText* _tmp73_;
+       GtkLabel* _tmp82_;
+       GtkComboBoxText* _tmp83_;
+       GtkGrid* _tmp84_;
+       GtkComboBoxText* _tmp85_;
+       GtkCheckButton* _tmp86_;
+       GtkGrid* _tmp87_;
+       GtkCheckButton* _tmp88_;
+       GtkLabel* _tmp89_;
+       GtkComboBoxText* _tmp90_;
+       Prefs _tmp91_;
+       gint _tmp92_;
+       GtkCheckButton* _tmp93_;
+       Prefs _tmp94_;
+       gboolean _tmp95_;
+       GtkComboBoxText* _tmp96_;
+       GtkCheckButton* _tmp97_;
+       GtkDialog* _tmp98_;
+       _tmp0_ = prefsbox;
+       if (_tmp0_ != NULL) {
+               GtkDialog* _tmp1_;
+               _tmp1_ = prefsbox;
+               gtk_window_present (G_TYPE_CHECK_INSTANCE_CAST (_tmp1_, gtk_window_get_type (), GtkWindow));
+               _g_object_unref0 (model);
+               _g_object_unref0 (renderer);
+               _g_object_unref0 (label);
+               _g_object_unref0 (grid);
+               _g_object_unref0 (notebook);
+               return;
+       }
+       _tmp2_ = window;
+       _tmp3_ = (GtkDialog*) gtk_dialog_new_with_buttons (_ ("Preferences"), _tmp2_, 
GTK_DIALOG_DESTROY_WITH_PARENT, NULL);
+       g_object_ref_sink (_tmp3_);
+       _g_object_unref0 (prefsbox);
+       prefsbox = _tmp3_;
+       _tmp4_ = prefsbox;
+       gtk_container_set_border_width ((GtkContainer*) _tmp4_, (guint) 5);
+       _tmp5_ = prefsbox;
+       _tmp6_ = gtk_dialog_get_content_area (_tmp5_);
+       gtk_box_set_spacing (_tmp6_, 2);
+       _tmp7_ = (GtkNotebook*) gtk_notebook_new ();
+       g_object_ref_sink (_tmp7_);
+       _g_object_unref0 (notebook);
+       notebook = _tmp7_;
+       _tmp8_ = notebook;
+       gtk_container_set_border_width ((GtkContainer*) _tmp8_, (guint) 5);
+       _tmp9_ = prefsbox;
+       _tmp10_ = gtk_dialog_get_content_area (_tmp9_);
+       _tmp11_ = notebook;
+       gtk_box_pack_start (_tmp10_, (GtkWidget*) _tmp11_, TRUE, TRUE, (guint) 0);
+       _tmp12_ = (GtkGrid*) gtk_grid_new ();
+       g_object_ref_sink (_tmp12_);
+       _g_object_unref0 (grid);
+       grid = _tmp12_;
+       _tmp13_ = grid;
+       gtk_grid_set_row_spacing (_tmp13_, (guint) 6);
+       _tmp14_ = grid;
+       gtk_grid_set_column_spacing (_tmp14_, (guint) 12);
+       _tmp15_ = grid;
+       gtk_container_set_border_width ((GtkContainer*) _tmp15_, (guint) 12);
+       _tmp16_ = (GtkLabel*) gtk_label_new (_ ("Game"));
+       g_object_ref_sink (_tmp16_);
+       _g_object_unref0 (label);
+       label = _tmp16_;
+       _tmp17_ = notebook;
+       _tmp18_ = grid;
+       _tmp19_ = label;
+       gtk_notebook_append_page (_tmp17_, (GtkWidget*) _tmp18_, (GtkWidget*) _tmp19_);
+       _tmp20_ = (GtkLabel*) gtk_label_new (_ ("Opponent:"));
+       g_object_ref_sink (_tmp20_);
+       _g_object_unref0 (label);
+       label = _tmp20_;
+       _tmp21_ = label;
+       gtk_widget_set_hexpand ((GtkWidget*) _tmp21_, TRUE);
+       _tmp22_ = grid;
+       _tmp23_ = label;
+       gtk_grid_attach (_tmp22_, (GtkWidget*) _tmp23_, 0, 0, 1, 1);
+       _tmp24_ = (GtkComboBox*) gtk_combo_box_new ();
+       g_object_ref_sink (_tmp24_);
+       _g_object_unref0 (combobox);
+       combobox = _tmp24_;
+       _tmp25_ = (GtkCellRendererText*) gtk_cell_renderer_text_new ();
+       g_object_ref_sink (_tmp25_);
+       _g_object_unref0 (renderer);
+       renderer = _tmp25_;
+       _tmp26_ = combobox;
+       _tmp27_ = renderer;
+       gtk_cell_layout_pack_start ((GtkCellLayout*) _tmp26_, (GtkCellRenderer*) _tmp27_, TRUE);
+       _tmp28_ = combobox;
+       _tmp29_ = renderer;
+       gtk_cell_layout_add_attribute ((GtkCellLayout*) _tmp28_, (GtkCellRenderer*) _tmp29_, "text", 0);
+       _tmp30_ = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT, -1);
+       _g_object_unref0 (model);
+       model = _tmp30_;
+       _tmp31_ = combobox;
+       _tmp32_ = model;
+       gtk_combo_box_set_model (_tmp31_, (GtkTreeModel*) _tmp32_);
+       _tmp33_ = model;
+       gtk_list_store_append (_tmp33_, &_tmp34_);
+       iter = _tmp34_;
+       _tmp35_ = model;
+       _tmp36_ = iter;
+       gtk_list_store_set (_tmp35_, &_tmp36_, 0, _ ("Human"), 1, LEVEL_HUMAN, -1);
+       _tmp37_ = p;
+       _tmp38_ = _tmp37_.level[PLAYER2];
+       if (_tmp38_ == LEVEL_HUMAN) {
+               GtkComboBox* _tmp39_;
+               GtkTreeIter _tmp40_;
+               _tmp39_ = combobox;
+               _tmp40_ = iter;
+               gtk_combo_box_set_active_iter (_tmp39_, &_tmp40_);
+       }
+       _tmp41_ = model;
+       gtk_list_store_append (_tmp41_, &_tmp42_);
+       iter = _tmp42_;
+       _tmp43_ = model;
+       _tmp44_ = iter;
+       gtk_list_store_set (_tmp43_, &_tmp44_, 0, _ ("Level one"), 1, LEVEL_WEAK, -1);
+       _tmp45_ = p;
+       _tmp46_ = _tmp45_.level[PLAYER2];
+       if (_tmp46_ == LEVEL_WEAK) {
+               GtkComboBox* _tmp47_;
+               GtkTreeIter _tmp48_;
+               _tmp47_ = combobox;
+               _tmp48_ = iter;
+               gtk_combo_box_set_active_iter (_tmp47_, &_tmp48_);
+       }
+       _tmp49_ = model;
+       gtk_list_store_append (_tmp49_, &_tmp50_);
+       iter = _tmp50_;
+       _tmp51_ = model;
+       _tmp52_ = iter;
+       gtk_list_store_set (_tmp51_, &_tmp52_, 0, _ ("Level two"), 1, LEVEL_MEDIUM, -1);
+       _tmp53_ = p;
+       _tmp54_ = _tmp53_.level[PLAYER2];
+       if (_tmp54_ == LEVEL_MEDIUM) {
+               GtkComboBox* _tmp55_;
+               GtkTreeIter _tmp56_;
+               _tmp55_ = combobox;
+               _tmp56_ = iter;
+               gtk_combo_box_set_active_iter (_tmp55_, &_tmp56_);
+       }
+       _tmp57_ = model;
+       gtk_list_store_append (_tmp57_, &_tmp58_);
+       iter = _tmp58_;
+       _tmp59_ = model;
+       _tmp60_ = iter;
+       gtk_list_store_set (_tmp59_, &_tmp60_, 0, _ ("Level thre"), 1, LEVEL_STRONG, -1);
+       _tmp61_ = p;
+       _tmp62_ = _tmp61_.level[PLAYER2];
+       if (_tmp62_ == LEVEL_STRONG) {
+               GtkComboBox* _tmp63_;
+               GtkTreeIter _tmp64_;
+               _tmp63_ = combobox;
+               _tmp64_ = iter;
+               gtk_combo_box_set_active_iter (_tmp63_, &_tmp64_);
+       }
+       _tmp65_ = combobox;
+       g_signal_connect (_tmp65_, "changed", (GCallback) _on_select_opponent_gtk_combo_box_changed, NULL);
+       _tmp66_ = grid;
+       _tmp67_ = combobox;
+       gtk_grid_attach (_tmp66_, (GtkWidget*) _tmp67_, 1, 0, 1, 1);
+       _tmp68_ = (GtkLabel*) gtk_label_new_with_mnemonic (_ ("_Theme:"));
+       g_object_ref_sink (_tmp68_);
+       _g_object_unref0 (label);
+       label = _tmp68_;
+       _tmp69_ = label;
+       gtk_label_set_xalign (_tmp69_, (gfloat) 0.0);
+       _tmp70_ = label;
+       gtk_label_set_yalign (_tmp70_, (gfloat) 0.5);
+       _tmp71_ = grid;
+       _tmp72_ = label;
+       gtk_grid_attach (_tmp71_, (GtkWidget*) _tmp72_, 0, 1, 1, 1);
+       _tmp73_ = (GtkComboBoxText*) gtk_combo_box_text_new ();
+       g_object_ref_sink (_tmp73_);
+       _g_object_unref0 (combobox_theme);
+       combobox_theme = _tmp73_;
+       {
+               gint i = 0;
+               i = 0;
+               {
+                       gboolean _tmp74_ = FALSE;
+                       _tmp74_ = TRUE;
+                       while (TRUE) {
+                               gint _tmp76_;
+                               gint _tmp77_;
+                               GtkComboBoxText* _tmp78_;
+                               gint _tmp79_;
+                               gchar* _tmp80_;
+                               gchar* _tmp81_;
+                               if (!_tmp74_) {
+                                       gint _tmp75_;
+                                       _tmp75_ = i;
+                                       i = _tmp75_ + 1;
+                               }
+                               _tmp74_ = FALSE;
+                               _tmp76_ = i;
+                               _tmp77_ = n_themes;
+                               if (!(_tmp76_ < _tmp77_)) {
+                                       break;
+                               }
+                               _tmp78_ = combobox_theme;
+                               _tmp79_ = i;
+                               _tmp80_ = theme_get_title (_tmp79_);
+                               _tmp81_ = _tmp80_;
+                               gtk_combo_box_text_append_text (_tmp78_, _ (_tmp81_));
+                               _g_free0 (_tmp81_);
+                       }
+               }
+       }
+       _tmp82_ = label;
+       _tmp83_ = combobox_theme;
+       gtk_label_set_mnemonic_widget (_tmp82_, (GtkWidget*) _tmp83_);
+       _tmp84_ = grid;
+       _tmp85_ = combobox_theme;
+       gtk_grid_attach (_tmp84_, (GtkWidget*) _tmp85_, 1, 1, 1, 1);
+       _tmp86_ = (GtkCheckButton*) gtk_check_button_new_with_mnemonic (_ ("E_nable sounds"));
+       g_object_ref_sink (_tmp86_);
+       _g_object_unref0 (checkbutton_sound);
+       checkbutton_sound = _tmp86_;
+       _tmp87_ = grid;
+       _tmp88_ = checkbutton_sound;
+       gtk_grid_attach (_tmp87_, (GtkWidget*) _tmp88_, 0, 2, 2, 1);
+       _tmp89_ = (GtkLabel*) gtk_label_new_with_mnemonic (_ ("Keyboard Controls"));
+       g_object_ref_sink (_tmp89_);
+       _g_object_unref0 (label);
+       label = _tmp89_;
+       _tmp90_ = combobox_theme;
+       _tmp91_ = p;
+       _tmp92_ = _tmp91_.theme_id;
+       gtk_combo_box_set_active ((GtkComboBox*) _tmp90_, _tmp92_);
+       _tmp93_ = checkbutton_sound;
+       _tmp94_ = p;
+       _tmp95_ = _tmp94_.do_sound;
+       gtk_toggle_button_set_active ((GtkToggleButton*) _tmp93_, _tmp95_);
+       _tmp96_ = combobox_theme;
+       g_signal_connect ((GtkComboBox*) _tmp96_, "changed", (GCallback) 
_on_select_theme_gtk_combo_box_changed, NULL);
+       _tmp97_ = checkbutton_sound;
+       g_signal_connect ((GtkToggleButton*) _tmp97_, "toggled", (GCallback) 
_on_toggle_sound_gtk_toggle_button_toggled, NULL);
+       _tmp98_ = prefsbox;
+       gtk_widget_show_all ((GtkWidget*) _tmp98_);
+       _g_object_unref0 (model);
+       _g_object_unref0 (renderer);
+       _g_object_unref0 (label);
+       _g_object_unref0 (grid);
+       _g_object_unref0 (notebook);
 }
+
+
+
diff --git a/src/prefs.h b/src/prefs.h
index 29d2ad9..3ebcc0a 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -1,4 +1,7 @@
 /* prefs.h */
+#ifndef PREFS_H
+#define PREFS_H
+#include <main.h>
 
 typedef struct _Prefs Prefs;
 struct _Prefs {
@@ -11,3 +14,4 @@ struct _Prefs {
 
 void prefs_init (void);
 void prefsbox_open (void);
+#endif
diff --git a/src/prefs.vala b/src/prefs.vala
new file mode 100644
index 0000000..a51f40a
--- /dev/null
+++ b/src/prefs.vala
@@ -0,0 +1,220 @@
+//public const int DEFAULT_THEME_ID = 0;
+extern int n_themes;
+extern Settings settings;
+Gtk.Dialog? prefsbox = null;
+Gtk.ComboBox combobox;
+Gtk.ComboBoxText combobox_theme;
+Gtk.CheckButton checkbutton_sound;
+const string GETTEXT_PACKAGE_CONTENT = Config.GETTEXT_PACKAGE;
+Prefs p;
+
+const uint DEFAULT_KEY_LEFT = Gdk.Key.Left;
+const uint DEFAULT_KEY_RIGHT = Gdk.Key.Right;
+const uint DEFAULT_KEY_DROP = Gdk.Key.Down;
+const int DEFAULT_THEME_ID = 0;
+
+
+static int sane_theme_id (int val)
+{
+  if (val < 0 || val >= n_themes)
+    return DEFAULT_THEME_ID;
+  return val;
+}
+
+public int sane_player_level (int val)
+{
+  if (val < Level.HUMAN)
+    return Level.HUMAN;
+  if (val > Level.STRONG)
+    return Level.STRONG;
+  return val;
+}
+
+public void on_select_theme (Gtk.ComboBox combo)
+{
+  int id = combo.get_active ();
+  settings.set_int ("theme-id", id);
+}
+
+public void on_toggle_sound (Gtk.ToggleButton t)
+{
+  p.do_sound = t.get_active ();
+  settings.set_boolean ("sound", t.get_active());
+}
+
+void prefs_init ()
+{
+  p.do_sound = settings.get_boolean ("sound");
+  p.level[PlayerID.PLAYER1] = Level.HUMAN;             /* Human. Always human. */
+  p.level[PlayerID.PLAYER2] = (Level) settings.get_int ("opponent");
+  p.keypress[Move.LEFT] = settings.get_int ("key-left");
+  p.keypress[Move.RIGHT] = settings.get_int ("key-right");
+  p.keypress[Move.DROP] = settings.get_int ("key-drop");
+  p.theme_id = settings.get_int ("theme-id");
+
+    settings.changed.connect(settings_changed_cb);
+  //g_signal_connect (settings, "changed", G_CALLBACK (settings_changed_cb), NULL);
+
+  p.level[PlayerID.PLAYER1] = (Level) sane_player_level (p.level[PlayerID.PLAYER1]);
+  p.level[PlayerID.PLAYER2] = (Level) sane_player_level (p.level[PlayerID.PLAYER2]);
+  p.theme_id = sane_theme_id (p.theme_id);
+}
+
+public void settings_changed_cb (string key)
+{
+  if (key == "sound") {
+    p.do_sound = settings.get_boolean ("sound");
+    ((Gtk.ToggleButton)checkbutton_sound).set_active (p.do_sound);
+  } else if (key == "key-left") {
+    p.keypress[Move.LEFT] = settings.get_int ( "key-left");
+  } else if (key == "key-right") {
+    p.keypress[Move.RIGHT] = settings.get_int ( "key-right");
+  } else if (key == "key-drop") {
+    p.keypress[Move.DROP] = settings.get_int ( "key-drop");
+  } else if (key == "theme-id") {
+    int val;
+
+    val = sane_theme_id (settings.get_int ("theme-id"));
+    if (val != p.theme_id) {
+      p.theme_id = val;
+      if (!Gfx.change_theme ())
+        return;
+      if (prefsbox == null)
+        return;
+      ((Gtk.ComboBox)combobox_theme).set_active (p.theme_id);
+    }
+  }
+}
+
+public void on_select_opponent (Gtk.ComboBox w)
+{
+  Gtk.TreeIter iter;
+  int value;
+
+  w.get_active_iter (out iter);
+  w.get_model().get (iter, 1, out value);
+
+  p.level[PlayerID.PLAYER2] = (Level)value;
+  settings.set_int ("opponent", value);
+  scorebox_reset ();
+  who_starts = PlayerID.PLAYER2;               /* This gets reversed in game_reset. */
+  game_reset ();
+}
+
+[CCode(cheader_filename="config.h")]
+public void prefsbox_open ()
+{
+    Gtk.Notebook notebook;
+    Gtk.Grid grid;
+    // GtkWidget *controls_list;
+    Gtk.Label label;
+    Gtk.CellRendererText renderer;
+    Gtk.ListStore model;
+    Gtk.TreeIter iter;
+    // gint i;
+
+    if (prefsbox != null) {
+        ((Gtk.Window)prefsbox).present ();
+        return;
+    }
+
+    prefsbox = new Gtk.Dialog.with_buttons (_("Preferences"),
+                                         window,
+                                         Gtk.DialogFlags.DESTROY_WITH_PARENT);
+
+    prefsbox.set_border_width(5);
+    prefsbox.get_content_area().set_spacing(2);
+
+  // g_signal_connect (G_OBJECT (prefsbox), "destroy",
+               //     G_CALLBACK (gtk_widget_destroyed), &prefsbox);
+
+    notebook = new Gtk.Notebook();
+    notebook.set_border_width(5);
+    prefsbox.get_content_area().pack_start(notebook, true, true, 0);
+
+    /* game tab */
+
+    grid = new Gtk.Grid();
+    grid.set_row_spacing(6);
+    grid.set_column_spacing(12);
+    grid.set_border_width(12);
+
+    label = new Gtk.Label(_("Game"));
+    notebook.append_page(grid, label);
+
+    label = new Gtk.Label(_("Opponent:"));
+    label.set_hexpand(true);
+    grid.attach(label,0,0 ,1, 1);
+
+    combobox = new Gtk.ComboBox();
+    renderer = new Gtk.CellRendererText();
+    combobox.pack_start(renderer, true);
+    combobox.add_attribute(renderer, "text", 0);
+    model = new Gtk.ListStore(2, typeof(string), typeof(int));
+    combobox.set_model(model);
+    model.append(out iter);
+    model.set(iter, 0, _("Human"), 1, Level.HUMAN);
+    if (p.level[PlayerID.PLAYER2] == Level.HUMAN)
+        combobox.set_active_iter(iter);
+    model.append(out iter);
+    model.set(iter, 0, _("Level one"), 1, Level.WEAK);
+    if (p.level[PlayerID.PLAYER2] == Level.WEAK)
+        combobox.set_active_iter(iter);
+    model.append(out iter);
+    model.set(iter, 0, _("Level two"), 1, Level.MEDIUM);
+    if (p.level[PlayerID.PLAYER2] == Level.MEDIUM)
+        combobox.set_active_iter(iter);
+    model.append(out iter);
+    model.set(iter, 0, _("Level thre"), 1, Level.STRONG);
+    if (p.level[PlayerID.PLAYER2] == Level.STRONG)
+        combobox.set_active_iter(iter);
+
+    combobox.changed.connect(on_select_opponent);
+    grid.attach(combobox, 1, 0, 1, 1);
+
+    label = new Gtk.Label.with_mnemonic(_("_Theme:"));
+    label.set_xalign((float)0.0);
+    label.set_yalign((float)0.5);
+    grid.attach(label, 0, 1, 1, 1);
+
+    combobox_theme = new Gtk.ComboBoxText();
+    for (int i = 0; i < n_themes; i++) {
+        combobox_theme.append_text(_(theme_get_title(i)));
+    }
+    label.set_mnemonic_widget(combobox_theme);
+    grid.attach(combobox_theme, 1, 1, 1, 1);
+
+    checkbutton_sound = new Gtk.CheckButton.with_mnemonic(_("E_nable sounds"));
+    grid.attach(checkbutton_sound, 0, 2, 2, 1);
+
+    /* keyboard tab */
+
+    label = new Gtk.Label.with_mnemonic (_("Keyboard Controls"));
+
+
+  // controls_list = games_controls_list_new (settings);
+  // games_controls_list_add_controls (GAMES_CONTROLS_LIST (controls_list),
+               //                  "key-left", _("Move left"), DEFAULT_KEY_LEFT,
+  //                                   "key-right", _("Move right"), DEFAULT_KEY_RIGHT,
+               //                  "key-drop", _("Drop marble"), DEFAULT_KEY_DROP,
+  //                                   NULL);
+  // gtk_container_set_border_width (GTK_CONTAINER (controls_list), 12);
+  // gtk_notebook_append_page (GTK_NOTEBOOK (notebook), controls_list, label);
+
+    /* fill in initial values */
+
+    combobox_theme.set_active(p.theme_id);
+    checkbutton_sound.set_active(p.do_sound);
+
+    /* connect signals */
+
+    //prefsbox.response.connect(on_dialog_close);
+  // g_signal_connect (prefsbox, "response", G_CALLBACK (on_dialog_close),
+               //     &prefsbox);
+
+    combobox_theme.changed.connect(on_select_theme);
+
+    checkbutton_sound.toggled.connect(on_toggle_sound);
+
+    prefsbox.show_all();
+}
diff --git a/src/temp.vapi b/src/temp.vapi
new file mode 100644
index 0000000..ba097d0
--- /dev/null
+++ b/src/temp.vapi
@@ -0,0 +1,88 @@
+[CCode (cname = "Prefs", cheader_filename="prefs.h")]
+struct Prefs {
+  bool do_sound;
+  int theme_id;
+  Level level[2];
+  int keypress[3];
+}
+
+[CCode (cname = "Theme", cheader_filename="theme.h")]
+struct Theme {
+    const string title;
+    const string fname_tileset;
+    const string fname_bground;
+    public string grid_color;
+    const string player1;
+    const string player2;
+    const string player1_win;
+    const string player2_win;
+    const string player1_turn;
+    const string player2_turn;
+}
+
+[CCode (cname = "AnimID", cprefix = "ANIM_", cheader_filename="main.h")]
+public enum AnimID {
+    NONE,
+    MOVE,
+    DROP,
+    BLINK,
+    HINT
+}
+
+[CCode (cname = "PlayerID", cprefix = "", cheader_filename="main.h")]
+public enum PlayerID {
+    PLAYER1,
+  PLAYER2,
+  NOBODY
+}
+
+
+[CCode (cname = "LevelID", cprefix = "LEVEL_", cheader_filename="main.h")]
+public enum Level {
+   HUMAN,
+  WEAK,
+  MEDIUM,
+  STRONG
+}
+
+
+[CCode (cname = "int", cprefix="TILE_", has_type_id = false, cheader_filename="main.h")]
+public enum Tile {
+    PLAYER1,
+    PLAYER2,
+    CLEAR,
+    CLEAR_CURSOR,
+    PLAYER1_CURSOR,
+    PLAYER2_CURSOR,
+}
+
+[CCode (cname = "MoveID", cprefix = "MOVE_", cheader_filename="main.h")]
+public enum Move {
+  LEFT,
+  RIGHT,
+  DROP
+}
+
+void game_reset ();
+void process_move(int c);
+void gfx_refresh_pixmaps();
+bool gfx_load_pixmaps();
+void gfx_paint_tile(Cairo.Context cr, int r, int c);
+//void gfx_draw_grid(Cairo.Context c);
+//static void gfx_draw_all ();
+void gfx_free ();
+void scorebox_update ();       /* update visible player descriptions */
+void prompt_player ();
+void scorebox_reset ();
+string theme_get_title(int i);
+void on_dialog_close(int response_id);
+bool on_animate();
+//static void settings_changed_cb (string key);
+
+[CCode (cprefix = "", lower_case_prefix = "", cheader_filename = "config.h")]
+namespace Config {
+    [CCode (cname = "GETTEXT_PACKAGE")]
+    public const string GETTEXT_PACKAGE;
+}
+//[CCode(cname="GETTEXT_PACKAGE", cheader_filename="config.h,glib/gi18n-lib.h")]
+//extern const string GETTEXT_PACKAGE;
diff --git a/src/theme.h b/src/theme.h
index 2be0138..ab449e2 100644
--- a/src/theme.h
+++ b/src/theme.h
@@ -1,6 +1,8 @@
 /* theme.h */
+#ifndef THEME_H
+#define THEME_H
 
-
+#include "main.h"
 
 typedef struct _Theme Theme;
 struct _Theme {
@@ -21,3 +23,5 @@ const gchar *theme_get_player (PlayerID who);
 const gchar *theme_get_player_win (PlayerID who);
 const gchar *theme_get_player_turn (PlayerID who);
 const gchar *theme_get_title (gint id);
+
+#endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]