/// <summary> /// 盤上の全交点に、その場所の石(または連)の総呼吸点の数を埋めます。 /// /// Gnugo1.2 では、eval 関数。 /// </summary> /// <param name="libertyOfNodes"> /// Gnugo1.2 では、l という名前のグローバル変数。liberty の略だろうか? /// eval で内容が設定され、その内容は exambord、findsavr、findwinr、suicideで使用されます。 /// </param> /// <param name="color">黒 or 白</param> public static void CountAll ( out int[,] libertyOfNodes, StoneColor color, Taikyoku taikyoku ) { int banSize = taikyoku.GobanBounds.BoardSize; // 何路盤 libertyOfNodes = new int[taikyoku.GobanBounds.BoardSize, taikyoku.GobanBounds.BoardSize]; // それぞれのピースの総呼吸点の数を数えます。 for (int i = 0; i < banSize; i++) { for (int j = 0; j < banSize; j++) { GobanPoint iLocation = new GobanPointImpl(i, j); if (taikyoku.Goban.At(iLocation) == color) // 指定の色の石のみ { int liberty; // Gnugo1.2 では、グローバル変数 lib = 0 でした。 Util_CountLiberty.Count(out liberty, iLocation, color, taikyoku); libertyOfNodes[i, j] = liberty; } } } }
/// <summary> /// 取るか、攻撃する相手のピースを探します。 /// /// Gnugo1.2 では findwinner 関数。 /// </summary> /// <param name="out_bestLocation">次の動きの 行、列番号</param> /// <param name="out_bestScore">Gnugo1.2 では *val 引数。評価値</param> /// <param name="libertyOfNodes"> /// カレント色の石のリバティー(四方の石を置けるところ) /// /// Gnugo1.2 では、l という名前のグローバル変数。liberty の略だろうか? /// eval で内容が設定され、その内容は exambord、findsavr、findwinr、suicideで使用されます。 /// </param> /// <param name="taikyoku"></param> /// <returns></returns> public static bool FindBestLocation ( out GobanPoint out_bestLocation, out int out_bestScore, int[,] libertyOfNodes, Taikyoku taikyoku ) { int banSize = taikyoku.GobanBounds.BoardSize; // 要素数 3 以下のリスト。 List <GobanPoint> adj3Locations = new List <GobanPoint>(3); // Gnugo1.2 では、それぞれ要素数[3]の ti配列、tj配列。 int tryScore; // Gnugo1.2 では tval 変数。 out_bestLocation = new GobanPointImpl(-1, -1); // 位置i,j out_bestScore = -1; // 評価値 // // リバティー(四方の置けるところ)が3つ以下の相手(人間)の石を探します。 // つまり、つながっている石(色が異なる石とつながっている場合もあり)か、端にある石ということです。 // for (int m = 0; m < banSize; m++) { for (int n = 0; n < banSize; n++) { GobanPoint iLocation = new GobanPointImpl(m, n); if ( // 相手(人間)の石で、 taikyoku.Goban.At(iLocation) == taikyoku.YourColor && // この石(あるいは連全体)で、呼吸点が3以下のものを選びます。 // 少なくとも 石か枠につながっている石であることを想定しています。 libertyOfNodes[m, n] < 4 ) { // これからフラグを立てていくためにクリアーします。 taikyoku.MarkingBoard.Initmark(taikyoku.GobanBounds.BoardSize); if ( // この石(連ではなく)の開いている方向(1方向〜3方向あるはずです) Util_FindOpen.FindOpen3Locations(adj3Locations, iLocation, taikyoku.YourColor, libertyOfNodes[m, n], taikyoku) ) { if (libertyOfNodes[m, n] == 1) { // アタリの状態なので、積極的に狙っていきます。(呼吸点が、どこか1方向しかない状態) if (out_bestScore < 120) // 評価値が 120 未満なら { // アタリの評価値は 120 点はあります。 // この位置の評価を上げ、ベストムーブとして更新します。 out_bestScore = 120; out_bestLocation.SetLocation(adj3Locations[0]); } } else { // アタリではなくとも。 // 呼吸点の数(2〜たくさん)に応じて。 int opens = libertyOfNodes[m, n]; // わたし(コンピューター)が置いたときと、相手(人間)に置き返されたときの // 全パターンについて // 配列のインデックスが 0,1 や、0,2 や、 1,2 など、異なるペア com,man になるもの // 全てについて。 for (int iCom = 0; iCom < opens; iCom++) //わたし(コンピューター)という想定 { for (int iMan = 0; iMan < opens; iMan++) //相手(人間)という想定 { if (iCom != iMan) { // 置く位置 GobanPoint adjLocation_com = adj3Locations[iCom]; // 置き返す位置 GobanPoint adjLocation_man = adj3Locations[iMan]; // わたしの(連または)石のリバティ int liberty_com; // Gnugo1.2 では、グローバル変数 lib = 0 でした。 Util_CountLiberty.Count(out liberty_com, adjLocation_com, taikyoku.MyColor, taikyoku); if (0 < liberty_com) // 妥当性チェック { // コンピューターの色の石を 位置 a に(試しに)置きます。 taikyoku.Goban.Put(adjLocation_com, taikyoku.MyColor); // look ahead opponent move int liberty_man; // Gnugo1.2 では、グローバル変数 lib = 0 でした。 Util_CountLiberty.Count(out liberty_man, adjLocation_man, taikyoku.YourColor, taikyoku); if ( 1 == liberty_com // 隣接する私(コンピューター)側の(連または)石の呼吸点は1個。 && 0 < liberty_man // 隣接するあなた(人間)側の(連または)石の呼吸点は1個以上。 ) { // 人間側の呼吸点の方が、コンピューター側と同じ、あるいは多いので、 // 位置 a に置く価値なし。 tryScore = 0; } else { // コンピューターが置いた手より、 // 人間が置く手に、呼吸点が同じ、また多い手がない場合、置く価値あり。 tryScore = 120 - 20 * liberty_man; } if (out_bestScore < tryScore) { // より評価値の高い指し手を見つけました。ベストムーブの位置を更新します。 out_bestScore = tryScore; out_bestLocation.SetLocation(adjLocation_com); } // (試しに置いた)石を取り除きます。盤上を元に戻すだけです。 taikyoku.Goban.Put(adjLocation_com, StoneColor.Empty); } } } //v } //u } } } } //n } //m if (0 < out_bestScore) // 指し手を見つけた。 { return(true); } else // 勝者の指し手を見つけるのには失敗した。 { return(false); } }
/// <summary> /// コンピューターの動きを作ります。 /// /// Gnugo1.2 では genmove関数。 /// </summary> /// <param name="out_bestMove">コンピューターが選んだ、一番いい石の置き場所</param> /// <param name="taikyoku"></param> public static void Generate_BestMove ( out GobanPoint out_bestMove, Taikyoku taikyoku ) { int bestScore; // Gnugo1.2 では val変数。評価値。 int try_ = 0; // トライの数 // ムーブと評価値を初期化します。 out_bestMove = new GobanPointImpl(-1, -1); bestScore = -1; // カレント色の石(または連)のリバティー(四方の石を置けるところ) // // Gnugo1.2 では、l という名前のグローバル変数。liberty の略だろうか? // eval で内容が設定され、その内容は exambord、findsavr、findwinr、suicideで使用されます。 int[,] libertyOfNodes; // 相手(人間)の呼吸点の数 を再び数えます。 Util_LibertyAtNode.CountAll(out libertyOfNodes, taikyoku.YourColor, taikyoku); // 相手のピースを取ったり、攻めたりする手を探します。 { GobanPoint foundLocation; // Gnugo1.2 では、 ti, tj という変数名。 int foundScore; // Gnugo1.2 では tval変数。試して算出した評価値。 if (Util_FindWinner.FindBestLocation(out foundLocation, out foundScore, libertyOfNodes, taikyoku)) { if (bestScore < foundScore) // 新しい最善手を見つけたなら { bestScore = foundScore; // 最善の評価値と置き場所を、更新します。 out_bestMove.SetLocation(foundLocation); } } } // もし脅かされていれば、幾つかのピースを守ります。 { GobanPoint foundLocation; // Gnugo1.2 では、 ti, tj という変数名。 int foundScore; // Gnugo1.2 では tval変数。試して算出した評価値。 if (Util_SasiteSaver.FindLocation_LibertyWeak(out foundLocation, out foundScore, libertyOfNodes, taikyoku)) { if (bestScore < foundScore) // 新しい最善手を見つけたなら { bestScore = foundScore; // 最善の評価値と置き場所を、更新します。 out_bestMove.SetLocation(foundLocation); } } } // 新しい動きのためのローカル・プレー・パターンに一致するか試します。 { GobanPoint foundLocation; // Gnugo1.2 では、 ti, tj という変数名。 int foundScore; // Gnugo1.2 では tval変数。試して算出した評価値。 if (Util_FindOpeningZyoseki.FindPattern(out foundLocation, out foundScore, taikyoku)) { if (bestScore < foundScore) // 新しい最善手を見つけたなら { bestScore = foundScore; // 最善の評価値と置き場所を、更新します。 out_bestMove.SetLocation(foundLocation); } } } // いい手が無ければ、ランダムに打ちます。 if (bestScore < 0) { int count_libertyOfPiece;// Gnugo1.2 では、静的グローバル変数 lib でした。 // くり返し。 do { // 行は 盤幅でランダム。 out_bestMove.I = taikyoku.Random.Next() % taikyoku.GobanBounds.BoardSize; // 低いラインを避ける、中央の領域 if ( out_bestMove.OutOfI(2, 16) //0〜1行、または 17〜18行だ。 || out_bestMove.ContainsI(6, 12) //6〜12行のどこかにある。 ) { // 振りなおし out_bestMove.I = taikyoku.Random.Next() % taikyoku.GobanBounds.BoardSize; if (out_bestMove.OutOfI(2, 16))//0〜1行、または 17〜18行だ。 { // 振りなおし out_bestMove.I = taikyoku.Random.Next() % taikyoku.GobanBounds.BoardSize; } } // 列は 盤幅 でランダム。 out_bestMove.J = taikyoku.Random.Next() % taikyoku.GobanBounds.BoardSize; // 低いラインを避ける、中央の領域 if ( out_bestMove.OutOfJ(2, 16) //0〜1列、または 17〜18列だ。 || // または、 out_bestMove.ContainsJ(6, 12) //6〜12列のどこかにある。 ) { // 振りなおし out_bestMove.J = taikyoku.Random.Next() % taikyoku.GobanBounds.BoardSize; if (out_bestMove.OutOfJ(2, 16))//0〜1列、または 17〜18列だ。 { // 振りなおし out_bestMove.J = taikyoku.Random.Next() % taikyoku.GobanBounds.BoardSize; } } // リバティーを数えなおし。 Util_CountLiberty.Count(out count_libertyOfPiece, out_bestMove, taikyoku.MyColor, taikyoku); ++try_; }while ( try_ < MAXTRY // まだ次もトライできます。 && ( // 次の3つの条件のどれかを満たすようなら、再トライします。 // (1)ベストムーブか空っぽだ。非合法手かも。 // (2)ピースのリバティーが 0〜1 しかない。 taikyoku.Goban.At(out_bestMove) != StoneColor.Empty || count_libertyOfPiece < 2 || // (3)自分の目を埋める手なら。 Util_OwnEye.IsThis(out_bestMove, taikyoku) ) ); } if (MAXTRY <= try_) // 最大試行回数を超えていたら、コンピューターはパス。 { taikyoku.Pass++; //---------------------------------------- // コンピューターの指し手を表示します。 //---------------------------------------- Console.WriteLine("I pass."); out_bestMove.SetPass(); } else // 妥当な指し手を指します。 { taikyoku.Pass = 0; //---------------------------------------- // コンピューターの指し手を表示します。 //---------------------------------------- Console.Write("my move: "); // 座標の列番号を、アスキー文字コードに変換します。 char a; if (out_bestMove.J < 8) { a = (char)(out_bestMove.J + 65); } else { a = (char)(out_bestMove.J + 66); } Console.Write(a); int ii; // Gnugo1.2 では、行i を反転させた変数名が ii。 ii = taikyoku.GobanBounds.BoardSize - out_bestMove.I; if (ii < 10) { Console.WriteLine("{0,1}", ii); } else { Console.WriteLine("{0,2}", ii); } } }
/// <summary> /// 序盤定石以外の、局地的な定石にあてはまるかをしらべ、定石があれば置く場所を取得します。 /// </summary> /// <param name="out_location">次の手の 行、列番号</param> /// <param name="out_score">Gnugo1.2 では val 引数。評価値</param> /// <param name="origin_location">Gnugo1.2 では、 原点の 行 m、列 n 引数。</param> /// <param name="taikyoku"></param> /// <returns></returns> public static bool FindPattern ( out GobanPoint out_location, out int out_score, GobanPoint origin_location, Taikyoku taikyoku ) { GobanPoint tryLocation = new GobanPointImpl(0, 0); // Gnugo1.2 では、ti,tj という変数名。// 2015-11-26 追加 0,0 で初期化。 out_location = new GobanPointImpl(-1, -1); out_score = -1; for (int ptnNo = 0; ptnNo < Util_LocalZyoseki.Patterns.Length; ptnNo++) // それぞれのパターンを試します。 { for (int ll = 0; ll < Util_LocalZyoseki.Patterns[ptnNo].LastTrfNo; ll++) /* try each orientation transformation */ { int k = 0; bool isContinueLoop = true; // Gnugo1.2 では cont変数。continueの略か? // // 条件に一致していないものを、ふるい落としていきます。 // 条件に一致しているものは、どんどん次のループに進みます。 // while ( k != Util_LocalZyoseki.Patterns[ptnNo].Stones.Length && isContinueLoop )/* いくつかのポイントに一致 */ { // // 変形(transform)して、盤上の座標に変換します。 // int nx = origin_location.J + Util_FindLocalZyoseki.Trf[ll, 0, 0] * Util_LocalZyoseki.Patterns[ptnNo].Stones[k].P.X + Util_FindLocalZyoseki.Trf[ll, 0, 1] * Util_LocalZyoseki.Patterns[ptnNo].Stones[k].P.Y ; int my = origin_location.I + Util_FindLocalZyoseki.Trf[ll, 1, 0] * Util_LocalZyoseki.Patterns[ptnNo].Stones[k].P.X + Util_FindLocalZyoseki.Trf[ll, 1, 1] * Util_LocalZyoseki.Patterns[ptnNo].Stones[k].P.Y ; /* outside the board */ if ( !Util_AboutBoard.In_Board(my, taikyoku.GobanBounds) || !Util_AboutBoard.In_Board(nx, taikyoku.GobanBounds) ) { isContinueLoop = false; break; } GobanPoint mnLocation = new GobanPointImpl(my, nx); switch (Util_LocalZyoseki.Patterns[ptnNo].Stones[k].Att) { case LocalZyoseki_StoneAttribute._0_Empty: if (taikyoku.Goban.At(mnLocation) == StoneColor.Empty) /* open */ { break; } else { isContinueLoop = false; break; } case LocalZyoseki_StoneAttribute._1_YourPiece: if (taikyoku.Goban.At(mnLocation) == taikyoku.YourColor) /* your piece */ { break; } else { isContinueLoop = false; break; } case LocalZyoseki_StoneAttribute._2_MyPiece: if (taikyoku.Goban.At(mnLocation) == taikyoku.MyColor) /* my piece */ { break; } else { isContinueLoop = false; break; } case LocalZyoseki_StoneAttribute._3_MyNextMove: if (taikyoku.Goban.At(mnLocation) == StoneColor.Empty) /* open for new move */ { int libertyOfPiece; // Gnugo1.2 では、グローバル変数 lib = 0 でした。 Util_CountLiberty.Count(out libertyOfPiece, mnLocation, taikyoku.MyColor, taikyoku); /* check liberty */ if (1 < libertyOfPiece) /* move o.k. */ { tryLocation.SetLocation(my, nx); break; } else { isContinueLoop = false; break; } } else { isContinueLoop = false; break; } case LocalZyoseki_StoneAttribute._4_EmptyOnEdge: if ( taikyoku.Goban.At(mnLocation) == StoneColor.Empty /* open on edge */ && ( Util_AboutBoard.On_Edge(my, taikyoku.GobanBounds) || Util_AboutBoard.On_Edge(nx, taikyoku.GobanBounds) ) ) { break; } else { isContinueLoop = false; break; } case LocalZyoseki_StoneAttribute._5_YourPieceOnEdge: if ( taikyoku.Goban.At(mnLocation) == taikyoku.YourColor /* your piece on edge */ && ( Util_AboutBoard.On_Edge(my, taikyoku.GobanBounds) || Util_AboutBoard.On_Edge(nx, taikyoku.GobanBounds) ) ) { break; } else { isContinueLoop = false; break; } case LocalZyoseki_StoneAttribute._6_MyPieceOnEdge: if ( taikyoku.Goban.At(mnLocation) == taikyoku.MyColor /* my piece on edge */ && ( Util_AboutBoard.On_Edge(my, taikyoku.GobanBounds) || Util_AboutBoard.On_Edge(nx, taikyoku.GobanBounds) ) ) { break; } else { isContinueLoop = false; break; } } ++k; } if (isContinueLoop) // パターンに一致しています。 { int tryScore = Util_LocalZyoseki.Patterns[ptnNo].Score; // Gnugo1.2 では、tval 変数。 if ( // パターン番号 8〜13 には、報酬とペナルティーを付けます。 8 <= ptnNo && ptnNo <= 13 /* patterns for expand region */ ) { if (7 < Util_FindLocalZyoseki.DistanceFromCenter(tryLocation.I, taikyoku.GobanBounds)) { // 中心から 8以上離れている(端と、その隣ぐらいの位置)ならば、ペナルティーを付けます。 tryScore--; } else if ((Util_FindLocalZyoseki.DistanceFromCenter(tryLocation.I, taikyoku.GobanBounds) == 6) || (Util_FindLocalZyoseki.DistanceFromCenter(tryLocation.I, taikyoku.GobanBounds) == 7)) { // 中心から 6〜7 離れている位置(端から3,4番目ぐらい)には、報酬を与えます。 tryScore++; } if (7 < Util_FindLocalZyoseki.DistanceFromCenter(tryLocation.J, taikyoku.GobanBounds)) /* penalty on line 1, 2 */ { tryScore--; } else if ((Util_FindLocalZyoseki.DistanceFromCenter(tryLocation.J, taikyoku.GobanBounds) == 6) || (Util_FindLocalZyoseki.DistanceFromCenter(tryLocation.J, taikyoku.GobanBounds) == 7)) { tryScore++; /* reward on line 3, 4 */ } } if (tryScore > out_score) { out_score = tryScore; out_location.SetLocation(tryLocation); } } }//for } if (0 < out_score) // パターンにマッチしました。 { return(true); } else // マッチに失敗しました。 { return(false); } }
/// <summary> /// 相手の盤上i,jの動きが自殺手でないか調べます。 /// </summary> /// <param name="location">Gnugo1.2 では、i,j という引数名。</param> /// <param name="taikyoku"></param> /// <returns></returns> public static bool Aa_Suicide( GobanPoint location, Taikyoku taikyoku ) { int banSize = taikyoku.GobanBounds.BoardSize; // 新しい動きのリバティーを数えなおします。 int liberty; // Gnugo1.2 では、グローバル変数 lib = 0 でした。 Util_CountLiberty.Count(out liberty, location, taikyoku.YourColor, taikyoku); if (liberty == 0) // 調べて、もしコンピューターのピースズを殺して、コの可能性があれば、 // 新しい動きは自殺手です。 { // assume alive taikyoku.Goban.Put(location, taikyoku.YourColor); // カレント色の石のリバティー(四方の石を置けるところ) // // Gnugo1.2 では、l という名前のグローバル変数。liberty の略だろうか? // eval で内容が設定され、その内容は exambord、findsavr、findwinr、suicideで使用されます。 int[,] libertyOfNodes; // コンピューターの呼吸点の数を数えます。 Util_LibertyAtNode.CountAll(out libertyOfNodes, taikyoku.MyColor, taikyoku); int k = 0; for (int m = 0; m < banSize; m++) { for (int n = 0; n < banSize; n++) { // 殺されるかもしれないピースズを数えます。 if ( (taikyoku.Goban.At(new GobanPointImpl(m, n)) == taikyoku.MyColor) && libertyOfNodes[m, n] == 0 ) { ++k; } if ( (k == 0) || ( k == 1 && ( (location.I == taikyoku.YourKo.I) && (location.J == taikyoku.YourKo.J) ) ) ) // either no effect on my pieces or an illegal Ko take back { taikyoku.Goban.Put(location, StoneColor.Empty); /* restore to open */ return(true); } else { /* good move */ return(false); } } } return(false);// 2015-11-26 追加 } else { /* valid move */ return(false); } }
/// <summary> /// 弱っている石を助ける手を探します。 /// 助けるというのは、(襲われそうな)自分の石の 横にツケることです。 /// /// 位置m,nを含むグループから、 /// 上下左右に隣接する石(または連)の呼吸点を調べ、 /// 最もスコアの高い石(または連)の場所 i,j と、評価値を探します。(連の場合、どこか1つの石の場所) /// /// Gnugo1.2 では findnextmove 関数。 /// </summary> /// <param name="out_bestLocation">次の動きの 行、列番号</param> /// <param name="out_bestScore">Gnugo1.2では val という名前のポインター変数。次の指し手の評価値</param> /// <param name="myStone_location">(脅かされているかもしれない)コンピューターの石の 行番号 m、列番号 n</param> /// <param name="currentLiberty">現在のリバティーの数。1〜3を、脅かされていると考えます。Gnugo1.2 では minlib 変数。</param> /// <param name="taikyoku"></param> /// <returns></returns> public static bool FindStone_LibertyWeak ( out GobanPoint out_bestLocation, out int out_bestScore, GobanPoint myStone_location, int currentLiberty, Taikyoku taikyoku ) { out_bestLocation = new GobanPointImpl(-1, -1); out_bestScore = -1; // カレント位置をマークします。 taikyoku.MarkingBoard.Done_Current(myStone_location); // // 東西南北のどこかに 空きスペース (がないと助けられません)があるはずです。 // //-------------------------------------------------------------------------- // 北隣を調べます。 { GobanPoint tryLocation = new GobanPointImpl(0, 0); // Gnugo1.2 では ti,tj という変数名。// 初期値は 2015-11-26 追加 int tryScore = 0; // Gnugo1.2 では tval 変数。 隣位置の評価値。 // 2015-11-26 追加 0 で初期化。 bool found = false; if (!myStone_location.IsNorthEnd()) // 北端でない石のみ。 { if (taikyoku.Goban.NorthOf(myStone_location) == StoneColor.Empty) { // わたしの石の北隣にある空きスペースの位置。 tryLocation.SetLocation(myStone_location.ToNorth()); // 空きスペースに石を置いたと考えて、石を置いた局面のその自分の石(または連)の呼吸点を数えます。 int futureLiberty; // Gnugo1.2 では、グローバル変数 lib = 0 でした。 Util_CountLiberty.Count(out futureLiberty, tryLocation, taikyoku.MyColor, taikyoku); // 評価値計算 tryScore = Util_SasiteNext.Evaluate_LibertyWeak(futureLiberty, currentLiberty); found = true; } else if ( taikyoku.Goban.NorthOf(myStone_location) == taikyoku.MyColor // 北隣がコンピューターの石で、 && taikyoku.MarkingBoard.CanDo_North(myStone_location) // 北隣のマーキングが 0 なら ) { if (Util_SasiteNext.FindStone_LibertyWeak(out tryLocation, out tryScore, myStone_location.ToNorth(), currentLiberty, taikyoku)) // 再帰的に検索 { found = true; } } } if (found) // 見つかったら1 { found = false; if (out_bestScore < tryScore && !Util_OwnEye.IsThis(tryLocation, taikyoku)) { out_bestScore = tryScore; // 高い方の評価値を残している? out_bestLocation.SetLocation(tryLocation); // 高い方の交点i,jを残している? } } } //-------------------------------------------------------------------------- // 南ネイバーを調べます。 { GobanPoint tryLocation = new GobanPointImpl(0, 0); // Gnugo1.2 では ti,tj という変数名。// 初期値は 2015-11-26 追加 int tryScore = 0; // Gnugo1.2 では tval 変数。 隣位置の評価値。 // 2015-11-26 追加 0 で初期化。 bool found = false; if (!myStone_location.IsSouthEnd(taikyoku.GobanBounds)) // 南端でなければ。 { if (taikyoku.Goban.SouthOf(myStone_location) == StoneColor.Empty) { // 南隣の石(または連)の呼吸点の数を調べ、 // 期待する呼吸点の数より 大きいほど高い評価値を付けます。 tryLocation.SetLocation(myStone_location.ToSouth()); int futureLiberty; // Gnugo1.2 では、グローバル変数 lib = 0 でした。 Util_CountLiberty.Count(out futureLiberty, tryLocation, taikyoku.MyColor, taikyoku); tryScore = Util_SasiteNext.Evaluate_LibertyWeak(futureLiberty, currentLiberty); found = true; } else if ( taikyoku.Goban.SouthOf(myStone_location) == taikyoku.MyColor && taikyoku.MarkingBoard.CanDo_South(myStone_location) // 南側 ) { if (Util_SasiteNext.FindStone_LibertyWeak(out tryLocation, out tryScore, myStone_location.ToSouth(), currentLiberty, taikyoku)) { found = true; } } } if (found) // 見つかったら1 { found = false; if (out_bestScore < tryScore && !Util_OwnEye.IsThis(tryLocation, taikyoku)) { out_bestScore = tryScore; out_bestLocation.SetLocation(tryLocation); } } } //-------------------------------------------------------------------------- // 西ネイバーを調べます。 { GobanPoint tryLocation = new GobanPointImpl(0, 0); // Gnugo1.2 では ti,tj という変数名。// 初期値は 2015-11-26 追加 int tryScore = 0; // Gnugo1.2 では tval 変数。 隣位置の評価値。 // 2015-11-26 追加 0 で初期化。 bool found = false; if (!myStone_location.IsWestEnd()) // 西端でなければ。 { if (taikyoku.Goban.WestOf(myStone_location) == StoneColor.Empty) { tryLocation.SetLocation(myStone_location.ToWest()); int futureLiberty; // Gnugo1.2 では、グローバル変数 lib = 0 でした。 Util_CountLiberty.Count(out futureLiberty, tryLocation, taikyoku.MyColor, taikyoku); tryScore = Util_SasiteNext.Evaluate_LibertyWeak(futureLiberty, currentLiberty); found = true; } else { if ( taikyoku.Goban.WestOf(myStone_location) == taikyoku.MyColor && taikyoku.MarkingBoard.CanDo_West(myStone_location) // 西側 ) { if (Util_SasiteNext.FindStone_LibertyWeak(out tryLocation, out tryScore, myStone_location.ToWest(), currentLiberty, taikyoku)) { found = true; } } } } if (found) // 見つかっていれば 1 { found = false; if (tryScore > out_bestScore && !Util_OwnEye.IsThis(tryLocation, taikyoku)) { out_bestScore = tryScore; out_bestLocation.SetLocation(tryLocation); } } } //-------------------------------------------------------------------------- // 東ネイバーを調べます。 { GobanPoint tryLocation = new GobanPointImpl(0, 0); // Gnugo1.2 では ti,tj という変数名。// 初期値は 2015-11-26 追加 int tryScore = 0; // Gnugo1.2 では tval 変数。 隣位置の評価値。 // 2015-11-26 追加 0 で初期化。 bool found = false; if (!myStone_location.IsEastEnd(taikyoku.GobanBounds)) // 東端でなければ。 { if (taikyoku.Goban.EastOf(myStone_location) == StoneColor.Empty) { tryLocation.SetLocation(myStone_location.ToEast()); int futureLiberty; // Gnugo1.2 では、グローバル変数 lib = 0 でした。 Util_CountLiberty.Count(out futureLiberty, tryLocation, taikyoku.MyColor, taikyoku); tryScore = Util_SasiteNext.Evaluate_LibertyWeak(futureLiberty, currentLiberty); found = true; } else { if ( taikyoku.Goban.EastOf(myStone_location) == taikyoku.MyColor && taikyoku.MarkingBoard.CanDo_East(myStone_location) // 東側 ) { if (Util_SasiteNext.FindStone_LibertyWeak(out tryLocation, out tryScore, myStone_location.ToEast(), currentLiberty, taikyoku)) { found = true; } } } } if (found) // Gnugo1.2では、見つかっていれば 1 でした。 { found = false; if (out_bestScore < tryScore && !Util_OwnEye.IsThis(tryLocation, taikyoku)) { out_bestScore = tryScore; out_bestLocation.SetLocation(tryLocation); } } } //-------------------------------------------------------------------------- if (0 < out_bestScore) // 次の動きを見つけた。 { return(true); } else // 次の動きは失敗。 { return(false); } }