// Return the operator's category that is the lowest among the applicable
    // operators for state.
    public static int LowestOperatorCategory(GoBangBoard board)
    {
        // A maximum, not important, just must be larger than any real
        // category
        int max = 99;

        // Search category 0 and 1 in G_5
        foreach (GoBangBoard.StoneSet ss in board.G5)
        {
            // There is no category below zero, so we can return early.
            if (GBOperatorFive.Present(ss))
            {
                return(0);
            }

            if (GBOperatorFour.Present(ss))
            {
                max = 1;
            }
        }

        if (max < 99)
        {
            return(max);
        }

        // Search category 1 and 2 in G_6
        foreach (GoBangBoard.StoneSet ss in board.G6)
        {
            // If there was no 0/1 before, this is certainly the minimum.
            if (GBOperatorStraightFour.Present(ss))
            {
                return(1);
            }

            if (max > 2 && GBOperatorBrokenThree.Present(ss))
            {
                max = 2;
            }
            else if (max > 2 && GBOperatorThree3.Present(ss))
            {
                max = 2;
            }
        }

        if (max < 99)
        {
            return(max);
        }

        foreach (GoBangBoard.StoneSet ss in board.G7)
        {
            if (GBOperatorThree2.Present(ss))
            {
                return(2);
            }
        }

        return(99);
    }
