Move FindTilesInCircle from WorldUtils to Map

This commit is contained in:
Pavlos Touboulidis
2014-06-13 14:24:53 +03:00
parent 03b8096807
commit 060d5326ed
11 changed files with 70 additions and 60 deletions

View File

@@ -573,5 +573,38 @@ namespace OpenRA
var y = dir.Y == 0 ? int.MaxValue : ((dir.Y < 0 ? tl.Y : br.Y) - pos.Y) / dir.Y;
return new WRange(Math.Min(x, y) * dir.Length);
}
public const int MaxTilesInCircleRange = 50;
static List<CVec>[] TilesByDistance = InitTilesByDistance(MaxTilesInCircleRange);
static List<CVec>[] InitTilesByDistance(int max)
{
var ts = new List<CVec>[max + 1];
for (var i = 0; i < max + 1; i++)
ts [i] = new List<CVec>();
for (var j = -max; j <= max; j++)
for (var i = -max; i <= max; i++)
if (max * max >= i * i + j * j)
ts [(int)Math.Ceiling(Math.Sqrt(i * i + j * j))].Add(new CVec(i, j));
return ts;
}
public IEnumerable<CPos> FindTilesInCircle(CPos center, int range)
{
if (range >= TilesByDistance.Length)
throw new InvalidOperationException("FindTilesInCircle supports queries for only <= {0}".F(MaxTilesInCircleRange));
for(var i = 0; i <= range; i++)
{
foreach(var offset in TilesByDistance[i])
{
var t = offset + center;
if (Bounds.Contains(t.X, t.Y))
yield return t;
}
}
}
}
}

View File

