/* ai.c generated by valac 0.56.18, the Vala compiler
 * generated from ai.vala, do not modify */

/* -*- Mode: vala; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
   This file is part of GNOME Four-in-a-row.

   Copyright © 2014 Nikhar Agrawal

   GNOME 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 3 of the License, or
   (at your option) any later version.

   GNOME 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 GNOME Four-in-a-row.  If not, see <https://www.gnu.org/licenses/>.
*/

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

#define AI_POSITIVE_INFINITY ((gint16) 32000)
#define AI_NEGATIVE_INFINITY ((gint16) -32000)
#define AI_LESS_THAN_NEGATIVE_INFINITY ((gint16) -32001)
#define AI_MAX_HEURIST_VALUE ((gint16) 3200)
#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_MSC_VER)
#define VALA_EXTERN __declspec(dllexport) extern
#elif __GNUC__ >= 4
#define VALA_EXTERN __attribute__((visibility("default"))) extern
#else
#define VALA_EXTERN extern
#endif
#endif

typedef enum  {
	DIFFICULTY_EASY,
	DIFFICULTY_MEDIUM,
	DIFFICULTY_HARD
} Difficulty;

#define TYPE_DIFFICULTY (difficulty_get_type ())
typedef enum  {
	PLAYER_NOBODY,
	PLAYER_HUMAN,
	PLAYER_OPPONENT
} Player;

#define TYPE_PLAYER (player_get_type ())
#define _g_free0(var) (var = (g_free (var), NULL))

VALA_EXTERN GType difficulty_get_type (void) G_GNUC_CONST ;
VALA_EXTERN guint8 ai_playgame (guint8 size,
                    Difficulty level,
                    const gchar* vstr,
                    guint8 line);
VALA_EXTERN GType player_get_type (void) G_GNUC_CONST ;
VALA_EXTERN void ai_init_board_from_string (guint8 size,
                                const gchar* vstr,
                                Player** board,
                                gint* board_length1,
                                gint* board_length2);
VALA_EXTERN guint8 ai_immediate_win (Player player,
                         guint8 line,
                         Player** board,
                         gint* board_length1,
                         gint* board_length2);
VALA_EXTERN gint16 ai_negamax (guint8 height,
                   gint16 alpha,
                   gint16 beta,
                   Player player,
                   Difficulty level,
                   guint8 line,
                   Player** board,
                   gint* board_length1,
                   gint* board_length2,
                   guint8* next_move_in_column);
VALA_EXTERN guint8 ai_playandcheck (guint8 size,
                        Difficulty level,
                        const gchar* vstr,
                        guint8 line);
VALA_EXTERN void ai_update_board (const gchar* vstr,
                      Player** board,
                      gint* board_length1,
                      gint* board_length2);
VALA_EXTERN gboolean ai_board_full (Player** board,
                        gint* board_length1,
                        gint* board_length2);
VALA_EXTERN gint16 ai_heurist (Difficulty level,
                   guint8 line,
                   Player** board,
                   gint* board_length1,
                   gint* board_length2);
VALA_EXTERN gboolean ai_move (Player player,
                  guint8 column,
                  Player** board,
                  gint* board_length1,
                  gint* board_length2);
VALA_EXTERN gboolean ai_victory (Player player,
                     guint8 line,
                     guint8 column,
                     Player** board,
                     gint* board_length1,
                     gint* board_length2);
VALA_EXTERN void ai_unmove (guint8 column,
                Player** board,
                gint* board_length1,
                gint* board_length2);
VALA_EXTERN gboolean ai_vertical_win (Player player,
                          guint8 line,
                          guint8 i,
                          guint8 j,
                          Player** board,
                          gint* board_length1,
                          gint* board_length2);
VALA_EXTERN gboolean ai_horizontal_win (Player player,
                            guint8 line,
                            guint8 _i,
                            guint8 _j,
                            Player** board,
                            gint* board_length1,
                            gint* board_length2);
VALA_EXTERN gboolean ai_forward_diagonal_win (Player player,
                                  guint8 line,
                                  guint8 _i,
                                  guint8 _j,
                                  Player** board,
                                  gint* board_length1,
                                  gint* board_length2);
VALA_EXTERN gboolean ai_backward_diagonal_win (Player player,
                                   guint8 line,
                                   guint8 _i,
                                   guint8 _j,
                                   Player** board,
                                   gint* board_length1,
                                   gint* board_length2);
VALA_EXTERN gint16 ai_heurist_easy (guint8 line,
                        Player** board,
                        gint* board_length1,
                        gint* board_length2);
VALA_EXTERN gint16 ai_heurist_medium (void);
VALA_EXTERN gint16 ai_heurist_hard (guint8 line,
                        Player** board,
                        gint* board_length1,
                        gint* board_length2);
VALA_EXTERN gint8 ai_count_3_in_a_row (Player player,
                           guint8 line,
                           Player** board,
                           gint* board_length1,
                           gint* board_length2);
VALA_EXTERN gboolean ai_all_adjacent_empty (guint8 _i,
                                guint8 _j,
                                Player** board,
                                gint* board_length1,
                                gint* board_length2);

const guint8 AI_plies[3] = {(guint8) 4, (guint8) 7, (guint8) 7};

