private void CollectBarrels(TurnState turnState) { if (turnState.myShips.Count == 1) { strateg.decisions[turnState.myShips[0].id] = CollectFreeBarrels(turnState, turnState.myShips[0]); return; } if (turnState.enemyShips.Count == 1) { CollectEnemyBarrels(turnState, turnState.enemyShips[0], turnState.enemyShips[0]); return; } var ship1 = turnState.myShips[0]; var ship2 = turnState.myShips[1]; var enemyShip1 = turnState.enemyShips[0]; var enemyShip2 = turnState.enemyShips[1]; if (FastShipPosition.DistanceTo(ship1.fposition, enemyShip1.fcoord) > FastShipPosition.DistanceTo(ship2.fposition, enemyShip1.fcoord)) { enemyShip1 = turnState.enemyShips[1]; enemyShip2 = turnState.enemyShips[0]; } CollectEnemyBarrels(turnState, enemyShip1, enemyShip2); }
public void DistanceTo_ReturnsValidValue() { for (int xt = 0; xt < Constants.MAP_WIDTH; xt++) { for (int yt = 0; yt < Constants.MAP_HEIGHT; yt++) { for (int x = 0; x < Constants.MAP_WIDTH; x++) { for (int y = 0; y < Constants.MAP_HEIGHT; y++) { for (int speed = 0; speed <= Constants.MAX_SHIP_SPEED; speed++) { for (int orientation = 0; orientation < 6; orientation++) { var shipPosition = new ShipPosition(new Coord(x, y), orientation, speed); var target = new Coord(xt, yt); var fastShipPosition = FastShipPosition.Create(shipPosition); FastShipPosition.DistanceTo(fastShipPosition, FastCoord.Create(target)).Should().Be(shipPosition.DistanceTo(target), $"shipPosition: {shipPosition}; target: {target}"); } } } } } } }
public CollectableBarrel FindNearestBarrelToCollect(TurnState turnState, Ship ship, HashSet <int> used = null) { var barrelsHitTurns = new Dictionary <int, int>(); foreach (var barrel in turnState.barrels) { foreach (var cannonball in turnState.cannonballs) { if (cannonball.fcoord == barrel.fcoord) { int prevTurns; if (!barrelsHitTurns.TryGetValue(barrel.id, out prevTurns) || prevTurns > cannonball.turns) { barrelsHitTurns[barrel.id] = cannonball.turns; } } } } var nextShipPosition1 = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship.fposition, ShipMoveCommand.Faster)); var nextShipPosition2 = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship.fposition, ShipMoveCommand.Wait)); var bestDist = int.MaxValue; Barrel bestBarrel = null; foreach (var barrel in turnState.barrels) { if (used == null || !used.Contains(barrel.id)) { var dist = FastShipPosition.DistanceTo(nextShipPosition1, barrel.fcoord); if (dist < bestDist) { var enemyTravelTime = dist / 2 + 1; int hitTurns; if (barrelsHitTurns.TryGetValue(barrel.id, out hitTurns) && hitTurns <= enemyTravelTime) { continue; } bestBarrel = barrel; bestDist = dist; } dist = FastShipPosition.DistanceTo(nextShipPosition2, barrel.fcoord); if (dist < bestDist) { var enemyTravelTime = dist / 2 + 1; int hitTurns; if (barrelsHitTurns.TryGetValue(barrel.id, out hitTurns) && hitTurns <= enemyTravelTime) { continue; } bestBarrel = barrel; bestDist = dist; } } } return(bestBarrel == null ? null : new CollectableBarrel { barrel = bestBarrel, dist = bestDist }); }
public void DistanceTo_StrangeCase_ReturnsValidValue() { //coord: 23, 5, orientation: 0, speed: 0 23, 5 var shipPosition = new ShipPosition(new Coord(23, 5), 0, 0); var target = new Coord(20, 5); var fastShipPosition = FastShipPosition.Create(shipPosition); var fastTarget = FastCoord.Create(target); FastShipPosition.DistanceTo(fastShipPosition, fastTarget).Should().Be(1000); }
public StrategicDecision MakeStrategicDecision(TurnState turnState, StrategicDecision prevDecision, Ship ship, Ship enemyShip) { var barrels = CollectableBarrels(turnState, enemyShip); var nextShipPosition1 = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship.fposition, ShipMoveCommand.Faster)); var nextShipPosition2 = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship.fposition, ShipMoveCommand.Wait)); var target = barrels.FirstOrDefault( b => FastShipPosition.DistanceTo(nextShipPosition1, b.barrel.fcoord) < b.dist - 1 || FastShipPosition.DistanceTo(nextShipPosition2, b.barrel.fcoord) < b.dist - 1); if (target == null) { return(strateg.RunAway(turnState, ship, prevDecision)); } var barrelToFire = barrels.TakeWhile(b => b != target).LastOrDefault(); return(strateg.Collect(target.barrel).FireTo(barrelToFire?.barrel.fcoord)); }
private ShipPathChainItem( ShipPathChainItem prev, ShipMoveCommand command, int fposition, int depth, ShipMoveCommand startCommand, int ftarget, int pathDamage) { this.prev = prev; this.command = command; this.fposition = fposition; this.depth = depth; this.startCommand = startCommand; dist = FastShipPosition.DistanceTo(fposition, ftarget); this.pathDamage = pathDamage; if (depth == Settings.NAVIGATION_PATH_DEPTH) { SetDamage(pathDamage); } }
public StrategicDecision WalkFree(TurnState turnState, Ship ship, StrategicDecision prevDecision) { switch (prevDecision?.role) { case StrategicRole.Free: break; default: prevDecision = new StrategicDecision { role = StrategicRole.Free, targetCoord = freeTargets[0] }; break; } if (FastShipPosition.DistanceTo(ship.fposition, prevDecision.targetCoord.Value) < Settings.FREE_WALK_TARGET_REACH_DIST) { var freeIndex = (Array.IndexOf(freeTargets, prevDecision.targetCoord.Value) + 1) % freeTargets.Length; return(new StrategicDecision { role = StrategicRole.Free, targetCoord = freeTargets[freeIndex] }); } return(prevDecision); }
public void CollectEnemyBarrels(TurnState turnState, Ship enemyShip1, Ship enemyShip2) { var barrels1 = strateg.strategy1vs1.CollectableBarrels(turnState, enemyShip1); var barrels2 = strateg.strategy1vs1.CollectableBarrels(turnState, enemyShip2); var ship1 = turnState.myShips[0]; var ship2 = turnState.myShips[1]; var nextShip1Position1 = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship1.fposition, ShipMoveCommand.Faster)); var nextShip1Position2 = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship1.fposition, ShipMoveCommand.Wait)); var nextShip2Position1 = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship2.fposition, ShipMoveCommand.Faster)); var nextShip2Position2 = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship2.fposition, ShipMoveCommand.Wait)); var target1 = barrels1.FirstOrDefault( b => FastShipPosition.DistanceTo(nextShip1Position1, b.barrel.fcoord) < b.dist - 1 || FastShipPosition.DistanceTo(nextShip1Position2, b.barrel.fcoord) < b.dist - 1); var target2 = barrels2.FirstOrDefault( b => FastShipPosition.DistanceTo(nextShip2Position1, b.barrel.fcoord) < b.dist - 1 || FastShipPosition.DistanceTo(nextShip2Position2, b.barrel.fcoord) < b.dist - 1); while (true) { if (target1 == null) { StrategicDecision decision; strateg.decisions.TryGetValue(ship1.id, out decision); strateg.decisions[ship1.id] = strateg.RunAway(turnState, ship1, decision); } if (target2 == null) { StrategicDecision decision; strateg.decisions.TryGetValue(ship2.id, out decision); strateg.decisions[ship2.id] = strateg.RunAway(turnState, ship2, decision); } if (target1 == null && target2 == null) { return; } if (target1 != null && target2 == null) { var barrelToFire = barrels1.TakeWhile(b => b != target1).LastOrDefault(); strateg.decisions[ship1.id] = strateg.Collect(target1.barrel).FireTo(barrelToFire?.barrel.fcoord); return; } if (target2 != null && target1 == null) { var barrelToFire = barrels2.TakeWhile(b => b != target2).LastOrDefault(); strateg.decisions[ship2.id] = strateg.Collect(target2.barrel).FireTo(barrelToFire?.barrel.fcoord); return; } if (target1.barrel != target2.barrel) { var barrelToFire1 = barrels1.TakeWhile(b => b.barrel != target1.barrel && b.barrel != target2.barrel).LastOrDefault(); strateg.decisions[ship1.id] = strateg.Collect(target1.barrel).FireTo(barrelToFire1?.barrel.fcoord); var barrelToFire2 = barrels2.TakeWhile(b => b.barrel != target1.barrel && b.barrel != target2.barrel && b.barrel != barrelToFire1?.barrel).LastOrDefault(); strateg.decisions[ship2.id] = strateg.Collect(target2.barrel).FireTo(barrelToFire2?.barrel.fcoord); return; } var dist1 = Math.Min(FastShipPosition.DistanceTo(nextShip1Position1, target1.barrel.fcoord), FastShipPosition.DistanceTo(nextShip1Position2, target1.barrel.fcoord)); var dist2 = Math.Min(FastShipPosition.DistanceTo(nextShip2Position1, target1.barrel.fcoord), FastShipPosition.DistanceTo(nextShip2Position2, target1.barrel.fcoord)); if (dist1 < dist2) { target2 = barrels2.FirstOrDefault( b => b.barrel != target1.barrel && (FastShipPosition.DistanceTo(nextShip2Position1, b.barrel.fcoord) < b.dist - 1 || FastShipPosition.DistanceTo(nextShip2Position2, b.barrel.fcoord) < b.dist - 1)); } else { target1 = barrels1.FirstOrDefault( b => b.barrel != target2.barrel && (FastShipPosition.DistanceTo(nextShip1Position1, b.barrel.fcoord) < b.dist - 1 || FastShipPosition.DistanceTo(nextShip1Position2, b.barrel.fcoord) < b.dist - 1)); } } }
private static void Main22(string[] args) { FastCoord.Init(); var coordsX = new List <Coord>(); for (int x = -1; x < Constants.MAP_WIDTH + 1; x++) { for (int y = -1; y < Constants.MAP_HEIGHT + 1; y++) { var coord = new Coord(x, y); coordsX.Add(coord); } } var indexes = Enumerable.Range(0, coordsX.Count).ToArray(); var seed = new Random().Next(); Console.Out.WriteLine($"Seed: {seed}"); var random = new Random(seed); for (int i = 0; i < indexes.Length; i++) { var r = random.Next(i, indexes.Length); var tmp = indexes[r]; indexes[r] = indexes[i]; indexes[i] = tmp; } var coords = indexes.Select(i => coordsX[i]).ToArray(); var fastCoords = indexes.Select(i => FastCoord.Create(coords[i])).ToArray(); var ships = coords.Select(c => new ShipPosition(c, random.Next(6), random.Next(3))).ToArray(); var fastShips = ships.Select(FastShipPosition.Create).ToArray(); var stopwatch = Stopwatch.StartNew(); Console.Out.WriteLine("IsInsideMap"); stopwatch.Restart(); int ind = 0; for (int i = 0; i < 10000000; i++) { coords[ind++].IsInsideMap(); if (ind >= indexes.Length) { ind = 0; } } stopwatch.Stop(); Console.Out.WriteLine(stopwatch.ElapsedMilliseconds); stopwatch.Restart(); ind = 0; for (int i = 0; i < 10000000; i++) { FastCoord.IsInsideMap(fastCoords[ind++]); if (ind >= indexes.Length) { ind = 0; } } stopwatch.Stop(); Console.Out.WriteLine(stopwatch.ElapsedMilliseconds); Console.Out.WriteLine("DistanceTo"); stopwatch.Restart(); ind = 0; for (int i = 0; i < 10000000; i++) { coords[ind++].DistanceTo(coords[0]); if (ind >= indexes.Length) { ind = 0; } } stopwatch.Stop(); Console.Out.WriteLine(stopwatch.ElapsedMilliseconds); stopwatch.Restart(); ind = 0; for (int i = 0; i < 10000000; i++) { FastCoord.Distance(fastCoords[ind++], fastCoords[0]); if (ind >= indexes.Length) { ind = 0; } } stopwatch.Stop(); Console.Out.WriteLine(stopwatch.ElapsedMilliseconds); Console.Out.WriteLine("Neighbor"); stopwatch.Restart(); ind = 0; for (int i = 0; i < 10000000; i++) { coords[ind].Neighbor(0); coords[ind].Neighbor(1); coords[ind].Neighbor(2); coords[ind].Neighbor(3); coords[ind].Neighbor(4); coords[ind].Neighbor(5); if (++ind >= indexes.Length) { ind = 0; } } stopwatch.Stop(); Console.Out.WriteLine(stopwatch.ElapsedMilliseconds); stopwatch.Restart(); ind = 0; for (int i = 0; i < 10000000; i++) { FastCoord.Neighbor(fastCoords[ind], 0); FastCoord.Neighbor(fastCoords[ind], 1); FastCoord.Neighbor(fastCoords[ind], 2); FastCoord.Neighbor(fastCoords[ind], 3); FastCoord.Neighbor(fastCoords[ind], 4); FastCoord.Neighbor(fastCoords[ind], 5); if (++ind >= indexes.Length) { ind = 0; } } stopwatch.Stop(); Console.Out.WriteLine(stopwatch.ElapsedMilliseconds); Console.Out.WriteLine("ShipDistanceTo"); var shipPosition = new ShipPosition(coords[0], 0, 0); stopwatch.Restart(); ind = 0; for (int i = 0; i < 10000000; i++) { shipPosition.DistanceTo(coords[ind]); if (++ind >= indexes.Length) { ind = 0; } } stopwatch.Stop(); Console.Out.WriteLine(stopwatch.ElapsedMilliseconds); var fastShipPosition = FastShipPosition.Create(shipPosition); stopwatch.Restart(); ind = 0; for (int i = 0; i < 10000000; i++) { FastShipPosition.DistanceTo(fastShipPosition, fastCoords[ind++]); if (ind >= indexes.Length) { ind = 0; } } stopwatch.Stop(); Console.Out.WriteLine(stopwatch.ElapsedMilliseconds); Console.Out.WriteLine("Collides"); stopwatch.Restart(); ind = 0; for (int i = 0; i < 10000000; i++) { shipPosition.Collides(coords[ind++]); if (ind >= indexes.Length) { ind = 0; } } stopwatch.Stop(); Console.Out.WriteLine(stopwatch.ElapsedMilliseconds); stopwatch.Restart(); ind = 0; for (int i = 0; i < 10000000; i++) { FastShipPosition.Collides(fastShipPosition, fastCoords[ind++]); if (ind >= indexes.Length) { ind = 0; } } stopwatch.Stop(); Console.Out.WriteLine(stopwatch.ElapsedMilliseconds); Console.Out.WriteLine("CollidesShip"); stopwatch.Restart(); ind = 0; for (int i = 0; i < 10000000; i++) { shipPosition.CollidesShip(ships[ind++]); if (ind >= indexes.Length) { ind = 0; } } stopwatch.Stop(); Console.Out.WriteLine(stopwatch.ElapsedMilliseconds); stopwatch.Restart(); ind = 0; for (int i = 0; i < 10000000; i++) { FastShipPosition.CollidesShip(fastShipPosition, fastShips[ind++]); if (ind >= indexes.Length) { ind = 0; } } stopwatch.Stop(); Console.Out.WriteLine(stopwatch.ElapsedMilliseconds); Console.Out.WriteLine("Move"); stopwatch.Restart(); ind = 0; for (int i = 0; i < 1_000_000; i++) { foreach (var moveCommand in ShipMoveCommands.all) { ships[ind].Apply(moveCommand); } if (++ind >= indexes.Length) { ind = 0; } } stopwatch.Stop(); Console.Out.WriteLine(stopwatch.ElapsedMilliseconds); stopwatch.Restart(); ind = 0; for (int i = 0; i < 1_000_000; i++) { foreach (var moveCommand in ShipMoveCommands.all) { var moved = FastShipPosition.Move(fastShips[ind], moveCommand); FastShipPosition.GetMovedPosition(moved); FastShipPosition.GetFinalPosition(moved); } if (++ind >= indexes.Length) { ind = 0; } } stopwatch.Stop(); Console.Out.WriteLine(stopwatch.ElapsedMilliseconds); stopwatch.Restart(); ind = 0; for (int i = 0; i < 1_000_000; i++) { foreach (var moveCommand in ShipMoveCommands.all) { uint myMovement; uint otherMovement; CollisionChecker.Move(fastShips[ind], moveCommand, fastShips[(ind + 1) % indexes.Length], moveCommand, out myMovement, out otherMovement); FastShipPosition.GetMovedPosition(myMovement); FastShipPosition.GetFinalPosition(myMovement); } if (++ind >= indexes.Length) { ind = 0; } } stopwatch.Stop(); Console.Out.WriteLine(stopwatch.ElapsedMilliseconds); }
public List <PathItem> FindPath(TurnState turnState, int ftarget, NavigationMethod navigationMethod) { var ship = turnState.FindMyShip(shipId); //if (FastShipPosition.Collides(ship.fposition, ftarget)) // return new List<PathItem>(); var queue = new Queue <ShipPathChainItem>(); queue.Enqueue(ShipPathChainItem.Start(ship.fposition, ftarget)); var used = new Dictionary <ShipMovementState, ShipPathChainItem>(); while (queue.Any()) { var current = queue.Dequeue(); if (current.depth != Settings.NAVIGATION_PATH_DEPTH) { var turnForecast = gameState.forecaster.GetTurnForecast(current.depth); foreach (var moveCommand in ShipMoveCommands.all) { var newShipMovement = FastShipPosition.Move(current.fposition, moveCommand); var newMovedPos = FastShipPosition.GetMovedPosition(newShipMovement); var newPos = FastShipPosition.GetFinalPosition(newShipMovement); var newMovementState = new ShipMovementState(newPos, current.depth + 1); if (!used.ContainsKey(newMovementState)) { var onMyShip = false; foreach (var otherShip in turnState.myShips) { if (otherShip == ship) { continue; } var otherPosition = turnForecast.myShipsSourcePositions[otherShip.index]; uint myMovement; uint otherMovement; var collisionType = CollisionChecker.Move(current.fposition, moveCommand, otherPosition, turnForecast.myShipsMoveCommands[otherShip.index], out myMovement, out otherMovement); if ((collisionType & (CollisionType.MyMove | CollisionType.MyRotation)) != CollisionType.None) { newShipMovement = myMovement; newMovedPos = FastShipPosition.GetMovedPosition(newShipMovement); newPos = FastShipPosition.GetFinalPosition(newShipMovement); newMovementState = new ShipMovementState(newPos, current.depth + 1); onMyShip = used.ContainsKey(newMovementState); break; } } if (onMyShip) { continue; } var onEnemyShip = false; if (current.depth == 0) { foreach (var enemyShip in turnState.enemyShips) { var enemyPosition = enemyShip.fposition; foreach (var enemyMoveCommand in ShipMoveCommands.all) { uint myMovement; uint enemyMovement; var collisionType = CollisionChecker.Move(current.fposition, moveCommand, enemyPosition, enemyMoveCommand, out myMovement, out enemyMovement); if ((collisionType & (CollisionType.MyMove | CollisionType.MyRotation)) != CollisionType.None) { newShipMovement = myMovement; newMovedPos = FastShipPosition.GetMovedPosition(newShipMovement); newPos = FastShipPosition.GetFinalPosition(newShipMovement); newMovementState = new ShipMovementState(newPos, current.depth + 1); onEnemyShip = used.ContainsKey(newMovementState); break; } } } } else { var prevEnemyFinalPositions = gameState.forecaster.GetTurnForecast(Math.Min(current.depth - 1, Settings.NAVIGATOR_ENEMY_POSITION_DEPTH)).enemyShipsFinalPositions; foreach (var enemyPosition in prevEnemyFinalPositions) { uint myMovement; uint enemyMovement; var collisionType = CollisionChecker.Move(current.fposition, moveCommand, enemyPosition, ShipMoveCommand.Wait, out myMovement, out enemyMovement); if ((collisionType & (CollisionType.MyMove | CollisionType.MyRotation)) != CollisionType.None) { newShipMovement = myMovement; newMovedPos = FastShipPosition.GetMovedPosition(newShipMovement); newPos = FastShipPosition.GetFinalPosition(newShipMovement); newMovementState = new ShipMovementState(newPos, current.depth + 1); onEnemyShip = used.ContainsKey(newMovementState); break; } } //onEnemyShip = gameState.forecaster.GetTurnForecast(Math.Min(current.depth, Settings.NAVIGATOR_ENEMY_POSITION_DEPTH)).enemyShipsFinalPositions // .Any(m => FastShipPosition.CollidesShip(newPos, m) || FastShipPosition.CollidesShip(newMovedPos, m)); } if (onEnemyShip) { //used.Add(newMovementState, null); continue; } var damage = turnForecast.mineDamageCoordMap[FastShipPosition.Coord(newPos)] + turnForecast.mineDamageCoordMap[FastShipPosition.Bow(newPos)] + turnForecast.mineDamageCoordMap[FastShipPosition.Stern(newPos)] + turnForecast.nearMineDamageCoordMap[FastShipPosition.Bow(newPos)] + turnForecast.nearMineDamageCoordMap[FastShipPosition.Stern(newPos)]; if (newMovedPos != newPos) { damage += turnForecast.mineDamageCoordMap[FastShipPosition.Bow(newMovedPos)] + turnForecast.mineDamageCoordMap[FastShipPosition.Stern(newMovedPos)] + turnForecast.nearMineDamageCoordMap[FastShipPosition.Bow(newMovedPos)] + turnForecast.nearMineDamageCoordMap[FastShipPosition.Stern(newMovedPos)]; } var cannonedBowOrStern = turnForecast.cannonballCoordsMap[FastShipPosition.Bow(newPos)] || turnForecast.cannonballCoordsMap[FastShipPosition.Stern(newPos)]; if (cannonedBowOrStern) { damage += Constants.LOW_DAMAGE; } var cannonedCenter = turnForecast.cannonballCoordsMap[FastShipPosition.Coord(newPos)]; if (cannonedCenter) { damage += Constants.HIGH_DAMAGE; } if (Settings.NEAR_ENEMYSHIP_VIRTUAL_DAMAGE > 0) { var nearEnemyShip = turnState.enemyShips.Any(m => FastShipPosition.DistanceTo(newPos, m.fcoord) < Settings.NEAR_ENEMY_SHIP_MIN_DIST); if (nearEnemyShip) { damage += Settings.NEAR_ENEMYSHIP_VIRTUAL_DAMAGE; } } var next = current.Next(newPos, moveCommand, ftarget, damage); queue.Enqueue(next); used.Add(newMovementState, next); } } } } ShipPathChainItem bestChainItem = null; foreach (var chainItem in used.Values.Where(v => v != null)) { if (chainItem.prev != null) { if (bestChainItem == null) { bestChainItem = chainItem; } else { switch (navigationMethod) { case NavigationMethod.Approach: bestChainItem = SelectBestPath_Approach(chainItem, bestChainItem, ship); break; case NavigationMethod.Collect: bestChainItem = SelectBestPath_Collect(chainItem, bestChainItem, ship); break; default: bestChainItem = SelectBestPath(chainItem, bestChainItem, ship); break; } } } } if (bestChainItem == null) { return(new List <PathItem>()); } var chainDump = new List <ShipPathChainItem>(); var chain = new List <PathItem>(); while (bestChainItem.prev != null) { chain.Add(new PathItem { command = bestChainItem.command, targetPosition = bestChainItem.fposition, sourcePosition = bestChainItem.prev.fposition }); chainDump.Add(bestChainItem); bestChainItem = bestChainItem.prev; } chainDump.Reverse(); if (Settings.DUMP_BEST_PATH) { Console.Error.WriteLine($"Best path for ship {shipId}"); foreach (var item in chainDump) { Console.Error.WriteLine($"{item.command} - {FastShipPosition.ToShipPosition(item.fposition)} - dmg:{item.damage}"); } } chain.Reverse(); return(chain); }