#include "ThoughtGo.h"
#include "MT.h"

using namespace std;

int  m_playout_try = 5000;
int  m_ko_pos = 0;
int  m_playout_hands = 19 * 19 * 2;   /* プレイアウト処理の最大手数 */
int  m_dir4[4] = { 1,-1,999,-999 }; /* 右左下上の隣接位置の４つの加算値 */
								  /* (999 と -999 はサイズ決定後に書替え) */
int  m_pure_board_size = PURE_BOARD_SIZE;  // 盤の辺の大きさ  
int  m_pos_array[(19 + 2)*(19 + 2)];
char m_check_base[(19 + 2)*(19 + 2)]; /* 各位置のチェック状態初期値 */
double m_komi = 6.5;
node *m_que = NULL;
node *m_root = NULL;

/* プレイアウト数の設定 */
void SetPlayoutX(int in_playout)
{
	m_playout_try = in_playout;
}
/* 使用する盤の路数の設定・盤面をクリアする */
void SetBoardSizeX(int size)
{
	m_pure_board_size = size;
	/* プレイアウト処理の最大手数設定 */
	m_playout_hands = size * size * 4;
	/* 隣接位置情報設定 */
	m_dir4[2] = size + 2;
	m_dir4[3] = (-1) * size - 2;
	ClearBoardX();
}
/* 盤面をクリアする */
void ClearBoardX()
{
	int i;
	m_ko_pos = 0;
	node *work;
	/* 確保済メモリを解放 */
	while (m_que != NULL) {
		work = m_que->next;
		free(m_que);
		m_que = work;
	}
	/* 各位置のチェック状態をチェック前として初期化 */
	memset(m_check_base, '\0', (m_pure_board_size + 2) * (m_pure_board_size + 2));
	memset(m_pos_array, '\0', (m_pure_board_size + 2) * (m_pure_board_size + 2));
	/* 碁盤の外周(横方向の先頭と最終)をチェック済とする  */
	for (i = 0; i < (m_pure_board_size + 2); i++) {
		m_check_base[i] = 1;
		m_check_base[i + (m_pure_board_size + 2) * (m_pure_board_size + 1)] = 1;
		m_pos_array[i] = SENTINEL;
		m_pos_array[i + (m_pure_board_size + 2) * (m_pure_board_size + 1)] = SENTINEL;
	}
	/* 碁盤の外周(縦方向の先頭と最終)をチェック済とする  */
	for (i = 1; i < (m_pure_board_size + 1); i++) {
		m_check_base[(m_pure_board_size + 2) * i] = 1;
		m_check_base[m_pure_board_size + 1 + (m_pure_board_size + 2) * i] = 1;
		m_pos_array[(m_pure_board_size + 2) * i] = SENTINEL;
		m_pos_array[m_pure_board_size + 1 + (m_pure_board_size + 2) * i] = SENTINEL;
	}
}
/* コミを設定する */
void SetKomiX(double new_komi)
{
	m_komi = new_komi;
}
/* 指定した色を指定した座標に着手する */
void PutStoneX(int pos, int color)
{
	//printf("pos:%d color:%d\n",pos,color);
	verify_legal(pos, color, m_pos_array, &m_ko_pos, 2);
	//for(int i=0;i<(m_pure_board_size+2)*(m_pure_board_size+2);i++)
	//printf("%d,",m_pos_array[i]);
	//printf("\n");
}
/* 指定した色の最良手を生成し着手する */
int UctSearchX(int color)
{
	int i, j, rtn;
	int posl[(19 + 2)*(19 + 2)];
	int playout_max, win_max;
	int best_pos;
	int rate_min, rate_max;
	node *work;

	/* 乱数シード値設定 */
	init_genrand((unsigned)time(NULL));
	/* ルートノード作成(ひとつ) */
	m_que = NULL;
	m_root = make_uct();
	if (m_root == NULL) return 0; /* メモリ不足 */
								/* 子ノード作成(全着手可能な位置分) */
	if (expand_node(m_root, m_pos_array, m_ko_pos) != 0) {
		free(m_root);
		return 0; /* メモリ不足 */
	}
	/* プレイアウト数分UCT探索を繰り返す */
	for (int i = 0; i<m_playout_try; i++) {
		/* 盤上の現在の碁石の配置を作業用のエリアにコピー */
		memcpy(posl, m_pos_array, sizeof(posl[0])*(m_pure_board_size + 2)*(m_pure_board_size + 2));
		/* 子ノード(UCT)探索 */
		if ((rtn = search_uct(m_root, color, m_pure_board_size, posl)) < 0) {
			/* 置ける場所がないかメモリ不足なら確保済メモリを解放 */
			while (1) {
				work = m_que->next;
				free(m_que);
				if (work == NULL) break;
				m_que = work;
			}
			if (rtn == -1) return  0; /* 置ける場所がない */
			else          return -9; /* メモリ不足 */
		}
	}
	/* 候補手を決定する */
	playout_max = -999;
	win_max = 0;
	rate_min = 1;
	rate_max = 0;
	best_pos = 0;
	/* １層目の子ノードを調べる */
	for (i = 0, j = 0; j < m_root->child_num; i++) {
		if (m_root->child[i] == NULL) continue;
		j++;
		if (verify_legal(m_root->child[i]->pos, color, m_pos_array, &m_ko_pos, 0) == 0)
			/* 置けない石はないはずだが念のためチェックアウト */
			continue;
		if (color == BLACK) {
			/* 現在の手番が黒石のときの処理 */
			/* プレイアウト回数の多いものを候補手とする */
			if (m_root->child[i]->playout_sum > playout_max) {
				best_pos = m_root->child[i]->pos;
				playout_max = m_root->child[i]->playout_sum;
				win_max = m_root->child[i]->win_black;
			}
			/* プレイアウト回数が同じなら勝利数の多いものを候補手とする */
			else if (m_root->child[i]->playout_sum == playout_max) {
				if (m_root->child[i]->win_black > win_max) {
					best_pos = m_root->child[i]->pos;
					win_max = m_root->child[i]->win_black;
				}
			}
			/* 最小勝率 100% 未満はあるか? */
			if (rate_min == 1) {
				if (m_root->child[i]->win_black < m_root->child[i]->playout_sum)
					rate_min = 0;
			}
			/* 最大勝率 0% 以外はあるか? */
			if (rate_max == 0) {
				if (m_root->child[i]->win_black > 0)
					rate_max = 1;
			}
		}
		else {
			/* 現在の手番が白石のときの処理 */
			/* プレイアウト回数の多いものを候補手とする */
			if (m_root->child[i]->playout_sum > playout_max)
			{
				best_pos = m_root->child[i]->pos;
				playout_max = m_root->child[i]->playout_sum;
				win_max = m_root->child[i]->win_white;
			}
			/* プレイアウト回数が同じなら勝利数の多いものを候補手とする */
			else if (m_root->child[i]->playout_sum == playout_max) {
				if (m_root->child[i]->win_white > win_max) {
					best_pos = m_root->child[i]->pos;
					win_max = m_root->child[i]->win_white;
				}
			}
			/* 最小勝率 100% 未満はあるか? */
			if (rate_min == 1) {
				if (m_root->child[i]->win_white < m_root->child[i]->playout_sum)
					rate_min = 0;
			}
			/* 最大勝率 0% 以外はあるか? */
			if (rate_max == 0) {
				if (m_root->child[i]->win_white > 0)
					rate_max = 1;
			}
		}
	}
/*
	FILE *fp;
	fopen_s(&fp, "debug.txt", "a+");
//	if (best_pos == 0 || rate_min == 1 || rate_max == 0) {
		for (i = 0, j = 0; j < m_root->child_num; i++) {
			if (m_root->child[i] == NULL) continue;
			j++;
			fprintf(fp, "%d %d %d %d\n",
				m_root->child[i]->pos,
				m_root->child[i]->win_black,
				m_root->child[i]->win_white,
				m_root->child[i]->playout_sum);
		}
//	}
	fclose(fp);
*/
	/* 確保済メモリを解放 */
	while (1) {
		work = m_que->next;
		free(m_que);
		if (work == NULL) break;
		m_que = work;
	}
	/* 候補手(盤上の碁石の位置)を返却 */
	if (best_pos == 0) {       /* 置ける場所がない */
		return 0;
	}
	else if (rate_min == 1) { /* 勝利 */
		return best_pos;
		//		*x = 0;
		//		if(color == BLACK) *y = 1; /* 黒の勝ち */
		//		else               *y = 2; /* 白の勝ち */
	}
	else if (rate_max == 0) { /* 敗北 */
		return best_pos;
		//		*x = 0;
		//		if(color == BLACK) *y = 2; /* 白の勝ち */
		//		else               *y = 1; /* 黒の勝ち */
		//	}else{
		//		*x = best_pos % (size+2);
		//		*y = best_pos / (size+2);
	}
	return best_pos;
}
/* 終局した対局のスコアを計算する */
int UctAnalyzeX(int color)
{
	return 0;
}
/* ノード(UCT)領域確保 */
/*   引数:メモリ解放用の先頭キューノード,碁盤サイズ(9,13,19) */
/*   戻値:着手位置管理ノード(UCT) */
node* make_uct()
{
	node *uct, *work;
	/* メモリ確保 */
	if ((uct = (node *)
		malloc(sizeof(node)
			+ sizeof(uct->child)*(m_pure_board_size*m_pure_board_size - 1))) == NULL)
		return(NULL); /* メモリ不足 */
					  /* メモリクリア */
	memset(uct, '\0', sizeof(node)
		+ sizeof(uct->child)*(m_pure_board_size*m_pure_board_size - 1));
	/* メモリ解放用にノードキュー先頭にエンキュー */
	work = m_que;
	m_que = uct;
	uct->next = work;
	return uct;
}
/* 探索子ノード(UCT)作成 */
/*   引数:メモリ解放用の先頭キューノード,親ノード,碁盤サイズ(9,13,19),現碁盤配置,現劫位置 */
/*   戻値:0(正常) -9(メモリ不足) */
int expand_node(node* parent, int *posl, int ko)
{
	for (int pos = 0; pos<m_pure_board_size*m_pure_board_size; pos++) {
		/* 劫以外の空き位置(最大19×19=361)分、子ノードを作成 */
		if (posl[(pos + m_pure_board_size) / m_pure_board_size * (m_pure_board_size + 2)
			+ 1 + pos % m_pure_board_size] == SPACE
			&& (pos + m_pure_board_size) / m_pure_board_size * (m_pure_board_size + 2)
			+ 1 + pos % m_pure_board_size != ko) {
			parent->child[pos] = make_uct();
			if (parent->child[pos] == NULL) return(-9); /* メモリ不足 */
														/* 親ノードを更新 */
			parent->child_num++; /* 子ノード数 */
								 /* 子ノードを更新 */
			parent->child[pos]->pos = (pos + m_pure_board_size) / m_pure_board_size * (m_pure_board_size + 2)
				+ 1 + pos % m_pure_board_size; /* 盤上の位置 */
			parent->child[pos]->parent = parent; /* 親ノードのアドレス */
		}
	}
	return(0);
}
/* 子ノード(UCT)探索 */
/*   引数:メモリ解放用の先頭キューノード,親ノード,現手番の色,碁盤サイズ(9,13,19),現碁盤配置 */
/*   戻値:0(正常) -1(置ける場所がない) -9(メモリ不足) */
int search_uct(node *my_node, int color, int size, int *posl)
{
	int i, j, tmp_ko_pos, select_i;
	int score;
	double ucb, max_ucb;
	node *select_node;
	node *parent_node;

	tmp_ko_pos = 0;
	select_node = NULL;
	/* 子ノード検索 */
	while (my_node->child_num > 0) {
		max_ucb = -999;
		select_i = 0;
		select_node = NULL;
		/* 子ノード選択 */
		for (i = 0, j = 0; j<my_node->child_num; i++) {
			if (my_node->child[i] == NULL) continue;
			j++;
			/* UCB(Upper Confidence Bound)判定 */
			if (my_node->child[i]->playout_sum == 0) {
				/* プレイアウト未のノードを優先するよう適当な値を設定 */
				ucb = genrand_int32();
			}
			else {
				/* プレイアウト済なら UCB を算出 */
				if (color == BLACK)
					ucb = (double)(my_node->child[i]->win_black)
					/ (double)(my_node->child[i]->playout_sum)
					+ C *
					sqrt(2.0 * (double)log(my_node->child[i]->parent->playout_sum)
						/ (double)my_node->child[i]->playout_sum);
				else
					ucb = (double)(my_node->child[i]->win_white)
					/ (double)(my_node->child[i]->playout_sum)
					+ C *
					sqrt(2.0 * (double)log(my_node->child[i]->parent->playout_sum)
						/ (double)my_node->child[i]->playout_sum);
			}
			/* UCB の大きいノードを候補手とする */
			if (ucb > max_ucb) {
				max_ucb = ucb;
				select_i = i;
				select_node = my_node->child[i];
			}
		}
		/* 候補手がなければ検索は終了(置ける場所がない) */
		if (select_node == NULL) return(-1);
		/* 碁石が打てれば子ノード検索は終了 */
		if (verify_legal(select_node->pos, color, posl, &tmp_ko_pos, 1))
			break;
		/* 碁石が打てない子ノードは選択候補からはずし再選択 */
		my_node->child_num--;
		my_node->child[select_i] = NULL;
	}
	/* 選択ノードがなければ検索は終了(置ける場所がない) */
	if (select_node == NULL) return(-1);
	/* 選択ノードのプレイアウト回数判定 */
	if (select_node->playout_sum < THRESHOLD) {
		/* 選択ノードのプレイアウト回数が閾値未満はプレイアウト処理 */
		score = playout((-1)*color, size, posl, tmp_ko_pos);
		/* 選択ノードのプレイアウト回数更新 */
		select_node->playout_sum += 1;
		if (score > 0) {
			/* 黒石の勝ちなら選択ノードの黒石勝利数更新 */
			select_node->win_black++;
			/* 親ノード更新(逆伝播) */
			while (select_node->parent != NULL) {
				parent_node = select_node->parent;
				parent_node->win_black++;      /* 黒石勝利数 */
				parent_node->playout_sum += 1; /* プレイアウト回数 */
				select_node = parent_node;
			}
		}
		else {
			/* 白石の勝ちなら選択ノードの白石勝利数更新 */
			select_node->win_white++;
			/* 親ノード更新(逆伝播) */
			while (select_node->parent != NULL) {
				parent_node = select_node->parent;
				parent_node->win_white++;      /* 白石勝利数 */
				parent_node->playout_sum += 1; /* プレイアウト回数 */
				select_node = parent_node;
			}
		}
		return(0);
	}
	else {
		/* 選択ノードのプレイアウト回数が閾値になったら */
		if (select_node->child_num == 0) {
			/* 子ノード作成 */
			if (expand_node(select_node, posl, tmp_ko_pos) != 0)
				return(-9); /* メモリ不足 */
		}
		/* 子ノード(UCT)探索(再帰処理) */
		if (search_uct(select_node, (-1)*color, size, posl) == -9)
			return(-9); /* メモリ不足 */
	}
	return(0);
}
/* プレイアウト処理 */
/*   引数:現手番の色,碁盤サイズ(9,13,19),現碁盤配置,現劫位置 */
/*   戻値:黒の地の数 - コミ */
int playout(int color, int size, int *posl, int ko_pos)
{
	int  i, j, jp, jr, selected, rand_pos;
	int  win, color_tmp, pre_pos;
	int  possibles[19 * 19 + 1];
	int  stone_num[3], neighbor_num[5];
	int  score;

	win = 1;
	color_tmp = color;
	pre_pos = -1;
	/* 黒白交互にランダム着手 */
	for (i = 0; i<m_playout_hands; i++) {
		/* 盤上の現在の碁石の配置より着手位置候補を抽出 */
		memset(possibles, '\0', sizeof(possibles));
		for (j = size + 3, jp = 0; j<(size + 2)*(size + 1) - 1; j++) {
			if (posl[j] == SPACE && j != ko_pos) {
				/* 劫でない空きなら候補位置に追加 */
				possibles[jp] = j;
				jp++;
			}
		}
		/* 石が打てるまで候補位置で着手をトライ */
		while (1) {
			if (jp == 0) {
				/* 着手位置候補がなければ着手断念 */
				selected = 0;
				break;
			}
			else {
				/* ランダムな着手位置候補に石を打つ */
				rand_pos = genrand_int32() % jp;
				selected = possibles[rand_pos];
				if (verify_legal(selected, color_tmp, posl, &ko_pos, 1))
					/* 問題なく石を打てたら次の打ち込みへ */
					break;
				/* 石を打てない位置なら着手位置候補から除外 */
				for (jr = rand_pos; jr + 1<jp; jr++) {
					possibles[jr] = possibles[jr + 1];
					possibles[jr + 1] = 0;
				}
				jp--;
			}
		}
		/* 自分と相手で続けて石を打てなくなったらプレイアウト終了 */
		if (selected == 0 && pre_pos == 0) break;
		pre_pos = selected;
		color_tmp *= (-1);
	}
//printf("%d\n",i);
	/* 勝敗判定(中国ルール) */
	score = 0;
	memset(stone_num, '\0', sizeof(stone_num));
	/* 盤上の全位置をチェックする */
	for (i = size + 3; i<(size + 2)*(size + 1) - 1; i++) {
		/* 壁は無視 */
		if (posl[i] == SENTINEL) continue;
		/* 空き、黒石、白石の数を更新 */
		/* 石の生き死に判定ができないので死に石まで加算！ */
		/* 中国ルールで打てるかぎり打つという前提で黙認！ */
		stone_num[posl[i] + 1]++;
		/* 空きの場合四方の石の数で判断 */
		if (posl[i] != SPACE) continue;
		memset(neighbor_num, '\0', sizeof(neighbor_num));
		/* 隣接する石の空き、黒石、白石、壁の数を更新 */
		for (j = 0; j<4; j++) neighbor_num[posl[i + m_dir4[j]] + 1]++;
		/* 黒石あり、白石なしならば得点加算 */
		if (neighbor_num[BLACK + 1] > 0 && neighbor_num[WHITE + 1] == 0)
			score++;
		/* 白石あり、黒石なしならば得点減算 */
		if (neighbor_num[WHITE + 1] > 0 && neighbor_num[BLACK + 1] == 0)
			score--;
	}
	/* 得点に(黒 - 白 - コミ)を加算 */
	score += (stone_num[BLACK + 1] - stone_num[WHITE + 1] - int(m_komi));
	/* 黒の勝敗を返却 */
	return(score);
}
/* 碁石の着手位置検証と更新 */
/*   引数:着手位置,現手番の色,現碁盤配置,現劫位置,更新要否 */
/*   戻値:黒石の地数 */
int verify_legal(int pos, int color, int *posl, int *ko_pos, int update)
{
	int  i, j, c_len, n_len, liberty;
	int  exist_space, is_ko, eye;
	short n[19 * 19];
	short captures[19 * 19];
	char check[(19 + 2)*(19 + 2)];

	/* 碁石の着手位置が空きなし、劫は着手不可で復帰 */
	if (posl[pos] != SPACE || pos == *ko_pos) return(0);
	/* 劫位置と取り込む石(アゲハマ)を初期化 */
	is_ko = 0;
	memset(captures, '\0', sizeof(captures));
	c_len = 0;
	eye = 0;
	/* 着手位置のダメの数を確認 */
	memcpy(check, m_check_base, sizeof(check));
	liberty = verify_liberty(pos, color, check, posl);
	/* 隣接４位置をチェック */
	for (i = 0; i<4; i++) {
		/* 相手の石のみチェックする */
		if (posl[pos + m_dir4[i]] != (-1)*color) {
			if (posl[pos + m_dir4[i]] != SPACE)
				eye++; /* 自分の石か壁 */
			continue;
		}
		memcpy(check, m_check_base, sizeof(check));
		check[pos] = 1;
		exist_space = 0;
		/* 隣接する石の隣接状態をチェックする */
		n_len = verify_neighbor(pos + m_dir4[i], (-1)*color, check, posl, n);
		/* 隣接する石が単独で囲まれていたら劫の可能性ありとする */
		if (n_len == 1) is_ko = 1;
		/* 隣接する石が囲まれていたら */
		/*if (n_len >= 1) eye--;*/
		/* 隣接する石が囲まれていたら取り込む石(アゲハマ)に追加する */
		for (j = 0; j<n_len; j++) {
			captures[c_len] = n[j];
			c_len++;
		}
	}
	if (update != 2) {
		/* 着手位置が眼なら着手不可とする */
		if (eye == 4){
			for (i = 0; i<4; i++) {
				if (posl[pos + m_dir4[i]] != color) continue;
				memcpy(check, m_check_base, sizeof(check));
				check[pos] = 1;
				n_len = verify_neighbor(pos + m_dir4[i], color, check, posl, n);
				if (n_len > 0) break;
			}
			if (i >= 4) return(0);
		}
		/* 着手位置のダメの数がひとつ以下なら着手不可とする */
		if (liberty <= 1 && c_len == 0) return(0);
		if (update == 0) return(1);
	}
	/* 盤上の現在の碁石の配置状態を更新 */
	posl[pos] = color;
	/* 隣接する取り込む石があれば */
	if (c_len > 0) {
		/* 盤上の現在の碁石の配置状態を更新(取った位置を空きとする) */
		for (i = 0; i<c_len; i++) posl[captures[i]] = SPACE;
		/* 着手位置に劫の可能性があれば着手位置のダメの数を確認 */
		if (is_ko) {
			/* 着手位置のダメ検証 */
			memcpy(check, m_check_base, sizeof(check));
			liberty = verify_liberty(pos, color, check, posl);
			/* 着手位置のダメの数がひとつなら劫の位置を更新 */
			if (liberty == 1) {
				*ko_pos = captures[0];
				return(1);
			}
		}
	}
	/* 着手成功 */
	*ko_pos = 0;
	return(1);
}
/* 隣接位置検証 */
/*   引数:着手位置,現手番の色,各位置のチェック状態,現碁盤配置,取り込む石のリスト */
/*   戻値:取り込む石の数 */
int verify_neighbor(int pos, int color, char *check, int *posl, short *captures)
{
	int   i, j, y, c_len, n_len, ni, found_new;
	short newly_found[19 * 19 + 1];
	short n[19 * 19 + 1];

	newly_found[0] = (short)pos;
	newly_found[1] = 0;
	captures[0] = (short)pos;
	c_len = 1;
	found_new = 1;
	/* まず入力の隣接位置から検証する */
	while (found_new) {
		found_new = 0;
		n_len = 0;
		memset(n, '\0', sizeof(n));
		for (i = 0; newly_found[i] != 0; i++) {
			for (j = 0; j<4; j++) {
				y = newly_found[i] + m_dir4[j];
				if (check[y])
					/* 隣接する位置がチェック済なら次の隣接位置のチェックへ */
					continue;
				else if (posl[y] == SPACE)
					/* 隣接する位置がひとつでも空いていればチェック終了 */
					return(0);
				else if (posl[y] == color) {
					/* 隣接する位置に相手の石があれば退避済か確認 */
					for (ni = 0; ni<n_len; ni++)
						if (y == n[ni]) break;
					/* 退避済でなければ隣接位置リストに追加する */
					if (ni == n_len) {
						n[ni] = (short)y;
						n_len++;
						found_new = 1;
					}
				}
			}
			/* チェックした位置をチェック済とする */
			check[newly_found[i]] = 1;
		}
		if (found_new) {
			/* 次の隣接位置検証がまだ必要なら取り込み対象に加え */
			for (i = 0; i<n_len; i++) {
				captures[c_len] = n[i];
				c_len++;
			}
			/* 検証位置リストに隣接位置リストをコピーする */
			memcpy(newly_found, n, n_len * sizeof(n[0]));
			newly_found[n_len] = 0;
		}
	}
	/* 取り込む石の数を返却する */
	return(c_len);
}
/* ダメ検証 */
/*   引数:着手位置,現手番の色,各位置のチェック状態,現碁盤配置 */
/*   戻値:取り込む石の数 */
int verify_liberty(int pos, int color, char *check, int *posl)
{
	int   i, j, y, found_new;
	int   liberty_pos;
	short newly_found[19 * 19 + 1];
	short n[19 * 19 + 1];

	liberty_pos = 0;
	newly_found[0] = (short)pos;
	newly_found[1] = 0;
	found_new = 1;
	/* まず入力の自分の位置から検証する */
	while (found_new) {
		found_new = 0;
		memset(n, '\0', sizeof(n));
		for (i = 0; newly_found[i] != 0; i++) {
			/* 自分の位置をチェック済とする */
			check[newly_found[i]] = 1;
			for (j = 0; j<4; j++) {
				y = newly_found[i] + m_dir4[j];
				/* 隣接する位置がチェック済なら次の隣接位置のチェックへ */
				if (check[y]) continue;
				/* 隣接する位置をチェック済とする */
				check[y] = 1;
				if (posl[y] == SPACE)
					/* 隣接する位置が空いていたらダメの数を更新する */
					liberty_pos++;
				else if (posl[y] == color) {
					/* 自分の石なら隣接位置リストに追加する */
					n[found_new] = (short)y;
					found_new++;
				}
			}
		}
		if (found_new) {
			/* 検証位置リストに隣接位置リストをコピーする */
			memcpy(newly_found, n, found_new * sizeof(n[0]));
			newly_found[found_new] = 0;
		}
	}
	/* ダメの数を返却する */
	return(liberty_pos);
}
////////////////////////////////////
//  2次元表記から1次元表記へ変換  //
////////////////////////////////////
int
StringToIntegerX(char *cpos)
{
	char alphabet;
	int /*i,*/ x, y, pos;

	if (strcmp(cpos, "pass") == 0 ||
		strcmp(cpos, "PASS") == 0) {
		pos = PASS;
	}
	else {
		alphabet = (char)toupper(cpos[0]);
		if (alphabet < 'I') x = alphabet - '@';
		else if (alphabet > 'I') x = alphabet - '@' - 1;
		else                     x = 0;
		y = m_pure_board_size - atoi(&cpos[1]) + 1;
		pos = x + y * (m_pure_board_size + 2);
	}
	return pos;
}