guint8
ai_playgame (guint8 size,
             Difficulty level,
             const gchar* vstr,
             guint8 line)
{
	Player* board = NULL;
	gint board_length1 = 0;
	gint board_length2 = 0;
	Player* _tmp0_ = NULL;
	gint _tmp1_ = 0;
	gint _tmp2_ = 0;
	guint8 temp = 0U;
	guint8 _tmp3_;
	guint8 _tmp4_;
	guint8 next_move_in_column = 0U;
	guint8 _tmp5_;
	guint8 result;
	g_return_val_if_fail (vstr != NULL, 0U);
	ai_init_board_from_string (size, vstr, &_tmp0_, &_tmp1_, &_tmp2_);
	board = (g_free (board), NULL);
	board = _tmp0_;
	board_length1 = _tmp1_;
	board_length2 = _tmp2_;
	_tmp3_ = ai_immediate_win (PLAYER_OPPONENT, line, &board, (gint*) (&board_length1), (gint*) (&board_length2));
	temp = _tmp3_;
	if (temp < size) {
		result = temp;
		board = (g_free (board), NULL);
		return result;
	}
	_tmp4_ = ai_immediate_win (PLAYER_HUMAN, line, &board, (gint*) (&board_length1), (gint*) (&board_length2));
	temp = _tmp4_;
	if (temp < size) {
		result = temp;
		board = (g_free (board), NULL);
		return result;
	}
	next_move_in_column = G_MAXUINT8;
	_tmp5_ = AI_plies[level];
	ai_negamax (_tmp5_, AI_NEGATIVE_INFINITY, AI_POSITIVE_INFINITY, PLAYER_OPPONENT, level, line, &board, (gint*) (&board_length1), (gint*) (&board_length2), &next_move_in_column);
	result = next_move_in_column;
	board = (g_free (board), NULL);
	return result;
}

guint8
ai_playandcheck (guint8 size,
                 Difficulty level,
                 const gchar* vstr,
                 guint8 line)
{
	Player* board = NULL;
	gint board_length1 = 0;
	gint board_length2 = 0;
	Player* _tmp0_ = NULL;
	gint _tmp1_ = 0;
	gint _tmp2_ = 0;
	guint8 temp = 0U;
	guint8 _tmp3_;
	guint8 _tmp4_;
	guint8 next_move_in_column = 0U;
	guint8 _tmp5_;
	guint8 result;
	g_return_val_if_fail (vstr != NULL, 0U);
	ai_init_board_from_string (size, vstr, &_tmp0_, &_tmp1_, &_tmp2_);
	board = (g_free (board), NULL);
	board = _tmp0_;
	board_length1 = _tmp1_;
	board_length2 = _tmp2_;
	_tmp3_ = ai_immediate_win (PLAYER_OPPONENT, line, &board, (gint*) (&board_length1), (gint*) (&board_length2));
	temp = _tmp3_;
	if (temp < size) {
		result = (guint8) 100;
		board = (g_free (board), NULL);
		return result;
	}
	_tmp4_ = ai_immediate_win (PLAYER_HUMAN, line, &board, (gint*) (&board_length1), (gint*) (&board_length2));
	temp = _tmp4_;
	if (temp < size) {
		result = temp;
		board = (g_free (board), NULL);
		return result;
	}
	next_move_in_column = G_MAXUINT8;
	_tmp5_ = AI_plies[level];
	ai_negamax (_tmp5_, AI_NEGATIVE_INFINITY, AI_POSITIVE_INFINITY, PLAYER_OPPONENT, level, line, &board, (gint*) (&board_length1), (gint*) (&board_length2), &next_move_in_column);
	result = next_move_in_column;
	board = (g_free (board), NULL);
	return result;
}

void
ai_init_board_from_string (guint8 size,
                           const gchar* vstr,
                           Player** board,
                           gint* board_length1,
                           gint* board_length2)
{
	Player* _vala_board = NULL;
	gint _vala_board_length1 = 0;
	gint _vala_board_length2 = 0;
	guint8 n_rows = 0U;
	guint8 n_cols = 0U;
	Player* _tmp0_;
	g_return_if_fail (vstr != NULL);
	n_rows = (guint8) (size - 1);
	n_cols = size;
	_tmp0_ = g_new0 (Player, n_rows * n_cols);
	_vala_board = (g_free (_vala_board), NULL);
	_vala_board = _tmp0_;
	_vala_board_length1 = n_rows;
	_vala_board_length2 = n_cols;
	{
		guint8 i = 0U;
		i = (guint8) 0;
		{
			gboolean _tmp1_ = FALSE;
			_tmp1_ = TRUE;
			while (TRUE) {
				if (!_tmp1_) {
					guint8 _tmp2_;
					_tmp2_ = i;
					i = _tmp2_ + 1;
				}
				_tmp1_ = FALSE;
				if (!(i < n_rows)) {
					break;
				}
				{
					guint8 j = 0U;
					j = (guint8) 0;
					{
						gboolean _tmp3_ = FALSE;
						_tmp3_ = TRUE;
						while (TRUE) {
							Player* _tmp5_;
							gint _tmp5__length1;
							gint _tmp5__length2;
							if (!_tmp3_) {
								guint8 _tmp4_;
								_tmp4_ = j;
								j = _tmp4_ + 1;
							}
							_tmp3_ = FALSE;
							if (!(j < n_cols)) {
								break;
							}
							_tmp5_ = _vala_board;
							_tmp5__length1 = _vala_board_length1;
							_tmp5__length2 = _vala_board_length2;
							_tmp5_[(i * _tmp5__length2) + j] = PLAYER_NOBODY;
						}
					}
				}
			}
		}
	}
	if (g_strcmp0 (vstr, "") == 0) {
		if (board) {
			*board = _vala_board;
		} else {
			_vala_board = (g_free (_vala_board), NULL);
		}
		if (board_length1) {
			*board_length1 = _vala_board_length1;
		}
		if (board_length2) {
			*board_length2 = _vala_board_length2;
		}
		return;
	}
	ai_update_board (vstr, &_vala_board, (gint*) (&_vala_board_length1), (gint*) (&_vala_board_length2));
	if (board) {
		*board = _vala_board;
	} else {
		_vala_board = (g_free (_vala_board), NULL);
	}
	if (board_length1) {
		*board_length1 = _vala_board_length1;
	}
	if (board_length2) {
		*board_length2 = _vala_board_length2;
	}
}

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

