// 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); }
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")); } }