/// <summary> /// Двигаемся к закрытому /// </summary> /// <param name="moveRate"></param> protected virtual void MoveToUnknown(MoveRate moveRate) { var tilesWithUnknown = Board.AllTiles(x => x.Type == TileType.Unknown).ToList(); if (!tilesWithUnknown.Any()) { return; } //Ищем минимальное растояние до закрытого до хода и после хода var distBefore = tilesWithUnknown.Select(t => new Tuple <int, Tile>(Distance(moveRate.Move.From.Position, t.Position), t)).ToList(); var distAfter = tilesWithUnknown.Select(t => new Tuple <int, Tile>(Distance(moveRate.Move.To.Position, t.Position), t)).ToList(); var minMovesBefore = distBefore.Select(t => t.Item1).Min(); var minMovesAfter = distAfter.Select(t => t.Item1).Min(); //TODO: Ищем кол-во закрытых в радиусе. Приоритет отдать тем, что близко к своему караблю if (minMovesAfter >= minMovesBefore) { return; } moveRate.AddRate("MoveToUnknown", Coef.MoveToUnknown * DistanceCoef(minMovesAfter)); }
protected void AboardToShipWithGold(MoveRate moveRate) { if (moveRate.Move.WithCoins && TargetIsShip(moveRate.Move)) { moveRate.AddRate("AboardToShipWithGold", Coef.AboardToShipWithGold); } }
/// <summary> /// Отнимаем золото /// </summary> /// <param name="moveRate"></param> protected void MoveToOccupiedGold(MoveRate moveRate) { var tilesWithGold = Board.AllTiles(x => x.Type != TileType.Water && x.Coins > 0).ToList(); if (!tilesWithGold.Any()) { return; } //Исключаем свободное золото tilesWithGold.RemoveAll(t => AllEnemies.Count(e => e.Position.Position == t.Position) < t.Coins); if (!tilesWithGold.Any()) { return; } //Ищем минимальное растояние до золота до хода и после хода var distBefore = tilesWithGold.Select(t => new Tuple <int, Tile>(Distance(moveRate.Move.From.Position, t.Position), t)).ToList(); var distAfter = tilesWithGold.Select(t => new Tuple <int, Tile>(Distance(moveRate.Move.To.Position, t.Position), t)).ToList(); var minMovesBefore = distBefore.Select(t => t.Item1).Min(); var minMovesAfter = distAfter.Select(t => t.Item1).Min(); if (minMovesAfter >= minMovesBefore) { return; } moveRate.AddRate("MoveToOccupiedGold", (Coef.MoveToOccupiedGold * DistanceCoef(minMovesAfter))); }
/// <summary> /// Двигаемся к золоту /// </summary> /// <param name="moveRate"></param> protected virtual void MoveToGold(MoveRate moveRate) { //TODO: исключить те, что супер далеко или те у которых уже полно пиратов других и своих var tilesWithGold = Board.AllTiles(x => x.Type != TileType.Water && x.Coins > 0).ToList(); //Исключаем, те, что уже у моих пиратов tilesWithGold.RemoveAll(t => MyPirates.Count(e => e.Position.Position == t.Position) >= t.Coins); if (!tilesWithGold.Any()) { return; } //Исключаем золото уже у чужого пирата tilesWithGold.RemoveAll(t => AllEnemies.Count(e => e.Position.Position == t.Position) >= t.Coins); if (!tilesWithGold.Any()) { return; } //Ищем минимальное растояние до золота до хода и после хода var distBefore = tilesWithGold.Select(t => new Tuple <int, Tile>(Distance(moveRate.Move.From.Position, t.Position), t)).ToList(); var distAfter = tilesWithGold.Select(t => new Tuple <int, Tile>(Distance(moveRate.Move.To.Position, t.Position), t)).ToList(); var minMovesBefore = distBefore.Select(t => t.Item1).Min(); var minMovesAfter = distAfter.Select(t => t.Item1).Min(); if (minMovesAfter >= minMovesBefore) { return; } moveRate.AddRate("MoveToGold", (Coef.MoveToGold * DistanceCoef(minMovesAfter))); }
/// <summary> /// Атака /// </summary> /// <param name="moveRate"></param> protected virtual void Atack(MoveRate moveRate) { var enemiesOnPosition = EnemiesOnPosition(moveRate.Move.To.Position); var coinsTo = GoldOnPosition(moveRate.Move.To.Position); var coinsFrom = GoldOnPosition(moveRate.Move.From.Position); if (enemiesOnPosition == 0) // || (coinsTo == 0 && coinsFrom == 0)) { return; } //Если стоим с золотом прямо у корабля - не атакуем если у врага нет золота //if (coinsFrom > 0 && coinsTo == 0 && Distance(MyShip.Position, moveRate.Move.Pirate.Position) == 1) // return; //Если кто-то другой без золота может атаковать этого же чудика, а я с золотом - не бьем var myEmptyFriendAtackers = MyPirates.Count(p => p.Position.Position != moveRate.Move.From.Position && GoldOnPosition(p.Position.Position) == 0 && Distance(p.Position.Position, moveRate.Move.To.Position) <= 1); if (myEmptyFriendAtackers > 0 && coinsFrom > 0) { return; } //Не атаковать если враг в 2-х ходах от его корабля var occupationTeamId = Board.Map[moveRate.Move.To.X, moveRate.Move.To.Y].OccupationTeamId; if (occupationTeamId.HasValue && Distance(Board.Teams[occupationTeamId.Value].Ship.Position, moveRate.Move.To.Position) < 3) { return; } moveRate.AddRate("Atack", (Coef.Atack + ((enemiesOnPosition - 1) * Coef.AtackManyEnemies)) * (1 + coinsFrom * 0.1) * (1 + coinsTo * 0.1)); }
/// <summary> /// перемещаем золото ближе к кораблю /// </summary> /// <param name="moveRate"></param> protected override void MoveToShipWithGold(MoveRate moveRate) { if (!moveRate.Move.WithCoins) { return; } var currentDistance = Distance(moveRate.Move.From.Position, MyShip.Position); var newDistance = Distance(moveRate.Move.To.Position, MyShip.Position); if (currentDistance <= newDistance) { return; } moveRate.AddRate("MoveToShipWithGold", Coef.MoveToShipWithGold * DefenceGoldCoef(moveRate)); }
/// <summary> /// Двигаемся к золоту /// </summary> /// <param name="moveRate"></param> protected override void MoveToGold(MoveRate moveRate) { //Если я уже с золотом - нечего бегать за другим if (GoldOnPosition(moveRate.Move.From.Position) > 0) { return; } //Ищем все золото к кому приближаемся var tilesWithGold = Board.AllTiles(x => x.Type != TileType.Water && x.Coins > 0 && Distance(moveRate.Move.From.Position, x.Position) > Distance(moveRate.Move.To.Position, x.Position)).Select(t => new PosRate(t.Position)).ToList(); if (!tilesWithGold.Any()) { return; } //Для каждого золота считаем tilesWithGold.ForEach(t => t.Rate = t.Rate * MoveToGoldNewPosDistanceCoef(moveRate.Move.To.Position, t.Pos)); //расстояние до своего корабля tilesWithGold.ForEach(t => t.Rate = t.Rate * MoveToGoldMyShipDistanceCoef(MyShip.Position, t.Pos)); //расстояние до ближайшего чужего корабля tilesWithGold.ForEach(t => t.Rate = t.Rate * MoveToGoldEnemyShipDistanceCoef(t.Pos)); //даем приемущество шариться по углам (треугольнико от углов) //tilesWithGold.ForEach(t => t.Rate = t.Rate * MoveToGoldCornersDistanceCoef(t.Pos)); //Если двигаем корабль к золоту - чуток получаем приемущество //Если двигаем корабль - чуток получаем приемущество if (IsShipMove(moveRate.Move)) { tilesWithGold.ForEach(t => t.Rate = t.Rate * 1.05); } //TODO: кол-во чужих и своих пиратов которым ближе чем мне. Исключам то золото которое не отнять или оно уже у нас tilesWithGold.ForEach(t => t.Rate = t.Rate * MoveToGoldOccupaneCoef(moveRate.Move.From.Position, t.Pos)); //берем наилучший вариант var res = tilesWithGold.Max(t => t.Rate); moveRate.AddRate("MoveToGold", Coef.MoveToGold * res); }
/// <summary> /// Уход от удара /// </summary> /// <param name="moveRate"></param> protected override void MoveFromAtack(MoveRate moveRate) { //Не боимся слазить с корабля стоя на нем if (moveRate.Move.From.Position == MyShip.Position) { return; } if (AllEnemies.Any(e => Distance(e.Position.Position, moveRate.Move.From.Position) == 1) && AllEnemies.All(e => Distance(e.Position.Position, moveRate.Move.To.Position) != 1)) { moveRate.AddRate("MoveFromAtack", Coef.MoveFromAtack * (moveRate.Move.WithCoins ? 1.3 : 1) * (GoldOnPosition(moveRate.Move.To.Position) > 0 ? 1.2 : 1) * (Distance(moveRate.Move.From.Position, MyShip.Position) > Distance(moveRate.Move.To.Position, MyShip.Position) ? 1.1 : 1) * (Distance(moveRate.Move.From.Position, MyShip.Position) < Distance(moveRate.Move.To.Position, MyShip.Position) ? 0.9 : 1) ); moveRate.AddApplyToAllRate("MoveFromAtackToAll", Coef.MoveFromAtackToAll); } }
/// <summary> /// перемещаем золото ближе к кораблю /// </summary> /// <param name="moveRate"></param> protected override void MoveShipToMyPirateWithGold(MoveRate moveRate) { if (!IsShipMove(moveRate.Move)) { return; } var myPiratesWithGold = MyPirates.Where(p => GoldOnPosition(p.Position.Position) > 0 && Distance(moveRate.Move.From.Position, p.Position.Position) > Distance(moveRate.Move.To.Position, p.Position.Position)).ToList(); if (!myPiratesWithGold.Any()) { return; } var coins = myPiratesWithGold.Sum(p => GoldOnPosition(p.Position.Position)); moveRate.AddRate("MoveShipToPirateWithGold", Coef.MoveToShipWithGold * (myPiratesWithGold.Count > 1 ? (1 + myPiratesWithGold.Count * 0.1) : 1) * (coins > 1 ? (1 + coins * 0.1) : 1) ); }
/// <summary> /// Двигаемся к закрытому /// </summary> /// <param name="moveRate"></param> protected override void MoveToUnknown(MoveRate moveRate) { //Собираем все закрытые к которым приближаемся var tilesWithUnknown = Board.AllTiles(x => x.Type == TileType.Unknown && Distance(moveRate.Move.From.Position, x.Position) > Distance(moveRate.Move.To.Position, x.Position)).Select(t => new PosRate(t.Position)).ToList(); if (!tilesWithUnknown.Any()) { return; } //Cчитаем коэф закрытых к оставшемуся золоту - шансы на золото var hiddenGold = 37 - Board.AllTiles(t => t.Coins > 0).Sum(t => t.Coins) - Board.Teams.Sum(t => t.Ship.Coins); if (hiddenGold == 0) { return; } var unknownCount = Board.AllTiles(t => t.Type == TileType.Unknown).Count(); var goldPossibility = (double)unknownCount / hiddenGold; if (goldPossibility > 30) { goldPossibility = 0.3; } else if (goldPossibility > 8) { goldPossibility = 0.6; } else if (goldPossibility > 2) { goldPossibility = 0.8; } else { goldPossibility = 1; } //Для каждого: //расстояние до пирата tilesWithUnknown.ForEach(t => t.Rate = t.Rate * MoveToUnknownPirateDistanceCoef(moveRate.Move.To.Position, t.Pos)); //расстояние до своего корабля tilesWithUnknown.ForEach(t => t.Rate = t.Rate * MoveToUnknownMyShipDistanceCoef(MyShip.Position, t.Pos)); //расстояние до ближайшего чужего корабля tilesWithUnknown.ForEach(t => t.Rate = t.Rate * MoveToUnknownEnemyShipDistanceCoef(t.Pos)); //даем приемущество шариться по углам (треугольнико от углов) tilesWithUnknown.ForEach(t => t.Rate = t.Rate * MoveToUnknownCornersDistanceCoef(t.Pos)); //Если двигаем корабль - чуток получаем приемущество if (IsShipMove(moveRate.Move)) { tilesWithUnknown.ForEach(t => t.Rate = t.Rate * 1.05); } //TODO: коэф присутствия врагов //берем наилучший вариант * goldPossibility var res = tilesWithUnknown.Max(t => t.Rate) * goldPossibility; moveRate.AddRate("MoveToUnknown", Coef.MoveToUnknown * res); }