inline void
ai_update_board (const gchar* vstr,
                 Player** board,
                 gint* board_length1,
                 gint* board_length2)
{
	guint8 n_rows = 0U;
	gint _tmp0_;
	Player _tmp1_ = 0;
	gint _tmp2_;
	gint _tmp3_;
	Player move = 0;
	g_return_if_fail (vstr != NULL);
	_tmp0_ = *board_length1;
	n_rows = (guint8) _tmp0_;
	_tmp2_ = strlen (vstr);
	_tmp3_ = _tmp2_;
	if ((_tmp3_ % 2) == 0) {
		_tmp1_ = PLAYER_OPPONENT;
	} else {
		_tmp1_ = PLAYER_HUMAN;
	}
	move = _tmp1_;
	{
		guint8 i = 0U;
		i = (guint8) 0;
		{
			gboolean _tmp4_ = FALSE;
			_tmp4_ = TRUE;
			while (TRUE) {
				gint _tmp6_;
				gint _tmp7_;
				guint8 column = 0U;
				gchar* _tmp8_;
				gchar* _tmp9_;
				guint8 _tmp10_;
				gint8 row = 0;
				Player _tmp15_ = 0;
				if (!_tmp4_) {
					guint8 _tmp5_;
					_tmp5_ = i;
					i = _tmp5_ + 1;
				}
				_tmp4_ = FALSE;
				_tmp6_ = strlen (vstr);
				_tmp7_ = _tmp6_;
				if (!(((gint) i) < _tmp7_)) {
					break;
				}
				_tmp8_ = g_strdup_printf ("%c", string_get (vstr, (glong) i));
				_tmp9_ = _tmp8_;
				_tmp10_ = (guint8) (((guint8) atoi (_tmp9_)) - 1);
				_g_free0 (_tmp9_);
				column = _tmp10_;
				{
					gboolean _tmp11_ = FALSE;
					row = (gint8) (n_rows - 1);
					_tmp11_ = TRUE;
					while (TRUE) {
						gboolean _tmp13_ = FALSE;
						if (!_tmp11_) {
							gint8 _tmp12_;
							_tmp12_ = row;
							row = _tmp12_ - 1;
						}
						_tmp11_ = FALSE;
						if (((gint) row) >= 0) {
							Player _tmp14_;
							_tmp14_ = (*board)[(row * (*board_length2)) + column];
							_tmp13_ = _tmp14_ != PLAYER_NOBODY;
						} else {
							_tmp13_ = FALSE;
						}
						if (!_tmp13_) {
							break;
						}
					}
				}
				(*board)[(row * (*board_length2)) + column] = move;
				if (move == PLAYER_HUMAN) {
					_tmp15_ = PLAYER_OPPONENT;
				} else {
					_tmp15_ = PLAYER_HUMAN;
				}
				move = _tmp15_;
			}
		}
	}
}

