#Include "XO.bi"

'Функция вычисления, не закончена ли игра

Function XO.end_analyze() As Integer Export

	'Проход по всему полю (расчет ведется для каждой клетки)

	for i As Integer=0 To size_x

		for j As Integer=0 To size_y

			'Пропускаем пустую клетку

			if fields(i,j)=0 Then Continue For

			Dim As Integer tek = fields(i,j) 'Значение текущей клетки

			Dim As Integer EndRyad 'Текущая длина ряда

			Dim As Integer u 'Доп. счетчик

			'Смотрим вправо от текущей клетки

			for k As Integer= j To j+5

				if k = size_y or fields(i,k) <> tek Then Exit For 'Нет ряда из 5

				EndRyad+=1

			Next

			if EndRyad = 5 Then

				'Есть ряд из 5 - конец игры

				For k As Integer = j To j+4

					SetGadgetColor(k*(size_x+1)+i+1,0,255,2)

				Next

				flag=1

				return 1

			EndIf



			'Смотрим вниз и вправо от текущей клетки

			EndRyad = 0

			u=i

			for k As Integer = j To j+4

				if k = size_y or u=size_x or fields(u,k) <> tek Then Exit For 'Нет ряда из 5

				EndRyad+=1

				u+=1

			Next

			if EndRyad = 5 Then

				'Есть ряд из 5 - конец игры

				u=i

				for k As Integer = j To j+4

					SetGadgetColor(k*(size_x+1)+u+1,0,255,2)

					u+=1

				Next

				flag=1

				return 1

			EndIf

			'Смотрим вниз и влево от текущей клетки

			EndRyad = 0

			u=i

			for k as Integer= j to j-4 Step -1

				if k = -1 or u=size_x or fields(u,k) <> tek Then Exit For 'Нет ряда из 5


				EndRyad+=1

				u+=1

			Next

			if EndRyad = 5 Then

				'Есть ряд из 5 - конец игры

				u=i

				For k As Integer = j To j-4 step -1

					SetGadgetColor(k*(size_x+1)+u+1,0,255,2)

					u+=1

				Next

				flag=1

				Return 1

			EndIf

			'Смотрим вниз от текущей клетки

			EndRyad = 0

			For k As Integer = i To i+4

				if k = size_x or fields(k,j) <> tek Then Exit For 'Нет ряда из 5

				EndRyad+=1

			Next

			if EndRyad = 5 Then 'Есть ряд из 5 - конец игры

				for k As Integer= i To i+4

					SetGadgetColor(j*(size_x+1)+k+1,0,255,2)

				Next

				flag=1

				return 1

			EndIf

		Next

	Next

	'Игра не окончена

	return 0

End Function

'Функция расчета оценочной функции

