public ZyosekiNode(
     GobanPoint p,
     int[] next
     )
 {
     this.P    = p;
     this.Next = next;
 }
Exemplo n.º 2
0
 /// <summary>
 /// 交点の番号。
 ///
 /// 例えば19路盤であれば、左上から右へ、右上から次の行の左端へと、
 /// 0,1,2…,18、
 /// 19,20,21...37、
 /// といったように番号が振られます。
 ///
 /// Gnugo1.2 では、endgame.c の node関数。
 /// </summary>
 /// <param name="location">Gnugo1.2 では、i,j という変数名。</param>
 /// <returns></returns>
 public static int GetNodeByLocation
 (
     GobanPoint location,
     GobanRectangleA gobanBounds
 )
 {
     return(location.I * gobanBounds.BoardSize + location.J);
 }
Exemplo n.º 3
0
        /// <summary>
        /// 人間の入力したコマンドに対応した処理を行います。
        /// 間違った入力があった場合、再帰的に呼び出されます。
        ///
        /// Gnugo1.2 では、getmove関数。
        /// </summary>
        /// <param name="move_charArray">入力した文字列。a1やT19などの指し手。</param>
        /// <param name="out_sasite">指し手。石を置く位置</param>
        /// <param name="taikyoku"></param>
        public static void DoCommand
        (
            string command_str,
            out GobanPoint out_sasite,
            Taikyoku taikyoku
        )
        {
            if (command_str == "stop")  // ゲームを終了します。
            {
                taikyoku.PlayState = GameState.Stop;
                out_sasite         = new GobanPointImpl(-1, -1);// 2015-11-26 追加
            }
            else
            {
                if (command_str == "save")  // データを保存して、ゲームを終了します。
                {
                    // 局面を、テキストファイルに書き出します。
                    Util_Save.Save(taikyoku);

                    taikyoku.PlayState = GameState.Saved;
                    // i が -1 のときは、パスのシグナルです。
                    out_sasite = new GobanPointImpl(-1, -1); // 2015-11-26 追加
                }
                else if (command_str == "pass")              // 人間のパス
                {
                    taikyoku.Pass++;
                    // i が -1 のときは、パスのシグナルです。
                    out_sasite = new GobanPointImpl(-1, -1);// 2015-11-26 追加
                }
                else
                {
                    taikyoku.Pass = 0;
                    if (
                        // 例えば、 a1 や、 T19 といった入力文字を解析し、盤上の位置に変換します。
                        !PointFugoImpl.TryParse(command_str, out out_sasite, taikyoku)
                        ||
                        (taikyoku.Goban.At(out_sasite) != StoneColor.Empty)
                        ||
                        Util_Suicide.Aa_Suicide(out_sasite, taikyoku)
                        )
                    {
                        //
                        // 非合法手だった場合、再入力を促します。
                        //
                        Console.WriteLine("illegal move !"); // [" + command_str + "] 2015-11-26 入力されたコマンドを表示するように拡張
                        Console.Write("your move? ");

                        // 続けて、再帰的に処理実行。
                        string command_str2 = Console.ReadLine();
                        //scanf("%s", move);

                        Util_CommandDriven.DoCommand(command_str2, out out_sasite, taikyoku);
                    }
                }
            }
        }
Exemplo n.º 4
0
 /// <summary>
 /// 交点の番号を、碁盤の座標 i,j に戻します。
 ///
 /// Gnugo1.2 では、endgame.c の node2ij関数。
 /// </summary>
 /// <param name="out_location"></param>
 /// <param name="node"></param>
 public static void GetLocationByNode(
     out GobanPoint out_location,
     int node,
     GobanRectangleA gobanBounds
     )
 {
     out_location = new GobanPointImpl(
         node / gobanBounds.BoardSize,
         node % gobanBounds.BoardSize
         );
 }
        /// <summary>
        /// 碁盤の指定の交点 i,j にある石を起点に、つながっている同じ色の(1つ、または連の)石(color piece)の総リバーティを数えます。
        ///
        /// Gnugo1.2 では、countlib関数です。
        /// </summary>
        /// <param name="out_count">Gnugo1.2 では、グローバル変数 lib でした。</param>
        /// <param name="startLocation_inPiece">Gnugo1.2では、 行番号 m = 0〜18、列番号 n = 0〜18。</param>
        /// <param name="color">黒 or 白</param>
        public static void Count
        (
            out int out_count,
            GobanPoint startLocation_inPiece,
            StoneColor color,
            Taikyoku taikyoku
        )
        {
            out_count = 0;// Gnugo1.2 では、countlib関数の呼び出し元で グローバル変数を lib = 0 していました。


            // 全てのピースを数えなおせるように、リセットします。
            taikyoku.CountedBoard.FillAll_WeCan(taikyoku.GobanBounds.BoardSize);

            // カレント・ピースのリバティーを数えます。
            Util_CountLiberty.Count_Recursive(ref out_count, startLocation_inPiece, color, taikyoku);
        }
