public List <IllegalMove> CalculateIllegalMoves() { List <IllegalMove> illegalPoints = new List <IllegalMove>(); bool[,] potentialMovesAlreadyChecked = new bool[15, 15]; //dynamic programming implementation foreach (Stone stone in StonesToCheckAround) { //check the adjacent 8 positions around each stone on board to find potential illegal moves (instead of the entire board) int startingX = Math.Max(0, stone.point.X - 2); int endingX = Math.Min(GameConfiguration.BOARD_SIZE - 1, stone.point.X + 2); int startingY = Math.Max(0, stone.point.Y - 2); int endingY = Math.Min(GameConfiguration.BOARD_SIZE - 1, stone.point.Y + 2); for (int x = startingX; x <= endingX; x++) { for (int y = startingY; y <= endingY; y++) { CurrentPointBeingChecked = Point.At(x, y); if (potentialMovesAlreadyChecked[x, y]) { continue; //already reached this point through a neighbour } if (RenjuBoard.GetPointOnBoardOccupancyState(CurrentPointBeingChecked) == OccupancyState.Black || RenjuBoard.GetPointOnBoardOccupancyState(CurrentPointBeingChecked) == OccupancyState.White) { continue; //can't move to an occupied position } if (MoveProducesFiveToWin(CurrentPointBeingChecked, OccupancyState.Black)) { //stop checking; if it's a winning move, it's automatically allowed (make sure this move doesn't product overline though) } else if (MoveProducesOverline(CurrentPointBeingChecked)) { illegalPoints.Add(new IllegalMove(CurrentPointBeingChecked, IllegalMoveReason.Overline)); } else if (CountOpenThrees(CurrentPointBeingChecked) >= 2) { illegalPoints.Add(new IllegalMove(CurrentPointBeingChecked, IllegalMoveReason.Double3)); } else if (CountOpenFours(CurrentPointBeingChecked) >= 2) { illegalPoints.Add(new IllegalMove(CurrentPointBeingChecked, IllegalMoveReason.Double4)); } else { //unoccupied position AND not illegal move potentialMovesAlreadyChecked[x, y] = true; } } } } return(illegalPoints); }