public static void ExpandMax(DataEntry Entry, int Depth, int DepthLimit) { CountOfConfigurationsScored += 1; var recurseLimit = DepthLimit; if (Depth >= DepthReached) DepthReached = Depth; if (Entry.Moves == null) { AI.Expand(Entry); recurseLimit = Depth + 1; } if (Entry.Moves.Count == 0) { Entry.ScoreAdjustment = 100000; WinConditionFound = true; } else { var baseMax = Entry.Moves.Max(m => m.Score); var index = Random.Next(0, Entry.Moves.Where(m => m.Score == baseMax).Count()); foreach (var move in Entry.Moves) move.Ignored = true; var bestMove = Entry.Moves.Where(m => m.Score == baseMax).ElementAt(index); if (Depth < DepthLimit) ExpandMax(bestMove.NextBoard, Depth + 1, recurseLimit); bestMove.Score = bestMove.NextBoard.CombinedScore; bestMove.Ignored = false; Entry.ScoreAdjustment = -(Entry.Moves.Max(m => m.Score) * 0.8f); } }
public static void Expand(DataEntry Entry) { if (Entry.Moves == null) { Entry.Moves = new List<MoveTransition>(Coerceo.EnumerateLegalMoves(Entry.Board).Select(move => { var nextBoard = new DataEntry { ScoreAdjustment = 0, Moves = null, Board = Coerceo.ApplyMove(Entry.Board, move) }; nextBoard.BaseScore = ScoreBoard(Entry.Board, nextBoard.Board); return new MoveTransition { NextBoard = nextBoard, Move = move, Ignored = false, Score = nextBoard.BaseScore }; })); } }
public static void CalculateAdjustedScore(DataEntry Entry, int Depth) { CountOfConfigurationsScored += 1; if (CountOfConfigurationsScored > 10000) return; if (Entry.Moves == null) Expand(Entry); if (Entry.Moves.Count == 0) { // This board is a dead end - the player lost. It gets a strong negative penalty, but not too strong // or it will wrap and the other player will think this move is really fantastic. Entry.ScoreAdjustment = -100000; } else { if (Depth < DepthReached) DepthReached = Depth; var max = float.MinValue; var baseAverage = Entry.Moves.Sum(m => m.Score) / Entry.Moves.Count; var baseMax = Entry.Moves.Max(m => m.Score); foreach (var move in Entry.Moves) { if (move.Score >= baseMax) { if (Depth > 0) CalculateAdjustedScore(move.NextBoard, Depth - 1); move.Score = move.NextBoard.CombinedScore; if (move.Score > max) max = move.Score; move.Ignored = false; } else move.Ignored = true; } if (max < baseAverage) // The best moves turned out worse than average { foreach (var move in Entry.Moves.Where(m => m.Ignored)) { if (move.Score >= baseAverage) { if (Depth > 0) CalculateAdjustedScore(move.NextBoard, System.Math.Max(Depth - 2, 0)); // We can't afford to look very deeply, though. move.Score = move.NextBoard.CombinedScore; if (move.Score > max) max = move.Score; move.Ignored = false; } else move.Ignored = true; } } if (max < baseAverage) // Well we tried the second best and they still sucked. { foreach (var move in Entry.Moves.Where(m => m.Ignored)) { if (Depth > 0) CalculateAdjustedScore(move.NextBoard, 0); // We can't afford to look very deeply, though. move.Score = move.NextBoard.CombinedScore; if (move.Score > max) max = move.Score; move.Ignored = false; } } Entry.ScoreAdjustment = -(int)(max * 0.8f); } }