Esempio n. 1
0
        public override ActivityStep ResolveStep(GameEntity entity)
        {
            float chanceToStop = entity.isAggressive ? 0.2f : 0.07f;

            if (!_targetToKeepDistanceTo.hasPosition || _rng.Check(chanceToStop))
            {
                return(Succeed(entity));
            }
            int turnsPassed = 1;         // osnowatodo Contexts.sharedInstance.game.turMinelo.Tur;

            bool  targetPositionHasChanged = _targetToKeepDistanceTo.position.Position != _lastTargetPosition;
            float chanceToKeepPosition     = 0.8f;
            bool  shouldKeepPosition       = !targetPositionHasChanged && _rng.Check(chanceToKeepPosition);

            if (shouldKeepPosition)
            {
                return(KeepPosition(entity));
            }

            bool recalculateCooldownHasPassed = turnsPassed >= _turnsPassedToRecalculate;
            bool shouldRecalculate            = (_navigationDataToGoodPosition == null) ||
                                                (recalculateCooldownHasPassed && (targetPositionHasChanged || _rng.Check(0.2f)));

            if (shouldRecalculate)
            {
                _turnsPassedToRecalculate = turnsPassed + 3;
                _lastTargetPosition       = _targetToKeepDistanceTo.position.Position;

                IFloodArea targetFlood = _calculatedAreaAccessor.FetchWalkableFlood(_lastTargetPosition, _preferredDistance);
                _navigationDataToGoodPosition = FindNavigationDataToGoodPosition(entity, targetFlood, _preferredDistance);
                if (_navigationDataToGoodPosition == null)
                {
                    return(Fail(entity));
                }
            }

            Position         nextStep;
            NavigationResult navigationResult = _navigator.ResolveNextStep(_navigationDataToGoodPosition, entity.position.Position, out nextStep);

            if (navigationResult == NavigationResult.Finished)
            {
                return(new ActivityStep
                {
                    GameAction = _actionFactory.CreatePassAction(entity),
                    State = ActivityState.InProgress
                });
            }
            if (nextStep == PositionUtilities.Min)
            {
                return(Fail(entity));
            }

            IGameAction moveGameAction = CreateMoveAction(entity, nextStep);

            return(new ActivityStep
            {
                State = ActivityState.InProgress,
                GameAction = moveGameAction
            });
        }
Esempio n. 2
0
 private IEnumerable <Position> GetPositionsOnFloodWithGivenDistance(IFloodArea targetFlood, int preferredDistance)
 {
     foreach (Position position in targetFlood.Bounds.AllPositions())
     {
         int value = targetFlood.GetValueAtPosition(position);
         if (value == preferredDistance)
         {
             yield return(position);
         }
     }
 }
Esempio n. 3
0
    public void Show(IFloodArea floodArea)
    {
        if (!gameObject.activeInHierarchy)
        {
            return;
        }
        List <Text> numbersInPoolBeforeStart = _numbersInPool.ToList();

        foreach (Position position in floodArea.Bounds.AllPositions())
        {
            Position numberPosition           = position;
            Vector3  worldPositionOfNewNumber = _unityGridInfoProvider.GetCellCenterWorld(numberPosition);
            Text     textChild = PlaceChild(numbersInPoolBeforeStart, worldPositionOfNewNumber);
            int      value     = floodArea.GetValueAtPosition(position);
            textChild.text = value == int.MaxValue ? "-" : value.ToString();
        }
    }
Esempio n. 4
0
        public override ActivityStep ResolveStep(GameEntity entity)
        {
            if (_followStepsActivity != null)
            {
                ActivityStep goToResult = _followStepsActivity.CheckAndResolveStep(entity);
                if (goToResult.State != ActivityState.FinishedFailure)
                {
                    return(goToResult);
                }
            }

            int escapeFloodRange = entity.vision.VisionRange;
            int allowedDelay     = 3;

            IFloodArea enemyFlood = _calculatedAreaAccessor.FetchWalkableFlood(_floodSource, escapeFloodRange);

            Position startingPosition       = entity.position.Position;
            bool     standingOutsideOfFlood = enemyFlood.GetValueAtPosition(startingPosition) == int.MaxValue;

            if (standingOutsideOfFlood)
            {
                return(new ActivityStep
                {
                    GameAction = _actionFactory.CreatePassAction(entity),
                    State = ActivityState.InProgress
                });
            }
            Position         targetPosition;
            var              predecessors = FindBestPositionInFloodToFleeTo(entity, startingPosition, allowedDelay, enemyFlood, out targetPosition);
            Stack <Position> steps        = new Stack <Position>();

            CreateStepsStack(targetPosition, steps, predecessors);
            if (!steps.Any())
            {
                Debug.LogError($"can't find best flood position starting at {startingPosition}.");
            }

            _followStepsActivity = new FollowStepsActivity(_actionFactory, steps, "Run away — steps");

            return(_followStepsActivity.CheckAndResolveStep(entity));
        }
