public void AttackClosestEnemyTankToOwnBase(GameState currGameState, Tank killerTank, Tank targetTank, TankActionSet actionSet, bool[] moveChosenByTankNumber) { MobileState killerTankState = currGameState.GetMobileState(killerTank.Index); if (killerTankState.IsActive) { MobileState enemyTankState = currGameState.GetMobileState(targetTank.Index); if (enemyTankState.IsActive) { DirectionalMatrix <DistanceCalculation> attackMatrix = currGameState.CalculationCache.GetIncomingAttackMatrixForTankByTankIndex(targetTank.Index); if (attackMatrix != null) { DistanceCalculation attackCalculation = attackMatrix[killerTankState.Dir, killerTankState.Pos]; TankAction[] tankActions = PathCalculator.GetTankActionsOnIncomingShortestPath(attackMatrix, killerTankState, enemyTankState.Pos, currGameState.CalculationCache.FiringLinesForTanksMatrix, keepMovingCloserOnFiringLastBullet: true); if (tankActions.Length > 0) { actionSet.Actions[killerTank.Number] = tankActions[0]; moveChosenByTankNumber[killerTank.Number] = true; } } } } }
public static void Main() { // The first three problems are in this project Point3D point = new Point3D(5.4m, 6.6m, 3.1m); Console.WriteLine(point); Point3D anotherPoint = new Point3D(1m, 5.78m, -2.75m); Console.WriteLine(anotherPoint); Console.WriteLine("{0:F3}", DistanceCalculation.CalculateDistance(point, anotherPoint)); Point3D basePoint = Point3D.StartingPoint; Console.WriteLine(basePoint); Path3D listOfPoints = new Path3D(); listOfPoints.AddPoint(point); listOfPoints.AddPoint(basePoint); listOfPoints.AddPoint(anotherPoint); Storage.SavePath(listOfPoints); }
public TankAction[] GetActionsToReachLineOfFireDefencePointByIncomingAttackDirection( int playerIndex, int tankNumber, Direction finalIncomingDirectionOfAttack) { Player player = Game.Current.Players[playerIndex]; Tank tank = player.Tanks[tankNumber]; MobileState tankState = GetTankState(playerIndex, tankNumber); if (tankState.IsActive) // TODO: Check if locked in a firefight also { DirectionalMatrix <DistanceCalculation> distanceMatrix = GameState.CalculationCache.GetDistanceMatrixFromTankByTankIndex(tank.Index); Direction defenceDir = finalIncomingDirectionOfAttack.GetOpposite(); if (defenceDir == Direction.NONE) { defenceDir = Direction.RIGHT; } int startPosOffsetFromBase = Constants.TANK_OUTER_EDGE_OFFSET; int endPosOffsetFromBase = startPosOffsetFromBase + MAX_POINTS_TO_TRY_FOR_DEFENCE_POS; for (int offsetSize = startPosOffsetFromBase; offsetSize < endPosOffsetFromBase; offsetSize++) { Point defencePos = player.Base.Pos + defenceDir.GetOffset(offsetSize); DistanceCalculation tankDefenceCalc = distanceMatrix[defenceDir, defencePos]; if (tankDefenceCalc.CodedDistance == 0) { // This defence point can't be reached, try further away continue; } return(PathCalculator.GetTankActionsOnOutgoingShortestPath(distanceMatrix, defenceDir, defencePos)); } } return(new TankAction[0]); }
public int GetDistanceFromTankToPointUsingDistanceMatrix( DirectionalMatrix <DistanceCalculation> distanceMatrix, Direction directionAtDestination, Point destination) { DistanceCalculation distanceCalc = distanceMatrix[directionAtDestination, destination]; return(distanceCalc.Distance); }
//TO FIND ALL ROUTER CONNECTION AND ROUTER CINNECTED LINK public void Connectivity(string SR, string DR, ArrayList arryConnection) { DistanceCalculation.arryConnection.Clear(); DistanceCalculation.arryConnection = arryConnection; arryCon = arryConnection; //LINK BETWEEN SOURCE AND DESTINATION destination = DR; //DESSTINATION source = SR; //SOURCE for (int i = 0; i < arryConnection.Count; i++) { rec = arryConnection[i].ToString(); splt = rec.Split('-'); if (source.Equals(splt[0])) { middle = splt[1]; } else if (source.Equals(splt[1])) { middle = splt[0]; } else { continue; } if (middle.Equals(destination)) { arryNeighR1 = new ArrayList(); arryNeighR1.Add(source); arryNeighR1.Add(middle); //ADD NEIGHBOUR NODE FOR EACH ROUTER DistanceCalculation.PossiblePath.Add(arryNeighR1); for (int k = 0; k < DistanceCalculation.PossiblePathDistance.Count; k++) { strngB = DistanceCalculation.PossiblePathDistance[k].ToString(); splt1 = strngB.Split('-'); if (((splt1[0] == source) && splt1[1] == destination) || ((splt1[1] == source) && (splt1[0] == destination))) { km = Convert.ToDouble(splt1[2]); break; } } // ADD ROUTER DISTANCE DistanceCalculation.distance.Add(km); } else { arryNeighR1 = new ArrayList(); arryNeighR1.Add(source); arryNeighR1.Add(middle); DistanceCalculation dc = new DistanceCalculation(); //TO CALL GETPATH METHOD FOR CHECK ROUTER LINK dc.getpath(source, destination, arryNeighR1, middle); } } }
public int GetDistanceFromTankToPoint(int playerIndex, int tankNumber, Direction directionAtDestination, Point destination) { Tank tank = Game.Current.Players[playerIndex].Tanks[tankNumber]; DirectionalMatrix <DistanceCalculation> distanceMatrix = GameState.CalculationCache.GetDistanceMatrixFromTankByTankIndex(tank.Index); DistanceCalculation distanceCalc = distanceMatrix[directionAtDestination, destination]; return(distanceCalc.Distance); }
public int GetAttackDistanceFromHypotheticalTankStateToTank( MobileState attackTankState, int targetPlayerIndex, int targetTankNumber, EdgeOffset[] edgeOffsets) { Tank targetTank = Game.Current.Players[targetPlayerIndex].Tanks[targetTankNumber]; DirectionalMatrix <DistanceCalculation> distanceMatrix = GameState.CalculationCache.GetIncomingAttackMatrixForTankByTankIndex(targetTank.Index); DistanceCalculation distanceCalc = distanceMatrix[attackTankState]; return(distanceCalc.Distance); }
public int GetDistanceFromTankToTargetTank( int attackPlayerIndex, int attackTankNumber, int targetPlayerIndex, int targetTankNumber) { Tank attackTank = Game.Current.Players[attackPlayerIndex].Tanks[attackTankNumber]; DirectionalMatrix <DistanceCalculation> distanceMatrix = GameState.CalculationCache.GetDistanceMatrixFromTankByTankIndex(attackTank.Index); Tank defenceTank = Game.Current.Players[targetPlayerIndex].Tanks[targetTankNumber]; MobileState targetTankState = GetTankState(targetPlayerIndex, targetTankNumber); DistanceCalculation distanceCalc = distanceMatrix[targetTankState]; return(distanceCalc.Distance); }
protected void btnSubmitAddress_Click(object sender, EventArgs e) { string inputAddress = txtAddress.Text; Address inputLatLong = GeoCodingApi.GetGeoCod(inputAddress); if (!string.IsNullOrEmpty(inputAddress)) { foreach (Address address in addressStore) { if (address != null) { address.Distance = DistanceCalculation.Distance(address.Latitude, address.Longitude, inputLatLong.Latitude, inputLatLong.Longitude, 'K'); //address.Distance = DistanceMatrixApi.GetDistance(address, inputLatLong); Get distance from Google Distance Matrix API } } var closestAddress = addressStore.OrderBy(x => x.Distance).Take(5); repAddress.DataSource = closestAddress; repAddress.DataBind(); } }
public Umap( DistanceCalculation distance = null, IProvideRandomValues random = null, int dimensions = 2, int numberOfNeighbors = 15, int?customNumberOfEpochs = null, ProgressReporter progressReporter = null) { if ((customNumberOfEpochs != null) && (customNumberOfEpochs <= 0)) { throw new ArgumentOutOfRangeException(nameof(customNumberOfEpochs), "if non-null then must be a positive value"); } _distanceFn = distance ?? DistanceFunctions.Cosine; _random = random ?? DefaultRandomGenerator.Instance; _nNeighbors = numberOfNeighbors; _optimizationState = new OptimizationState { Dim = dimensions }; _customNumberOfEpochs = customNumberOfEpochs; _progressReporter = progressReporter; }
/// <summary> /// Calculates the distance (in km) between two specified <see cref="LatLng">latlong points</see>. /// By default this uses the Law of Cosines formula (http://en.wikipedia.org/wiki/Law_of_cosines). /// </summary> /// <param name="pointOne">The first point to use in the calculation.</param> /// <param name="pointTwo">The second point to use in the calculation.</param> /// <param name="calculation"> /// <para>The calculation to use.</para> /// <para>By default this uses the Law of Cosines formula.</para> /// </param> /// <returns> /// The distance (in km) between the two points specified. /// </returns> /// <exception cref="ArgumentOutOfRangeException"> /// The specified <paramref name="calculation"/> is outside the allowable <see cref="DistanceCalculation">values</see>. /// </exception> public static double Distance( LatLng pointOne, LatLng pointTwo, DistanceCalculation calculation = DistanceCalculation.LawOfCosines) { switch (calculation) { case DistanceCalculation.Haversine: double pointOneLatitude = pointOne.Latitude.ToRadians(); double pointOneLongitude = pointOne.Longitude.ToRadians(); double pointTwoLatitude = pointTwo.Latitude.ToRadians(); double pointTwoLongitude = pointTwo.Longitude.ToRadians(); double longitude = pointTwoLongitude - pointOneLongitude; double latitude = pointTwoLatitude - pointOneLatitude; double intermediateResult = Math.Pow(Math.Sin(latitude / 2.0), 2.0) + Math.Cos(pointOneLatitude) * Math.Cos(pointTwoLatitude) * Math.Pow(Math.Sin(longitude / 2.0), 2.0); // Intermediate result c (great circle distance in Radians). double c = 2.0 * Math.Atan2(Math.Sqrt(intermediateResult), Math.Sqrt(1.0 - intermediateResult)); return(EarthsRadiusInKilometers * c); case DistanceCalculation.LawOfCosines: return((Math.Acos( Math.Sin(pointOne.Latitude) * Math.Sin(pointTwo.Latitude) + Math.Cos(pointOne.Latitude) * Math.Cos(pointTwo.Latitude) * Math.Cos(pointTwo.Longitude - pointOne.Longitude) ) * EarthsRadiusInKilometers).ToRadians()); default: throw new ArgumentOutOfRangeException("calculation"); } }
private void ChooseShortestPathBotMoves() { GameState currGameState = Game.Current.CurrentTurn.GameState; TankActionSet actionSet = new TankActionSet(YourPlayerIndex, currGameState.Tick); bool[] moveChosen = new bool[Constants.TANKS_PER_PLAYER]; RespondToBullets(currGameState, actionSet, moveChosen); Tuple <int, int, TankAction>[] tankNumberDistanceAndActionArray = new Tuple <int, int, TankAction> [Constants.TANKS_PER_PLAYER]; // The closest bot can attack the base: for (int tankNumber = 0; tankNumber < Constants.TANKS_PER_PLAYER; tankNumber++) { Tank tank = You.Tanks[tankNumber]; MobileState tankState = currGameState.GetMobileState(tank.Index); if (!tankState.IsActive) { tankNumberDistanceAndActionArray[tankNumber] = new Tuple <int, int, TankAction>(tankNumber, Constants.UNREACHABLE_DISTANCE, TankAction.NONE); continue; } Base enemyBase = Opponent.Base; DirectionalMatrix <DistanceCalculation> distancesToEnemyBase = currGameState.CalculationCache.GetIncomingDistanceMatrixForBase(Opponent.Index); DistanceCalculation distanceCalc = distancesToEnemyBase[tankState.Dir, tankState.Pos]; FiringLineMatrix firingLineMatrix = currGameState.CalculationCache.FiringLinesForPointsMatrix; TankAction[] tankActions = PathCalculator.GetTankActionsOnIncomingShortestPath(distancesToEnemyBase, tankState.Dir, tankState.Pos.X, tankState.Pos.Y, enemyBase.Pos.X, enemyBase.Pos.Y, firingLineMatrix, keepMovingCloserOnFiringLastBullet: false); if (tankActions.Length == 0) { tankNumberDistanceAndActionArray[tankNumber] = new Tuple <int, int, TankAction>(tankNumber, Constants.UNREACHABLE_DISTANCE, TankAction.NONE); } else { tankNumberDistanceAndActionArray[tankNumber] = new Tuple <int, int, TankAction>(tankNumber, distanceCalc.Distance, tankActions[0]); } } int chosenTank; if (tankNumberDistanceAndActionArray[1].Item2 < tankNumberDistanceAndActionArray[0].Item2) { chosenTank = 1; } else { chosenTank = 0; } actionSet.Actions[chosenTank] = tankNumberDistanceAndActionArray[chosenTank].Item3; // The other bot can attack the closest enemy tank: Tank killerTank = You.Tanks[1 - chosenTank]; MobileState killerTankState = currGameState.GetMobileState(killerTank.Index); if (killerTankState.IsActive) { Tank enemyTank1 = Opponent.Tanks[0]; MobileState enemyTankState1 = currGameState.GetMobileState(enemyTank1.Index); int killerDistance1 = Constants.UNREACHABLE_DISTANCE; TankAction killerAction1 = TankAction.NONE; if (enemyTankState1.IsActive) { DirectionalMatrix <DistanceCalculation> attackMatrix1 = currGameState.CalculationCache.GetIncomingAttackMatrixForTankByTankIndex(enemyTank1.Index); if (attackMatrix1 != null) { DistanceCalculation attackCalculation1 = attackMatrix1[killerTankState.Dir, killerTankState.Pos]; killerDistance1 = attackCalculation1.Distance; TankAction[] tankActions = PathCalculator.GetTankActionsOnIncomingShortestPath(attackMatrix1, killerTankState, enemyTankState1.Pos, currGameState.CalculationCache.FiringLinesForTanksMatrix, keepMovingCloserOnFiringLastBullet: true); if (tankActions.Length > 0) { killerAction1 = tankActions[0]; } } } Tank enemyTank2 = Opponent.Tanks[1]; MobileState enemyTankState2 = currGameState.GetMobileState(enemyTank2.Index); int killerDistance2 = Constants.UNREACHABLE_DISTANCE; TankAction killerAction2 = TankAction.NONE; if (enemyTankState2.IsActive) { DirectionalMatrix <DistanceCalculation> attackMatrix2 = currGameState.CalculationCache.GetIncomingAttackMatrixForTankByTankIndex(enemyTank2.Index); if (attackMatrix2 != null) { DistanceCalculation attackCalculation2 = attackMatrix2[killerTankState.Dir, killerTankState.Pos]; killerDistance2 = attackCalculation2.Distance; TankAction[] tankActions = PathCalculator.GetTankActionsOnIncomingShortestPath(attackMatrix2, killerTankState, enemyTankState2.Pos, currGameState.CalculationCache.FiringLinesForTanksMatrix, keepMovingCloserOnFiringLastBullet: true); if (tankActions.Length > 0) { killerAction2 = tankActions[0]; } } } actionSet.Actions[1 - chosenTank] = (killerDistance1 <= killerDistance2) ? killerAction1 : killerAction2; } Coordinator.SetBestMoveSoFar(actionSet); }
/// <summary> /// Calculates the distance (in km) between the current point and the <see cref="LatLng">point</see> specified. /// By default this uses the Law of Cosines formula (http://en.wikipedia.org/wiki/Law_of_cosines). /// </summary> /// <param name="otherPoint">The point we want to calculate the distance to.</param> /// <param name="calculation"> /// <para>The distance calculation to use.</para> /// <para>By default this uses the Law of Cosines formula.</para> /// </param> /// <returns> /// The distance (in km) between the current point and the <paramref name="otherPoint"/> specified. /// </returns> /// <exception cref="ArgumentOutOfRangeException"> /// The specified <paramref name="calculation"/> is outside the allowable <see cref="DistanceCalculation">values</see>. /// </exception> public double DistanceTo(LatLng otherPoint, DistanceCalculation calculation = DistanceCalculation.LawOfCosines) { return Distance(this, otherPoint, calculation); }
/// <summary> /// Calculates the distance (in km) between two specified <see cref="LatLng">latlong points</see>. /// By default this uses the Law of Cosines formula (http://en.wikipedia.org/wiki/Law_of_cosines). /// </summary> /// <param name="pointOne">The first point to use in the calculation.</param> /// <param name="pointTwo">The second point to use in the calculation.</param> /// <param name="calculation"> /// <para>The calculation to use.</para> /// <para>By default this uses the Law of Cosines formula.</para> /// </param> /// <returns> /// The distance (in km) between the two points specified. /// </returns> /// <exception cref="ArgumentOutOfRangeException"> /// The specified <paramref name="calculation"/> is outside the allowable <see cref="DistanceCalculation">values</see>. /// </exception> public static double Distance( LatLng pointOne, LatLng pointTwo, DistanceCalculation calculation = DistanceCalculation.LawOfCosines) { switch (calculation) { case DistanceCalculation.Haversine: double pointOneLatitude = pointOne.Latitude.ToRadians(); double pointOneLongitude = pointOne.Longitude.ToRadians(); double pointTwoLatitude = pointTwo.Latitude.ToRadians(); double pointTwoLongitude = pointTwo.Longitude.ToRadians(); double longitude = pointTwoLongitude - pointOneLongitude; double latitude = pointTwoLatitude - pointOneLatitude; double intermediateResult = Math.Pow(Math.Sin(latitude / 2.0), 2.0) + Math.Cos(pointOneLatitude) * Math.Cos(pointTwoLatitude) * Math.Pow(Math.Sin(longitude / 2.0), 2.0); // Intermediate result c (great circle distance in Radians). double c = 2.0 * Math.Atan2(Math.Sqrt(intermediateResult), Math.Sqrt(1.0 - intermediateResult)); return EarthsRadiusInKilometers * c; case DistanceCalculation.LawOfCosines: return (Math.Acos( Math.Sin(pointOne.Latitude) * Math.Sin(pointTwo.Latitude) + Math.Cos(pointOne.Latitude) * Math.Cos(pointTwo.Latitude) * Math.Cos(pointTwo.Longitude - pointOne.Longitude) ) * EarthsRadiusInKilometers).ToRadians(); default: throw new ArgumentOutOfRangeException("calculation"); } }
/// <summary> /// Calculates the distance (in km) between the current point and the <see cref="LatLng">point</see> specified. /// By default this uses the Law of Cosines formula (http://en.wikipedia.org/wiki/Law_of_cosines). /// </summary> /// <param name="otherPoint">The point we want to calculate the distance to.</param> /// <param name="calculation"> /// <para>The distance calculation to use.</para> /// <para>By default this uses the Law of Cosines formula.</para> /// </param> /// <returns> /// The distance (in km) between the current point and the <paramref name="otherPoint"/> specified. /// </returns> /// <exception cref="ArgumentOutOfRangeException"> /// The specified <paramref name="calculation"/> is outside the allowable <see cref="DistanceCalculation">values</see>. /// </exception> public double DistanceTo(LatLng otherPoint, DistanceCalculation calculation = DistanceCalculation.LawOfCosines) { return(Distance(this, otherPoint, calculation)); }
/// <summary> /// Create a version of nearest neighbor descent. /// </summary> public static NNDescentFn MakeNNDescent(DistanceCalculation distanceFn, IProvideRandomValues random) { return((data, leafArray, nNeighbors, nIters, maxCandidates, delta, rho, rpTreeInit, startingIteration) => { var nVertices = data.Length; var currentGraph = MakeHeap(data.Length, nNeighbors); for (var i = 0; i < data.Length; i++) { var indices = Utils.RejectionSample(nNeighbors, data.Length, random); for (var j = 0; j < indices.Length; j++) { var d = distanceFn(data[i], data[indices[j]]); HeapPush(currentGraph, i, d, indices[j], 1); HeapPush(currentGraph, indices[j], d, i, 1); } } if (rpTreeInit) { for (var n = 0; n < leafArray.Length; n++) { for (var i = 0; i < leafArray[n].Length; i++) { if (leafArray[n][i] < 0) { break; } for (var j = i + 1; j < leafArray[n].Length; j++) { if (leafArray[n][j] < 0) { break; } var d = distanceFn(data[leafArray[n][i]], data[leafArray[n][j]]); HeapPush(currentGraph, leafArray[n][i], d, leafArray[n][j], 1); HeapPush(currentGraph, leafArray[n][j], d, leafArray[n][i], 1); } } } } for (var n = 0; n < nIters; n++) { startingIteration?.Invoke(n, nIters); var candidateNeighbors = BuildCandidates(currentGraph, nVertices, nNeighbors, maxCandidates, random); var c = 0; for (var i = 0; i < nVertices; i++) { for (var j = 0; j < maxCandidates; j++) { var p = (int)Math.Floor(candidateNeighbors[0][i][j]); if ((p < 0) || (random.NextFloat() < rho)) { continue; } for (var k = 0; k < maxCandidates; k++) { var q = (int)Math.Floor(candidateNeighbors[0][i][k]); var cj = candidateNeighbors[2][i][j]; var ck = candidateNeighbors[2][i][k]; if (q < 0 || ((cj == 0) && (ck == 0))) { continue; } var d = distanceFn(data[p], data[q]); c += HeapPush(currentGraph, p, d, q, 1); c += HeapPush(currentGraph, q, d, p, 1); } } } if (c <= delta * nNeighbors * data.Length) { break; } } return DeHeapSort(currentGraph); }); }
private static void CalculateBulletThreats(BulletCalculation bulletCalc, GameState gameState, Player you) { TurnCalculationCache turnCalcCache = Game.Current.Turns[gameState.Tick].CalculationCache; Tank[] tanks; if (you != null) { tanks = you.Tanks; } else { tanks = Game.Current.Tanks; } foreach (Tank tank in tanks) { MobileState tankState = gameState.GetMobileState(tank.Index); foreach (BulletPathCalculation bulletPathCalc in bulletCalc.BulletPaths) { List <BulletThreat> bulletThreats = new List <BulletThreat>(); foreach (BulletPathPoint bulletPathPoint in bulletPathCalc.BulletPathPoints) { if (bulletPathPoint.DangerArea.ContainsPoint(tankState.Pos)) { BulletThreat bulletThreat = new BulletThreat(bulletPathCalc) { FiringTank = bulletPathCalc.Bullet.Tank, TankThreatened = tank }; bulletThreats.Add(bulletThreat); // Take the bullet on: FiringLineMatrix firingLineMatrix = gameState.CalculationCache.FiringLinesForPointsMatrix; AttackTargetDistanceCalculator attackCalculator = new AttackTargetDistanceCalculator( ElementType.BULLET, firingLineMatrix, gameState.CalculationCache, turnCalcCache); attackCalculator.MovementDirections = new Direction[] { bulletPathCalc.BulletState.Dir.GetOpposite() }; Cell bulletCell = turnCalcCache.CellMatrix[bulletPathCalc.BulletState.Pos]; DirectionalMatrix <DistanceCalculation> distanceCalcs = attackCalculator.CalculateMatrixOfShortestDistancesToTargetCell(bulletCell); DistanceCalculation distanceCalc = distanceCalcs[tankState]; if (distanceCalc.Distance <= bulletPathPoint.TicksToEscape) { Node[] nodes = PathCalculator.GetIncomingNodesOnShortestPath( distanceCalcs, tankState.Dir, tankState.Pos.X, tankState.Pos.Y, bulletPathCalc.BulletState.Pos.X, bulletPathCalc.BulletState.Pos.Y, firingLineMatrix, keepMovingCloserOnFiringLastBullet: true); bulletThreat.NodePathToTakeOnBullet = nodes; TankAction[] tankActions = PathCalculator.GetTankActionsOnIncomingShortestPath(distanceCalcs, tankState.Dir, tankState.Pos.X, tankState.Pos.Y, bulletPathCalc.BulletState.Pos.X, bulletPathCalc.BulletState.Pos.Y, firingLineMatrix, keepMovingCloserOnFiringLastBullet: true); bulletThreat.TankActionsToTakeOnBullet = tankActions; } // Move off his path in one direction: Point tankOffset = tankState.Pos - bulletPathCalc.BulletState.Pos; Point bulletMovementOffset = bulletPathCalc.BulletState.Dir.GetOffset(); Point newTankPoint1; Point newTankPoint2; Direction newTankDir1; Direction newTankDir2; if (bulletPathCalc.BulletState.Dir.ToAxis() == Axis.Horizontal) { newTankPoint1 = new Point( (short)tankState.Pos.X, (short)(bulletPathCalc.BulletState.Pos.Y - Constants.TANK_OUTER_EDGE_OFFSET)); newTankDir1 = Direction.UP; newTankPoint2 = new Point( (short)tankState.Pos.X, (short)(bulletPathCalc.BulletState.Pos.Y + Constants.TANK_OUTER_EDGE_OFFSET)); newTankDir2 = Direction.DOWN; } else { newTankPoint1 = new Point( (short)(bulletPathCalc.BulletState.Pos.X - Constants.TANK_OUTER_EDGE_OFFSET), (short)tankState.Pos.Y); newTankDir1 = Direction.LEFT; newTankPoint2 = new Point( (short)(bulletPathCalc.BulletState.Pos.X + Constants.TANK_OUTER_EDGE_OFFSET), (short)tankState.Pos.Y); newTankDir2 = Direction.RIGHT; } DirectionalMatrix <DistanceCalculation> tankDistanceCalcs = gameState.CalculationCache.GetDistanceMatrixFromTankByTankIndex(tank.Index); distanceCalc = tankDistanceCalcs[newTankDir1, newTankPoint1.X, newTankPoint1.Y]; if (distanceCalc.Distance <= bulletPathPoint.TicksToEscape) { Node[] shortestPathsIn1Direction = PathCalculator.GetOutgoingNodesOnShortestPath(tankDistanceCalcs, newTankDir1, newTankPoint1.X, newTankPoint1.Y); bulletThreat.LateralMoveInOneDirection = shortestPathsIn1Direction; TankAction[] tankActionsIn1Direction = PathCalculator.GetTankActionsOnOutgoingShortestPath(tankDistanceCalcs, newTankDir1, newTankPoint1.X, newTankPoint1.Y); bulletThreat.TankActionsForLateralMoveInOneDirection = tankActionsIn1Direction; } distanceCalc = tankDistanceCalcs[newTankDir2, newTankPoint2.X, newTankPoint2.Y]; if (distanceCalc.Distance <= bulletPathPoint.TicksToEscape) { Node[] shortestPathsInOtherDirection = PathCalculator.GetOutgoingNodesOnShortestPath(tankDistanceCalcs, newTankDir2, newTankPoint2.X, newTankPoint2.Y); bulletThreat.LateralMoveInOtherDirection = shortestPathsInOtherDirection; TankAction[] tankActionsInOtherDirection = PathCalculator.GetTankActionsOnOutgoingShortestPath(tankDistanceCalcs, newTankDir2, newTankPoint2.X, newTankPoint2.Y); bulletThreat.TankActionsForLateralMoveInOtherDirection = tankActionsInOtherDirection; } } } bulletPathCalc.BulletThreats = bulletThreats.ToArray(); } } }
public double EvaluateSmallestAttackDistanceToEnemyBase() { int[] minDistanceToAttackEnemyBaseByPlayerIndex = new int[Constants.PLAYERS_PER_GAME]; int[] minDistanceToDefendOwnBaseByPlayerIndex = new int[Constants.PLAYERS_PER_GAME]; bool[] isUnmarked = new bool[Constants.PLAYERS_PER_GAME]; Direction[] attackDirOnEnemyBaseByPlayerIndex = new Direction[Constants.PLAYERS_PER_GAME]; double[] score = new double[Constants.PLAYERS_PER_GAME]; foreach (Player player in Game.Current.Players) { int minDistanceToEnemyBase = Constants.UNREACHABLE_DISTANCE; foreach (Tank tank in player.Tanks) { MobileState tankState = GameState.GetMobileState(tank.Index); if (tankState.IsActive) // TODO: Check if locked in a firefight also { DistanceCalculation baseAttackCalc = GameState.CalculationCache.GetIncomingDistanceMatrixForBase(1 - player.Index)[tankState]; int distanceToEnemyBase = baseAttackCalc.Distance; if (distanceToEnemyBase < minDistanceToEnemyBase) { minDistanceToEnemyBase = distanceToEnemyBase; attackDirOnEnemyBaseByPlayerIndex[player.Index] = baseAttackCalc.AdjacentNode.Dir; } } } minDistanceToAttackEnemyBaseByPlayerIndex[player.Index] = minDistanceToEnemyBase; } foreach (Player player in Game.Current.Players) { int minDistanceToDefendOwnBase = Constants.UNREACHABLE_DISTANCE; foreach (Tank tank in player.Tanks) { MobileState tankState = GameState.GetMobileState(tank.Index); if (tankState.IsActive) // TODO: Check if locked in a firefight also { DirectionalMatrix <DistanceCalculation> distanceMatrix = GameState.CalculationCache.GetDistanceMatrixFromTankByTankIndex(tank.Index); Direction attackDir = attackDirOnEnemyBaseByPlayerIndex[1 - player.Index]; Direction defenceDir = attackDir.GetOpposite(); DistanceCalculation tankDefenceCalc = distanceMatrix[ defenceDir, player.Base.Pos + (Constants.SEGMENT_SIZE + 1) * defenceDir.GetOffset()]; int distance = tankDefenceCalc.Distance; if (distance < minDistanceToDefendOwnBase) { minDistanceToDefendOwnBase = distance; } } } minDistanceToDefendOwnBaseByPlayerIndex[player.Index] = minDistanceToDefendOwnBase; if (minDistanceToAttackEnemyBaseByPlayerIndex[1 - player.Index] < minDistanceToDefendOwnBase) { isUnmarked[1 - player.Index] = true; } } foreach (Player player in Game.Current.Players) { int minAttackDistance = minDistanceToAttackEnemyBaseByPlayerIndex[player.Index]; int playerScore = 0; if (!(Game.Current.CurrentTurn.Tick + minAttackDistance > Game.Current.FinalTickInGame)) { if (isUnmarked[Player.Index]) { playerScore = 100000 * (250 - minAttackDistance); } else { playerScore = 100 * (minDistanceToDefendOwnBaseByPlayerIndex[1 - player.Index] - minAttackDistance); } } score[player.Index] = playerScore; } return(score[Player.Index] - score[1 - Player.Index]); }
static async Task Main(string[] args) { /* * Check if arguments are provided and try to parse them as the longitude and latitude to look for. * First argument should be Longitude. (North is positive, South is negative.) * Second argument should be Latitude. (East is positive, West is negative.) */ if (args.Length > 0) { bool validLongitude = decimal.TryParse(args[0], out decimal longitude); bool validLatitude = decimal.TryParse(args[1], out decimal latitude); // Try to parse and return an error message if this fails. if (!validLongitude || !validLatitude) { Console.WriteLine("Failed to parse the command-line arguments.\n" + "Please make sure that the arguments are valid.\n" + "First argument should be Longitude. (North is positive, South is negative.)\n" + "Second argument should be Latitude. (East is positive, West is negative.)"); } Console.WriteLine($"Looking for States near the {longitude} - {latitude}"); var apiFetcher = new ApiFetcher(); var distanceCalculation = new DistanceCalculation(); StatesResponse response = await apiFetcher.GetStatesNearCoordinates(longitude, latitude); var shortestDistance = double.MaxValue; State foundState = null; // Calculate the distances for every state and return the shortest. foreach (var state in response.ConvertedStates) { var distance = distanceCalculation.CalculateGeodesicDistance(longitude, latitude, state.Longitude, state.Latitude); // Overwrite the new shortest before checking other States. if (distance < shortestDistance) { shortestDistance = distance; foundState = state; } } Console.WriteLine($"Closest State to the given coordinates ({longitude}, {latitude}):\n" + $"Geodesic distance: {shortestDistance}\n" + $"Callsign: {foundState.CallSign}\n" + $"Longitude: {foundState.Longitude}\n" + $"Latitude: {foundState.Latitude}\n" + $"Geometric Altitude: {foundState.GeoAltitude}\n" + $"Country of Origin: {foundState.OriginCountry}\n" + $"ICAO24 ID: {foundState.ICAO24}"); } // Otherwise test it out with the two given challenge inputs. else { var apiFetcher = new ApiFetcher(); var distanceCalculation = new DistanceCalculation(); /* * Eiffel Tower * Longitude: 48.8584 N * Latitude: 2.2945 E */ Console.WriteLine("Looking for States near the Eiffel Tower..."); var longitude = 48.8584M; var latitude = 2.2945M; StatesResponse response = await apiFetcher.GetStatesNearCoordinates(longitude, latitude); var shortestDistance = double.MaxValue; State foundState = null; // Calculate the distances for every state and return the shortest. foreach (var state in response.ConvertedStates) { var distance = distanceCalculation.CalculateGeodesicDistance(longitude, latitude, state.Longitude, state.Latitude); // Overwrite the new shortest before checking other States. if (distance < shortestDistance) { shortestDistance = distance; foundState = state; } } Console.WriteLine($"Closest State to the Eiffel Tower:\n" + $"Geodesic distance: {shortestDistance}\n" + $"Callsign: {foundState.CallSign}\n" + $"Longitude: {foundState.Longitude}\n" + $"Latitude: {foundState.Latitude}\n" + $"Geometric Altitude: {foundState.GeoAltitude}\n" + $"Country of Origin: {foundState.OriginCountry}\n" + $"ICAO24 ID: {foundState.ICAO24}"); /* * John F. Kennedy Airport * Longitude: 40.6413 N * Latitude: 73.7781 W */ Console.WriteLine("Looking for States near the John F. Kennedy Airport..."); longitude = 40.6413M; latitude = -73.7781M; response = await apiFetcher.GetStatesNearCoordinates(longitude, latitude); shortestDistance = double.MaxValue; foundState = null; // Calculate the distances for every state and return the shortest. foreach (var state in response.ConvertedStates) { var distance = distanceCalculation.CalculateGeodesicDistance(longitude, latitude, state.Longitude, state.Latitude); // Overwrite the new shortest before checking other States. if (distance < shortestDistance) { shortestDistance = distance; foundState = state; } } Console.WriteLine($"Closest State to the John F. Kennedy Airport:\n" + $"Geodesic distance: {shortestDistance}\n" + $"Callsign: {foundState.CallSign}\n" + $"Longitude: {foundState.Longitude}\n" + $"Latitude: {foundState.Latitude}\n" + $"Geometric Altitude: {foundState.GeoAltitude}\n" + $"Country of Origin: {foundState.OriginCountry}\n" + $"ICAO24 ID: {foundState.ICAO24}"); } }
public void ChooseActions(GameState currGameState, TankActionSet actionSet, bool[] moveChosenByTankNumber) { int[] minDistanceToAttackEnemyBaseByPlayerIndex = new int[Constants.PLAYERS_PER_GAME]; int[] minDistanceToDefendOwnBaseByPlayerIndex = new int[Constants.PLAYERS_PER_GAME]; bool[] isUnmarked = new bool[Constants.PLAYERS_PER_GAME]; Direction[] attackDirOnEnemyBaseByPlayerIndex = new Direction[Constants.PLAYERS_PER_GAME]; for (int p = 0; p < 2; p++) { attackDirOnEnemyBaseByPlayerIndex[p] = Direction.NONE; } Tank closestFriendlyTankToAttackEnemyBase = null; Tank closestFriendlyTankToDefendOwnBase = null; Tank closestEnemyTankToAttackYourBase = null; TankAction[] tankActionsForClosestFriendlyTankToAttackEnemyBase = null; TankAction[] tankActionsForClosestFriendlyTankToDefendOwnBase = null; foreach (Player player in Game.Current.Players) { int minDistanceToEnemyBase = Constants.UNREACHABLE_DISTANCE; foreach (Tank tank in player.Tanks) { MobileState tankState = currGameState.GetMobileState(tank.Index); if (!tankState.IsActive) // TODO: Check if locked in a firefight also { continue; } DirectionalMatrix <DistanceCalculation> distanceCalcMatrix = currGameState.CalculationCache.GetIncomingDistanceMatrixForBase(1 - player.Index); DistanceCalculation baseAttackCalc = distanceCalcMatrix[tankState]; int distanceToEnemyBase = baseAttackCalc.Distance; if (distanceToEnemyBase < minDistanceToEnemyBase) { minDistanceToEnemyBase = distanceToEnemyBase; attackDirOnEnemyBaseByPlayerIndex[player.Index] = baseAttackCalc.AdjacentNode.Dir; if (player == You) { closestFriendlyTankToAttackEnemyBase = tank; Base enemyBase = Game.Current.Players[1 - You.Index].Base; FiringLineMatrix firingLineMatrix = currGameState.CalculationCache.FiringLinesForPointsMatrix; tankActionsForClosestFriendlyTankToAttackEnemyBase = PathCalculator.GetTankActionsOnIncomingShortestPath( distanceCalcMatrix, tankState, enemyBase.Pos, firingLineMatrix, true); } else { closestEnemyTankToAttackYourBase = tank; } } } minDistanceToAttackEnemyBaseByPlayerIndex[player.Index] = minDistanceToEnemyBase; } foreach (Player player in Game.Current.Players) { int minDistanceToDefendOwnBase = Constants.UNREACHABLE_DISTANCE; foreach (Tank tank in player.Tanks) { MobileState tankState = currGameState.GetMobileState(tank.Index); if (tankState.IsActive) // TODO: Check if locked in a firefight also { DirectionalMatrix <DistanceCalculation> distanceMatrix = currGameState.CalculationCache.GetDistanceMatrixFromTankByTankIndex(tank.Index); Direction attackDir = attackDirOnEnemyBaseByPlayerIndex[1 - player.Index]; Direction defenceDir = attackDir.GetOpposite(); if (defenceDir == Direction.NONE) { defenceDir = Direction.RIGHT; } Point defencePos = player.Base.Pos + (Constants.SEGMENT_SIZE + 1) * defenceDir.GetOffset(); DistanceCalculation tankDefenceCalc = distanceMatrix[ defenceDir, defencePos]; int distance = tankDefenceCalc.Distance; if (distance < minDistanceToDefendOwnBase) { minDistanceToDefendOwnBase = distance; if (player == You) { closestFriendlyTankToDefendOwnBase = tank; tankActionsForClosestFriendlyTankToDefendOwnBase = PathCalculator.GetTankActionsOnOutgoingShortestPath( distanceMatrix, defenceDir, defencePos.X, defencePos.Y); } } } } minDistanceToDefendOwnBaseByPlayerIndex[player.Index] = minDistanceToDefendOwnBase; if (minDistanceToAttackEnemyBaseByPlayerIndex[1 - player.Index] < minDistanceToDefendOwnBase) { isUnmarked[1 - player.Index] = true; } } /* * int minAttackDistance = minDistanceToAttackEnemyBaseByPlayerIndex[You.Index]; * if (Game.Current.CurrentTurn.Tick + minAttackDistance > Game.Current.FinalTickInGame) * { * // Can't attack in time, rather defend... * return; * } */ // You're unmarked... Tank attackTank = closestFriendlyTankToAttackEnemyBase; if (isUnmarked[You.Index] && attackTank != null) { bool shouldAttack = true; // Enemy is marked... if (!isUnmarked[1 - You.Index]) { int minAttackDistance = minDistanceToAttackEnemyBaseByPlayerIndex[You.Index]; int minEnemyAttackDistance = minDistanceToAttackEnemyBaseByPlayerIndex[1 - You.Index]; // But if you stop marking them, by going for their base, they can get there first... if ((minAttackDistance > minEnemyAttackDistance) && (closestFriendlyTankToDefendOwnBase == attackTank)) { shouldAttack = false; // TODO: See if your other tank can do defence duty instead... } } if (shouldAttack && !moveChosenByTankNumber[attackTank.Number]) { actionSet.Actions[attackTank.Number] = tankActionsForClosestFriendlyTankToAttackEnemyBase[0]; moveChosenByTankNumber[attackTank.Number] = true; } } // If there is a slack of less than 5 ticks to defend your base, get back to defend it: Tank defenceTank = closestFriendlyTankToDefendOwnBase; if ((defenceTank != null) && (minDistanceToAttackEnemyBaseByPlayerIndex[1 - You.Index] < minDistanceToDefendOwnBaseByPlayerIndex[You.Index] + 5)) { if (!moveChosenByTankNumber[defenceTank.Number]) { actionSet.Actions[defenceTank.Number] = tankActionsForClosestFriendlyTankToAttackEnemyBase[0]; moveChosenByTankNumber[defenceTank.Number] = true; } } // Otherwise choose an enemy tank to attack: for (int t = 0; t < Constants.TANKS_PER_PLAYER; t++) { if ((closestEnemyTankToAttackYourBase != null) && (!moveChosenByTankNumber[t])) { // Rather attack an enemy tank in a firefight with own tank.. Tank killerTank = You.Tanks[t]; AttackClosestEnemyTankToOwnBase(currGameState, killerTank, closestEnemyTankToAttackYourBase, actionSet, moveChosenByTankNumber); } } }