public Ship(int index, int id, int x, int y, int orientation, int speed, int rum, int owner) : base(id, EntityType.Ship, x, y) { this.index = index; this.orientation = orientation; this.speed = speed; this.rum = rum; this.owner = owner; bow = coord.Neighbor(orientation); stern = coord.Neighbor((orientation + 3) % 6); fposition = FastShipPosition.Create(x, y, orientation, speed); fbow = FastShipPosition.Bow(fposition); fstern = FastShipPosition.Stern(fposition); }
public void Bow_ReturnsValidCoord() { 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 fastShipPosition = FastShipPosition.Create(shipPosition); FastCoord.ToCoord(FastShipPosition.Bow(fastShipPosition)).Should().Be(shipPosition.bow, shipPosition.ToString()); } } } } }
private List <FireTarget> GetFireTargets(Ship ship, Ship enemyShip) { var result = new List <FireTarget>(); var enemyIndex = enemyShip.index; var cannonCoord = FastShipPosition.Bow(ship.fposition); for (var turn = 0; turn < Settings.CANNONS_TRAVEL_TIME_LIMIT + 1; turn++) { var forecast = gameState.forecaster.GetTurnForecast(turn); var enemyPosition = forecast.enemyShipsFinalPositions[enemyIndex]; var coords = new[] { FastShipPosition.Coord(enemyPosition), FastShipPosition.Bow(enemyPosition), FastShipPosition.Stern(enemyPosition) }; var targetTypes = new[] { FireTargetType.ShipCenter, FireTargetType.ShipBow, FireTargetType.ShipStern }; for (var i = 0; i < coords.Length; i++) { var target = coords[i]; if (FastCoord.IsInsideMap(target)) { if (forecast.myShipsPositions.Any(m => FastShipPosition.Collides(m, target))) { continue; } var distanceTo = FastCoord.Distance(cannonCoord, target); if (distanceTo <= 10) { var travelTime = (int)(1 + Math.Round(distanceTo / 3.0)); if (travelTime == turn) { result.Add(new FireTarget(target, turn, i == 0 ? Constants.HIGH_DAMAGE : Constants.LOW_DAMAGE, targetTypes[i])); } } } } } return(result); }
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); }