gint16
ai_negamax (guint8 height,
            gint16 alpha,
            gint16 beta,
            Player player,
            Difficulty level,
            guint8 line,
            Player** board,
            gint* board_length1,
            gint* board_length2,
            guint8* next_move_in_column)
{
	guint8 n_cols = 0U;
	gint _tmp0_;
	gboolean _tmp1_ = FALSE;
	gint16 max = 0;
	guint8 next = 0U;
	guint8 _tmp12_;
	gint16 result;
	_tmp0_ = *board_length2;
	n_cols = (guint8) _tmp0_;
	if (((gint) height) == 0) {
		_tmp1_ = TRUE;
	} else {
		gboolean _tmp2_;
		_tmp2_ = ai_board_full (board, (gint*) (board_length1), (gint*) (board_length2));
		_tmp1_ = _tmp2_;
	}
	if (_tmp1_) {
		if (player == PLAYER_OPPONENT) {
			gint16 _tmp3_;
			_tmp3_ = ai_heurist (level, line, board, (gint*) (board_length1), (gint*) (board_length2));
			result = _tmp3_;
			return result;
		} else {
			if (player == PLAYER_HUMAN) {
				gint16 _tmp4_;
				_tmp4_ = ai_heurist (level, line, board, (gint*) (board_length1), (gint*) (board_length2));
				result = (gint16) (-1 * _tmp4_);
				return result;
			} else {
				g_assert_not_reached ();
			}
		}
	}
	max = AI_LESS_THAN_NEGATIVE_INFINITY;
	next = G_MAXUINT8;
	{
		guint8 column = 0U;
		column = (guint8) 0;
		{
			gboolean _tmp5_ = FALSE;
			_tmp5_ = TRUE;
			while (TRUE) {
				gboolean _tmp7_;
				gint16 _tmp8_ = 0;
				gboolean _tmp9_;
				gint16 temp = 0;
				if (!_tmp5_) {
					guint8 _tmp6_;
					_tmp6_ = column;
					column = _tmp6_ + 1;
				}
				_tmp5_ = FALSE;
				if (!(column < n_cols)) {
					break;
				}
				_tmp7_ = ai_move (player, column, board, (gint*) (board_length1), (gint*) (board_length2));
				if (!_tmp7_) {
					continue;
				}
				_tmp9_ = ai_victory (player, line, column, board, (gint*) (board_length1), (gint*) (board_length2));
				if (_tmp9_) {
					_tmp8_ = AI_MAX_HEURIST_VALUE * height;
				} else {
					Player _tmp10_ = 0;
					gint16 _tmp11_;
					if (player == PLAYER_OPPONENT) {
						_tmp10_ = PLAYER_HUMAN;
					} else {
						_tmp10_ = PLAYER_OPPONENT;
					}
					_tmp11_ = ai_negamax ((guint8) (height - 1), (gint16) (-1 * beta), (gint16) (-1 * alpha), _tmp10_, level, line, board, (gint*) (board_length1), (gint*) (board_length2), next_move_in_column);
					_tmp8_ = (gint16) (-1 * _tmp11_);
				}
				temp = _tmp8_;
				ai_unmove (column, board, (gint*) (board_length1), (gint*) (board_length2));
				if (temp > max) {
					next = column;
					max = temp;
				}
				if (temp > alpha) {
					alpha = temp;
				}
				if (alpha >= beta) {
					break;
				}
			}
		}
	}
	_tmp12_ = AI_plies[level];
	if (height == _tmp12_) {
		*next_move_in_column = next;
	}
	result = max;
	return result;
}

gboolean
ai_victory (Player player,
            guint8 line,
            guint8 column,
            Player** board,
            gint* board_length1,
            gint* board_length2)
{
	guint8 n_rows = 0U;
	gint _tmp0_;
	guint8 row = 0U;
	gboolean _tmp5_ = FALSE;
	gboolean _tmp6_ = FALSE;
	gboolean _tmp7_ = FALSE;
	gboolean _tmp8_;
	gboolean result;
	_tmp0_ = *board_length1;
	n_rows = (guint8) _tmp0_;
	{
		gboolean _tmp1_ = FALSE;
		row = (guint8) 0;
		_tmp1_ = TRUE;
		while (TRUE) {
			gboolean _tmp3_ = FALSE;
			if (!_tmp1_) {
				guint8 _tmp2_;
				_tmp2_ = row;
				row = _tmp2_ + 1;
			}
			_tmp1_ = FALSE;
			if (row < n_rows) {
				Player _tmp4_;
				_tmp4_ = (*board)[(row * (*board_length2)) + column];
				_tmp3_ = _tmp4_ == PLAYER_NOBODY;
			} else {
				_tmp3_ = FALSE;
			}
			if (!_tmp3_) {
				break;
			}
		}
	}
	_tmp8_ = ai_vertical_win (player, line, row, column, board, (gint*) (board_length1), (gint*) (board_length2));
	if (_tmp8_) {
		_tmp7_ = TRUE;
	} else {
		gboolean _tmp9_;
		_tmp9_ = ai_horizontal_win (player, line, row, column, board, (gint*) (board_length1), (gint*) (board_length2));
		_tmp7_ = _tmp9_;
	}
	if (_tmp7_) {
		_tmp6_ = TRUE;
	} else {
		gboolean _tmp10_;
		_tmp10_ = ai_forward_diagonal_win (player, line, row, column, board, (gint*) (board_length1), (gint*) (board_length2));
		_tmp6_ = _tmp10_;
	}
	if (_tmp6_) {
		_tmp5_ = TRUE;
	} else {
		gboolean _tmp11_;
		_tmp11_ = ai_backward_diagonal_win (player, line, row, column, board, (gint*) (board_length1), (gint*) (board_length2));
		_tmp5_ = _tmp11_;
	}
	result = _tmp5_;
	return result;
}