@@ -55,39 +55,6 @@ namespace OpenRA
}
}
public static IEnumerable<CPos> FindTilesInCircle(this World world, CPos a, int r)
{
if (r >= TilesByDistance.Length)
throw new InvalidOperationException("FindTilesInCircle supports queries for only <= {0}".F(MaxRange));
for(var i = 0; i <= r; i++)
{
foreach(var offset in TilesByDistance[i])
{
var t = offset + a;
if (world.Map.Bounds.Contains(t.X, t.Y))
yield return t;
}
}
}
static List<CVec>[] InitTilesByDistance(int max)
{
var ts = new List<CVec>[max+1];
for (var i = 0; i < max+1; i++)
ts[i] = new List<CVec>();
for (var j = -max; j <= max; j++)
for (var i = -max; i <= max; i++)
if (max * max >= i * i + j * j)
ts[(int)Math.Ceiling(Math.Sqrt(i*i + j*j))].Add(new CVec(i,j));
return ts;
}
public const int MaxRange = 50;
static List<CVec>[] TilesByDistance = InitTilesByDistance(MaxRange);
public static CPos ChooseRandomEdgeCell(this World w)
{
var isX = w.SharedRandom.Next(2) == 0;

View File

@@ -345,7 +345,7 @@ namespace OpenRA.Mods.RA.AI
{
for (var k = MaxBaseDistance; k >= 0; k--)
{
var tlist = world.FindTilesInCircle(center, k)
var tlist = Map.FindTilesInCircle(center, k)
.OrderBy(a => (a.CenterPosition - pos).LengthSquared);
foreach (var t in tlist)
@@ -365,7 +365,7 @@ namespace OpenRA.Mods.RA.AI
return enemyBase != null ? findPos(enemyBase.CenterPosition, defenseCenter) : null;
case BuildingType.Refinery:
var tilesPos = world.FindTilesInCircle(baseCenter, MaxBaseDistance)
var tilesPos = Map.FindTilesInCircle(baseCenter, MaxBaseDistance)
.Where(a => resourceTypeIndices.Contains(Map.GetTerrainIndex(new CPos(a.X, a.Y))));
if (tilesPos.Any())
{
@@ -377,7 +377,7 @@ namespace OpenRA.Mods.RA.AI
case BuildingType.Building:
for (var k = 0; k < maxBaseDistance; k++)
{
foreach (var t in world.FindTilesInCircle(baseCenter, k))
foreach (var t in Map.FindTilesInCircle(baseCenter, k))
{
if (world.CanPlaceBuilding(actorType, bi, t, null))
{
@@ -696,7 +696,7 @@ namespace OpenRA.Mods.RA.AI
// Won't work for shipyards...
CPos ChooseRallyLocationNear(CPos startPos)
{
var possibleRallyPoints = world.FindTilesInCircle(startPos, Info.RallyPointScanRadius)
var possibleRallyPoints = Map.FindTilesInCircle(startPos, Info.RallyPointScanRadius)
.Where(IsRallyPointValid);
if (!possibleRallyPoints.Any())

View File

@@ -25,7 +25,7 @@ namespace OpenRA.Mods.RA.Activities
bool screenFlash;
string sound;
const int maxCellSearchRange = WorldUtils.MaxRange;
const int maxCellSearchRange = Map.MaxTilesInCircleRange;
public Teleport(Actor chronosphere, CPos destination, int? maximumDistance, bool killCargo, bool screenFlash, string sound)
{
@@ -90,7 +90,7 @@ namespace OpenRA.Mods.RA.Activities
CPos? ChooseBestDestinationCell(Actor self, CPos destination)
{
var restrictTo = maximumDistance == null ? null : self.World.FindTilesInCircle(self.Location, maximumDistance.Value);
var restrictTo = maximumDistance == null ? null : self.World.Map.FindTilesInCircle(self.Location, maximumDistance.Value);
if (maximumDistance != null)
destination = restrictTo.MinBy(x => (x - destination).LengthSquared);
@@ -102,7 +102,7 @@ namespace OpenRA.Mods.RA.Activities
var searched = new List<CPos>();
for (int r = 1; r <= maxCellSearchRange || (maximumDistance != null && r <= maximumDistance); r++)
{
foreach (var tile in self.World.FindTilesInCircle(destination, r).Except(searched))
foreach (var tile in self.World.Map.FindTilesInCircle(destination, r).Except(searched))
{
if (self.Owner.Shroud.IsExplored(tile)
&& (restrictTo == null || (restrictTo != null && restrictTo.Contains(tile)))

View File

@@ -53,12 +53,12 @@ namespace OpenRA.Mods.RA
if (warhead.Size[0] > 0)
{
var resLayer = world.WorldActor.Trait<ResourceLayer>();
var allCells = world.FindTilesInCircle(targetTile, warhead.Size[0]).ToList();
var allCells = world.Map.FindTilesInCircle(targetTile, warhead.Size[0]).ToList();
// `smudgeCells` might want to just be an outer shell of the cells:
IEnumerable<CPos> smudgeCells = allCells;
if (warhead.Size.Length == 2)
smudgeCells = smudgeCells.Except(world.FindTilesInCircle(targetTile, warhead.Size[1]));
smudgeCells = smudgeCells.Except(world.Map.FindTilesInCircle(targetTile, warhead.Size[1]));
// Draw the smudges:
foreach (var sc in smudgeCells)
@@ -110,17 +110,21 @@ namespace OpenRA.Mods.RA
var damage = (int)GetDamageToInflict(pos, victim, warhead, weapon, firepowerModifier, true);
victim.InflictDamage(firedBy, damage, warhead);
}
} break;
}
break;
case DamageModel.PerCell:
{
foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0]))
foreach (var t in world.Map.FindTilesInCircle(targetTile, warhead.Size[0]))
{
foreach (var unit in world.ActorMap.GetUnitsAt(t))
{
var damage = (int)GetDamageToInflict(pos, unit, warhead, weapon, firepowerModifier, false);
unit.InflictDamage(firedBy, damage, warhead);
}
} break;
}
}
break;
case DamageModel.HealthPercentage:
{
@@ -135,9 +139,11 @@ namespace OpenRA.Mods.RA
var healthInfo = victim.Info.Traits.Get<HealthInfo>();
damage = (float)(damage / 100 * healthInfo.HP);
}
victim.InflictDamage(firedBy, (int)damage, warhead);
}
} break;
}
break;
}
}

View File

@@ -324,13 +324,15 @@ namespace OpenRA.Mods.RA.Move
var searched = new List<CPos>();
// Limit search to a radius of 10 tiles
for (int r = minRange; r < maxRange; r++)
foreach (var tile in self.World.FindTilesInCircle(target, r).Except(searched))
{
foreach (var tile in self.World.Map.FindTilesInCircle(target, r).Except(searched))
{
if (CanEnterCell(tile))
return tile;
searched.Add(tile);
}
}
// Couldn't find a cell
return target;
@@ -343,13 +345,15 @@ namespace OpenRA.Mods.RA.Move
var searched = new List<CPos>();
for (int r = minRange; r < maxRange; r++)
foreach (var tile in self.World.FindTilesInCircle(target, r).Except(searched))
{
foreach (var tile in self.World.Map.FindTilesInCircle(target, r).Except(searched))
{
if (check(tile))
return tile;
searched.Add(tile);
}
}
// Couldn't find a cell
return target;

View File

@@ -92,7 +92,7 @@ namespace OpenRA.Mods.RA.Move
// Select only the tiles that are within range from the requested SubCell
// This assumes that the SubCell does not change during the path traversal
var tilesInRange = world.FindTilesInCircle(targetCell, range.Range / 1024 + 1)
var tilesInRange = world.Map.FindTilesInCircle(targetCell, range.Range / 1024 + 1)
.Where(t => (t.CenterPosition - target).LengthSquared <= rangeSquared
&& mi.CanEnterCell(self.World, self, t, null, true, true));

View File

@@ -58,7 +58,7 @@ namespace OpenRA.Mods.RA
var total = (double)world.Map.Bounds.Width * world.Map.Bounds.Height;
MapControl = world.Actors
.Where(a => !a.IsDead() && a.IsInWorld && a.Owner == player && a.HasTrait<RevealsShroud>())
.SelectMany(a => world.FindTilesInCircle(a.Location, a.Trait<RevealsShroud>().Range.Clamp(WRange.Zero, WRange.FromCells(50)).Range / 1024))
.SelectMany(a => world.Map.FindTilesInCircle(a.Location, a.Trait<RevealsShroud>().Range.Clamp(WRange.Zero, WRange.FromCells(50)).Range / 1024))
.Distinct()
.Count() / total;
}

View File

@@ -52,8 +52,8 @@ namespace OpenRA.Mods.RA
return;
// Spawn support units in an annulus around the base actor
var supportSpawnCells = w.FindTilesInCircle(sp, unitGroup.OuterSupportRadius)
.Except(w.FindTilesInCircle(sp, unitGroup.InnerSupportRadius));
var supportSpawnCells = w.Map.FindTilesInCircle(sp, unitGroup.OuterSupportRadius)
.Except(w.Map.FindTilesInCircle(sp, unitGroup.InnerSupportRadius));
foreach (var s in unitGroup.SupportActors)
{

View File

@@ -55,7 +55,7 @@ namespace OpenRA.Mods.RA
public IEnumerable<Actor> UnitsInRange(CPos xy)
{
var range = ((ChronoshiftPowerInfo)Info).Range;
var tiles = self.World.FindTilesInCircle(xy, range);
var tiles = self.World.Map.FindTilesInCircle(xy, range);
var units = new List<Actor>();
foreach (var t in tiles)
units.AddRange(self.World.ActorMap.GetUnitsAt(t));
@@ -69,8 +69,8 @@ namespace OpenRA.Mods.RA
return false;
var range = ((ChronoshiftPowerInfo)Info).Range;
var sourceTiles = self.World.FindTilesInCircle(xy, range);
var destTiles = self.World.FindTilesInCircle(sourceLocation, range);
var sourceTiles = self.World.Map.FindTilesInCircle(xy, range);
var destTiles = self.World.Map.FindTilesInCircle(sourceLocation, range);
using (var se = sourceTiles.GetEnumerator())
using (var de = destTiles.GetEnumerator())
@@ -134,7 +134,7 @@ namespace OpenRA.Mods.RA
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world)
{
var xy = wr.Position(wr.Viewport.ViewToWorldPx(Viewport.LastMousePos)).ToCPos();
var tiles = world.FindTilesInCircle(xy, range);
var tiles = world.Map.FindTilesInCircle(xy, range);
var pal = wr.Palette("terrain");
foreach (var t in tiles)
yield return new SpriteRenderable(tile, t.CenterPosition, WVec.Zero, -511, pal, 1f, true);
@@ -216,11 +216,11 @@ namespace OpenRA.Mods.RA
var pal = wr.Palette("terrain");
// Source tiles
foreach (var t in world.FindTilesInCircle(sourceLocation, range))
foreach (var t in world.Map.FindTilesInCircle(sourceLocation, range))
yield return new SpriteRenderable(sourceTile, t.CenterPosition, WVec.Zero, -511, pal, 1f, true);
// Destination tiles
foreach (var t in world.FindTilesInCircle(xy, range))
foreach (var t in world.Map.FindTilesInCircle(xy, range))
yield return new SpriteRenderable(sourceTile, t.CenterPosition, WVec.Zero, -511, pal, 1f, true);
// Unit previews

View File

@@ -60,7 +60,7 @@ namespace OpenRA.Mods.RA
public IEnumerable<Actor> UnitsInRange(CPos xy)
{
int range = ((IronCurtainPowerInfo)Info).Range;
var tiles = self.World.FindTilesInCircle(xy, range);
var tiles = self.World.Map.FindTilesInCircle(xy, range);
var units = new List<Actor>();
foreach (var t in tiles)
units.AddRange(self.World.ActorMap.GetUnitsAt(t));
@@ -110,7 +110,7 @@ namespace OpenRA.Mods.RA
{
var xy = wr.Position(wr.Viewport.ViewToWorldPx(Viewport.LastMousePos)).ToCPos();
var pal = wr.Palette("terrain");
foreach (var t in world.FindTilesInCircle(xy, range))
foreach (var t in world.Map.FindTilesInCircle(xy, range))
yield return new SpriteRenderable(tile, t.CenterPosition, WVec.Zero, -511, pal, 1f, true);
}