using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using V3.Objects;
namespace V3.Map
{
public enum AreaType
{
Village, // has no soldiers or knights, only peasants
Castle, // many knights patrolling around
Graveyard // here you can respawn zombies
}
///
/// Holding area data of the map. Later used for generating enemies.
///
public sealed class Area
{
private const int DistanceHorizontal = 64;
private const int DistanceVertical = 32;
private readonly AreaType mType;
private Rectangle mArea;
private readonly double mDensity;
private readonly double mChance;
///
/// Gets the area type.
///
public AreaType Type => mType;
///
/// Creates a new area for generating population.
///
/// Which type of area. Determines which population is spawned.
/// The size and position of the area.
/// The population density. Together with chance.
/// The chance that a creature is actually created.
/// Name of the area as shown in the game.
// ReSharper disable once UnusedParameter.Local
public Area(string type, Rectangle data, double density = 0d, double chance = 0d, string name = "")
{
switch (type)
{
case "village":
mType = AreaType.Village;
break;
case "castle":
mType = AreaType.Castle;
break;
case "graveyard":
mType = AreaType.Graveyard;
break;
default:
throw new Exception("Error parsing the map. There is no behaviour defined for objects of type " + type + ".");
}
if (density > 1d || chance > 1d || density < 0d || chance < 0d)
{
throw new Exception("Error when parsing area data from map. Density and/or chance is not in range 0.0 to 1.0.");
}
mArea = data;
mDensity = density;
mChance = chance;
}
///
/// Creates the initial population for this area.
///
/// The factory used for creating creatures.
/// Used for checking collisions when creating population.
///
public List GetPopulation(CreatureFactory creatureFactory, Pathfinder pathfinder)
{
var population = new List();
if (mDensity <= 0) return population; // Catch division by zero.
var rndInt = new Random();
var rnd = new Random();
for (double i = DistanceVertical / mDensity + mArea.Y; i < mArea.Height + mArea.Y; i += DistanceVertical / mDensity )
{
for (double j = DistanceHorizontal / mDensity + mArea.X; j < mArea.Width + mArea.X; j += DistanceHorizontal / mDensity )
{
if (mChance < rnd.NextDouble()) continue;
var position = new Vector2((float) j, (float) i);
if (mType == AreaType.Village)
{
ICreature peasant;
if (rnd.NextDouble() < 0.5d)
{
peasant = creatureFactory.CreateMalePeasant(position, (MovementDirection)rndInt.Next(8));
}
else
{
peasant = creatureFactory.CreateFemalePeasant(position, (MovementDirection)rndInt.Next(8));
}
if (!pathfinder.AllWalkable(peasant.BoundaryRectangle)) continue;
population.Add(peasant);
}
else if (mType == AreaType.Castle)
{
ICreature guard = creatureFactory.CreateKingsGuard(position, (MovementDirection)rndInt.Next(8));
if (!pathfinder.AllWalkable(guard.BoundaryRectangle)) continue;
population.Add(guard);
}
}
}
return population;
}
///
/// Is a given creature standing in the area?
///
/// Check for this creature.
///
public bool Contains(ICreature creature)
{
return mArea.Contains(creature.Position.ToPoint());
}
}
}