Exemplo n.º 6
0
        /// <summary>
        /// もし四角形 (i1,j1)〜(i2,j2)がオープン(全て空っぽ)なら、調べます。
        ///
        /// Gnugo1.2 では、 openregion関数。
        /// </summary>
        /// <param name="corner1">Gnugo1.2 では、i1,j1 引数。</param>
        /// <param name="corner2">Gnugo1.2 では、i2,j2 引数。</param>
        /// <param name="taikyoku"></param>
        /// <returns></returns>
        public static bool IsEmptyRectangle
        (
            GobanPoint corner1,
            GobanPoint corner2,
            Taikyoku taikyoku
        )
        {
            int minx, maxx, miny, maxy, x, y;

            // 上下の限界を差替えます。
            if (corner1.I < corner2.I)
            {
                miny = corner1.I;
                maxy = corner2.I;
            }
            else
            {
                miny = corner2.I;
                maxy = corner1.I;
            }

            if (corner1.J < corner2.J)
            {
                minx = corner1.J;
                maxx = corner2.J;
            }
            else
            {
                minx = corner2.J;
                maxx = corner1.J;
            }

            // 空っぽ領域を調べます。
            for (y = miny; y <= maxy; y++)
            {
                for (x = minx; x <= maxx; x++)
                {
                    if (taikyoku.Goban.At(new GobanPointImpl(y, x)) != StoneColor.Empty)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
        /// <summary>
        /// ゲームツリーから序盤のための動きを取得します。
        /// </summary>
        /// <param name="p"></param>
        /// <param name="ref_nodeNo">Gnugo1.2 では 引数cnd。</param>
        /// <param name="moveType"></param>
        /// <param name="taikyoku"></param>
        /// <returns></returns>
        public static bool Opening
        (
            out GobanPoint p,
            ref int ref_nodeNo,
            MoveType moveType,
            Taikyoku taikyoku
        )
        {
            int m;

            p = new GobanPointImpl();

            /* get i, j */
            if (moveType == MoveType.Inverted || moveType == MoveType.Inverted_And_Reflected)
            {
                p.I = taikyoku.GobanBounds.BoardEnd - OpeningZyosekiImpl.ZyosekiTree[ref_nodeNo].P.I;   /* inverted */
            }
            else
            {
                p.I = OpeningZyosekiImpl.ZyosekiTree[ref_nodeNo].P.I;
            }

            if (moveType == MoveType.Reflected || moveType == MoveType.Inverted_And_Reflected)
            {
                p.J = taikyoku.GobanBounds.BoardEnd - OpeningZyosekiImpl.ZyosekiTree[ref_nodeNo].P.J;   /* reflected */
            }
            else
            {
                p.J = OpeningZyosekiImpl.ZyosekiTree[ref_nodeNo].P.J;
            }

            if (OpeningZyosekiImpl.ZyosekiTree[ref_nodeNo].Next.Length != 0) // 定石に、次の指し手がまだあるなら。
            {
                // 次にどの定石を進むかはランダム(等確率)。
                m          = taikyoku.Random.Next() % OpeningZyosekiImpl.ZyosekiTree[ref_nodeNo].Next.Length;
                ref_nodeNo = OpeningZyosekiImpl.ZyosekiTree[ref_nodeNo].Next[m]; // 定石グラフ図の新しいノード番号へ。
                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemplo n.º 8
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);
            }
        }
Exemplo n.º 9
0
 public void SetLocation(GobanPoint p)
 {
     this.I = p.I;
     this.J = p.J;
 }
Exemplo n.º 10
0
 /// <summary>
 /// 碁石を交点に置きます。
 /// </summary>
 /// <param name="location"></param>
 /// <param name="color"></param>
 public void Put(GobanPoint location, StoneColor color)
 {
     this.Position[location.I, location.J] = color;
 }
Exemplo n.º 11
0
        /// <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>
        /// 指定した交点(a)から、四方に接続している石を全て数え上げて、返します。
        ///
        /// aの交点は、人間がコンソールから入力して指定します。
        /// </summary>
        /// <param name="out_connectedStones_asNode">Gnugo1.2 では、listpt という名前のグローバル配列。</param>
        /// <param name="humanInput_location">Gnugo1.2 では、i,j という変数名。人間がコンソールに入力した交点が入っている。</param>
        /// <param name="list_neswStones_asNode_eachPoint">Gnugo1.2 では、 movelist という名称。</param>
        private static void GetConnectedStones_AsNode_FromPoint
        (
            out List <int> out_connectedStones_asNode,
            GobanPoint humanInput_location,
            Dictionary <int, List <int> > list_neswStones_asNode_eachPoint,
            Taikyoku taikyoku
        )
        {
            out_connectedStones_asNode = new List <int>();

            //
            // この交点は数えたかどうかのフラグです。
            //
            // Gnugo1.2 では color という変数名だったが、石の色と紛らわしいので名称を変更した。
            //
            CheckFlag_Ending[] counted_onBoard = new CheckFlag_Ending[taikyoku.GobanBounds.Nodes];

            //
            // 全ての交点を、まだ数えていないという設定にします。
            //
            for (int node = 0; node < taikyoku.GobanBounds.Nodes; node++)
            {
                counted_onBoard[node] = CheckFlag_Ending.Yet;
            }

            //
            // 人間がコンソール入力した交点にある石と、四方がつながっている同じ色の石が
            // このキューに入っては出て、を連鎖します。
            //
            // Gnugo1.2 では、キューも自作していたが、C#盤では 既存のものを使うように変更。
            //
            Queue queue_connectedNodes = new Queue(150);

            // 人間が指定した交点は チェック済みにし、キューに追加します。
            counted_onBoard[Util_AboutBoard.GetNodeByLocation(humanInput_location, taikyoku.GobanBounds)] = CheckFlag_Ending.Working;
            queue_connectedNodes.Enqueue(Util_AboutBoard.GetNodeByLocation(humanInput_location, taikyoku.GobanBounds));
#if DEBUG
            Console.WriteLine("Survived first enqueue in bfslist.");
#endif

            //
            // キューが空になるまで、処理の連鎖を繰り返します。
            //
            while (queue_connectedNodes.Count != 0)
            {
                // まず、人間に指定された交点。(ループの2週目からは、その隣接する石)
                int node_a = (int)queue_connectedNodes.Dequeue();

                // 指定された交点の、存在する北東南西隣の石。(既に調べて配列に入れてあります)
                for (int nesw = 0; nesw < list_neswStones_asNode_eachPoint[node_a].Count; nesw++)//
                {
                    // その北東南西隣の石について
                    int node_b = list_neswStones_asNode_eachPoint[node_a][nesw];

                    // まだ数えていなければ
                    if (counted_onBoard[node_b] == CheckFlag_Ending.Yet)
                    {
                        // その交点には作業中フラグを立て、
                        // その交点(隣の石)を、次に判定する石としてキューに追加します。連鎖的な動きになります。
                        counted_onBoard[node_b] = CheckFlag_Ending.Working;
                        queue_connectedNodes.Enqueue(node_b); //
                    }
                }
#if DEBUG
                Console.WriteLine("Just prior to first dequeue!.");
#endif

                // 人間に指定された交点(ループの2週目からは、その隣接する石)は、
                // 数え上げる対象から外し、返却用のリストに追加します。
                counted_onBoard[node_a] = CheckFlag_Ending.Finished;
                out_connectedStones_asNode.Add(node_a);
            }
        }
Exemplo n.º 13
0
 /// <summary>
 /// 引数で指定したポイントの西隣が、このポイントなら真。
 /// </summary>
 /// <returns></returns>
 public bool Is_WestOf(GobanPoint location)
 {
     return(this.I == location.I && this.J == location.J - 1);
 }
Exemplo n.º 14
0
        /// <summary>
        /// 指定したポイントについて、全てのリバティーが開いているスペースを探します。
        ///
        /// 再帰します。
        ///
        /// Gnugo1.2 では findopen関数。
        /// </summary>
        /// <param name="try3Locations">(mutable)隣接する東西南北の最大3方向がこの配列に入るはず。Gnugo1.2 では、i配列、j配列。</param>
        /// <param name="curLocation">Gnugo1.2では、 カレント 行番号 m = 0〜18、列番号 n = 0〜18。</param>
        /// <param name="color">黒 or 白</param>
        /// <param name="liberty123OfPiece">Gnugo1.2 では minlib 引数。3以下のリバティー</param>
        /// <param name="taikyoku"></param>
        /// <returns></returns>
        public static bool FindOpen3Locations
        (
            List <GobanPoint> try3Locations,
            GobanPoint curLocation,
            StoneColor color,
            int liberty123OfPiece,
            Taikyoku taikyoku
        )
        {
            bool  result;
            Board ban = taikyoku.Goban; // 碁盤

            // この位置はもう調べた、というフラグを立てます。
            taikyoku.MarkingBoard.Done_Current(curLocation);

            // 北ネイバー
            if (!curLocation.IsNorthEnd())//北端でなければ
            {
                if
                (
                    // 北隣が空っぽで。
                    ban.NorthOf(curLocation) == StoneColor.Empty
                    &&
                    // 北隣が、石を取った場所(コウになるかもしれない)でなければ。
                    !taikyoku.MyKo.Is_NorthOf(curLocation)
                )
                {
                    // 北隣を候補として追加。
                    try3Locations.Add(curLocation.ToNorth());
                    if (try3Locations.Count == liberty123OfPiece)
                    {
                        // リバティーの数分追加したなら正常終了。
                        result = true;
                        goto gt_EndMethod;
                    }
                }
                else if
                (
                    // 指定したポイントの北隣が指定の色で。
                    ban.NorthOf(curLocation) == color
                    &&
                    taikyoku.MarkingBoard.CanDo_North(curLocation) // 北側をまだ調べていないなら
                )
                {
                    if
                    (
                        Util_FindOpen.FindOpen3Locations(try3Locations, curLocation.ToNorth(), color, liberty123OfPiece, taikyoku)
                        &&
                        try3Locations.Count == liberty123OfPiece
                    )
                    {
                        result = true;
                        goto gt_EndMethod;
                    }
                }
            }

            // 南ネイバーを調べます。
            if (!curLocation.IsSouthEnd(taikyoku.GobanBounds))
            {
                if
                (
                    ban.SouthOf(curLocation) == StoneColor.Empty
                    &&
                    // 南隣が、取った石(コウかもしれない)でなければ。
                    !taikyoku.MyKo.Is_SouthOf(curLocation)
                )
                {
                    try3Locations.Add(curLocation.ToSouth());
                    if (try3Locations.Count == liberty123OfPiece)
                    {
                        result = true;
                        goto gt_EndMethod;
                    }
                }
                else
                {
                    if
                    (
                        ban.SouthOf(curLocation) == color
                        &&
                        taikyoku.MarkingBoard.CanDo_South(curLocation)
                    )
                    {
                        if
                        (
                            Util_FindOpen.FindOpen3Locations(try3Locations, curLocation.ToSouth(), color, liberty123OfPiece, taikyoku)
                            &&
                            try3Locations.Count == liberty123OfPiece
                        )
                        {
                            result = true;
                            goto gt_EndMethod;
                        }
                    }
                }
            }

            // 西ネイバーを調べます。
            if (curLocation.J != 0)
            {
                if
                (
                    ban.WestOf(curLocation) == StoneColor.Empty
                    &&
                    // 西隣が、取った石(コウかもしれない)でなければ。
                    taikyoku.MyKo.Is_WestOf(curLocation)
                )
                {
                    try3Locations.Add(curLocation.ToWest());
                    if (try3Locations.Count == liberty123OfPiece)
                    {
                        result = true;
                        goto gt_EndMethod;
                    }
                }
                else if
                (
                    ban.WestOf(curLocation) == color
                    &&
                    taikyoku.MarkingBoard.CanDo_West(curLocation)
                )
                {
                    if
                    (
                        Util_FindOpen.FindOpen3Locations(try3Locations, curLocation.ToWest(), color, liberty123OfPiece, taikyoku)
                        &&
                        try3Locations.Count == liberty123OfPiece
                    )
                    {
                        result = true;
                        goto gt_EndMethod;
                    }
                }
            }

            // 東ネイバーを調べます。
            if (!curLocation.IsEastEnd(taikyoku.GobanBounds))
            {
                if
                (
                    ban.EastOf(curLocation) == StoneColor.Empty
                    &&
                    // 東隣が、取った石(コウかもしれない)でなければ。
                    taikyoku.MyKo.Is_EastOf(curLocation)
                )
                {
                    try3Locations.Add(curLocation.ToEast());
                    if (try3Locations.Count == liberty123OfPiece)
                    {
                        result = true;
                        goto gt_EndMethod;
                    }
                }
                else if
                (
                    ban.EastOf(curLocation) == color
                    &&
                    taikyoku.MarkingBoard.CanDo_East(curLocation)
                )
                {
                    if
                    (
                        Util_FindOpen.FindOpen3Locations(try3Locations, curLocation.ToEast(), color, liberty123OfPiece, taikyoku)
                        &&
                        try3Locations.Count == liberty123OfPiece
                    )
                    {
                        result = true;
                        goto gt_EndMethod;
                    }
                }
            }

            // 開いているポイントを見つけるのに失敗したら
            result = false;

gt_EndMethod:
            return(result);
        }
Exemplo n.º 15
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);
            }
        }
