protected override void OnMakeMove(GameState gameState, LogicMoveResult moves) { foreach (var unitState in gameState.UnitStates) { if (unitState.IsDead) { lock (_targetPointsLock) { _unitIdToTargetPointMap.Remove(unitState.UniqueId); } continue; } Point2D targetPoint; lock (_targetPointsLock) { targetPoint = _unitIdToTargetPointMap.GetValueOrDefault(unitState.UniqueId, unitState.Position); } var needNewTargetPoint = unitState.PreviousMoveState.IsRejected() || unitState.Position.GetDistance(targetPoint) .IsZero(GameConstants.ChickenUnit.DefaultRectilinearSpeed); if (needNewTargetPoint) { targetPoint = ChooseTargetPoint(gameState, unitState); } var move = GameHelper.GetBestMoveDirection(unitState.Position, unitState.BeakAngle, targetPoint); var turn = GameHelper.GetBestBeakTurnNormalized(unitState.Position, unitState.BeakAngle, targetPoint); var fireMode = unitState.CanShoot && RandomGenerator.Next(10) == 0 ? FireMode.Regular : FireMode.None; var moveInfo = new MoveInfo(move, turn, fireMode); moves.Set(unitState, moveInfo); } }
protected override void OnMakeMove(GameState gameState, LogicMoveResult moves) { var allShots = gameState .UnitStates .SelectMany(item => item.View.Shots) .Distinct(KeyedEqualityComparer.For <ShotViewData> .Create(state => state.UniqueId)) .ToArray(); var enemyUnits = gameState .UnitStates .SelectMany(item => item.View.Chickens.Where(visibleUnit => visibleUnit.Team != this.Team)) .Distinct(KeyedEqualityComparer.For <ChickenViewData> .Create(data => data.UniqueId)) .ToArray(); foreach (var unitState in gameState.UnitStates) { if (unitState.IsDead) { continue; } MoveDirection safestMoveDirection = null; if (_features.IsAnySet(Features.TurningAway)) { safestMoveDirection = FindSafestMove(allShots, unitState); } if (unitState.PreviousMoveState.IsRejected()) { var blockedDirections = _blockedDirectionMap.GetValueOrDefault(unitState.UniqueId); if (blockedDirections == null) { blockedDirections = new HashSet <MoveDirection>(); _blockedDirectionMap[unitState.UniqueId] = blockedDirections; } blockedDirections.Add(unitState.PreviousMove.MoveDirection); var moveDirection = GameHelper .BasicActiveMoveDirections .FirstOrDefault(item => !blockedDirections.Contains(item)); var unblockingMove = moveDirection == null || moveDirection.IsNone ? new MoveInfo(MoveDirection.None, BeakTurn.FullyClockwise, FireMode.None) : new MoveInfo(moveDirection, BeakTurn.None, FireMode.None); moves.Set(unitState, unblockingMove); continue; } _blockedDirectionMap.Remove(unitState.UniqueId); var possibleActions = new List <PossibleActionInfo>(unitState.View.Chickens.Count); //// ReSharper disable once LoopCanBeConvertedToQuery foreach (var enemyUnit in enemyUnits) { var shotTargetPosition = GetShotTargetPosition(unitState, enemyUnit); var moveDirection = safestMoveDirection ?? GameHelper.GetBestMoveDirection( unitState.Position, unitState.BeakAngle, shotTargetPosition); var turn = GameHelper.GetBestBeakTurn( unitState.Position, unitState.BeakAngle, shotTargetPosition); possibleActions.Add( new PossibleActionInfo { EnemyUnit = enemyUnit, MoveDirection = moveDirection, BeakTurn = turn, DistanceSquared = unitState.Position.GetDistanceSquared(enemyUnit.Position) }); } var bestAction = possibleActions .OrderBy(item => item.DistanceSquared) .ThenBy(item => item.BeakTurn) .FirstOrDefault(); if (bestAction == null) { var minBorderDistance = gameState.Data.BoardBorder.Edges.Min( item => GameHelper.GetDistanceToLine(unitState.Position, item.Start, item.End)); if (minBorderDistance <= _tooCloseBorderDistance) { var boardCenter = new Point2D(gameState.Data.RealSize) / 2f; var direction = GameHelper.GetBestMoveDirection( unitState.Position, unitState.BeakAngle, boardCenter); moves.Set(unitState, new MoveInfo(direction, BeakTurn.None, FireMode.None)); continue; } if (safestMoveDirection != null) { moves.Set(unitState, new MoveInfo(safestMoveDirection, BeakTurn.None, FireMode.None)); } else { var seekingMove = new MoveInfo( unitState.PreviousMoveState.IsRejected() || minBorderDistance <= _rotateOnlyBorderDistance ? MoveDirection.None : MoveDirection.MoveForward, BeakTurn.FullyClockwise, FireMode.None); moves.Set(unitState, seekingMove); } continue; } var beakTurn = bestAction.BeakTurn.NormalizeBeakTurn(); var doFire = bestAction.BeakTurn.IsInRange(BeakTurn.ValueRange) || bestAction.DistanceSquared <= _forceFireDistanceSquared; var move = new MoveInfo( bestAction.MoveDirection, beakTurn, doFire ? FireMode.Regular : FireMode.None); moves.Set(unitState, move); } }