inline gboolean
ai_forward_diagonal_win (Player player,
                         guint8 line,
                         guint8 _i,
                         guint8 _j,
                         Player** board,
                         gint* board_length1,
                         gint* board_length2)
{
	guint8 n_rows = 0U;
	gint _tmp0_;
	guint8 n_cols = 0U;
	gint _tmp1_;
	gint8 i = 0;
	gint8 j = 0;
	guint8 count = 0U;
	gboolean result;
	_tmp0_ = *board_length1;
	n_rows = (guint8) _tmp0_;
	_tmp1_ = *board_length2;
	n_cols = (guint8) _tmp1_;
	i = (gint8) _i;
	j = (gint8) _j;
	count = (guint8) 0;
	{
		gint8 k = 0;
		gint8 l = 0;
		k = i;
		l = j;
		{
			gboolean _tmp2_ = FALSE;
			_tmp2_ = TRUE;
			while (TRUE) {
				gboolean _tmp6_ = FALSE;
				gboolean _tmp7_ = FALSE;
				if (!_tmp2_) {
					gint8 _tmp3_;
					gint8 _tmp4_;
					guint8 _tmp5_;
					_tmp3_ = k;
					k = _tmp3_ - 1;
					_tmp4_ = l;
					l = _tmp4_ + 1;
					_tmp5_ = count;
					count = _tmp5_ + 1;
				}
				_tmp2_ = FALSE;
				if (((gint) k) >= 0) {
					_tmp7_ = ((guint8) l) < n_cols;
				} else {
					_tmp7_ = FALSE;
				}
				if (_tmp7_) {
					Player _tmp8_;
					_tmp8_ = (*board)[(k * (*board_length2)) + l];
					_tmp6_ = _tmp8_ == player;
				} else {
					_tmp6_ = FALSE;
				}
				if (!_tmp6_) {
					break;
				}
			}
		}
	}
	{
		gint8 k = 0;
		gint8 l = 0;
		k = (gint8) (i + 1);
		l = (gint8) (j - 1);
		{
			gboolean _tmp9_ = FALSE;
			_tmp9_ = TRUE;
			while (TRUE) {
				gboolean _tmp13_ = FALSE;
				gboolean _tmp14_ = FALSE;
				if (!_tmp9_) {
					gint8 _tmp10_;
					gint8 _tmp11_;
					guint8 _tmp12_;
					_tmp10_ = k;
					k = _tmp10_ + 1;
					_tmp11_ = l;
					l = _tmp11_ - 1;
					_tmp12_ = count;
					count = _tmp12_ + 1;
				}
				_tmp9_ = FALSE;
				if (((guint8) k) < n_rows) {
					_tmp14_ = ((gint) l) >= 0;
				} else {
					_tmp14_ = FALSE;
				}
				if (_tmp14_) {
					Player _tmp15_;
					_tmp15_ = (*board)[(k * (*board_length2)) + l];
					_tmp13_ = _tmp15_ == player;
				} else {
					_tmp13_ = FALSE;
				}
				if (!_tmp13_) {
					break;
				}
			}
		}
	}
	result = count >= line;
	return result;
}

inline gboolean
ai_backward_diagonal_win (Player player,
                          guint8 line,
                          guint8 _i,
                          guint8 _j,
                          Player** board,
                          gint* board_length1,
                          gint* board_length2)
{
	guint8 n_rows = 0U;
	gint _tmp0_;
	guint8 n_cols = 0U;
	gint _tmp1_;
	gint8 i = 0;
	gint8 j = 0;
	guint8 count = 0U;
	gboolean result;
	_tmp0_ = *board_length1;
	n_rows = (guint8) _tmp0_;
	_tmp1_ = *board_length2;
	n_cols = (guint8) _tmp1_;
	i = (gint8) _i;
	j = (gint8) _j;
	count = (guint8) 0;
	{
		gint8 k = 0;
		gint8 l = 0;
		k = i;
		l = j;
		{
			gboolean _tmp2_ = FALSE;
			_tmp2_ = TRUE;
			while (TRUE) {
				gboolean _tmp6_ = FALSE;
				gboolean _tmp7_ = FALSE;
				if (!_tmp2_) {
					gint8 _tmp3_;
					gint8 _tmp4_;
					guint8 _tmp5_;
					_tmp3_ = k;
					k = _tmp3_ - 1;
					_tmp4_ = l;
					l = _tmp4_ - 1;
					_tmp5_ = count;
					count = _tmp5_ + 1;
				}
				_tmp2_ = FALSE;
				if (((gint) k) >= 0) {
					_tmp7_ = ((gint) l) >= 0;
				} else {
					_tmp7_ = FALSE;
				}
				if (_tmp7_) {
					Player _tmp8_;
					_tmp8_ = (*board)[(k * (*board_length2)) + l];
					_tmp6_ = _tmp8_ == player;
				} else {
					_tmp6_ = FALSE;
				}
				if (!_tmp6_) {
					break;
				}
			}
		}
	}
	{
		gint8 k = 0;
		gint8 l = 0;
		k = (gint8) (i + 1);
		l = (gint8) (j + 1);
		{
			gboolean _tmp9_ = FALSE;
			_tmp9_ = TRUE;
			while (TRUE) {
				gboolean _tmp13_ = FALSE;
				gboolean _tmp14_ = FALSE;
				if (!_tmp9_) {
					gint8 _tmp10_;
					gint8 _tmp11_;
					guint8 _tmp12_;
					_tmp10_ = k;
					k = _tmp10_ + 1;
					_tmp11_ = l;
					l = _tmp11_ + 1;
					_tmp12_ = count;
					count = _tmp12_ + 1;
				}
				_tmp9_ = FALSE;
				if (((guint8) k) < n_rows) {
					_tmp14_ = ((guint8) l) < n_cols;
				} else {
					_tmp14_ = FALSE;
				}
				if (_tmp14_) {
					Player _tmp15_;
					_tmp15_ = (*board)[(k * (*board_length2)) + l];
					_tmp13_ = _tmp15_ == player;
				} else {
					_tmp13_ = FALSE;
				}
				if (!_tmp13_) {
					break;
				}
			}
		}
	}
	result = count >= line;
	return result;
}