Exemplo n.º 16
0
 /// <summary>
 /// 指定の交点の東側の石の色を見ます。
 /// </summary>
 /// <param name="location"></param>
 /// <returns></returns>
 public StoneColor EastOf(GobanPoint location)
 {
     // Gnugo1.2 で、 p[m][n + 1] は東隣。
     return(this.Position[location.I, location.J + 1]);
 }
Exemplo n.º 17
0
 /// <summary>
 /// 指定の交点の北側の石の色を見ます。
 /// </summary>
 /// <param name="location"></param>
 /// <returns></returns>
 public StoneColor NorthOf(GobanPoint location)
 {
     // Gnugo1.2 で、 p[m - 1][n] は北隣。
     return(this.Position[location.I - 1, location.J]);
 }
Exemplo n.º 18
0
 /// <summary>
 /// 指定の交点の石の色を見ます。
 /// </summary>
 /// <param name="location"></param>
 /// <returns></returns>
 public StoneColor At(GobanPoint location)
 {
     return(this.Position[location.I, location.J]);
 }
        /// <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);
            }
        }
Exemplo n.º 20
0
 /// <summary>
 /// 指定の交点の南側の石の色を見ます。
 /// </summary>
 /// <param name="location"></param>
 /// <returns></returns>
 public StoneColor SouthOf(GobanPoint location)
 {
     // Gnugo1.2 で、 p[m + 1][n] は南隣。
     return(this.Position[location.I + 1, location.J]);
 }
