/// <summary>
        /// 整地された地かどうかを、確認します。
        ///
        /// 場所を1つ指定し、
        /// その4方向は 石がないか、同じ色の石だけで構成されている、
        /// そういう場所は 整地されている自分の陣地として正しい。
        ///
        /// Gnugo1.2 では findcolr 関数。
        /// </summary>
        /// <param name="location">Gnugo1.2 では、 行番号 i = 0〜18、列番号 j = 0〜18。</param>
        /// <param name="taikyoku"></param>
        /// <returns></returns>
        public static StoneColor Test_SeitiZi
        (
            GobanPoint location,
            Taikyoku taikyoku
        )
        {
            //----------------------------------------
            // 実装の説明
            //----------------------------------------
            //
            // 盤上の交点を1つ指定します。
            //
            // そこに石があれば、その色を返します。
            //
            // 石がなければ、4方向の直線上で最初に突き当たる石の色を調べます。
            // (まるで、将棋の飛車の動きのように)
            //

            StoneColor result = StoneColor.Empty;     // 色 // 2015-11-26 追加 Emptyで初期化。

            /// [0]北、[1]南、[2]西、[3]東
            StoneColor[] color = new StoneColor[4];


            //
            // 指定した盤上の位置に石があれば、その色を返します。
            //
            if (taikyoku.Goban.At(location) != StoneColor.Empty)
            {
                return(taikyoku.Goban.At(location));
            }

            // 北ネイバーを、石に突き当たるまで調べます。
            if (!location.IsNorthEnd())//北端でなければ
            {
                // 指定の行番号 〜 0 まで。突き当たらなければ k は 北端 まで。
                int k = location.I;
                do
                {
                    --k;
                }while (
                    taikyoku.Goban.At(new GobanPointImpl(k, location.J)) == StoneColor.Empty
                    &&
                    0 < k
                    );
                color[0] = taikyoku.Goban.At(new GobanPointImpl(k, location.J));
            }
            else
            {
                // 空っぽ。
                color[0] = StoneColor.Empty;
            }

            // 南ネイバーを、石に突き当たるまで調べます。
            if (!location.IsSouthEnd(taikyoku.GobanBounds))
            {
                // (18より小さい、指定の行番号)〜 南端 まで。
                int k = location.I;
                do
                {
                    ++k;
                }while
                (
                    taikyoku.Goban.At(new GobanPointImpl(k, location.J)) == StoneColor.Empty
                    &&
                    k < taikyoku.GobanBounds.BoardEnd
                );
                color[1] = taikyoku.Goban.At(new GobanPointImpl(k, location.J));
            }
            else
            {
                // 空っぽ。
                color[1] = StoneColor.Empty;
            }

            // 西ネイバーを、石に突き当たるまで調べます。
            if (!location.IsWestEnd())
            {
                // (0より大きい、指定の列番号)〜 1 まで。
                int k = location.J;
                do
                {
                    --k;
                }while
                (
                    taikyoku.Goban.At(new GobanPointImpl(location.I, k)) == StoneColor.Empty
                    &&
                    k > 0
                );
                color[2] = taikyoku.Goban.At(new GobanPointImpl(location.I, k));
            }
            else
            {
                // 空っぽ。
                color[2] = StoneColor.Empty;
            }

            // 東ネイバーを、石に突き当たるまで調べます。
            if (!location.IsEastEnd(taikyoku.GobanBounds))
            {
                // (18より小さい、指定の列番号)〜 17 まで。
                int k = location.J;
                do
                {
                    ++k;
                }while
                (
                    taikyoku.Goban.At(new GobanPointImpl(location.I, k)) == StoneColor.Empty
                    &&
                    k < taikyoku.GobanBounds.BoardEnd
                );
                color[3] = taikyoku.Goban.At(new GobanPointImpl(location.I, k));
            }
            else
            {
                // 空っぽ。
                color[3] = StoneColor.Empty;
            }

            // 4方向のうち、空っぽでない交点の色を1つだけ知りたい。
            for (int k = 0; k < 4; k++)
            {
                if (color[k] == StoneColor.Empty)
                {
                    continue;
                }
                else
                {
                    result = color[k];
                    break;
                }
            }

            // クロスチェックします。
            // もし  わたしたちがエラーを見つけたなら、全ての死ピースは盤から取らない。
            // わたしたちはこれを修正するようプレイヤーたちに促す。
            for (int k = 0; k < 4; k++)
            {
                // 色が設定されているのに、返す結果の色が違っていたらエラーです。問題です。
                if
                (
                    color[k] != StoneColor.Empty
                    &&
                    color[k] != result
                )
                {
                    return(StoneColor.Empty);// 0;
                }
            }

            // もし、わたしたちが全てのチェックにOKすれば、結果をレポートします。
            return(result);
        }
        /// <summary>
        /// 碁盤の指定の交点 i,j にある石を起点に、つながっている同じ色の石の(1つ、または連の)総リバーティを数えます。
        /// 再帰的に呼び出されます。
        /// Countlib関数から呼び出してください。
        ///
        /// Gnugo1.2 では、count関数です。
        /// </summary>
        /// <param name="count">Gnugo1.2 では、グローバル変数 lib でした。</param>
        /// <param name="location">Gnugo1.2では、行番号 i = 0〜18、列番号 j = 0〜18。</param>
        /// <param name="color">黒 or 白</param>
        /// <param name="taikyoku"></param>
        private static void Count_Recursive(
            ref int count,
            GobanPoint location,
            StoneColor color,
            Taikyoku taikyoku
            )
        {
            //----------------------------------------
            // 実装の解説
            //----------------------------------------
            // 石の周り4方向について、
            // 数えていない空き交点であれば リバティーを 1加算します。
            // 数えていなくて、指定した色(主に同じ色)の石であれば、その石から同メソッドを再帰呼び出しします。
            //

            // 指定した位置は、調査済みとしてマークします。
            taikyoku.CountedBoard.Done_Current(location);

            // 北隣の石を調べます。
            if (!location.IsNorthEnd())//北端でなければ
            {
                if
                (
                    taikyoku.Goban.NorthOf(location) == StoneColor.Empty
                    &&
                    taikyoku.CountedBoard.CanDo_North(location)
                )
                {
                    // 北隣が空いていて  まだ数えていないなら、
                    // リバティーを1つ数え上げます。次からは重複して数えません。
                    ++count;
                    taikyoku.CountedBoard.Done_North(location);
                }
                else if
                (
                    taikyoku.Goban.NorthOf(location) == color
                    &&
                    taikyoku.CountedBoard.CanDo_North(location)
                )
                {
                    // 北隣に 指定色の石が置いてあり、まだ数えていないなら、
                    // その石からさらにカウントを続けます。
                    Util_CountLiberty.Count_Recursive(ref count, location.ToNorth(), color, taikyoku);
                }
                // 指定した色でない石が置いてあれば何もしない。
            }

            // 南隣を調べます。
            if (!location.IsSouthEnd(taikyoku.GobanBounds))//南端でなければ
            {
                // もう、だいたい分かるだろう☆(^▽^)
                if
                (
                    taikyoku.Goban.SouthOf(location) == StoneColor.Empty
                    &&
                    taikyoku.CountedBoard.CanDo_South(location)
                )
                {
                    ++count;
                    taikyoku.CountedBoard.Done_South(location);
                }
                else if
                (
                    taikyoku.Goban.SouthOf(location) == color
                    &&
                    taikyoku.CountedBoard.CanDo_South(location)
                )
                {
                    Util_CountLiberty.Count_Recursive(ref count, location.ToSouth(), color, taikyoku);
                }
            }

            // 西隣を調べます。
            if (!location.IsWestEnd())//西端でなければ
            {
                if
                (
                    taikyoku.Goban.WestOf(location) == StoneColor.Empty
                    &&
                    taikyoku.CountedBoard.CanDo_West(location)
                )
                {
                    ++count;
                    taikyoku.CountedBoard.Done_West(location);
                }
                else if
                (
                    taikyoku.Goban.WestOf(location) == color
                    &&
                    taikyoku.CountedBoard.CanDo_West(location)
                )
                {
                    Util_CountLiberty.Count_Recursive(ref count, location.ToWest(), color, taikyoku);
                }
            }

            // 東隣を調べます。
            if (!location.IsEastEnd(taikyoku.GobanBounds))//東端でなければ
            {
                if
                (
                    (taikyoku.Goban.EastOf(location) == StoneColor.Empty)
                    &&
                    taikyoku.CountedBoard.CanDo_East(location)
                )
                {
                    ++count;
                    taikyoku.CountedBoard.Done_East(location);
                }
                else if
                (
                    taikyoku.Goban.EastOf(location) == color
                    &&
                    taikyoku.CountedBoard.CanDo_East(location)
                )
                {
                    Util_CountLiberty.Count_Recursive(ref count, location.ToEast(), color, taikyoku);
                }
            }
        }