inline gboolean
ai_horizontal_win (Player player,
                   guint8 line,
                   guint8 _i,
                   guint8 _j,
                   Player** board,
                   gint* board_length1,
                   gint* board_length2)
{
	guint8 n_cols = 0U;
	gint _tmp0_;
	gint8 i = 0;
	gint8 j = 0;
	guint8 count = 0U;
	gboolean result;
	_tmp0_ = *board_length2;
	n_cols = (guint8) _tmp0_;
	i = (gint8) _i;
	j = (gint8) _j;
	count = (guint8) 0;
	{
		gint8 k = 0;
		k = j;
		{
			gboolean _tmp1_ = FALSE;
			_tmp1_ = TRUE;
			while (TRUE) {
				gboolean _tmp4_ = FALSE;
				if (!_tmp1_) {
					gint8 _tmp2_;
					guint8 _tmp3_;
					_tmp2_ = k;
					k = _tmp2_ - 1;
					_tmp3_ = count;
					count = _tmp3_ + 1;
				}
				_tmp1_ = FALSE;
				if (((gint) k) >= 0) {
					Player _tmp5_;
					_tmp5_ = (*board)[(i * (*board_length2)) + k];
					_tmp4_ = _tmp5_ == player;
				} else {
					_tmp4_ = FALSE;
				}
				if (!_tmp4_) {
					break;
				}
			}
		}
	}
	{
		gint8 k = 0;
		k = (gint8) (j + 1);
		{
			gboolean _tmp6_ = FALSE;
			_tmp6_ = TRUE;
			while (TRUE) {
				gboolean _tmp9_ = FALSE;
				if (!_tmp6_) {
					gint8 _tmp7_;
					guint8 _tmp8_;
					_tmp7_ = k;
					k = _tmp7_ + 1;
					_tmp8_ = count;
					count = _tmp8_ + 1;
				}
				_tmp6_ = FALSE;
				if (((guint8) k) < n_cols) {
					Player _tmp10_;
					_tmp10_ = (*board)[(i * (*board_length2)) + k];
					_tmp9_ = _tmp10_ == player;
				} else {
					_tmp9_ = FALSE;
				}
				if (!_tmp9_) {
					break;
				}
			}
		}
	}
	result = count >= line;
	return result;
}

inline gboolean
ai_vertical_win (Player player,
                 guint8 line,
                 guint8 i,
                 guint8 j,
                 Player** board,
                 gint* board_length1,
                 gint* board_length2)
{
	guint8 n_rows = 0U;
	gint _tmp0_;
	guint8 count = 0U;
	gboolean result;
	_tmp0_ = *board_length1;
	n_rows = (guint8) _tmp0_;
	count = (guint8) 0;
	{
		guint8 k = 0U;
		k = i;
		{
			gboolean _tmp1_ = FALSE;
			_tmp1_ = TRUE;
			while (TRUE) {
				gboolean _tmp4_ = FALSE;
				if (!_tmp1_) {
					guint8 _tmp2_;
					guint8 _tmp3_;
					_tmp2_ = k;
					k = _tmp2_ + 1;
					_tmp3_ = count;
					count = _tmp3_ + 1;
				}
				_tmp1_ = FALSE;
				if (k < n_rows) {
					Player _tmp5_;
					_tmp5_ = (*board)[(k * (*board_length2)) + j];
					_tmp4_ = _tmp5_ == player;
				} else {
					_tmp4_ = FALSE;
				}
				if (!_tmp4_) {
					break;
				}
			}
		}
	}
	result = count >= line;
	return result;
}

gboolean
ai_board_full (Player** board,
               gint* board_length1,
               gint* board_length2)
{
	guint8 n_cols = 0U;
	gint _tmp0_;
	gboolean result;
	_tmp0_ = *board_length2;
	n_cols = (guint8) _tmp0_;
	{
		guint8 i = 0U;
		i = (guint8) 0;
		{
			gboolean _tmp1_ = FALSE;
			_tmp1_ = TRUE;
			while (TRUE) {
				Player _tmp3_;
				if (!_tmp1_) {
					guint8 _tmp2_;
					_tmp2_ = i;
					i = _tmp2_ + 1;
				}
				_tmp1_ = FALSE;
				if (!(i < n_cols)) {
					break;
				}
				_tmp3_ = (*board)[(0 * (*board_length2)) + i];
				if (_tmp3_ == PLAYER_NOBODY) {
					result = FALSE;
					return result;
				}
			}
		}
	}
	result = TRUE;
	return result;
}

gboolean
ai_move (Player player,
         guint8 column,
         Player** board,
         gint* board_length1,
         gint* board_length2)
{
	guint8 n_rows = 0U;
	gint _tmp0_;
	gint8 row = 0;
	gboolean result;
	_tmp0_ = *board_length1;
	n_rows = (guint8) _tmp0_;
	{
		gboolean _tmp1_ = FALSE;
		row = (gint8) (n_rows - 1);
		_tmp1_ = TRUE;
		while (TRUE) {
			gboolean _tmp3_ = FALSE;
			if (!_tmp1_) {
				gint8 _tmp2_;
				_tmp2_ = row;
				row = _tmp2_ - 1;
			}
			_tmp1_ = FALSE;
			if (((gint) row) >= 0) {
				Player _tmp4_;
				_tmp4_ = (*board)[(row * (*board_length2)) + column];
				_tmp3_ = _tmp4_ != PLAYER_NOBODY;
			} else {
				_tmp3_ = FALSE;
			}
			if (!_tmp3_) {
				break;
			}
		}
	}
	if (((gint) row) < 0) {
		result = FALSE;
		return result;
	}
	(*board)[(row * (*board_length2)) + column] = player;
	result = TRUE;
	return result;
}

void
ai_unmove (guint8 column,
           Player** board,
           gint* board_length1,
           gint* board_length2)
{
	guint8 n_rows = 0U;
	gint _tmp0_;
	guint8 row = 0U;
	_tmp0_ = *board_length1;
	n_rows = (guint8) _tmp0_;
	{
		gboolean _tmp1_ = FALSE;
		row = (guint8) 0;
		_tmp1_ = TRUE;
		while (TRUE) {
			gboolean _tmp3_ = FALSE;
			if (!_tmp1_) {
				guint8 _tmp2_;
				_tmp2_ = row;
				row = _tmp2_ + 1;
			}
			_tmp1_ = FALSE;
			if (row < n_rows) {
				Player _tmp4_;
				_tmp4_ = (*board)[(row * (*board_length2)) + column];
				_tmp3_ = _tmp4_ == PLAYER_NOBODY;
			} else {
				_tmp3_ = FALSE;
			}
			if (!_tmp3_) {
				break;
			}
		}
	}
	(*board)[(row * (*board_length2)) + column] = PLAYER_NOBODY;
}

guint8
ai_immediate_win (Player player,
                  guint8 line,
                  Player** board,
                  gint* board_length1,
                  gint* board_length2)
{
	guint8 n_cols = 0U;
	gint _tmp0_;
	guint8 result;
	_tmp0_ = *board_length2;
	n_cols = (guint8) _tmp0_;
	{
		guint8 i = 0U;
		i = (guint8) 0;
		{
			gboolean _tmp1_ = FALSE;
			_tmp1_ = TRUE;
			while (TRUE) {
				gboolean _tmp3_;
				gboolean player_wins = FALSE;
				gboolean _tmp4_;
				if (!_tmp1_) {
					guint8 _tmp2_;
					_tmp2_ = i;
					i = _tmp2_ + 1;
				}
				_tmp1_ = FALSE;
				if (!(i < n_cols)) {
					break;
				}
				_tmp3_ = ai_move (player, i, board, (gint*) (board_length1), (gint*) (board_length2));
				if (!_tmp3_) {
					continue;
				}
				_tmp4_ = ai_victory (player, line, i, board, (gint*) (board_length1), (gint*) (board_length2));
				player_wins = _tmp4_;
				ai_unmove (i, board, (gint*) (board_length1), (gint*) (board_length2));
				if (player_wins) {
					result = i;
					return result;
				}
			}
		}
	}
	result = G_MAXUINT8;
	return result;
}

inline gint16
ai_heurist (Difficulty level,
            guint8 line,
            Player** board,
            gint* board_length1,
            gint* board_length2)
{
	gint16 result;
	switch (level) {
		case DIFFICULTY_EASY:
		{
			gint16 _tmp0_;
			_tmp0_ = ai_heurist_easy (line, board, (gint*) (board_length1), (gint*) (board_length2));
			result = _tmp0_;
			return result;
		}
		case DIFFICULTY_MEDIUM:
		{
			result = ai_heurist_medium ();
			return result;
		}
		case DIFFICULTY_HARD:
		{
			gint16 _tmp1_;
			_tmp1_ = ai_heurist_hard (line, board, (gint*) (board_length1), (gint*) (board_length2));
			result = _tmp1_;
			return result;
		}
		default:
		{
			g_assert_not_reached ();
		}
	}
}

gint16
ai_heurist_easy (guint8 line,
                 Player** board,
                 gint* board_length1,
                 gint* board_length2)
{
	gint16 _tmp0_;
	gint16 result;
	_tmp0_ = ai_heurist_hard (line, board, (gint*) (board_length1), (gint*) (board_length2));
	result = (gint16) (-1 * _tmp0_);
	return result;
}

inline gint16
ai_heurist_medium (void)
{
	gint16 result;
	result = (gint16) g_random_int_range ((gint32) 1, (gint32) 49);
	return result;
}

gint16
ai_heurist_hard (guint8 line,
                 Player** board,
                 gint* board_length1,
                 gint* board_length2)
{
	gint8 count = 0;
	gint8 _tmp0_;
	gint8 _tmp1_;
	gint16 _tmp2_ = 0;
	gint16 result;
	_tmp0_ = ai_count_3_in_a_row (PLAYER_OPPONENT, line, board, (gint*) (board_length1), (gint*) (board_length2));
	_tmp1_ = ai_count_3_in_a_row (PLAYER_HUMAN, line, board, (gint*) (board_length1), (gint*) (board_length2));
	count = _tmp0_ - _tmp1_;
	if (((gint) count) == 0) {
		_tmp2_ = (gint16) g_random_int_range ((gint32) 1, (gint32) 49);
	} else {
		_tmp2_ = (gint16) (((gint16) count) * 100);
	}
	result = _tmp2_;
	return result;
}