Exemplo n.º 21
0
        /// <summary>
        /// 次の動きのためにマッチする定石(パターン)を探します。
        ///
        /// Gnugo1.2 では findpatn関数。
        /// </summary>
        /// <param name="out_location">次の動きの   行、列番号</param>
        /// <param name="out_score">Gnugo1.2 では val 引数。次の指し手の評価値</param>
        /// <param name="taikyoku"></param>
        /// <returns></returns>
        public static bool FindPattern
        (
            out GobanPoint out_location,
            out int out_score,
            Taikyoku taikyoku
        )
        {
            GobanPoint tryLocation; // Gnugo1.2 では、ti,tj という変数名
            int        tryScore;    // Gnugo1.2 では、tval という変数名。

            //
            // オープニングの定石は、盤面全体のものです。
            //
            // まず、序盤で占領(オキュパイ;occupy)できる角(corners)を狙い、
            // 次に、開いている四辺を狙っていきます。
            //

            //----------------------------------------
            // 定石[4] 最後の動きの続き
            //----------------------------------------
            //
            // 初回はOFFです。他の定石が順調に進んでいるとき、このフラグが立っています。
            //
            if (taikyoku.OpeningZyosekiFlag[4])
            {
                taikyoku.OpeningZyosekiFlag[4] = false; // この定石をOFFにします。

                // 前回のデータを取り出します。
                int      cnd      = ((ComputerPlayerB)taikyoku.ComputerPlayer).NodeNo;
                MoveType movetype = ((ComputerPlayerB)taikyoku.ComputerPlayer).Movetype;
                if (OpeningZyosekiImpl.Opening(out out_location, ref cnd, movetype, taikyoku))
                {
                    taikyoku.OpeningZyosekiFlag[4] = true; // もっと動くなら、この定石をONにリセットします。
                }
                ((ComputerPlayerB)taikyoku.ComputerPlayer).NodeNo = cnd;

                if (taikyoku.Goban.At(out_location) == StoneColor.Empty) // 置けるなら
                {
                    out_score = Util_FindOpeningZyoseki.ZYOSEKI_SCORE;   // 定石の評価値
                    return(true);
                }
                else
                {
                    // 石を置けなかったら、この定石も終わります。
                    taikyoku.OpeningZyosekiFlag[4] = false;
                }
            }

            //----------------------------------------
            // 定石[0] 西北の角
            //----------------------------------------
            if (taikyoku.OpeningZyosekiFlag[0])
            {
                taikyoku.OpeningZyosekiFlag[0] = false; // フラグをクリアー。
                if (Util_EmptyRectangle.IsEmptyRectangle(new GobanPointImpl(0, 0), new GobanPointImpl(5, 5), taikyoku))
                {
                    int      cnd      = 0;
                    MoveType movetype = MoveType.Basic;
                    OpeningZyosekiImpl.Opening(out out_location, ref cnd, movetype, taikyoku);  // 次の手のための新しいノードを取得します。
                    if (OpeningZyosekiImpl.Opening(out out_location, ref cnd, movetype, taikyoku))
                    {
                        taikyoku.OpeningZyosekiFlag[4] = true;
                    }
                    ((ComputerPlayerB)taikyoku.ComputerPlayer).NodeNo   = cnd;
                    ((ComputerPlayerB)taikyoku.ComputerPlayer).Movetype = movetype;

                    out_score = Util_FindOpeningZyoseki.ZYOSEKI_SCORE;  // 評価値
                    return(true);
                }
            }

            //----------------------------------------
            // 定石[1] 南西の角
            //----------------------------------------
            if (taikyoku.OpeningZyosekiFlag[1])
            {
                taikyoku.OpeningZyosekiFlag[1] = false;
                if (Util_EmptyRectangle.IsEmptyRectangle(new GobanPointImpl(13, 0), new GobanPointImpl(18, 5), taikyoku))
                {
                    int      cnd      = 0;
                    MoveType movetype = MoveType.Inverted;
                    OpeningZyosekiImpl.Opening(out out_location, ref cnd, movetype, taikyoku); // 次の手のための新しいノードを取得します。
                    if (OpeningZyosekiImpl.Opening(out out_location, ref cnd, movetype, taikyoku))
                    {
                        taikyoku.OpeningZyosekiFlag[4] = true;
                    }
                    ((ComputerPlayerB)taikyoku.ComputerPlayer).NodeNo   = cnd;
                    ((ComputerPlayerB)taikyoku.ComputerPlayer).Movetype = movetype;

                    out_score = Util_FindOpeningZyoseki.ZYOSEKI_SCORE;  // 評価値
                    return(true);
                }
            }

            //----------------------------------------
            // 定石[2] 北東の角
            //----------------------------------------
            if (taikyoku.OpeningZyosekiFlag[2])
            {
                taikyoku.OpeningZyosekiFlag[2] = false;
                if (Util_EmptyRectangle.IsEmptyRectangle(new GobanPointImpl(0, 13), new GobanPointImpl(5, 18), taikyoku))
                {
                    int      cnd      = 0;
                    MoveType movetype = MoveType.Reflected;
                    OpeningZyosekiImpl.Opening(out out_location, ref cnd, movetype, taikyoku);   // 次の手のための新しいノードを取得します。
                    if (OpeningZyosekiImpl.Opening(out out_location, ref cnd, movetype, taikyoku))
                    {
                        taikyoku.OpeningZyosekiFlag[4] = true;
                    }
                    ((ComputerPlayerB)taikyoku.ComputerPlayer).NodeNo   = cnd;
                    ((ComputerPlayerB)taikyoku.ComputerPlayer).Movetype = movetype;

                    out_score = Util_FindOpeningZyoseki.ZYOSEKI_SCORE;  // 評価値
                    return(true);
                }
            }

            //----------------------------------------
            // 定石[3] 南東の角
            //----------------------------------------
            if (taikyoku.OpeningZyosekiFlag[3])
            {
                taikyoku.OpeningZyosekiFlag[3] = false;
                if (Util_EmptyRectangle.IsEmptyRectangle(new GobanPointImpl(13, 13), new GobanPointImpl(18, 18), taikyoku))
                {
                    int      cnd      = 0;
                    MoveType movetype = MoveType.Inverted_And_Reflected;
                    OpeningZyosekiImpl.Opening(out out_location, ref cnd, movetype, taikyoku);   // 次の手のための新しいノードを取得します。
                    if (OpeningZyosekiImpl.Opening(out out_location, ref cnd, movetype, taikyoku))
                    {
                        taikyoku.OpeningZyosekiFlag[4] = true;
                    }
                    ((ComputerPlayerB)taikyoku.ComputerPlayer).NodeNo   = cnd;
                    ((ComputerPlayerB)taikyoku.ComputerPlayer).Movetype = movetype;

                    out_score = Util_FindOpeningZyoseki.ZYOSEKI_SCORE;  // 評価値
                    return(true);
                }
            }

            //
            // 辺(edges)のオキュパイ(occupy)
            //

            //----------------------------------------
            // 定石[5] 北辺
            //----------------------------------------
            //
            // 碁番の北側の矩形領域が空っぽなら、打ち込む場所の定石が1つあります。この定石はこの1箇所だけです。
            //
            if (taikyoku.OpeningZyosekiFlag[5])
            {
                taikyoku.OpeningZyosekiFlag[5] = false;
                if (Util_EmptyRectangle.IsEmptyRectangle(new GobanPointImpl(0, 6), new GobanPointImpl(4, 11), taikyoku))
                {
                    out_location = new GobanPointImpl(3, 9);              // 次の指し手の位置i,j
                    out_score    = Util_FindOpeningZyoseki.ZYOSEKI_SCORE; // 評価値
                    return(true);
                }
            }

            //----------------------------------------
            // 定石[6] 南辺
            //----------------------------------------
            //
            // 碁番の南側の矩形領域が空っぽなら、打ち込む場所の定石が1つあります。この定石はこの1箇所だけです。
            //
            if (taikyoku.OpeningZyosekiFlag[6])
            {
                taikyoku.OpeningZyosekiFlag[6] = false;
                if (Util_EmptyRectangle.IsEmptyRectangle(new GobanPointImpl(18, 6), new GobanPointImpl(14, 11), taikyoku))
                {
                    out_location = new GobanPointImpl(15, 9);             // 次の指し手の位置i,j
                    out_score    = Util_FindOpeningZyoseki.ZYOSEKI_SCORE; // 評価値
                    return(true);
                }
            }

            //----------------------------------------
            // 定石[7] 西辺
            //----------------------------------------
            //
            // 碁番の西側の矩形領域が空っぽなら、打ち込む場所の定石が1つあります。この定石はこの1箇所だけです。
            //
            if (taikyoku.OpeningZyosekiFlag[7])
            {
                taikyoku.OpeningZyosekiFlag[7] = false;
                if (Util_EmptyRectangle.IsEmptyRectangle(new GobanPointImpl(6, 0), new GobanPointImpl(11, 4), taikyoku))
                {
                    out_location = new GobanPointImpl(9, 3);              // 次の指し手の位置i,j
                    out_score    = Util_FindOpeningZyoseki.ZYOSEKI_SCORE; // 評価値
                    return(true);
                }
            }

            //----------------------------------------
            // 定石[8] 東辺
            //----------------------------------------
            //
            // 碁番の東側の矩形領域が空っぽなら、打ち込む場所の定石が1つあります。この定石はこの1箇所だけです。
            //
            if (taikyoku.OpeningZyosekiFlag[8])
            {
                taikyoku.OpeningZyosekiFlag[8] = false;
                if (Util_EmptyRectangle.IsEmptyRectangle(new GobanPointImpl(6, 18), new GobanPointImpl(11, 14), taikyoku))
                {
                    out_location = new GobanPointImpl(9, 15);             // 次の指し手の位置i,j
                    out_score    = Util_FindOpeningZyoseki.ZYOSEKI_SCORE; // 評価値
                    return(true);
                }
            }

            //
            // 序盤定石のどれにも当てはまらなければ。
            //

            out_location = new GobanPointImpl(-1, -1);
            out_score    = -1;

            //
            // 局地的な定石を探します。
            //
            for (int m = 0; m < taikyoku.GobanBounds.BoardSize; m++)
            {
                for (int n = 0; n < taikyoku.GobanBounds.BoardSize; n++)
                {
                    GobanPoint mnLocation = new GobanPointImpl(m, n);
                    if
                    (
                        taikyoku.Goban.At(mnLocation) == taikyoku.MyColor // コンピューターの石
                        &&
                        Util_FindLocalZyoseki.FindPattern(out tryLocation, out tryScore, mnLocation, taikyoku)
                        &&
                        out_score < tryScore   // 評価値が高ければ
                    )
                    {
                        out_score = tryScore;                  // 評価値
                        out_location.SetLocation(tryLocation); // 次の指し手の位置i,j
                    }
                }
            }

            if (out_score > 0)   // 定石(パターン)を見つけました。
            {
                return(true);
            }
            else    // 定石は見つかりませんでした。
            {
                return(false);
            }
        }
 /// <summary>
 /// 指定した位置を使用したならチェックします。
 /// </summary>
 /// <param name="location"></param>
 /// <returns></returns>
 public void Done_Current(GobanPoint location)
 {
     // Gnugo1.2 では 1 (if文で真になる)でマークしていました。
     /// C#版に改造するにあたり、真偽値を逆にしました。
     this.ma[location.I, location.J] = false;// true;
 }
        /// <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);
                }
            }
        }
Exemplo n.º 24
0
 /// <summary>
 /// 引数で指定したポイントの南隣が、このポイントなら真。
 /// </summary>
 /// <returns></returns>
 public bool Is_SouthOf(GobanPoint location)
 {
     return(this.I == location.I + 1 && this.J == location.J);
 }
Exemplo n.º 25
0
        /// <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);
        }
Exemplo n.º 26
0
        /// <summary>
        /// 入力文字列を、i,j 座標へ変換します。
        ///
        /// Gnugo1.2 では、getij 関数だったものを改造。
        /// </summary>
        /// <param name="move_str"></param>
        /// <param name="out_location"></param>
        /// <returns></returns>
        public static bool TryParse
        (
            string move_str,             // 2桁、または3桁の指し手文字列。Gnugo1.2では move という引数名。
            out GobanPoint out_location, // 指し手の 行、列番号
            Taikyoku taikyoku
        )
        {
            // move[0] from A〜T
            // move[1] move[2] from 1〜19
            // 指し手を座標に変換します。
            char[] move = move_str.ToCharArray();
            int    k;

            out_location = new GobanPointImpl(-1, -1); // 2015-11-27 追加

            if (move.Length < 2)                       // 2015-11-26 追加
            {
                // 2文字未満なら非妥当。
                return(false);
            }

            // 1文字目
            if
            (
                // A〜H なら
                (move[0] >= 'A')
                &&
                (move[0] <= 'H')
            )
            {
                // 0〜7列 に変換
                out_location.J = move[0] - 'A';
            }
            else
            {
                if
                (
                    // J〜T なら
                    (move[0] >= 'J')
                    &&
                    (move[0] <= 'T')
                )
                {
                    // 8〜18列 に変換
                    out_location.J = move[0] - 'B';
                }
                else
                {
                    // a〜h なら
                    if ((move[0] >= 'a') && (move[0] <= 'h'))
                    {
                        // 0〜7列 に変換
                        out_location.J = move[0] - 'a';
                    }
                    else
                    {
                        // j〜t なら
                        if ((move[0] >= 'j') && (move[0] <= 't'))
                        {
                            // 8〜18列に変換
                            out_location.J = move[0] - 'b';
                        }
                        else
                        {
                            out_location.MoveToVanish();// 2015-11-26 追加
                            return(false);
                        }
                    }
                }
            }

            // 2文字目は、段に使う
            k = move[1] - '0';

            // 3文字目は段
            if (2 < move.Length)
            {
                k = k * 10 + move[2] - '0';
            }
            out_location.I = taikyoku.GobanBounds.BoardSize - k;

            if (out_location.ContainsI(0, taikyoku.GobanBounds.BoardEnd))
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
 /// <summary>
 /// 西側をチェック可能なら真。
 /// </summary>
 /// <param name="location"></param>
 /// <returns></returns>
 public bool CanDo_West(GobanPoint location)
 {
     /// Gnugo1.2 では if文の中で !ma[m][n-1] 判定していました。
     /// C#版に改造するにあたり、真偽値を逆にしました。
     return(this.ma[location.I, location.J - 1]);//!
 }
Exemplo n.º 28
0
 /// <summary>
 /// 指定の交点の西側の石の色を見ます。
 /// </summary>
 /// <param name="location"></param>
 /// <returns></returns>
 public StoneColor WestOf(GobanPoint location)
 {
     // Gnugo1.2 で、 p[m][n - 1] は西隣。
     return(this.Position[location.I, location.J - 1]);
 }
 /// <summary>
 /// 北側をチェック可能なら真。
 /// </summary>
 /// <param name="location"></param>
 /// <returns></returns>
 public bool CanDo_North(GobanPoint location)
 {
     /// Gnugo1.2 では if文の中で !ma[m-1][n] 判定していました。
     /// C#版に改造するにあたり、真偽値を逆にしました。
     return(this.ma[location.I - 1, location.J]);//!
 }
Exemplo n.º 30
0
        /// <summary>
        /// もし、幾つかのピースズが脅かされているなら、動きを探します。
        ///
        /// Gnugo1.2 では findsaver 関数。
        /// </summary>
        /// <param name="out_bestLocation">次の指し手の   行、列番号</param>
        /// <param name="out_maxScore">Gnugo1.2 では、val 引数。次の指し手の評価値</param>
        /// <param name="libertyOfNodes">
        /// カレント色の(1つ、または連の)石のリバティー(四方の石を置けるところ)
        ///
        /// Gnugo1.2 では、l という名前のグローバル変数。liberty の略だろうか?
        /// eval で内容が設定され、その内容は exambord、findsavr、findwinr、suicideで使用されます。
        /// </param>
        /// <param name="taikyoku"></param>
        /// <returns></returns>
        public static bool FindLocation_LibertyWeak
        (
            out GobanPoint out_bestLocation,
            out int out_maxScore,
            int[,] libertyOfNodes,
            Taikyoku taikyoku
        )
        {
            Board ban     = taikyoku.Goban;                 // 碁盤
            int   banSize = taikyoku.GobanBounds.BoardSize; //何路盤

            out_bestLocation = new GobanPointImpl(-1, -1);  // 位置i,j
            out_maxScore     = -1;                          // 評価値

            //
            // まず リバティが1つ、
            // 次に リバティが2つ、
            // と、リバティの少ない方から順に評価を付けていきます。
            // 盤面を4回探し回ることになります。
            //
            for (int iExpectedLiberty = 1; iExpectedLiberty < 4; iExpectedLiberty++)// リバティー 1〜3 のループカウンター。Gnugo1.2 では minlib 変数。
            {
                // 最小リバティーといっしょのピースを数えます。
                for (int m = 0; m < banSize; m++)
                {
                    for (int n = 0; n < banSize; n++)
                    {
                        GobanPoint iLocation = new GobanPointImpl(m, n);//検索中の位置。

                        if
                        (
                            ban.At(iLocation) == taikyoku.MyColor    // 脅かされているかもしれない自分(コンピューター)の色
                            &&
                            libertyOfNodes[m, n] == iExpectedLiberty // 呼吸点の数が少ないかもしれない
                        )
                        {
                            GobanPoint bestLocation; // Gnugo1.2 では、ti,tj (try i,j)という変数名。
                            int        bestScore;    // Gnugo1.2 では、tval 変数。評価値

                            // セーブ・ピースズへの動きを探します。
                            taikyoku.MarkingBoard.Initmark(taikyoku.GobanBounds.BoardSize);
                            if
                            (
                                Util_SasiteNext.FindStone_LibertyWeak(out bestLocation, out bestScore, iLocation, iExpectedLiberty, taikyoku)
                                &&
                                (out_maxScore < bestScore)   // 評価値が高い(リバティーが少なくて危険)ならば
                            )
                            {
                                out_maxScore = bestScore;                   // 評価値
                                out_bestLocation.SetLocation(bestLocation); // 位置i,j
                            }
                        }
                    }
                }
            }

            if (0 < out_maxScore)   // 動きが見つかれば
            {
                return(true);
            }
            else    // 動きが見つからなかったら
            {
                return(false);
            }
        }