public Boolean Step(IRover rover) { if (!Actions.MoveNext()) { return(true); } RoverAction action = Actions.Current; switch (action.Instruction) { case Instruction.CollectPower: rover.CollectPower(); break; case Instruction.CollectSample: rover.CollectSample(); break; case Instruction.ProcessSamples: rover.ProcessSamples(); break; case Instruction.Transmit: rover.Transmit(); break; case Instruction.Sense: rover.SenseSquare(action.Direction); break; case Instruction.Move: rover.Move(action.Direction); break; default: throw new InvalidOperationException(); } return(rover.IsHalted); }
public void Simulate(IRover rover) { while (true) { var adjacent = SenseAdjacent(rover); TerrainType occupied = rover.SenseSquare(Direction.None); (Direction? adjacentSmoothDir, Direction? adjacentRoughDir) = FindAdjacentUnsampled(adjacent); if (rover.MovesLeft <= 5) { DoLowMoves(rover); return; } if (rover.Power < LowPowerThreshold || (!adjacentSmoothDir.HasValue && occupied == TerrainType.Smooth)) { if (!HasExcessPower(rover)) { rover.CollectPower(); } if (rover.Power < LowPowerThreshold) { rover.Transmit(); } } // While we're gather power, we don't collect samples and instead abuse the Backtracking mechanic gather a large amount of power. if (occupied.IsSampleable() && (!_gatheringPower || (adjacentSmoothDir == null && occupied == TerrainType.Smooth))) { rover.CollectSample(); if (rover.SamplesCollected >= Parameters.SamplesPerProcess && rover.Power > Parameters.ProcessCost + Parameters.MoveSmoothCost) { rover.ProcessSamples(); } } Boolean hasExcessPower = HasExcessPower(rover); if (hasExcessPower) { _gatheringPower = false; } (Boolean isDeadEnd, Direction deadEndEscape) = CheckDeadEnd(adjacent); if (isDeadEnd) { AddDeadEnd(rover.Position); } if (adjacentSmoothDir.HasValue) { _destination = adjacentSmoothDir.Value; // Prioritize smooth squares } else if (hasExcessPower && !_gatheringPower && adjacentRoughDir.HasValue) { _destination = adjacentRoughDir.Value; // Visit rough squares if the rover has enough power } else if (isDeadEnd) { _destination = deadEndEscape; } Direction nextMove = _destination; if (nextMove == Direction.None || adjacent[nextMove] == TerrainType.Impassable) { if (_avoidanceDestination != Direction.None) { if (adjacent[_avoidanceDestination] == TerrainType.Impassable) { _destination = ResetDestination(adjacent); nextMove = _destination; _avoidanceDestination = Direction.None; } else { nextMove = _avoidanceDestination; } } else { nextMove = AvoidObstacle(adjacent); // Obstacle avoidance _avoidanceDestination = nextMove; } } else { _avoidanceDestination = Direction.None; } rover.Move(nextMove); _roundRobin++; } }
private void DoLowMoves(IRover rover) { if (rover.MovesLeft > 5) { return; } Boolean smoothOccupied = rover.SenseSquare(Direction.None) == TerrainType.Smooth; Boolean roughOccupied = rover.SenseSquare(Direction.None) == TerrainType.Rough; (Direction? smoothDir, Direction? roughDir) = FindAdjacentUnsampled(rover); if (rover.MovesLeft == 5 && rover.Power > Parameters.SampleCost + Parameters.MoveRoughCost + Parameters.SampleCost + Parameters.ProcessCost) { if (smoothOccupied || roughOccupied) { rover.CollectSample(); } Direction?moveDir = smoothDir ?? roughDir; if (moveDir.HasValue) { rover.Move(moveDir.Value); rover.CollectSample(); } rover.ProcessSamples(); rover.Transmit(); return; } if (rover.MovesLeft >= 4) { rover.CollectPower(); if (rover.Power > Parameters.ProcessCost) { if (rover.Power > Parameters.ProcessCost + Parameters.SampleCost && smoothOccupied) { rover.CollectSample(); } rover.ProcessSamples(); } } else if (rover.MovesLeft == 3) { if (rover.Power > Parameters.ProcessCost + Parameters.SampleCost && smoothOccupied) { rover.CollectSample(); } else { rover.CollectPower(); } if (rover.Power > Parameters.ProcessCost) { rover.ProcessSamples(); } } if (rover.MovesLeft == 2) { if (rover.Power == 0) { rover.CollectPower(); } else if (rover.Power > Parameters.ProcessCost && rover.SamplesCollected > 0) { rover.ProcessSamples(); } } if (rover.SamplesProcessed > 0) { rover.Transmit(); } return; }