Beispiel #1
0
        /// <summary>
        /// 囲われた石を、盤上から除外します。コウにならないかどうか、注意します。
        ///
        /// Gnugo1.2 では、exambord関数。
        /// </summary>
        /// <param name="colorKo">取られた方の、黒 or 白</param>
        /// <param name="taikyoku"></param>
        public static void RemoveStones_Surrounded
        (
            StoneColor colorKo,
            Taikyoku taikyoku
        )
        {
            // 盤上の全てのポイントに、呼吸点の数を記憶させます。
            int[,] libertyOfNodes;
            Util_LibertyAtNode.CountAll(out libertyOfNodes, colorKo, taikyoku);

            // 取った石の位置を初期化します。(コウで戻さなくてはならない石の位置を覚えていたもの)
            if (colorKo == taikyoku.MyColor)
            {
                taikyoku.MyKo.MoveToVanish();
            }
            else
            {
                taikyoku.YourKo.MoveToVanish();
            }


            // コウの動きで取れる石の数。
            int countOfDelete = 0;

            // リバティーのない石は全て碁番から削除します。
            // つまり四方を全て囲まれたピース(石のあつまり)です。
            for (int i = 0; i < taikyoku.GobanBounds.BoardSize; i++)
            {
                for (int j = 0; j < taikyoku.GobanBounds.BoardSize; j++)
                {
                    GobanPoint location = new GobanPointImpl(i, j);

                    if
                    (
                        // 取られる側の石であり、
                        taikyoku.Goban.At(location) == colorKo
                        &&
                        // ピースのリバティーが記録されていないなら
                        libertyOfNodes[i, j] == 0
                    )
                    {
                        // 石を除外します。
                        taikyoku.Goban.Put(location, StoneColor.Empty);

                        // (後で元に戻すこともあるので)取った石の位置を記憶し、取られた石の数をカウントアップします。
                        if (colorKo == taikyoku.MyColor)
                        {
                            // コンピューター側
                            taikyoku.MyKo.SetLocation(location);
                            ++taikyoku.Count_MyCaptured;
                        }
                        else
                        {
                            // 人間側
                            taikyoku.YourKo.SetLocation(location);
                            ++taikyoku.Count_YourCaptured;
                        }
                        ++countOfDelete;    // この指し手で取った駒の数?
                    }

                    // 取った石が2つ以上なら、コウ(Ko)の可能性がなくなります。石の位置の記憶をリセットします。
                    if (colorKo == taikyoku.MyColor && 1 < countOfDelete)
                    {
                        // コンピューターが取った石の位置(コウになるかもしれない)をクリアー。
                        taikyoku.MyKo.MoveToVanish();
                    }
                    else if (1 < countOfDelete) // TODO: こっちは 1 < countOfDelete しなくていいのか?
                    {
                        // 人間が取った石の位置(コウになるかもしれない)をクリアー。
                        taikyoku.YourKo.MoveToVanish();
                    }
                } //j
            }     //i
        }
        /// <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);
                }
            }
        }
Beispiel #3
0
        /// <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);
            }
        }