private ResolvedProfit <T> FindMostProfitableItem <T>(RoundData data, IProfitResolver <T> resovler) { IList <T> items = resovler.ResolveAccessibleItems(data); if (items.Count == 0) { return(null); } T bestItem = items.First(); ProfitData bestProfit = resovler.CalculateProfit(data, bestItem); for (int i = 1; i < items.Count; i++) { // TODO multiple best items T item = items[i]; ProfitData profit = resovler.CalculateProfit(data, item); if (profit.CompareTo(bestProfit) > 0) { bestItem = item; bestProfit = profit; } } return(new ResolvedProfit <T>(bestItem, bestProfit)); }
public IList <EnergyStation> ResolveAccessibleItems(RoundData data) { return(DistanceUtils.FilterByAccessibleRange( data.MyPosition, data.Map.Stations, new Func <EnergyStation, Position>(station => station.Position) )); }
public IList <Robot> ResolveAccessibleItems(RoundData data) { return(DistanceUtils.FilterByAccessibleRange( data.MyPosition, data.Robots, new Func <Robot, Position>(robot => robot.Position) ).FilterForeignRobots()); }
public RobotCommand DoStep(IList <Robot> robots, int robotToMoveIndex, Map map) { FileLogger.Log("\n\nMY MOVE\n\n"); Robot myRobot = robots[robotToMoveIndex]; if (CanClone(myRobot)) { FileLogger.Log("Decided to clone"); robotsCount++; return(new CreateNewRobotCommand()); } RoundData data = new RoundData(map, robots, myRobot); ResolvedProfit <EnergyStation> bestStation = FindMostProfitableItem(data, stationProfitResolver); ResolvedProfit <Robot> bestRobot = FindMostProfitableItem(data, robotProfitResolver); FileLogger.Log($"Round {currentRound}, Robot #{robotToMoveIndex} - {myRobot.Format()}"); FileLogger.Log($"Best station: {bestStation.Item.Format()} with profit {bestStation.Profit}"); FileLogger.Log($"Best robot: {bestRobot.Item.Format()} with profit {bestRobot.Profit}"); if (bestStation == null && bestRobot == null) { return new MoveCommand() { NewPosition = data.MyPosition } } ; int accessibleEnergy = ResolveAccessibleStationEnergy(data.MyPosition, data.Map.Stations); if (accessibleEnergy > bestStation?.Profit?.Profit && accessibleEnergy > bestRobot?.Profit?.Profit) { FileLogger.Log("Decided to collect energy now"); return(new CollectEnergyCommand()); } if (bestStation?.Profit?.CompareTo(bestRobot.Profit) > 0) { FileLogger.Log("Decided to work with station"); return(stationProfitResolver.ProcessStep(data, bestStation.Item, bestStation.Profit)); } else { FileLogger.Log("Decided to work with robot"); return(robotProfitResolver.ProcessStep(data, bestRobot.Item, bestRobot.Profit)); } }
public RobotCommand ProcessStep(RoundData data, EnergyStation station, ProfitData profit) { if (DistanceUtils.DistanceFromStation(data.MyPosition, station.Position) <= Constants.CollectingRadius) { FileLogger.Log("Collecting energy from stations nearby"); return(new CollectEnergyCommand()); } else { FileLogger.Log($"Moving to station {station.Format()} at position {profit.MovePosition}"); return(new MoveCommand() { NewPosition = profit.MovePosition }); } }
public RobotCommand ProcessStep(RoundData data, Robot robot, ProfitData profit) { if (data.MyPosition == robot.Position) { FileLogger.Log($"Attacking robot: {robot.Format()} at position {profit.MovePosition}"); } else { FileLogger.Log($"Moving to robot {robot} at position {profit.MovePosition}"); } return(new MoveCommand() { NewPosition = profit.MovePosition }); }
private int CalculateBestMoveStepsCount(RoundData data, Robot robot, float distance) { float instEnergy = robot.Energy * Constants.StoleRateEnergyAtAttack - Constants.AttackEnergyLoss; int stepsCount = 1; int energyToMove; while (distance / stepsCount > Constants.AttackMoveDistance) { energyToMove = DistanceUtils.ResolveMoveEnergy(data.MyPosition, robot.Position, stepsCount, data.Map, data.Robots); if (instEnergy > energyToMove && energyToMove < data.MyEnergy - Constants.MinEnegryAfterMove) { return(stepsCount); } stepsCount++; } return(stepsCount); }
public ProfitData CalculateProfit(RoundData data, Robot robot) { float distance = DistanceUtils.DistanceBetweenPoints(robot.Position, data.MyPosition); int stepsCount = CalculateBestMoveStepsCount(data, robot, distance); float speed = distance / stepsCount; int profit = ResolveTotalRobotProfit(robot, stepsCount); Position movePosition; if (stepsCount == 1) { movePosition = robot.Position; } else { movePosition = DistanceUtils.ResolveMovePosition( data.MyPosition, robot.Position, stepsCount, data.Map, data.Robots ); } float moveDistance = DistanceUtils.DistanceBetweenPoints(data.MyPosition, movePosition); float maxMoveDistanceWithDisplacement = speed + Constants.MaxMovementDisplacement; if (moveDistance > maxMoveDistanceWithDisplacement && movePosition != robot.Position) { movePosition = data.MyPosition; } return(new ProfitData( profit - DistanceUtils.ResolveMoveEnergy(data.MyPosition, robot.Position, stepsCount, data.Map, data.Robots), distance, stepsCount, movePosition )); }
public ProfitData CalculateProfit(RoundData data, EnergyStation station) { float distance = DistanceUtils.DistanceBetweenPoints(data.MyPosition, station.Position); KeyValuePair <float, int> bestStepDistanceToProfit = AverageStepDistances.ToDictionary( stepDitance => stepDitance, stepDistance => ResolveProfitWithAverageStepDistance(station, distance, stepDistance) ) .ToList() .MaxBy(entry => entry.Value); float averageStepDistance = bestStepDistanceToProfit.Key; int stepsCount = (int)Math.Ceiling(distance / averageStepDistance); if (stepsCount == 0) { stepsCount = 1; } int profit = bestStepDistanceToProfit.Value; Position positionToCollectEnergy = PositionHelper.FindNearestStationPositon( data.MyPosition, station.Position, data.Robots.FilterForeignRobots() ); Position movePosition; if (positionToCollectEnergy == null) { movePosition = data.MyPosition; } else { movePosition = DistanceUtils.ResolveMovePosition( data.MyPosition, positionToCollectEnergy, stepsCount, data.Map, data.Robots ); } if (movePosition == null) { FileLogger.Log("Failed to find move position"); movePosition = data.MyPosition; } float moveDistance = DistanceUtils.DistanceBetweenPoints(data.MyPosition, movePosition); float maxMoveDistanceWithDisplacement = distance / stepsCount + Constants.MaxMovementDisplacement; if (moveDistance > maxMoveDistanceWithDisplacement && movePosition != positionToCollectEnergy) { FileLogger.Log("Availabel move position is too far"); movePosition = data.MyPosition; } return(new ProfitData( profit - DistanceUtils.ResolveMoveEnergy(data.MyPosition, station.Position, stepsCount, data.Map, data.Robots), distance, stepsCount, movePosition )); }