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 void CombineCheck(ArrayList[,] affect) { int patternG5 = 0; GoBangBoard board = new GoBangBoard(); ArrayList[] affecting = new ArrayList[5]; foreach (GoBangBoard.StoneSet ss in board.G5) { for (int n = 0; n < ss.stones.Length; ++n) { affecting[n] = affect[ss.y + n * ss.ay, ss.x + n * ss.ax]; } // Now in positions we have 'oneBits' number of positions. CheckC2(affecting); #if false // Do a pre-filtering of sensible patterns in this G_5 bool[] fivePatterns = new bool[1 << 5]; for (int p = 0; p < fivePatterns.Length; ++p) { fivePatterns[p] = false; for (int n = 0; n < 5; ++n) { ss.stones[n] = (p & (1 << n)) == 0 ? 0 : 1; if (ss.stones[n] == 1 && affecting[n].Count == 0) { goto nextPattern; } } /* * Console.Write ("A pattern {0}: ", p); * for (int n = 0 ; n < 5 ; ++n) * Console.Write ("{0}", ss.stones[n] == 1 ? "O" : "."); * Console.WriteLine (); */ GBOperatorFive[] fiveP = GBOperatorFive.GetOperatorsIfValid(ss); GBOperatorFour[] fourP = GBOperatorFour.GetOperatorsIfValid(ss); /* * Console.WriteLine (" pattern {0}: {1} fives, {2} fours", p, * (fiveP == null) ? "-" : String.Format ("{0}", fiveP.Length), * (fourP == null) ? "-" : String.Format ("{0}", fourP.Length)); */ // Only if we trigger a pattern, we mark it for later action. if ((fiveP != null && fiveP.Length > 0) || (fourP != null && fourP.Length > 0)) { fivePatterns[p] = true; //Console.WriteLine (" pattern {0} OK", p); } nextPattern: ; } for (int p = 0; p < fivePatterns.Length; ++p) { if (fivePatterns[p] == false) { continue; } // Now examine the pattern really. Console.WriteLine("pattern {0} success", p); Console.WriteLine(" a[0 to 4]: {0}, {1}, {2}, {3}, {4}", affecting[0].Count, affecting[1].Count, affecting[2].Count, affecting[3].Count, affecting[4].Count); patternG5 += 1; // TODO // Now we have an array of list of affecting moves plus a // pattern they may trigger. We know that those moves in the // same array element are conflicting, so we do not need to // check those. Also, we know the new operators are // independent of exchange of operators (commutative), so we // must only check each combination once, regardless of the // order. int oneBits = 0; for (int n = 0; n < 5; ++n) { if ((p & (1 << n)) != 0) { oneBits += 1; } } int[] positions = new int[oneBits]; int oneBitPos = 0; for (int n = 0; n < 5; ++n) { if ((p & (1 << n)) == 0) { continue; } positions[oneBitPos] = n; oneBitPos += 1; } } #endif } //Console.WriteLine ("G5 patterns: {0}", patternG5); }