示例#3
0
        /// <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);
            }
        }
示例#4
0
        /// <summary>
        /// 自分(コンピューター)の目へ打ち込んだとき、真。(非合法手)
        /// </summary>
        /// <param name="location">Gnugo1.2 では、石の 行番号 i = 0〜18、列番号 j = 0〜18。</param>
        /// <param name="taikyoku"></param>
        /// <returns></returns>
        public static bool IsThis
        (
            GobanPoint location,
            Taikyoku taikyoku
        )
        {
            Board ban = taikyoku.Goban; // 碁盤

            // 上辺を調べます。
            if (location.IsNorthEnd())
            {
                if
                (
                    location.IsWestEnd()    // 北西の角
                    &&
                    // 北西の隅を囲む2つの石が自分(コンピューター)の色なら。
                    ban.At(new GobanPointImpl(1, 0)) == taikyoku.MyColor
                    &&
                    ban.At(new GobanPointImpl(0, 1)) == taikyoku.MyColor
                )
                {
                    return(true);
                }
                if
                (
                    location.IsEastEnd(taikyoku.GobanBounds)   // 北東角
                    &&
                    // 北東の隅を囲む2つの石が自分(コンピューター)の色なら。
                    ban.At(new GobanPointImpl(1, taikyoku.GobanBounds.BoardEnd)) == taikyoku.MyColor
                    &&
                    ban.At(new GobanPointImpl(0, taikyoku.GobanBounds.BoardEnd - 1)) == taikyoku.MyColor
                )
                {
                    return(true);
                }

                if
                (
                    // 上辺で、3方向がコンピューターの石なら
                    ban.At(new GobanPointImpl(1, location.J)) == taikyoku.MyColor // コンピューターの石
                    &&
                    // 左右ともコンピューターの石
                    ban.At(new GobanPointImpl(0, location.J - 1)) == taikyoku.MyColor
                    &&
                    ban.At(new GobanPointImpl(0, location.J + 1)) == taikyoku.MyColor
                )
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            // 下辺を調べます。
            if (location.IsSouthEnd(taikyoku.GobanBounds))
            {
                if
                (
                    location.IsWestEnd()    // 南西角
                    &&
                    // 南西の隅を囲む2つの石がコンピューターの色なら。
                    ban.At(new GobanPointImpl(taikyoku.GobanBounds.BoardEnd - 1, 0)) == taikyoku.MyColor
                    &&
                    ban.At(new GobanPointImpl(taikyoku.GobanBounds.BoardEnd, 1)) == taikyoku.MyColor
                )
                {
                    return(true);
                }

                if
                (
                    location.IsEastEnd(taikyoku.GobanBounds)   // 南東
                    &&
                    // 南東の隅を囲む2つの石がコンピューターの色なら。
                    ban.At(new GobanPointImpl(taikyoku.GobanBounds.BoardEnd - 1, taikyoku.GobanBounds.BoardEnd)) == taikyoku.MyColor
                    &&
                    ban.At(new GobanPointImpl(taikyoku.GobanBounds.BoardEnd, taikyoku.GobanBounds.BoardEnd - 1)) == taikyoku.MyColor
                )
                {
                    return(true);
                }

                if
                (
                    // 下辺で、3方向がコンピューターの石なら
                    ban.At(new GobanPointImpl(taikyoku.GobanBounds.BoardEnd - 1, location.J)) == taikyoku.MyColor
                    &&
                    ban.At(new GobanPointImpl(taikyoku.GobanBounds.BoardEnd, location.J - 1)) == taikyoku.MyColor
                    &&
                    ban.At(new GobanPointImpl(taikyoku.GobanBounds.BoardEnd, location.J + 1)) == taikyoku.MyColor
                )
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            // 左辺を調べます。
            if (location.IsWestEnd())
            {
                if
                (
                    // 左辺で、3方向がコンピューターの石なら
                    ban.At(new GobanPointImpl(location.I, 1)) == taikyoku.MyColor
                    &&
                    ban.At(new GobanPointImpl(location.I - 1, 0)) == taikyoku.MyColor
                    &&
                    ban.At(new GobanPointImpl(location.I + 1, 0)) == taikyoku.MyColor
                )
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            // 右辺を調べます。
            if (location.IsEastEnd(taikyoku.GobanBounds))
            {
                if
                (
                    // 右辺で、3方向がコンピューターの石なら
                    ban.At(new GobanPointImpl(location.I, taikyoku.GobanBounds.BoardEnd - 1)) == taikyoku.MyColor
                    &&
                    ban.At(new GobanPointImpl(location.I - 1, taikyoku.GobanBounds.BoardEnd)) == taikyoku.MyColor
                    &&
                    ban.At(new GobanPointImpl(location.I + 1, taikyoku.GobanBounds.BoardEnd)) == taikyoku.MyColor
                )
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            // 中央のピースを調べます。
            if
            (
                // 4方向がコンピューターの石なら
                ban.NorthOf(location) == taikyoku.MyColor
                &&
                ban.EastOf(location) == taikyoku.MyColor
                &&
                ban.SouthOf(location) == taikyoku.MyColor
                &&
                ban.WestOf(location) == taikyoku.MyColor
            )
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }