/// <summary>
        /// 盤上の各場所について、隣四方に同じ色の石があるかを調べ、
        /// あれば その場所を記憶します。
        ///
        /// Gnugo1.2 では createlist関数。二次元配列を使用していたが、Dictionary、List に変更した。
        /// </summary>
        /// <param name="color"></param>
        /// <param name="out_list_neswStones_asNode_eachPoint">Gnugo1.2 では、 movelist という名称。</param>
        /// <param name="taikyoku"></param>
        private static void GetNeswStones_AsNode_EachPoint(
            StoneColor color,
            out Dictionary <int, List <int> > out_list_neswStones_asNode_eachPoint,
            Taikyoku taikyoku
            )
        {
            //----------------------------------------
            // 実装の説明
            //----------------------------------------
            //
            // 各場所について、隣四方に同じ色の石があるかを調べ、
            // あれば その場所を記憶します。
            //

            out_list_neswStones_asNode_eachPoint = new Dictionary <int, List <int> >();

            for (int i = 0; i < taikyoku.GobanBounds.BoardSize; i++)
            {
                for (int j = 0; j < taikyoku.GobanBounds.BoardSize; j++)
                {
                    GobanPoint location = new GobanPointImpl(i, j);

                    if (taikyoku.Goban.At(location) == color)                                         //指定した色の石について
                    {
                        int node = Util_AboutBoard.GetNodeByLocation(location, taikyoku.GobanBounds); //盤上の場所の通し番号

                        // 北東南西の場所。石がある場合のみ。
                        List <int> neswNodes = new List <int>();
                        // まず、その場所の四方の様子を記憶するためのリストを用意。
                        out_list_neswStones_asNode_eachPoint.Add(node, neswNodes);

                        // 北隣を調べる
                        if (!location.IsNorthEnd())//北端ではないなら。
                        {
                            if (taikyoku.Goban.NorthOf(location) == color)
                            {
                                neswNodes.Add(Util_AboutBoard.GetNodeByLocation(location.ToNorth(), taikyoku.GobanBounds));//北隣の場所を追加。
                            }
                        }
                        // 東隣を調べる
                        if (!location.IsEastEnd(taikyoku.GobanBounds))//東端ではないなら。
                        {
                            if (taikyoku.Goban.EastOf(location) == color)
                            {
                                neswNodes.Add(Util_AboutBoard.GetNodeByLocation(location.ToEast(), taikyoku.GobanBounds));
                            }
                        }
                        // 南隣を調べる
                        if (!location.IsSouthEnd(taikyoku.GobanBounds))//南端ではないなら
                        {
                            if (taikyoku.Goban.SouthOf(location) == color)
                            {
                                neswNodes.Add(Util_AboutBoard.GetNodeByLocation(location.ToSouth(), taikyoku.GobanBounds));
                            }
                        }
                        // 西隣を調べる
                        if (!location.IsWestEnd())//西端ではないなら。
                        {
                            if (taikyoku.Goban.WestOf(location) == color)
                            {
                                neswNodes.Add(Util_AboutBoard.GetNodeByLocation(location.ToWest(), taikyoku.GobanBounds));
                            }
                        }
                    }
                    // end if for color
                }
                // End j loop
            }
            // End i loop
        }
        /// <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);
            }
        }
        /// <summary>
        /// 死んでいる石のつながりを、盤上から削除します。
        ///
        /// Gnugo1.2 では、endgame関数。
        /// </summary>
        /// <param name="taikyoku"></param>
        public static void Remove_DeadPieces(Taikyoku taikyoku)
        {
            bool isContinuePhase; // Gnugo1.2 では cont という変数名。continueの略だろうか?

            //
            // 最初にコンピューター側を調べ、次に人間側を調べます。
            // 盤上の各点の石が、どの方向に隣接する石を持っているかを調べています。
            //

            // コンピューター側
            Dictionary <int, List <int> > myList_neswStones_asNode_eachPoint;// Gnugo1.2 では、mymovelist という変数名。int mymovelist[NODES][5]。

            Util_EndOfGame.GetNeswStones_AsNode_EachPoint(taikyoku.MyColor, out myList_neswStones_asNode_eachPoint, taikyoku);

            // 人間側
            Dictionary <int, List <int> > yourList_neswStones_asNode_eachPoint;// Gnugo1.2 では、umovelist という変数名。int umovelist[NODES][5];。

            Util_EndOfGame.GetNeswStones_AsNode_EachPoint(taikyoku.YourColor, out yourList_neswStones_asNode_eachPoint, taikyoku);

            isContinuePhase = true;
            GobanPoint location;// Gnugo1.2 では、 i, j という変数名。

            do
            {
                Console.Write("Dead piece? ");

                // 死んでいる石の場所を入力してください。
                string an_str = Console.ReadLine();
                //scanf("%s", an);

                //----------------------------------------
                // 妥当な入力があるまで、くるくる回します。
                //----------------------------------------
                {//2015-11-27 追加
                    bool valid = false;

                    if (an_str == "stop")
                    {
                        valid    = true;
                        location = null;
                    }
                    else
                    {
                        valid = PointFugoImpl.TryParse(an_str, out location, taikyoku);
                    }

                    if (!valid)
                    {
                        // 入力が不妥当なので、ループし直し。
                        goto gt_DeadPieceContinue;
                    }
                }

                if (an_str == "stop")
                {
                    // ループから抜けます。
                    isContinuePhase = false;
                    goto gt_DeadPieceContinue;
                }
                else
                {
                    if (taikyoku.Goban.At(location) == taikyoku.MyColor)
                    {
#if DEBUG
                        Console.WriteLine("Just before bfslist.");
#endif
                        List <int> nodeList;
                        Util_EndOfGame.GetConnectedStones_AsNode_FromPoint(out nodeList, location, myList_neswStones_asNode_eachPoint, taikyoku);
#if DEBUG
                        Console.WriteLine("Survived first bfslist.");
#endif
                        // 示された場所を空にしていき、コンピューターの取られた石カウントを増やします。
                        foreach (int node in nodeList)
                        {
                            Util_AboutBoard.GetLocationByNode(out location, node, taikyoku.GobanBounds);
                            taikyoku.Goban.Put(location, StoneColor.Empty);
                            taikyoku.Count_MyCaptured++;
                        }
                    }
                    else if (taikyoku.Goban.At(location) == taikyoku.YourColor)
                    {
#if DEBUG
                        Console.WriteLine("Just before second bfslist.");
#endif
                        List <int> nodeList;
                        Util_EndOfGame.GetConnectedStones_AsNode_FromPoint(out nodeList, location, yourList_neswStones_asNode_eachPoint, taikyoku);

                        // 示された場所を空にしていき、人間の取られた石カウントを増やします。
                        foreach (int node in nodeList)
                        {
                            Util_AboutBoard.GetLocationByNode(out location, node, taikyoku.GobanBounds);
                            taikyoku.Goban.Put(location, StoneColor.Empty);
                            taikyoku.Count_YourCaptured++;
                        }
                    }
                    ((BoardPrinterB)taikyoku.BoardPrinter).ShowBoard(taikyoku);
                }

gt_DeadPieceContinue:
                ;
            }while (isContinuePhase);
        }
        /// <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);
            }
        }