Esempio n. 5
0
        private NavigationData FindNavigationDataToGoodPosition(GameEntity entity, IFloodArea targetFlood, int preferredDistance)
        {
            IList <Position> availablePositions = GetPositionsOnFloodWithGivenDistance(targetFlood, preferredDistance).ToList();

            int attemptsLimit = 5;
            int attempts      = 0;

            while (true)
            {
                ++attempts;
                if (attempts > attemptsLimit)
                {
                    Debug.Log("Failed after " + attempts + " attempts.");
                    return(null);
                }
                Position[] candidates = { _rng.Choice(availablePositions), _rng.Choice(availablePositions), _rng.Choice(availablePositions) };
                var        navigationsToCandidates = new List <NavigationData>(candidates.Length);

                foreach (Position candidatePosition in candidates)
                {
                    NavigationData navigation = _navigator.GetNavigationData(entity.position.Position, candidatePosition);
                    navigationsToCandidates.Add(navigation);
                }

                List <NavigationData> validCandidates = navigationsToCandidates.Where(c => c != null).ToList();
                if (!validCandidates.Any())
                {
                    return(null);
                }

                validCandidates.Sort((first, second) =>
                                     PositionUtilities.WalkDistance(entity.position.Position, first.Destination)
                                     .CompareTo(PositionUtilities.WalkDistance(entity.position.Position, second.Destination)));
                NavigationData closestValidCandidate = validCandidates.First();
                return(closestValidCandidate);
            }
        }
Esempio n. 6
0
 public void ShowFloodNumbers(IFloodArea floodArea)
 {
     _numbersAreaPresenter.Show(floodArea);
 }
Esempio n. 7
0
        private Dictionary <Position, Position> FindBestPositionInFloodToFleeTo(GameEntity entity, Position startingPosition,
                                                                                int allowedDelay, IFloodArea enemyFlood, out Position targetPosition)
        {
            var predecessors = new Dictionary <Position, Position>();
            var delays       = new Dictionary <Position, int> {
                [startingPosition] = 0
            };
            var openPositions = new Queue <Position>();

            Position[] bestPositionsForDelays = new Position[allowedDelay + 1];
            int[]      bestScoresForDelays    = new int[allowedDelay + 1];
            for (int i = 0; i < allowedDelay + 1; i++)
            {
                bestScoresForDelays[i] = Int32.MinValue / 2;
            }

            openPositions.Enqueue(entity.position.Position);

            do
            {
                Position currentPosition      = openPositions.Dequeue();
                int      currentDelay         = delays[currentPosition];
                int      currentPositionScore = enemyFlood.GetValueAtPosition(currentPosition);

                ProcessNeighbours(currentPosition, delays, enemyFlood, currentPositionScore, currentDelay, allowedDelay, predecessors,
                                  openPositions, bestScoresForDelays, bestPositionsForDelays);
            } while (openPositions.Any());

            int bestDelayAdjustedScore = -int.MaxValue;
            int optimalDelayIndex      = FindBestDelayCategoryOfPositions(allowedDelay, bestScoresForDelays, bestDelayAdjustedScore);

            targetPosition = bestPositionsForDelays[optimalDelayIndex];
            return(predecessors);
        }
Esempio n. 8
0
        private static void ProcessNeighbours(Position currentNode, Dictionary <Position, int> delays, IFloodArea enemyFlood,
                                              int currentNodeScore, int currentDelay, int allowedDelay, Dictionary <Position, Position> predecessors, Queue <Position> openPositions,
                                              int[] bestScoresForDelays, Position[] bestPositionsForDelays)
        {
            foreach (Position neighbour in PositionUtilities.Neighbours8(currentNode)
                     .Where(n => !delays.ContainsKey(n)))
            {
                int neighbourScore = enemyFlood.GetValueAtPosition(neighbour);
                if (neighbourScore == int.MaxValue)
                {
                    continue;
                }
                int neighbourDelay = currentNodeScore - neighbourScore + 1 + currentDelay;
                if (neighbourDelay > allowedDelay)
                {
                    continue;
                }

                delays[neighbour]       = neighbourDelay;
                predecessors[neighbour] = currentNode;
                openPositions.Enqueue(neighbour);
                if (neighbourScore > bestScoresForDelays[neighbourDelay])
                {
                    bestScoresForDelays[neighbourDelay]    = neighbourScore;
                    bestPositionsForDelays[neighbourDelay] = neighbour;
                }
            }
        }