Ejemplo n.º 1
0
        /// <summary>
        /// Checks for a specific visibility level of a space object for an empire.
        /// If the object has that level of visibility or higher, we return true.
        /// </summary>
        /// <remarks>
        /// This allows us to short circuit the more expensive scanner code.
        /// See also parallel code at <see cref="CheckSpaceObjectVisibility(ISpaceObject, Empire)"/>
        /// </remarks>
        /// <param name="sobj">The space object to check.</param>
        /// <param name="emp">The empire to check against.</param>
        /// <param name="desiredVisibility">The requested visibility level.</param>
        /// <returns>true if the space object has at least the requested visibility level, otherwise false.</returns>
        public static bool HasVisibility(this ISpaceObject sobj, Empire emp, Visibility desiredVisibility)
        {
            bool hasMemory = false;

            if (sobj.IsMemory)
            {
                var mowner = sobj.MemoryOwner();
                if (mowner == emp || mowner == null)
                {
                    return(Visibility.Fogged >= desiredVisibility);
                }
                else
                {
                    return(Visibility.Unknown >= desiredVisibility);                    // can't see other players' memories
                }
            }
            else
            {
                var mem = sobj.FindMemory(emp);
                if (mem != null)
                {
                    hasMemory = true;
                }
            }

            if (emp == sobj.Owner)
            {
                return(Visibility.Owned >= desiredVisibility);
            }

            // You can always scan space objects you are in combat with.
            // But only their state at the time they were in combat; not for the rest of the turn!
            // TODO - what about glassed planets, they have no owner...
            if (Galaxy.Current.Battles.Any(b =>
                                           (b.Combatants.OfType <ISpaceObject>().Contains(sobj) ||
                                            b.StartCombatants.Values.OfType <ISpaceObject>().Contains(sobj) ||
                                            b.EndCombatants.Values.OfType <ISpaceObject>().Contains(sobj)) &&
                                           b.Combatants.Any(c => c.Owner == emp)))
            {
                return(Visibility.Scanned >= desiredVisibility);
            }

            // do we have anything that can see it?
            var sys = sobj.StarSystem;

            if (sys == null)
            {
                return(Visibility.Unknown >= desiredVisibility);
            }
            var seers = sys.FindSpaceObjects <ISpaceObject>(s => s.Owner == emp && !s.IsMemory);

            if (!seers.Any() || sobj.IsHiddenFrom(emp))
            {
                if (Galaxy.Current.OmniscientView && sobj.StarSystem.ExploredByEmpires.Contains(emp))
                {
                    return(Visibility.Visible >= desiredVisibility);
                }
                if (emp.AllSystemsExploredFromStart)
                {
                    return(Visibility.Fogged >= desiredVisibility);
                }
                var known = emp.Memory[sobj.ID];
                if (known != null && sobj.GetType() == known.GetType())
                {
                    return(Visibility.Fogged >= desiredVisibility);
                }
                else if (Galaxy.Current.Battles.Any(b => b.Combatants.Any(c => c.ID == sobj.ID) && b.Combatants.Any(c => c.Owner == emp)))
                {
                    return(Visibility.Fogged >= desiredVisibility);
                }
                else if (hasMemory)
                {
                    return(Visibility.Fogged >= desiredVisibility);
                }
                else
                {
                    return(Visibility.Unknown >= desiredVisibility);
                }
            }

            // short circuit scanner code: we now know that the object is either visible or scanned
            // so if we only care if it's visible or less, we can skip the scanner check.
            if (Visibility.Visible >= desiredVisibility)
            {
                return(true);
            }

            if (!sobj.HasAbility("Scanner Jammer"))
            {
                var scanners = seers.Where(s =>
                                           s.HasAbility("Long Range Scanner") && s.GetAbilityValue("Long Range Scanner").ToInt() >= s.Sector.Coordinates.EightWayDistance(sobj.FindSector().Coordinates) ||
                                           s.HasAbility("Long Range Scanner - System"));
                if (scanners.Any())
                {
                    return(Visibility.Scanned >= desiredVisibility);
                }
            }

            // we know that the requested visibility level is greater than "visible"
            // and the object has a scanner jammer
            // therefore it can't be scanned, and we already know it's not owned, we checked that up top
            // so we can just return false because the requested visibility (scanned or owned) can't be met
            return(false);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Determines the level of visibility of a space object to an empire.
        /// <br/>
        /// If you only need to verify that a space object has at least a certain level of visibility,
        /// it is less expensive to call <see cref="HasVisibility(ISpaceObject, Empire, Visibility)"/>.
        /// </summary>
        /// <param name="sobj">The space object to check.</param>
        /// <param name="emp">The empire to check against.</param>
        /// <returns>The visibility level.</returns>
        internal static Visibility CheckSpaceObjectVisibility(this ISpaceObject sobj, Empire emp)
        {
            bool hasMemory = false;

            if (sobj.IsMemory)
            {
                var mowner = sobj.MemoryOwner();
                if (mowner == emp || mowner == null)
                {
                    return(Visibility.Fogged);
                }
                else
                {
                    return(Visibility.Unknown);                    // can't see other players' memories
                }
            }
            else
            {
                var mem = sobj.FindMemory(emp);
                if (mem != null)
                {
                    hasMemory = true;
                }
            }

            if (emp == sobj.Owner)
            {
                return(Visibility.Owned);
            }

            // You can always scan space objects you are in combat with.
            // But only their state at the time they were in combat; not for the rest of the turn!
            // TODO - what about glassed planets, they have no owner...
            if (Galaxy.Current.Battles.Any(b =>
                                           (b.Combatants.OfType <ISpaceObject>().Contains(sobj) ||
                                            b.StartCombatants.Values.OfType <ISpaceObject>().Contains(sobj) ||
                                            b.EndCombatants.Values.OfType <ISpaceObject>().Contains(sobj)) &&
                                           b.Combatants.Any(c => c.Owner == emp)))
            {
                return(Visibility.Scanned);
            }

            // do we have anything that can see it?
            var sys = sobj.StarSystem;

            if (sys == null)
            {
                return(Visibility.Unknown);
            }
            var seers = sys.FindSpaceObjects <ISpaceObject>(s => s.Owner == emp && !s.IsMemory);

            if (!seers.Any() || sobj.IsHiddenFrom(emp))
            {
                if (Galaxy.Current.OmniscientView && sobj.StarSystem.ExploredByEmpires.Contains(emp))
                {
                    return(Visibility.Visible);
                }
                if (emp.AllSystemsExploredFromStart)
                {
                    return(Visibility.Fogged);
                }
                var known = emp.Memory[sobj.ID];
                if (known != null && sobj.GetType() == known.GetType())
                {
                    return(Visibility.Fogged);
                }
                else if (Galaxy.Current.Battles.Any(b => b.Combatants.Any(c => c.ID == sobj.ID) && b.Combatants.Any(c => c.Owner == emp)))
                {
                    return(Visibility.Fogged);
                }
                else if (hasMemory)
                {
                    return(Visibility.Fogged);
                }
                else
                {
                    return(Visibility.Unknown);
                }
            }
            if (!sobj.HasAbility("Scanner Jammer"))
            {
                var scanners = seers.Where(s =>
                                           s.HasAbility("Long Range Scanner") && s.GetAbilityValue("Long Range Scanner").ToInt() >= s.Sector.Coordinates.EightWayDistance(sobj.FindSector().Coordinates) ||
                                           s.HasAbility("Long Range Scanner - System"));
                if (scanners.Any())
                {
                    return(Visibility.Scanned);
                }
            }
            return(Visibility.Visible);
        }