context: #region Copyright & License Information
  /*
   * Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
   * This file is part of OpenRA, which is free software. It is made
   * available to you under the terms of the GNU General Public License
   * as published by the Free Software Foundation, either version 3 of
   * the License, or (at your option) any later version. For more
   * information, see COPYING.
   */
  #endregion
  
  using System;
  using System.Collections.Generic;
  using System.Diagnostics.CodeAnalysis;
  using OpenRA.FileSystem;
  using OpenRA.Graphics;
  using OpenRA.Network;
  using OpenRA.Primitives;
  
  namespace OpenRA.Traits
  {
  	public sealed class RequireExplicitImplementationAttribute : Attribute { }
  
  	[Flags]
  	public enum DamageState
  	{
  		Undamaged = 1,
  		Light = 2,
  		Medium = 4,
  		Heavy = 8,
  		Critical = 16,
  		Dead = 32
  	}
  
  	/// <summary>
  	/// Type tag for DamageTypes <see cref="Primitives.BitSet{T}"/>.
  	/// </summary>
  	public sealed class DamageType { DamageType() { } }
  
  	public interface IHealthInfo : ITraitInfo
  	{
  		int MaxHP { get; }
  	}
  
  	public interface IHealth
  	{
  		DamageState DamageState { get; }
  		int HP { get; }
  		int MaxHP { get; }
  		int DisplayHP { get; }
  		bool IsDead { get; }
  
  		void InflictDamage(Actor self, Actor attacker, Damage damage, bool ignoreModifiers);
  		void Kill(Actor self, Actor attacker, BitSet<DamageType> damageTypes);
  	}
  
  	// depends on the order of pips in WorldRenderer.cs!
  	public enum PipType { Transparent, Green, Yellow, Red, Gray, Blue, Ammo, AmmoEmpty }
  
  	[Flags]
  	public enum Stance
  	{
  		None = 0,
  		Enemy = 1,
  		Neutral = 2,
  		Ally = 4,
  	}
  
  	public static class StanceExts
  	{
  		public static bool HasStance(this Stance s, Stance stance)
  		{
  			// PERF: Enum.HasFlag is slower and requires allocations.
  			return (s & stance) == stance;
  		}
  	}
  
  	public class AttackInfo
  	{
  		public Damage Damage;
  		public Actor Attacker;
  		public DamageState DamageState;
  		public DamageState PreviousDamageState;
  	}
  
  	public class Damage
  	{
  		public readonly int Value;
  		public readonly BitSet<DamageType> DamageTypes;
  
  		public Damage(int damage, BitSet<DamageType> damageTypes)
  		{
  			Value = damage;
  			DamageTypes = damageTypes;
  		}
  
  		public Damage(int damage)
  		{
  			Value = damage;
  			DamageTypes = default(BitSet<DamageType>);
  		}
  	}
  
  	[RequireExplicitImplementation]
  	public interface ITick { void Tick(Actor self); }
  	[RequireExplicitImplementation]
  	public interface ITickRender { void TickRender(WorldRenderer wr, Actor self); }
  	public interface IRender
  	{
  		IEnumerable<IRenderable> Render(Actor self, WorldRenderer wr);
  		IEnumerable<Rectangle> ScreenBounds(Actor self, WorldRenderer wr);
  	}
  
  	// TODO: Replace Rectangle with an int2[] polygon
  	public interface IMouseBounds { Rectangle MouseoverBounds(Actor self, WorldRenderer wr); }
  	public interface IMouseBoundsInfo : ITraitInfoInterface { }
  	public interface IAutoMouseBounds { Rectangle AutoMouseoverBounds(Actor self, WorldRenderer wr); }
  
  	// HACK: This provides a shim for legacy code until it can be rewritten
  	public interface IDecorationBounds { Rectangle DecorationBounds(Actor self, WorldRenderer wr); }
  	public interface IDecorationBoundsInfo : ITraitInfoInterface { }
  	public static class DecorationBoundsExtensions
  	{
  		public static Rectangle FirstNonEmptyBounds(this IEnumerable<IDecorationBounds> decorationBounds, Actor self, WorldRenderer wr)
  		{
  			// PERF: Avoid LINQ.
  			foreach (var decoration in decorationBounds)
  			{
  				var bounds = decoration.DecorationBounds(self, wr);
  				if (!bounds.IsEmpty)
  					return bounds;
  			}
  
  			return Rectangle.Empty;
  		}
  
  		public static Rectangle FirstNonEmptyBounds(this IDecorationBounds[] decorationBounds, Actor self, WorldRenderer wr)
  		{
  			// PERF: Avoid LINQ.
  			foreach (var decoration in decorationBounds)
  			{
  				var bounds = decoration.DecorationBounds(self, wr);
  				if (!bounds.IsEmpty)
  					return bounds;
  			}
  
  			return Rectangle.Empty;
  		}
  	}
  
  	public interface IIssueOrder
  	{
  		IEnumerable<IOrderTargeter> Orders { get; }
  		Order IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued);
  	}
  
  	[Flags] public enum TargetModifiers { None = 0, ForceAttack = 1, ForceQueue = 2, ForceMove = 4 }
  
  	public static class TargetModifiersExts
  	{
  		public static bool HasModifier(this TargetModifiers self, TargetModifiers m)
  		{
  			// PERF: Enum.HasFlag is slower and requires allocations.
  			return (self & m) == m;
  		}
  	}
  
  	public interface IOrderTargeter
  	{
  		string OrderID { get; }
  		int OrderPriority { get; }
  		bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor);
  		bool IsQueued { get; }
  		bool TargetOverridesSelection(TargetModifiers modifiers);
  	}
  
  	public interface IResolveOrder { void ResolveOrder(Actor self, Order order); }
  	public interface IValidateOrder { bool OrderValidation(OrderManager orderManager, World world, int clientId, Order order); }
  	public interface IOrderVoice { string VoicePhraseForOrder(Actor self, Order order); }
  
  	[RequireExplicitImplementation]
  	public interface INotifyCreated { void Created(Actor self); }
  
  	[RequireExplicitImplementation]
  	public interface INotifyAddedToWorld { void AddedToWorld(Actor self); }
  	[RequireExplicitImplementation]
  	public interface INotifyRemovedFromWorld { void RemovedFromWorld(Actor self); }
  
  	[RequireExplicitImplementation]
  	public interface INotifyActorDisposing { void Disposing(Actor self); }
  	public interface INotifyOwnerChanged { void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner); }
  	public interface INotifyEffectiveOwnerChanged { void OnEffectiveOwnerChanged(Actor self, Player oldEffectiveOwner, Player newEffectiveOwner); }
  	public interface INotifyOwnerLost { void OnOwnerLost(Actor self); }
  
  	[RequireExplicitImplementation]
  	public interface IVoiced
  	{
  		string VoiceSet { get; }
  		bool PlayVoice(Actor self, string phrase, string variant);
  		bool PlayVoiceLocal(Actor self, string phrase, string variant, float volume);
  		bool HasVoice(Actor self, string voice);
  	}
  
  	[RequireExplicitImplementation]
  	public interface IStoreResources { int Capacity { get; } }
  
  	public interface IEffectiveOwner
  	{
  		bool Disguised { get; }
  		Player Owner { get; }
  	}
  
  	public interface ITooltip
  	{
  		ITooltipInfo TooltipInfo { get; }
  		Player Owner { get; }
  	}
  
  	public interface ITooltipInfo : ITraitInfoInterface
  	{
  		string TooltipForPlayerStance(Stance stance);
  		bool IsOwnerRowVisible { get; }
  	}
  
  	public interface IProvideTooltipInfo
  	{
  		bool IsTooltipVisible(Player forPlayer);
  		string TooltipText { get; }
  	}
  
  	public interface IDisabledTrait { bool IsTraitDisabled { get; } }
  
  	public interface IDefaultVisibilityInfo : ITraitInfoInterface { }
  	public interface IDefaultVisibility { bool IsVisible(Actor self, Player byPlayer); }
  	public interface IVisibilityModifier { bool IsVisible(Actor self, Player byPlayer); }
  
  	public interface IActorMap
  	{
  		IEnumerable<Actor> GetActorsAt(CPos a);
  		IEnumerable<Actor> GetActorsAt(CPos a, SubCell sub);
  		bool HasFreeSubCell(CPos cell, bool checkTransient = true);
  		SubCell FreeSubCell(CPos cell, SubCell preferredSubCell = SubCell.Any, bool checkTransient = true);
  		SubCell FreeSubCell(CPos cell, SubCell preferredSubCell, Func<Actor, bool> checkIfBlocker);
  		bool AnyActorsAt(CPos a);
  		bool AnyActorsAt(CPos a, SubCell sub, bool checkTransient = true);
  		bool AnyActorsAt(CPos a, SubCell sub, Func<Actor, bool> withCondition);
  		void AddInfluence(Actor self, IOccupySpace ios);
  		void RemoveInfluence(Actor self, IOccupySpace ios);
  		int AddCellTrigger(CPos[] cells, Action<Actor> onEntry, Action<Actor> onExit);
  		void RemoveCellTrigger(int id);
  		int AddProximityTrigger(WPos pos, WDist range, WDist vRange, Action<Actor> onEntry, Action<Actor> onExit);
  		void RemoveProximityTrigger(int id);
  		void UpdateProximityTrigger(int id, WPos newPos, WDist newRange, WDist newVRange);
  		void AddPosition(Actor a, IOccupySpace ios);
  		void RemovePosition(Actor a, IOccupySpace ios);
  		void UpdatePosition(Actor a, IOccupySpace ios);
  
gt: 		IEnumerable<Actor> ActorsInBox(WPos a, WPos b);