protected override void StepOnSameTile(MoveRate moveRate) { if (!TargetIsShip(moveRate.Move) && MyPirates.Any(p => p.Position == moveRate.Move.To)) { moveRate.AddApplyToAllRate("StepOnSameTile", 0.9); } }
/// <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)); }
/// <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))); }
protected void AboardToShipWithGold(MoveRate moveRate) { if (moveRate.Move.WithCoins && TargetIsShip(moveRate.Move)) { moveRate.AddRate("AboardToShipWithGold", Coef.AboardToShipWithGold); } }
/// <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> /// <returns></returns> protected override double DefenceGoldCoef(MoveRate moveRate) { var pos = moveRate.Move.From.Position; var goldOnPos = GoldOnPosition(pos); //Если золота > 1 и я от корабля не дальше чем 5 ходов if (goldOnPos < 2 || Distance(MyShip.Position, pos) > 5) { return(1); } //Нет других пиратов //TODO: Проверка по Id пирата который ходит var myOtherPirtates = MyPirates.Where(p => p.Position.Position != moveRate.Move.From.Position).ToList(); if (!myOtherPirtates.Any()) { return(1); } //Возле корабля не защищаем if (Distance(MyShip.Position, pos) == 1) { return(1); } //и до ближайшего моего пирата не менее 4-х ходов if (myOtherPirtates.Min(p => Distance(p.Position.Position, pos)) > 5) { return(1); } //Если уже людей сколько и золота - мотаем на корабль if (MyPirates.Count(p => Distance(p.Position.Position, pos) <= 1) >= Math.Min(2, goldOnPos)) { return(1); } //Если до ближайшего корабля противника меньше 3-х ходов if (AllEnemyShips.Min(s => Distance(s.Position, pos)) < 4) { return(1); } //Если я под атакой 2-х врагов - бежим if (Board.Teams.Count(t => t.Id != TeamId && t.Pirates.Any(p => Distance(p.Position.Position, pos) == 1)) > 1) { return(1); } return(0.2); }
/// <summary> /// Удаление от корабля /// </summary> /// <param name="moveRate"></param> protected void MoveFromShip(MoveRate moveRate) { //Не считаем удаленность если двигаемся с корабля или с кораблем if (moveRate.Move.From.Position == MyShip.Position) { if (Distance(moveRate.Move.To.Position, MyShip.Position) < Distance(moveRate.Move.From.Position, MyShip.Position)) { return; } } moveRate.AddApplyToAllRate("MoveFromShip", DistanceCoefRevert(Distance(MyShip.Position, moveRate.Move.To.Position))); }
/// <summary> /// Ход под удар /// </summary> /// <param name="moveRate"></param> protected virtual void MoveUnderAtack(MoveRate moveRate) { //Не боимся слазить с корабля стоя на нем if (moveRate.Move.From.Position == MyShip.Position) { return; } if (AllEnemies.Any(e => Distance(e.Position.Position, moveRate.Move.To.Position) == 1)) { moveRate.AddApplyToAllRate("MoveUnderAtack", Coef.MoveUnderAtack); } }
/// <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 MoveUnderAtack(MoveRate moveRate) { //Не боимся слазить с корабля стоя на нем if (moveRate.Move.From.Position == MyShip.Position) { return; } var myAtakers = AllEnemies.Count(p => Distance(p.Position.Position, moveRate.Move.To.Position) == 1); if (myAtakers == 0) { return; } var myDefence = MyPirates.Count(p => Distance(p.Position.Position, moveRate.Move.To.Position) == 1) - 1; if (myDefence < myAtakers) { moveRate.AddApplyToAllRate("MoveUnderAtack", Coef.MoveUnderAtack); } }
public virtual MoveRate Rate(Move move) { if (RateActions == null) { CreateRateActionsList(); } var rate = new MoveRate { Move = move }; if (RateActions == null) { return(rate); } foreach (var rateAction in RateActions) { rateAction.Invoke(rate); } return(rate); }
/// <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); }