public IEnumerable <RoverAction> Simulate(IRoverStatusAccessor rover) { foreach (var action in GatherPower(rover)) { yield return(action); } while (true) { var adjacent = rover.Adjacent; TerrainType occupied = adjacent[Direction.None]; if (rover.MovesLeft <= 5) { foreach (var action in DoLowMoves(rover, adjacent)) { yield return(action); } yield break; } if (occupied.IsSampleable()) { yield return(RoverAction.CollectSample); UpdateMap(rover); if (rover.SamplesCollected >= Parameters.SamplesPerProcess && rover.Power > Parameters.ProcessCost + Parameters.MoveSmoothCost) { yield return(RoverAction.ProcessSamples); } } Direction nextMove = Direction.None; if (_path != null && _path.Count > 1) { nextMove = _path.Pop(); } else if (FindAdjacentSampleable(adjacent).HasValue) { nextMove = FindAdjacentSampleable(adjacent).Value; } if (nextMove == Direction.None || adjacent[nextMove] == TerrainType.Impassable) { Direction?reset = ResetDestination(rover.Position); if (reset == null) { yield break; // We're stuck. } nextMove = reset.Value; } yield return(new RoverAction(nextMove)); UpdateMap(rover); } }
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++; } }
public IEnumerable <RoverAction> Simulate(IRoverStatusAccessor rover) { while (true) { var adjacent = GetAdjacent(rover); TerrainType occupied = adjacent[Direction.None]; (Direction? adjacentSmoothDir, Direction? adjacentRoughDir, Int32 smoothCount) = FindAdjacentUnsampled(adjacent); if (rover.MovesLeft <= 5) { foreach (var action in DoLowMoves(rover, adjacent)) { yield return(action); } yield break; } if (rover.Power < LowPowerThreshold || (!adjacentSmoothDir.HasValue && occupied == TerrainType.Smooth)) { if (rover.Power < CalculateExcessPowerThershold(rover) / 2 && rover.NoBacktrack > 3) { yield return(RoverAction.CollectPower); } if (rover.Power < LowPowerThreshold) { yield return(RoverAction.Transmit); } } else if (_gatheringPower && HasExcessPower(rover, rover.CollectablePower)) { yield return(RoverAction.CollectPower); _gatheringPower = false; } // 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) || _gatherPowerDir != Direction.None)) { yield return(RoverAction.CollectSample); if (rover.SamplesCollected >= Parameters.SamplesPerProcess && rover.Power > Parameters.ProcessCost + Parameters.MoveSmoothCost) { yield return(RoverAction.ProcessSamples); } } Boolean hasExcessPower = HasExcessPower(rover); if (hasExcessPower) { _gatheringPower = false; } (Boolean isDeadEnd, Direction deadEndEscape) = CheckDeadEnd(adjacent); if (isDeadEnd && rover.Adjacent.Occupied != TerrainType.Smooth) { AddDeadEnd(rover.Position); } if (_gatherPowerDir != Direction.None) { _destination = _gatherPowerDir; } else 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; } if (_gatheringPower && rover.Adjacent.Occupied == TerrainType.Smooth && smoothCount > 1) { _gatherPowerDir = nextMove.Opposite(); } else { _gatherPowerDir = Direction.None; } yield return(new RoverAction(nextMove)); _roundRobin++; } }