/** Try to find a winning threat sequence for the opponent.
     *
     * @param board The current game board to be checked.
     * @param dbDefenseTimeLimit The limit in milliseconds to be allowed for
     * the search.
     *
     * @returns The winning threat sequence found null if none has been found.
     */
    private GBThreatSequence GetOpponentSequence(int[,] board, int dbDefenseTimeLimit)
    {
        int[,] boardRev = new int[board.GetLength(1), board.GetLength(0)];
        for (int y = 0; y < boardRev.GetLength(0); ++y)
        {
            for (int x = 0; x < boardRev.GetLength(1); ++x)
            {
                // Reverse, so we check for "us", where us is, in fact, the
                // opponent.
                boardRev[y, x] = -board[x, y];
            }
        }

        Console.WriteLine("Searching for opponent attackability of future board:");
        Console.WriteLine(new GoBangBoard(boardRev));

        GBThreatSequence seq = GBThreatSearch.FindWinning(boardRev,
                                                          dbDefenseTimeLimit * 1000, true);

        if (seq != null)
        {
            Console.WriteLine("Opponent sequence: {0}", seq);
        }

        return(seq);
    }
    public void RegisterNewNode(DBNode node, DBNode root)
    {
        DoExpirationCheck();

        if (node.IsGoal == false)
        {
            return;
        }

        // For goal nodes, we check if on-the-fly refutation is wanted, and if
        // so, we try to refute the goal node.
        if (doDefenseRefutationCheck)
        {
            GBSpaceState     gRootState = (GBSpaceState)root.State;
            GBThreatSequence seq        = GBThreatSearch.DefenseRefutable
                                              (gRootState.GB, root, node);

            if (seq != null)
            {
                throw (new GBThreatSearch.GBWinningThreatSequenceFoundException(seq));
            }
        }

        // This is old code
#if false
        // Now the last node did modify something, but we only want to cache
        // dependency nodes, as combination nodes will not be combined
        // themselves.
        if (node.Type != DBNode.NodeType.Dependency)
        {
            return;
        }

        GBSpaceState state = (GBSpaceState)node.State;
        GBOperator   last  = state.LastOperator;
        if (last == null)
        {
            return;
        }

        // Now, we add this node to the array at all its influencing places,
        // but only where it sets a stone of the attacker (which is the only
        // position that can create new possibilities for attack).
        for (int n = 0; n < last.fAdd.GetLength(0); ++n)
        {
            // Ignore everything except the attacker stones.
            if (last.fAdd[n, 2] != 1)
            {
                continue;
            }

            // Add coordinate
            nodesThatAffectSquares[last.fAdd[n, 1], last.fAdd[n, 0]].Add(node);

            return;
        }
#endif
    }
    // return type: ArrayList<Coordinate>
    private ArrayList GetDefensePriorityFields(int[,] board, ArrayList consider)
    {
        int[,] boardRev = new int[board.GetLength(1), board.GetLength(0)];
        for (int y = 0; y < boardRev.GetLength(0); ++y)
        {
            for (int x = 0; x < boardRev.GetLength(1); ++x)
            {
                // Reverse, so we check for "us", where us is, in fact, the
                // opponent.
                boardRev[y, x] = -board[x, y];
            }
        }

        int maxCount;

        int[,] operatorMap = GBThreatSearch.BuildOperatorMap
                                 (new GoBangBoard(boardRev), out maxCount);
        Console.WriteLine("operator map:");
        for (int y = 0; y < operatorMap.GetLength(0); ++y)
        {
            for (int x = 0; x < operatorMap.GetLength(1); ++x)
            {
                Console.Write("{0} ", operatorMap[y, x]);
            }
            Console.WriteLine();
        }

        // Only keep and determine the max fields of the consider list.
        int considerMaxCount = 0;

        foreach (Coordinate c in consider)
        {
            if (operatorMap[c.Y, c.X] > considerMaxCount)
            {
                considerMaxCount = operatorMap[c.Y, c.X];
            }
        }

        ArrayList fields = new ArrayList();

        foreach (Coordinate c in consider)
        {
            if (operatorMap[c.Y, c.X] == considerMaxCount)
            {
                fields.Add(new Coordinate(c.X, c.Y));
            }
        }

        return(fields);
    }
    /** Find a winning threat sequence for us.
     *
     * @param board The board to be checked.
     *
     * @returns The threat sequence found on success, or null if no sequence
     * has been found.
     */
    public GBThreatSequence FindWinning(int[,] board)
    {
        int[,] boardRev = new int[board.GetLength(1), board.GetLength(0)];
        for (int y = 0; y < boardRev.GetLength(0); ++y)
        {
            for (int x = 0; x < boardRev.GetLength(1); ++x)
            {
                boardRev[y, x] = board[x, y];
            }
        }

        Console.WriteLine("Searching for board");
        Console.WriteLine(new GoBangBoard(boardRev));

        // A timelimit of zero means no limit.
        return(GBThreatSearch.FindWinning(boardRev, dbtimelimit * 1000, false));
    }
    // timeoutMS: zero or timeout limit in ms
    public static GBThreatSequence FindWinning(int[,] board, int timeoutMS,
                                               bool defOpponentSearch)
    {
        GBThreatSearch gts = new GBThreatSearch(new GoBangBoard(board),
                                                defOpponentSearch);
        GBThreatSequence seq = gts.FindWinningThreatSeqOTF(timeoutMS);

        if (seq != null)
        {
            Console.WriteLine("Board:");
            Console.WriteLine(new GoBangBoard(board));
            Console.WriteLine();

            Console.WriteLine("Winning threat sequence found:");
            Console.WriteLine(seq);
        }
        else
        {
            Console.WriteLine("No winning threat sequence found.");
        }

        return(seq);
    }
    public static void Main(string[] args)
    {
        GoBangBoard gb  = new GoBangBoard();
        Random      rnd = new Random();

        /*
         * for (int n = 0 ; n < 23 ; ++n)
         *      gb.board[rnd.Next (0, gb.boardDim), rnd.Next (0, gb.boardDim)] =
         *              rnd.Next (0, 3) - 1;
         */

        /*
         * gb.board[5,5] = gb.board[5,8] = -1;
         * gb.board[7,4] = gb.board[7,9] = -1;
         *
         * gb.board[5,4] = gb.board[5,6] = gb.board[5,7] = gb.board[5,9] = 1;
         * gb.board[7,6] = gb.board[7,7] = 1;
         */

        /*
         * // Testcase A
         * gb.board[4,9] = gb.board[5,6] = gb.board[6,8] = 1;
         * gb.board[7,7] = gb.board[8,6] = gb.board[9,5] = gb.board[9,6] = 1;
         * gb.board[9,9] = gb.board[10,11] = 1;
         *
         * gb.board[5,9] = gb.board[5,10] = -1;
         * gb.board[6,7] = gb.board[6,9] = -1;
         * gb.board[7,8] = gb.board[7,9] = gb.board[8,9] = -1;
         * gb.board[9,10] = gb.board[10,4] = -1;
         */

        /*
         * // Testcase B
         * gb.board[5,5] = gb.board[4,6] = gb.board[7,5] = gb.board[7,6] = 1;
         * gb.board[5,6] = gb.board[6,6] = -1;
         */

        /*
         * gb.board[5,6] = gb.board[8,6] = gb.board[9,6] = 1;
         */

        /*
         * // FIXME: this sequence is not found as un-refutable, while it is in
         * // fact (magic case, we know exactly what it is caused by and this is
         * // unlikely to appear in a real game and difficult to fix (though
         * // possible))
         * // 138, figure 5.5
         * gb.board[0,0] = gb.board[1,1] = gb.board[2,2] = gb.board[5,13] = -1;
         * gb.board[6,9] = gb.board[7,7] = gb.board[7,8] = -1;
         * gb.board[8,6] = gb.board[8,12] = -1;
         * gb.board[10,7] = gb.board[10,9] = -1;
         * gb.board[10,2] = gb.board[11,1] = gb.board[12,0] = -1;
         *
         * gb.board[2,12] = gb.board[3,12] = 1;
         * gb.board[6,6] = gb.board[6,7] = gb.board[7,6] = gb.board[7,10] = 1;
         * gb.board[8,8] = gb.board[8,11] = gb.board[9,8] = 1;
         */

        // 127b
        gb.board[5, 6] = gb.board[6, 9] = gb.board[7, 7] = gb.board[8, 8] = 1;
        gb.board[8, 9] = 1;

        gb.board[6, 6] = gb.board[6, 8] = gb.board[7, 6] = gb.board[7, 10] = -1;
        gb.board[8, 6] = -1;

        /*
         * // 127a
         * gb.board[6,6] = gb.board[6,7] = gb.board[6,8] = 1;
         * gb.board[7,7] = gb.board[8,6] = gb.board[8,7] = gb.board[8,8] = 1;
         * gb.board[9,6] = gb.board[10,5] = gb.board[10,6] = gb.board[10,7] = 1;
         *
         * gb.board[6,5] = gb.board[7,5] = gb.board[7,6] = gb.board[7,8] = -1;
         * gb.board[8,5] = gb.board[8,9] = gb.board[9,5] = gb.board[9,7] = gb.board[9,9] = -1;
         * gb.board[10,4] = gb.board[11,6] = -1;
         *
         * // Move 1/2
         * gb.board[5,5] = 1;
         * gb.board[4,4] = -1;
         */

        /*
         * // Move 3/4
         * gb.board[5,7] = 1;
         * gb.board[4,7] = -1;
         *
         * // Move 5/6
         * gb.board[5,9] = 1;
         * gb.board[4,10] = -1;
         *
         * // Move 7/8
         * gb.board[5,8] = 1;
         * gb.board[5,6] = -1;
         *
         * // Move 9/10
         * gb.board[5,11] = 1;
         * gb.board[5,10] = -1;
         *
         * // Move 11/12
         * gb.board[6,10] = 1;
         * gb.board[6,9] = -1;
         *
         * // Move 13/14
         * gb.board[7,9] = 1;
         * gb.board[4,12] = -1;
         *
         * // Move 15/16
         * gb.board[4,6] = 1;
         * gb.board[3,5] = -1;
         */

        Console.WriteLine("Starting winning threat sequence search...");

        GBThreatSearch   gts = new GBThreatSearch(gb, false);
        GBThreatSequence seq = gts.FindWinningThreatSeqOTF();

        if (seq != null)
        {
            Console.WriteLine("Board:");
            Console.WriteLine(gb);
            Console.WriteLine();

            Console.WriteLine("winning threat sequence found:");
            Console.WriteLine(seq);
        }

        GBThreatSearch   gts2 = new GBThreatSearch(gb, true);
        GBThreatSequence seq2 = gts2.FindWinningThreatSeqOTF();

        if (seq2 != null)
        {
            Console.WriteLine("Board:");
            Console.WriteLine(gb);
            Console.WriteLine();

            Console.WriteLine("winning threat sequence found:");
            Console.WriteLine(seq2);
        }
    }
    public static void Main(string[] args)
    {
        GoBangBoard gb = new GoBangBoard ();
        Random rnd = new Random ();

        /*
        for (int n = 0 ; n < 23 ; ++n)
            gb.board[rnd.Next (0, gb.boardDim), rnd.Next (0, gb.boardDim)] =
                rnd.Next (0, 3) - 1;
        */

        /*
        gb.board[5,5] = gb.board[5,8] = -1;
        gb.board[7,4] = gb.board[7,9] = -1;

        gb.board[5,4] = gb.board[5,6] = gb.board[5,7] = gb.board[5,9] = 1;
        gb.board[7,6] = gb.board[7,7] = 1;
        */

        /*
        // Testcase A
        gb.board[4,9] = gb.board[5,6] = gb.board[6,8] = 1;
        gb.board[7,7] = gb.board[8,6] = gb.board[9,5] = gb.board[9,6] = 1;
        gb.board[9,9] = gb.board[10,11] = 1;

        gb.board[5,9] = gb.board[5,10] = -1;
        gb.board[6,7] = gb.board[6,9] = -1;
        gb.board[7,8] = gb.board[7,9] = gb.board[8,9] = -1;
        gb.board[9,10] = gb.board[10,4] = -1;
        */

        /*
        // Testcase B
        gb.board[5,5] = gb.board[4,6] = gb.board[7,5] = gb.board[7,6] = 1;
        gb.board[5,6] = gb.board[6,6] = -1;
        */

        /*
        gb.board[5,6] = gb.board[8,6] = gb.board[9,6] = 1;
        */

        /*
        // FIXME: this sequence is not found as un-refutable, while it is in
        // fact (magic case, we know exactly what it is caused by and this is
        // unlikely to appear in a real game and difficult to fix (though
        // possible))
        // 138, figure 5.5
        gb.board[0,0] = gb.board[1,1] = gb.board[2,2] = gb.board[5,13] = -1;
        gb.board[6,9] = gb.board[7,7] = gb.board[7,8] = -1;
        gb.board[8,6] = gb.board[8,12] = -1;
        gb.board[10,7] = gb.board[10,9] = -1;
        gb.board[10,2] = gb.board[11,1] = gb.board[12,0] = -1;

        gb.board[2,12] = gb.board[3,12] = 1;
        gb.board[6,6] = gb.board[6,7] = gb.board[7,6] = gb.board[7,10] = 1;
        gb.board[8,8] = gb.board[8,11] = gb.board[9,8] = 1;
        */

        // 127b
        gb.board[5,6] = gb.board[6,9] = gb.board[7,7] = gb.board[8,8] = 1;
        gb.board[8,9] = 1;

        gb.board[6,6] = gb.board[6,8] = gb.board[7,6] = gb.board[7,10] = -1;
        gb.board[8,6] = -1;

        /*
        // 127a
        gb.board[6,6] = gb.board[6,7] = gb.board[6,8] = 1;
        gb.board[7,7] = gb.board[8,6] = gb.board[8,7] = gb.board[8,8] = 1;
        gb.board[9,6] = gb.board[10,5] = gb.board[10,6] = gb.board[10,7] = 1;

        gb.board[6,5] = gb.board[7,5] = gb.board[7,6] = gb.board[7,8] = -1;
        gb.board[8,5] = gb.board[8,9] = gb.board[9,5] = gb.board[9,7] = gb.board[9,9] = -1;
        gb.board[10,4] = gb.board[11,6] = -1;

        // Move 1/2
        gb.board[5,5] = 1;
        gb.board[4,4] = -1;
        */

        /*
        // Move 3/4
        gb.board[5,7] = 1;
        gb.board[4,7] = -1;

        // Move 5/6
        gb.board[5,9] = 1;
        gb.board[4,10] = -1;

        // Move 7/8
        gb.board[5,8] = 1;
        gb.board[5,6] = -1;

        // Move 9/10
        gb.board[5,11] = 1;
        gb.board[5,10] = -1;

        // Move 11/12
        gb.board[6,10] = 1;
        gb.board[6,9] = -1;

        // Move 13/14
        gb.board[7,9] = 1;
        gb.board[4,12] = -1;

        // Move 15/16
        gb.board[4,6] = 1;
        gb.board[3,5] = -1;
        */

        Console.WriteLine ("Starting winning threat sequence search...");

        GBThreatSearch gts = new GBThreatSearch (gb, false);
        GBThreatSequence seq = gts.FindWinningThreatSeqOTF ();

        if (seq != null) {
            Console.WriteLine ("Board:");
            Console.WriteLine (gb);
            Console.WriteLine ();

            Console.WriteLine ("winning threat sequence found:");
            Console.WriteLine (seq);
        }

        GBThreatSearch gts2 = new GBThreatSearch (gb, true);
        GBThreatSequence seq2 = gts2.FindWinningThreatSeqOTF ();

        if (seq2 != null) {
            Console.WriteLine ("Board:");
            Console.WriteLine (gb);
            Console.WriteLine ();

            Console.WriteLine ("winning threat sequence found:");
            Console.WriteLine (seq2);
        }
    }
    // timeoutMS: zero or timeout limit in ms
    public static GBThreatSequence FindWinning(int[,] board, int timeoutMS,
		bool defOpponentSearch)
    {
        GBThreatSearch gts = new GBThreatSearch (new GoBangBoard (board),
            defOpponentSearch);
        GBThreatSequence seq = gts.FindWinningThreatSeqOTF (timeoutMS);

        if (seq != null) {
            Console.WriteLine ("Board:");
            Console.WriteLine (new GoBangBoard (board));
            Console.WriteLine ();

            Console.WriteLine ("Winning threat sequence found:");
            Console.WriteLine (seq);
        } else {
            Console.WriteLine ("No winning threat sequence found.");
        }

        return (seq);
    }
    public bool GetRemoteMove()
    {
        if (currentPlayer == ownPlayer)
        {
            return(false);
        }

        string netline = ReadNetworkLine();

        string[] win = netline.Split('\n');
        if (String.Compare(win[0], "You win!") == 0)
        {
            MessageDialog md = new MessageDialog(mainWindow,
                                                 DialogFlags.DestroyWithParent, MessageType.Info,
                                                 ButtonsType.Close,
                                                 "You won the game!\n\nCongratulations!");

            md.Run();
            md.Destroy();
            Application.Quit();
            return(true);
        }
        else if (String.Compare(win[0], "You lost!") == 0)
        {
            MessageDialog md = new MessageDialog(mainWindow,
                                                 DialogFlags.DestroyWithParent, MessageType.Info,
                                                 ButtonsType.Close,
                                                 "You lost the game...\n\nMaybe you have better luck next time!");

            md.Run();
            md.Destroy();
            Application.Quit();
            return(true);
        }
        string[] pos = netline.Split('/');
        int      px, py;

        px = Int32.Parse(pos[0]);
        py = Int32.Parse(pos[1]);

        DrawStone(currentPlayer, px, py);

        // Test GBThreatSearch
        if (clientDBSearchEnabled.Active)
        {
            int[,] boardRev = new int[xyDim, xyDim];
            for (int y = 0; y < xyDim; ++y)
            {
                for (int x = 0; x < xyDim; ++x)
                {
                    int stoneV = 0;

                    if (board[x, y] == currentPlayer)
                    {
                        stoneV = -1;
                    }
                    else if (board[x, y] == -1)
                    {
                        stoneV = 0;
                    }
                    else
                    {
                        stoneV = 1;
                    }
                    boardRev[y, x] = stoneV;
                }
            }

            Console.WriteLine("Searching for board");
            Console.WriteLine(new GoBangBoard(boardRev));
            GBThreatSearch.FindWinning(boardRev, 5000);
        }

        currentPlayer = (currentPlayer == 0) ? 1 : 0;

        return(true);
    }