gint8
ai_count_3_in_a_row (Player player,
                     guint8 line,
                     Player** board,
                     gint* board_length1,
                     gint* board_length2)
{
	guint8 n_rows = 0U;
	gint _tmp0_;
	guint8 n_cols = 0U;
	gint _tmp1_;
	gint8 count = 0;
	gint8 result;
	_tmp0_ = *board_length1;
	n_rows = (guint8) _tmp0_;
	_tmp1_ = *board_length2;
	n_cols = (guint8) _tmp1_;
	count = (gint8) 0;
	{
		guint8 j = 0U;
		j = (guint8) 0;
		{
			gboolean _tmp2_ = FALSE;
			_tmp2_ = TRUE;
			while (TRUE) {
				if (!_tmp2_) {
					guint8 _tmp3_;
					_tmp3_ = j;
					j = _tmp3_ + 1;
				}
				_tmp2_ = FALSE;
				if (!(j < n_cols)) {
					break;
				}
				{
					guint8 i = 0U;
					i = (guint8) 0;
					{
						gboolean _tmp4_ = FALSE;
						_tmp4_ = TRUE;
						while (TRUE) {
							Player _tmp6_;
							gboolean _tmp7_;
							gboolean _tmp8_;
							if (!_tmp4_) {
								guint8 _tmp5_;
								_tmp5_ = i;
								i = _tmp5_ + 1;
							}
							_tmp4_ = FALSE;
							if (!(i < n_rows)) {
								break;
							}
							_tmp6_ = (*board)[(i * (*board_length2)) + j];
							if (_tmp6_ != PLAYER_NOBODY) {
								break;
							}
							_tmp7_ = ai_all_adjacent_empty (i, j, board, (gint*) (board_length1), (gint*) (board_length2));
							if (_tmp7_) {
								continue;
							}
							(*board)[(i * (*board_length2)) + j] = player;
							_tmp8_ = ai_victory (player, line, j, board, (gint*) (board_length1), (gint*) (board_length2));
							if (_tmp8_) {
								if (count < G_MAXINT8) {
									gint8 _tmp9_;
									_tmp9_ = count;
									count = _tmp9_ + 1;
								} else {
									g_warning ("ai.vala:393: Method count_3_in_a_row() exceeded its maximum count.");
								}
							}
							(*board)[(i * (*board_length2)) + j] = PLAYER_NOBODY;
						}
					}
				}
			}
		}
	}
	result = count;
	return result;
}

inline gboolean
ai_all_adjacent_empty (guint8 _i,
                       guint8 _j,
                       Player** board,
                       gint* board_length1,
                       gint* board_length2)
{
	guint8 n_rows = 0U;
	gint _tmp0_;
	guint8 n_cols = 0U;
	gint _tmp1_;
	gint8 i = 0;
	gint8 j = 0;
	gboolean result;
	_tmp0_ = *board_length1;
	n_rows = (guint8) _tmp0_;
	_tmp1_ = *board_length2;
	n_cols = (guint8) _tmp1_;
	i = (gint8) _i;
	j = (gint8) _j;
	{
		gint8 k = 0;
		k = (gint8) -1;
		{
			gboolean _tmp2_ = FALSE;
			_tmp2_ = TRUE;
			while (TRUE) {
				if (!_tmp2_) {
					gint8 _tmp3_;
					_tmp3_ = k;
					k = _tmp3_ + 1;
				}
				_tmp2_ = FALSE;
				if (!(((gint) k) <= 1)) {
					break;
				}
				{
					gint8 l = 0;
					l = (gint8) -1;
					{
						gboolean _tmp4_ = FALSE;
						_tmp4_ = TRUE;
						while (TRUE) {
							gboolean _tmp6_ = FALSE;
							gboolean _tmp7_ = FALSE;
							gboolean _tmp8_ = FALSE;
							gboolean _tmp9_ = FALSE;
							gboolean _tmp10_ = FALSE;
							if (!_tmp4_) {
								gint8 _tmp5_;
								_tmp5_ = l;
								l = _tmp5_ + 1;
							}
							_tmp4_ = FALSE;
							if (!(((gint) l) <= 1)) {
								break;
							}
							if (((gint) k) == 0) {
								_tmp6_ = ((gint) l) == 0;
							} else {
								_tmp6_ = FALSE;
							}
							if (_tmp6_) {
								continue;
							}
							if (((gint) (i + k)) >= 0) {
								_tmp10_ = ((guint8) (i + k)) < n_rows;
							} else {
								_tmp10_ = FALSE;
							}
							if (_tmp10_) {
								_tmp9_ = ((gint) (j + l)) >= 0;
							} else {
								_tmp9_ = FALSE;
							}
							if (_tmp9_) {
								_tmp8_ = ((guint8) (j + l)) < n_cols;
							} else {
								_tmp8_ = FALSE;
							}
							if (_tmp8_) {
								Player _tmp11_;
								_tmp11_ = (*board)[((i + k) * (*board_length2)) + (j + l)];
								_tmp7_ = _tmp11_ != PLAYER_NOBODY;
							} else {
								_tmp7_ = FALSE;
							}
							if (_tmp7_) {
								result = FALSE;
								return result;
							}
						}
					}
				}
			}
		}
	}
	result = TRUE;
	return result;
}