示例#2
0
    public static GBOperatorThree3[] GetOperatorsIfValid
        (GoBangBoard.StoneSet ss)
    {
        if (Present(ss) == false)
        {
            return(null);
        }

        // Case A: ..oo..
        if (ss.stones[1] == 0 && ss.stones[4] == 0)
        {
            // Operator is valid, lets produce it (two variants)
            GBOperatorThree3 three31 = new GBOperatorThree3();
            GBOperatorThree3 three32 = new GBOperatorThree3();

            three31.fAdd = new int[4, 3];
            three32.fAdd = new int[4, 3];

            int hole = 0;
            for (int n = 1; n < (ss.stones.Length - 1); ++n)
            {
                if (ss.stones[n] != 0)
                {
                    continue;
                }

                three31.fAdd[hole, 0] = three32.fAdd[hole, 0] = ss.x + n * ss.ax;
                three31.fAdd[hole, 1] = three32.fAdd[hole, 1] = ss.y + n * ss.ay;

                if (hole == 0)
                {
                    three31.fAdd[0, 2] = 1;
                    three32.fAdd[0, 2] = -1;

                    hole += 1;
                }
                else
                {
                    three31.fAdd[1, 2] = -1;
                    three32.fAdd[1, 2] = 1;
                }
            }

            // Two defending moves (s_1 and s_6, index 0 and 5)
            three31.fAdd[2, 0] = three32.fAdd[2, 0] = ss.x;
            three31.fAdd[2, 1] = three32.fAdd[2, 1] = ss.y;
            three31.fAdd[2, 2] = three32.fAdd[2, 2] = -1;

            three31.fAdd[3, 0] = three32.fAdd[3, 0] = ss.x + 5 * ss.ax;
            three31.fAdd[3, 1] = three32.fAdd[3, 1] = ss.y + 5 * ss.ay;
            three31.fAdd[3, 2] = three32.fAdd[3, 2] = -1;

            return(new GBOperatorThree3[] { three31, three32 });
        }
        else if ((ss.stones[2] == 0 && ss.stones[4] == 0) ||
                 (ss.stones[1] == 0 && ss.stones[3] == 0))
        {
            // Case B & C: .o.o.. and ..o.o.
            // TODO
            GBOperatorThree3 three3 = new GBOperatorThree3();

            three3.fAdd = new int[4, 3];

            int stoneCount = 0;
            int pCell      = 0;
            for (int n = 1; n < (ss.stones.Length - 1); ++n)
            {
                if (ss.stones[n] != 0)
                {
                    stoneCount += 1;

                    continue;
                }

                three3.fAdd[pCell, 0] = ss.x + n * ss.ax;
                three3.fAdd[pCell, 1] = ss.y + n * ss.ay;

                if (stoneCount == 1)
                {
                    three3.fAdd[pCell, 2] = 1;
                }
                else
                {
                    three3.fAdd[pCell, 2] = -1;
                }

                pCell += 1;
            }

            // Two defending moves (s_1 and s_6, index 0 and 5)
            three3.fAdd[2, 0] = ss.x;
            three3.fAdd[2, 1] = ss.y;
            three3.fAdd[2, 2] = -1;

            three3.fAdd[3, 0] = ss.x + 5 * ss.ax;
            three3.fAdd[3, 1] = ss.y + 5 * ss.ay;
            three3.fAdd[3, 2] = -1;

            return(new GBOperatorThree3[] { three3, });
        }
        else if (ss.stones[3] == 0 && ss.stones[4] == 0)
        {
            // Case D: .oo...
            GBOperatorThree3 three3 = new GBOperatorThree3();

            three3.fAdd = new int[4, 3];

            three3.fAdd[0, 0] = ss.x + 3 * ss.ax;
            three3.fAdd[0, 1] = ss.y + 3 * ss.ay;
            three3.fAdd[0, 2] = 1;

            three3.fAdd[1, 0] = ss.x + 4 * ss.ax;
            three3.fAdd[1, 1] = ss.y + 4 * ss.ay;
            three3.fAdd[1, 2] = -1;

            // Two defending moves (s_1 and s_6, index 0 and 5)
            three3.fAdd[2, 0] = ss.x;
            three3.fAdd[2, 1] = ss.y;
            three3.fAdd[2, 2] = -1;

            three3.fAdd[3, 0] = ss.x + 5 * ss.ax;
            three3.fAdd[3, 1] = ss.y + 5 * ss.ay;
            three3.fAdd[3, 2] = -1;

            return(new GBOperatorThree3[] { three3, });
        }
        else if (ss.stones[1] == 0 && ss.stones[2] == 0)
        {
            // Case E: ...oo.
            GBOperatorThree3 three3 = new GBOperatorThree3();

            three3.fAdd = new int[4, 3];

            three3.fAdd[0, 0] = ss.x + 2 * ss.ax;
            three3.fAdd[0, 1] = ss.y + 2 * ss.ay;
            three3.fAdd[0, 2] = 1;

            three3.fAdd[1, 0] = ss.x + 1 * ss.ax;
            three3.fAdd[1, 1] = ss.y + 1 * ss.ay;
            three3.fAdd[1, 2] = -1;

            // Two defending moves (s_1 and s_6, index 0 and 5)
            three3.fAdd[2, 0] = ss.x;
            three3.fAdd[2, 1] = ss.y;
            three3.fAdd[2, 2] = -1;

            three3.fAdd[3, 0] = ss.x + 5 * ss.ax;
            three3.fAdd[3, 1] = ss.y + 5 * ss.ay;
            three3.fAdd[3, 2] = -1;

            return(new GBOperatorThree3[] { three3, });
        }
        else
        {
            throw (new ApplicationException("BUG in Three3, uncatched case"));
        }
    }
    public static GBOperator[] LegalOperators(GBSpaceState state, int maxCat)
    {
        ArrayList opersGoal   = new ArrayList();
        ArrayList opersFours  = new ArrayList();
        ArrayList opersThrees = new ArrayList();

        // Check G_5 for operators
        foreach (GoBangBoard.StoneSet ss in state.GB.G5)
        {
            if (IsLastOperatorDependent(ss, state.LastOperator) == false)
            {
                continue;
            }

            GBOperatorFive[] fives = null;
            if (maxCat >= 0)
            {
                fives = GBOperatorFive.GetOperatorsIfValid(ss);
            }

            GBOperatorFour[] fours = null;
            if (maxCat >= 1)
            {
                fours = GBOperatorFour.GetOperatorsIfValid(ss);
            }

            if (fives != null)
            {
                opersGoal.AddRange(fives);
            }
            if (fours != null)
            {
                opersFours.AddRange(fours);
            }
        }

        bool Three2Applicable = false;

        if (maxCat >= 2)
        {
            // Check G_7 for operators
            foreach (GoBangBoard.StoneSet ss in state.GB.G7)
            {
                if (IsLastOperatorDependent(ss, state.LastOperator) == false)
                {
                    continue;
                }

                /*
                 * Console.Write ("7ss: ");
                 * for (int n = 0 ; n < ss.stones.Length ; ++n)
                 *      Console.Write ("{0} ", ss.stones[n] == 1 ? "O" :
                 *              (ss.stones[n] == -1 ? "X" : "."));
                 * Console.WriteLine ();
                 */

                GBOperatorThree2[] three2 =
                    GBOperatorThree2.GetOperatorsIfValid(ss);

                if (three2 != null)
                {
                    Three2Applicable = true;
                    opersThrees.AddRange(three2);
                }
            }
        }

        // Check G_6 for operators
        if (maxCat >= 1)
        {
            foreach (GoBangBoard.StoneSet ss in state.GB.G6)
            {
                if (IsLastOperatorDependent(ss, state.LastOperator) == false)
                {
                    continue;
                }

                GBOperatorStraightFour[] sfours = null;
                if (maxCat >= 1)
                {
                    sfours = GBOperatorStraightFour.GetOperatorsIfValid(ss);
                }

                GBOperatorBrokenThree[] bthrees = null;
                GBOperatorThree3[]      three3s = null;
                if (maxCat >= 2)
                {
                    bthrees = GBOperatorBrokenThree.GetOperatorsIfValid(ss);
                }

                // Heuristic "restricted trees", page 141.
                // HEURISTIC
                // FIXME: re-enable this after testing.
                if (maxCat >= 2 /*&& Three2Applicable == false*/)
                {
                    three3s = GBOperatorThree3.GetOperatorsIfValid(ss);
                }

                if (sfours != null)
                {
                    opersGoal.AddRange(sfours);
                }
                if (bthrees != null)
                {
                    opersThrees.AddRange(bthrees);
                }
                if (three3s != null)
                {
                    opersThrees.AddRange(three3s);
                }
            }
        }

        // Order: goal, fours, threes
        opersGoal.AddRange(opersFours);
        opersGoal.AddRange(opersThrees);

        if (opersGoal.Count > 0)
        {
            return((GBOperator[])opersGoal.ToArray(typeof(GBOperator)));
        }

        return(null);
    }
    public static GBOperatorThree3[] GetOperatorsIfValid(GoBangBoard.StoneSet ss)
    {
        if (Present (ss) == false)
            return (null);

        // Case A: ..oo..
        if (ss.stones[1] == 0 && ss.stones[4] == 0) {
            // Operator is valid, lets produce it (two variants)
            GBOperatorThree3 three31 = new GBOperatorThree3 ();
            GBOperatorThree3 three32 = new GBOperatorThree3 ();

            three31.fAdd = new int[4,3];
            three32.fAdd = new int[4,3];

            int hole = 0;
            for (int n = 1 ; n < (ss.stones.Length-1) ; ++n) {
                if (ss.stones[n] != 0)
                    continue;

                three31.fAdd[hole,0] = three32.fAdd[hole,0] = ss.x + n*ss.ax;
                three31.fAdd[hole,1] = three32.fAdd[hole,1] = ss.y + n*ss.ay;

                if (hole == 0) {
                    three31.fAdd[0,2] = 1;
                    three32.fAdd[0,2] = -1;

                    hole += 1;
                } else {
                    three31.fAdd[1,2] = -1;
                    three32.fAdd[1,2] = 1;
                }
            }

            // Two defending moves (s_1 and s_6, index 0 and 5)
            three31.fAdd[2,0] = three32.fAdd[2,0] = ss.x;
            three31.fAdd[2,1] = three32.fAdd[2,1] = ss.y;
            three31.fAdd[2,2] = three32.fAdd[2,2] = -1;

            three31.fAdd[3,0] = three32.fAdd[3,0] = ss.x + 5*ss.ax;
            three31.fAdd[3,1] = three32.fAdd[3,1] = ss.y + 5*ss.ay;
            three31.fAdd[3,2] = three32.fAdd[3,2] = -1;

            return (new GBOperatorThree3[] { three31, three32 });
        } else if ((ss.stones[2] == 0 && ss.stones[4] == 0) ||
            (ss.stones[1] == 0 && ss.stones[3] == 0))
        {
            // Case B & C: .o.o.. and ..o.o.
            // TODO
            GBOperatorThree3 three3 = new GBOperatorThree3 ();

            three3.fAdd = new int[4,3];

            int stoneCount = 0;
            int pCell = 0;
            for (int n = 1 ; n < (ss.stones.Length-1) ; ++n) {
                if (ss.stones[n] != 0) {
                    stoneCount += 1;

                    continue;
                }

                three3.fAdd[pCell,0] = ss.x + n*ss.ax;
                three3.fAdd[pCell,1] = ss.y + n*ss.ay;

                if (stoneCount == 1) {
                    three3.fAdd[pCell,2] = 1;
                } else
                    three3.fAdd[pCell,2] = -1;

                pCell += 1;
            }

            // Two defending moves (s_1 and s_6, index 0 and 5)
            three3.fAdd[2,0] = ss.x;
            three3.fAdd[2,1] = ss.y;
            three3.fAdd[2,2] = -1;

            three3.fAdd[3,0] = ss.x + 5*ss.ax;
            three3.fAdd[3,1] = ss.y + 5*ss.ay;
            three3.fAdd[3,2] = -1;

            return (new GBOperatorThree3[] { three3, });
        } else if (ss.stones[3] == 0 && ss.stones[4] == 0) {
            // Case D: .oo...
            GBOperatorThree3 three3 = new GBOperatorThree3 ();

            three3.fAdd = new int[4,3];

            three3.fAdd[0,0] = ss.x + 3*ss.ax;
            three3.fAdd[0,1] = ss.y + 3*ss.ay;
            three3.fAdd[0,2] = 1;

            three3.fAdd[1,0] = ss.x + 4*ss.ax;
            three3.fAdd[1,1] = ss.y + 4*ss.ay;
            three3.fAdd[1,2] = -1;

            // Two defending moves (s_1 and s_6, index 0 and 5)
            three3.fAdd[2,0] = ss.x;
            three3.fAdd[2,1] = ss.y;
            three3.fAdd[2,2] = -1;

            three3.fAdd[3,0] = ss.x + 5*ss.ax;
            three3.fAdd[3,1] = ss.y + 5*ss.ay;
            three3.fAdd[3,2] = -1;

            return (new GBOperatorThree3[] { three3, });
        } else if (ss.stones[1] == 0 && ss.stones[2] == 0) {
            // Case E: ...oo.
            GBOperatorThree3 three3 = new GBOperatorThree3 ();

            three3.fAdd = new int[4,3];

            three3.fAdd[0,0] = ss.x + 2*ss.ax;
            three3.fAdd[0,1] = ss.y + 2*ss.ay;
            three3.fAdd[0,2] = 1;

            three3.fAdd[1,0] = ss.x + 1*ss.ax;
            three3.fAdd[1,1] = ss.y + 1*ss.ay;
            three3.fAdd[1,2] = -1;

            // Two defending moves (s_1 and s_6, index 0 and 5)
            three3.fAdd[2,0] = ss.x;
            three3.fAdd[2,1] = ss.y;
            three3.fAdd[2,2] = -1;

            three3.fAdd[3,0] = ss.x + 5*ss.ax;
            three3.fAdd[3,1] = ss.y + 5*ss.ay;
            three3.fAdd[3,2] = -1;

            return (new GBOperatorThree3[] { three3, });
        } else {
            throw (new ApplicationException ("BUG in Three3, uncatched case"));
        }
    }