public EvalState(TankAction action, EvalState previousState, int score, Grid grid) : this(action, grid) { if (previousState.Evaluated) { this.previousState = previousState; } this.Score = previousState.Score + score; }
public Grid(Grid copy) { this.Position = copy.Position; this.Health = copy.Health - 1; this.Energy = copy.Energy; this.EnemyHit = copy.EnemyHit; this.BatteryFound = copy.BatteryFound; Array.Copy(copy.Cells, 0, Cells, 0, Cells.Length); }
public override EvalState GetScore(EvalState state, SignalWeights weights) { Grid grid = new Grid(state.Grid); int score = -1000; if (grid.Energy > 0 && !grid.ItemBehind('L', 3) && !grid.ItemBehind('O', 8)) { int maxDistance = 10; int distance = 1; foreach (Position aheadPosition in grid.LookAhead(maxDistance)) { char item = grid.GetItem(aheadPosition); if (item == 'W') { score = -100; break; } else if ((item == 'L') && (grid.Energy >= 10)) { score = 100; grid.SetItem(aheadPosition, '_'); break; } else if (item == 'O') { score = (maxDistance - distance) * 100; grid.SetItem(aheadPosition, '_'); grid.EnemyHit = true; break; } else if (item == 'B') { // TODO: if opponent is going to get the battery first then shoot it! // TODO: One each evaluation move the lasers so they are in the right place. // TODO: I should also influance going left or right based upon where the batteries and opponents are. // TODO: Opponent behind what do we do? Shoot or turn around? if (CalculateBatteryNeedMultiplier(grid) < 1) { score = (maxDistance - distance) * 10; } grid.SetItem(aheadPosition, '_'); break; } distance++; } } grid.Energy -= 1; EvalState fireState = new EvalState(GetAction(), state, score, grid); return fireState; }
protected static double CalculateBatteryNeedMultiplier(Grid grid) { double needMultiplier = 1; if (grid.Health < 30 || grid.Energy < 2) { needMultiplier = 2; } else if (grid.Health > 280 && grid.Energy > 9) { needMultiplier = .8; } return needMultiplier; }
public TankAction GetBestAction(Grid grid, SignalWeights weights) { long turnStartTime = Stopwatch.GetTimestamp(); bool successfulActionFound = false; int depth = 1; List<Beam> beams = new List<Beam>(); { foreach (var operation in operations) //TankOperation operation = operations[1]; { Beam beam = new Beam(operation, grid, weights); beams.Add(beam); successfulActionFound = (successfulActionFound || beam.WasSuccessful()); } } int beamCompletedCount = 0; while (!successfulActionFound && (beamCompletedCount < beams.Count) && !IsTimeout(turnTimeout, turnStartTime)) { depth++; Parallel.ForEach(beams, (beam) => { if (beam.StillSearching()) { foreach (EvalState state in beam.Iterate()) { state.Grid.Health--; foreach (TankOperation operation in operations) { EvalState opState = operation.GetScore(state, weights); beam.Add(opState); } } beam.Evaluate(); beamCompletedCount += (beam.StillSearching() ? 0 : 1); successfulActionFound = (successfulActionFound || beam.WasSuccessful()); } }); } EvalState bestState = new EvalState(TankAction.Noop, grid); foreach (var beam in beams) { EvalState operationBest = beam.GetBest(); gameOutput.WriteLine(" Beam {0} ({3} pts) - depth: {1}, candidates: {2} - {4}", beam.StartAction, depth, beam.CandidateCount, operationBest.Score, operationBest); if (bestState.Score < operationBest.Score) { bestState = operationBest; } } gameOutput.WriteLine("TURN {0} - Best: ({1}) {2}", numberOfTurns, bestState.Score, bestState); return bestState.GetRootAction(); }
private Status ParseStatus(dynamic moveResponse, Grid grid) { Status status; Enum.TryParse(moveResponse.status, true, out status); gameOutput.WriteLine("\r\n\r\n=====================================\r\nTURN {0} \r\n{1}", numberOfTurns + 1, moveResponse.grid.ToString().Replace("\n", "\r\n")); grid.Update(moveResponse); return status; }
public void Run(SignalWeights weights) { dynamic joinResponse = client.Start(); turnTimeout = (joinResponse.config.turn_timeout / 1000) - 5000; Grid grid = new Grid(); Status status = ParseStatus(joinResponse, grid); while (status == Status.Running) { numberOfTurns++; TankAction action = GetBestAction(grid, weights); dynamic moveResponse = client.TakeAction(action); status = ParseStatus(moveResponse, grid); } }
public override EvalState GetScore(EvalState state, SignalWeights weights) { Grid grid = new Grid(state.Grid); int score = 0; if (state.Action == TankAction.Left) { score = -100; } else { Position rightPosition = grid.GetRight(); char item = grid.GetItem(rightPosition); if (item == '_') { score = 1; } else if (item == 'B') { score = 50; } else if (item == 'O') { score = (grid.Energy > 0 ? 60 : -100); } grid.Position = new Position(grid.Position.X, grid.Position.Y, rightPosition.Orientation); } return new EvalState(GetAction(), state, score, grid); }
public override EvalState GetScore(EvalState state, SignalWeights weights) { Grid grid = new Grid(state.Grid); int score = 0; if (grid.ItemBehind('L', 3) || grid.ItemBehind('O', 3)) { score = -1000; } else { int maxDistance = 15; int distance = 1; foreach (Position aheadPosition in grid.LookAhead(maxDistance)) { char item = grid.GetItem(aheadPosition); if (item == 'W') { if (distance == 1) { score = -1000; } break; } if (item == 'O') { if (grid.Energy == 0 && distance < 5) { score = -1000; } break; } else if (item == 'L') { score = -200; break; } else if (item == 'B') { int distanceMultiplier = (maxDistance - distance); score = (int)(((double)45) * distanceMultiplier * CalculateBatteryNeedMultiplier(grid)); if (distance == 1) { grid.Energy += 5; grid.Health += 20; grid.BatteryFound = true; } grid.SetItem(aheadPosition, '_'); break; } else if (item == '_') { score = 2; } distance++; } } grid.Position = grid.GetAhead(); return new EvalState(GetAction(), state, score, grid); }
public EvalState(TankAction action, Grid grid) { this.Action = action; this.Grid = grid; }
public Beam(TankOperation operation, Grid grid, SignalWeights weights) { StartAction = operation.GetAction(); EvalState startingState = new EvalState(operation.GetAction(), grid); bestStates[0] = operation.GetScore(startingState, weights); }