public float GetUtilityForUnit(IUnit unit, InfluenceMaps maps)
        {
            if (!unit.CanAttack)
            {
                return(0f);
            }

            IEnumerable <IHexCell> attackCandidates = null;

            if (unit.RangedAttackStrength > 0)
            {
                var unitLocation = UnitPositionCanon.GetOwnerOfPossession(unit);

                attackCandidates = Grid.GetCellsInRadius(unitLocation, unit.AttackRange)
                                   .Where(FilterLogic.GetRangedAttackFilter(unit));
            }
            else
            {
                attackCandidates = UnitVisibilityLogic.GetCellsVisibleToUnit(unit)
                                   .Where(FilterLogic.GetMeleeAttackFilter(unit));
            }

            if (attackCandidates.Any())
            {
                return(attackCandidates.Max(UtilityLogic.GetAttackUtilityFunction(unit, maps)));
            }
            else
            {
                return(0f);
            }
        }
        private IEnumerator ResetCellVisibility()
        {
            yield return(new WaitForEndOfFrame());

            while (Grid.Chunks.Any(chunk => chunk.IsRefreshing))
            {
                yield return(new WaitForEndOfFrame());
            }

            VisibilityCanon.ClearCellVisibility();

            foreach (var unit in UnitFactory.AllUnits)
            {
                var unitOwner = UnitPossessionCanon.GetOwnerOfPossession(unit);

                foreach (var visibleCell in UnitLineOfSightLogic.GetCellsVisibleToUnit(unit))
                {
                    VisibilityCanon.IncreaseCellVisibilityToCiv(visibleCell, unitOwner);
                    ExplorationCanon.SetCellAsExploredByCiv(visibleCell, unitOwner);
                }
            }

            foreach (var city in CityFactory.AllCities)
            {
                var cityOwner = CityPossessionCanon.GetOwnerOfPossession(city);

                foreach (var visibleCell in CityLineOfSightLogic.GetCellsVisibleToCity(city))
                {
                    VisibilityCanon.IncreaseCellVisibilityToCiv(visibleCell, cityOwner);
                    ExplorationCanon.SetCellAsExploredByCiv(visibleCell, cityOwner);
                }
            }

            foreach (var cell in Grid.Cells)
            {
                HexCellShaderData.RefreshVisibility(cell);
            }

            ResetVisionCoroutine = null;

            yield break;
        }
        public bool IsMeleeAttackValid(IUnit attacker, IUnit defender)
        {
            if (!CommonAttackValidityLogic.DoesAttackMeetCommonConditions(attacker, defender))
            {
                return(false);
            }

            var attackerLocation = UnitPositionCanon.GetOwnerOfPossession(attacker);
            var defenderLocation = UnitPositionCanon.GetOwnerOfPossession(defender);

            if (defenderLocation == null)
            {
                return(false);
            }

            var shortestPath = HexPathfinder.GetShortestPathBetween(
                attackerLocation, defenderLocation, attacker.CurrentMovement,
                (current, next) => UnitPositionCanon.GetTraversalCostForUnit(attacker, current, next, true),
                Grid.Cells
                );

            if (shortestPath == null)
            {
                return(false);
            }

            if (!LineOfSightLogic.GetCellsVisibleToUnit(attacker).Contains(defenderLocation))
            {
                return(false);
            }

            if (attacker.CombatStrength <= 0)
            {
                return(false);
            }

            return(true);
        }