Function XO.calculate (id As Integer,x As Integer,y As Integer) As UInteger Export

	'Подсчет оценочной функции

	'Ставим в массиве временно значение == id

	fields(x,y) = id

	Dim As Integer series_length 'Текущая длина ряда

	Dim As Uinteger sum 'Общее значение оценочной функции

	''''''''''Расчет сверху вниз'''''''''''

	'Проход по каждой клетки, которая может входить в ряд

	for i As Integer= 0 To 4

		'Проверка, не вышли ли за границы поля

		if (x-4+i) < 0 Then Continue For

		if (x+i) > (size_x) Then Exit For

		'Проход по всем возможным рядам, отстоящим от клетки не более чем на 5

		for j As Integer=0 To 4

			if fields(x-4+i+j,y) <> id And fields(x-4+i+j,y) <> 0 then

				'Конец ряда

				series_length = 0

				Exit For

			EndIf

			if fields(x-4+i+j,y) <> 0 then series_length+=1 'Ряд увеличивается

		Next

		if series_length = 1 Then series_length = 0 'Ряд из самой клетки не учитываем

		if series_length = 5 Then series_length = 100 'Выигрышная ситуация, ставим большое значение

		'Плюсуем серию к общей сумме

		Dim As Uinteger pow_st = valuation_factor

		if series_length = 100 Then

			if id = 2 then

				pow_st = 10000 'Большое значение при своем выигрыше

			else

				pow_st = 1000 'Большое значение при выигрыше соперника, но меньшее, чем при своем

			EndIf

		Else

			for i As Integer=0 To series_length-1 'Возводим оценочный коэффициент в степень длины серии

				pow_st*=valuation_factor

			Next

		EndIf

		sum += pow_st

		series_length = 0

	Next

	''''''''''''''Расчет слева направо'''''''''''''''
	'Проход по каждой клетки, которая может входить в ряд

	For i As Integer = 0 To 4

		'Проверка, не вышли ли за границы поля

		if (y-4+i) < 0 then Continue For

		if (y+i) > (size_y) then Exit For

		'Проход по всем возможным рядам, отстоящим от клетки не более чем на 5

		For j As Integer=0 To 4

			if fields(x,y-4+i+j) <> id and fields(x,y-4+i+j) <> 0 then

				'Конец ряда

				series_length = 0

				Exit For

			EndIf

			if fields(x,y-4+i+j)<> 0 Then series_length+=1 'Ряд увеличивается

		next

		If series_length = 1 Then series_length = 0 'Ряд из самой клетки не учитываем

		If series_length = 5 Then series_length = 100 'Выигрышная ситуация, ставим большое значение

		'Плюсуем серию к общей сумме

		Dim As UInteger pow_st = valuation_factor

		if series_length = 100 Then

			if id = 2 Then

				pow_st = 10000 'Большое значение при своем выигрыше

			Else

				pow_st = 1000 'Большое значение при выигрыше соперника, но меньшее, чем при своем

			EndIf

		Else

			for  i As Integer=0 To series_length-1 'Возводим оценочный коэффициент в степень длины серии

				pow_st*=valuation_factor

			Next

		EndIf

		sum += pow_st

		series_length = 0

	Next

	''''''''''''Расчет по диагонали с левого верхнего''''''''''''

	'Проход по каждой клетки, которая может входить в ряд

	for i As Integer = 0 To 4

		'Проверка, не вышли ли за границы поля

		if (y-4+i) < 0 Then Continue For

		if (x-4+i) < 0 Then Continue For

		if (x+i) > (size_x) Then Exit For

		if (y+i) > (size_y) Then Exit For

		'Проход по всем возможным рядам, отстоящим от клетки не более чем на 5

		For j As Integer=0 To 4

			If fields(x-4+i+j,y-4+i+j) <> id and fields(x-4+i+j,y-4+i+j) <> 0 Then

				'Конец ряда

				series_length = 0

				Exit For

			EndIf

			If fields(x-4+i+j,y-4+i+j) <> 0 Then series_length+=1 'Ряд увеличивается

		Next

		if series_length = 1 Then series_length = 0 'Ряд из самой клетки не учитываем

		if series_length = 5 Then series_length = 100 'Выигрышная ситуация, ставим большое значение

		'Плюсуем серию к общей сумме

		Dim As UInteger pow_st = valuation_factor

		if series_length = 100 Then

			if id = 2 Then

				pow_st = 10000 'Большое значение при своем выигрыше

			Else

				pow_st = 1000 'Большое значение при выигрыше соперника, но меньшее, чем при своем

			EndIf

		Else

			for i As Integer=0 To series_length-1 'Возводим оценочный коэффициент в степень длины серии

				pow_st*=valuation_factor

			Next

		EndIf

		sum += pow_st

		series_length = 0

	Next

	''''''''''Расчет по диагонали с левого нижнего'''''''''''''

	'Проход по каждой клетки, которая может входить в ряд

	For i As Integer=0 To 4

		'Проверка, не вышли ли за границы поля

		if (y-4+i) < 0 Then Continue For

		if (x+4-i) > (size_x) Then Continue for

		if (x-i) < 0 then Exit For

		if (y+i) > (size_y) then Exit for

		'Проход по всем возможным рядам, отстоящим от клетки не более чем на 5

		for j As Integer=0 To 4

			if fields(x+4-i-j,y-4+i+j) <> id and fields(x+4-i-j,y-4+i+j) <> 0 Then

				'Конец ряда

				series_length = 0

				Exit For

			EndIf

			If fields(x+4-i-j,y-4+i+j) <> 0 Then series_length+=1 'Ряд увеличивается

		Next

		if series_length = 1 Then series_length = 0 'Ряд из самой клетки не учитываем

		if series_length = 5 Then series_length = 100 'Выигрышная ситуация, ставим большое значение

		'Плюсуем серию к общей сумме

		Dim As UInteger pow_st = valuation_factor

		if series_length = 100 Then

			if id = 2 Then

				pow_st = 10000 'Большое значение при своем выигрыше

			Else

				pow_st = 1000 'Большое значение при выигрыше соперника, но меньшее, чем при своем

			EndIf

		Else

			for i As Integer=0 To series_length-1 'Возводим оценочный коэффициент в степень длины серии

				pow_st*=valuation_factor

			Next

		EndIf

		sum += pow_st

		series_length = 0

	Next

	'Возвращаем исходное значение

	fields(x,y) = 0

	Return sum

End Function

'Функция расчета действий компьютера

Sub XO.ii() Export

	Dim As Single max = -1 'Максимальное значение оценочной функции

	Dim As Integer cur_x , cur_y 'Текущие x и у

	Dim As Integer povtor_num 'Количество повторов одинаковых значений оценочной функции

	Dim As Integer cur_povtor 'Номер текущего повтора

	'Расчитываем оценочную функцию для всех клеток

	for i As Integer = 0 to size_x

		for j As Integer = 0 To size_y

			if fields(i,j) = 0 Then

				'Расчет оценочной функции

				calc_fields(i,j) = calculate(2,i,j) + calculate(1,i,j)* Cast(Single,attack_factor)

				'Берем в расчет уровень (для профессионала случайности нет)

				if comp_level = 1  Then 'Для любителя (небольшая случайность)

					calc_fields(i,j) = calc_fields(i,j) * (1 + Rnd * 32767 / 32767) / 2

				EndIf

				if comp_level = 2 Then 'Для новичка (максимальная случайность)

					calc_fields(i,j) = calc_fields(i,j) * (Rnd * 32767 / 32767)

				EndIf

				if calc_fields(i,j) = max Then

					'Еще одна клетка с максимальным значением оценочной функции

					povtor_num+=1

				EndIf

				If calc_fields(i,j) > max Then

					'Клетка с максимальным значением оценочной функции

					max = calc_fields(i,j)

					povtor_num = 0

					cur_x = i

					cur_y = j

				EndIf

			EndIf

		Next

	Next

	'Проверяем, есть ли вообще свободные клетки на поле

	if max = -1 then

		exit sub

	endif

	'Выбираем куда сделать ход

	if povtor_num > 0 Then

		'Выбираем куда ходить случайным образом из клеток с одинаковыми значениями оценочной функции

		cur_povtor = Rnd*32767 \ (32767 \ povtor_num) 'Номер элемента, куда надо ходить

		'Ищем его по полю

		Dim As Integer buf_povtor = -1

		for i As Integer=0 To size_x

			for j As Integer=0 To size_y

				if calc_fields(i,j) = max then

					buf_povtor+=1

					if buf_povtor = cur_povtor Then 'Клетка найдена


						fields(i,j) = 2 'Ставим крестик

						SetGadgetColor(last_y*(size_x+1)+last_x+1,0,0,2)

						last_x = i 'Запоминаем координаты последнего хода

						last_y = j

						SetGadgetColor(last_y*(size_x+1)+last_x+1,0,&hff0000,2)

						SetGadgetText(j*(size_x+1)+i+1,"O")

						If end_analyze() Then Beep

						Exit Sub

					EndIf

				EndIf

			Next

		Next

	Else

		'Одна клетка с максимальным значением

		fields(cur_x,cur_y) = 2 'Ставим крестик

		SetGadgetColor(last_y*(size_x+1)+last_x+1,0,0,2)

		last_x = cur_x 'Запоминаем координаты последнего хода

		last_y = cur_y

		SetGadgetText(cur_y*(size_x+1)+cur_x+1,"O")

		SetGadgetColor(cur_y*(size_x+1)+cur_x+1,0,&hff0000,2)

		If end_analyze() Then Beep

	EndIf

end Sub

