Tunneler.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using Alife.AlifeMaps;
namespace Alife.Agents
{
/**
*
* Basic agent that digs tunnels.
* 1upD
*
*/
[Serializable]
public clast Tunneler : BaseAgent
{
public int X;
public int Y;
public int Z;
public int Width;
public int Height;
public int Lifetime;
public int MaxLifetime;
public float ProbReproduce;
public float ProbTurn;
public float ProbAscend;
public float ProbSpawnRoomer;
public int MaxHeightDecayRate;
public int MinHeightDecayRate;
public int MaxWidthDecayRate;
public int MinWidthDecayRate;
public string Style;
public AlifeDirection Direction;
public bool SpawnRoomerOnDeath;
public int LifetimeDecayRate;
public int MaxVerticalDrop;
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public Tunneler()
{
this.X = 0;
this.Y = 0;
this.Z = 0;
this.Width = 1;
this.Height = 2;
this.Lifetime = 1;
this.MaxLifetime = 1;
this.ProbReproduce = 0.0f;
this.ProbAscend = 0.0f;
this.ProbTurn = 0.0f;
this.Direction = 0.0f;
this.Style = "";
this.MaxHeightDecayRate = 0;
this.MinHeightDecayRate = 0;
this.MaxWidthDecayRate = 0;
this.MinWidthDecayRate = 0;
this.MaxVerticalDrop = 1;
this.ProbSpawnRoomer = 0.0f;
this.SpawnRoomerOnDeath = true;
this.LifetimeDecayRate = 1;
}
/**
*
* Constructor takes a lot of arguments.
* 1upD
*
*/
public Tunneler(string style = "", int x = 0, int y = 0, int z = 0,
int width = 1, int height = 2,
int lifetime = 1, int maxLifetime = 1,
float probReproduce = 0.0f, float probTurn = 0.0f, float probAscend = 0.0f,
AlifeDirection direction = AlifeDirection.East, int MaxHeighDecayRate = 0, int MinHeightDecayRate = 0, int MaxWidthDecayRate = 0, int MinWidthDecayRate = 0, float ProbSpawnRoomer = 0.0f, bool spawnRoomerOnDeath = true, int LifeTimeDecayRate = 1, int maxVerticalDrop = 2)
{
this.X = x;
this.Y = y;
this.Z = z;
this.Width = width;
this.Height = height;
this.Lifetime = lifetime;
this.MaxLifetime = maxLifetime;
this.ProbReproduce = probReproduce;
this.ProbAscend = probAscend;
this.ProbTurn = probTurn;
this.Direction = direction;
this.Style = style;
this.ProbSpawnRoomer = ProbSpawnRoomer;
this.SpawnRoomerOnDeath = spawnRoomerOnDeath;
this.LifetimeDecayRate = 1;
this.MaxVerticalDrop = 1;
log.Debug(string.Format("Tunneler spawned at {0}, {1}, {2}.", this.X, this.Y, this.Z));
}
public new void GetObjectData(SerializationInfo info, StreamingContext context)
{
throw new NotImplementedException();
}
/**
*
* Gets the remaining number of turns. Useful if this agent needs to be culled.
* 1upD
*
*/
public override int GetTurnsLeft()
{
return this.Lifetime;
}
/**
*
* Step function for tunneler. Uses RNG to choose whether to turn or reproduce, then moves forward in a direction. Marks all occupied spaces in the provided map.
* 1upD
*
*
*/
public override void Step(AlifeMap map)
{
try {
int seed = this.X + this.Y + this.Z + (int)this.Direction + this.Height + this.Width + (int)System.DateTime.Now.Ticks;
// Get random number
Random random = new Random(seed);
double sample = random.NextDouble();
// Check turn probability. If turning, change direction 90 degrees
if (sample < this.ProbTurn)
{
sample = random.NextDouble();
int polarity = sample > 0.5 ? 1 : -1;
this.Direction = AlifeDirectionOperations.Add(this.Direction, polarity);
}
// Get new random seed
sample = random.NextDouble();
// Check reproduction probability
if (sample < this.ProbReproduce)
{
sample = random.NextDouble();
int polarity = sample > 0.5 ? 1 : -1;
AlifeDirection childDirection = AlifeDirectionOperations.Add(this.Direction, polarity);
int widthDecay = random.Next(this.MinWidthDecayRate, this.MaxWidthDecayRate);
int heightDecay = random.Next(this.MinHeightDecayRate, this.MaxHeightDecayRate);
Tunneler child = new Tunneler(this.Style, this.X, this.Y, this.Z, this.Width - widthDecay, this.Height - heightDecay, this.MaxLifetime - this.LifetimeDecayRate, this.MaxLifetime - this.LifetimeDecayRate, this.ProbReproduce, this.ProbTurn, this.ProbAscend, childDirection);
map.Agents.Add(child);
}
else
{
sample = random.NextDouble();
if (sample < this.ProbSpawnRoomer)
{
Roomer child = new Roomer(x: this.X, y: this.Y, z: this.Z, style: this.Style, height: Math.Max(this.Height, 2), maxWidth: Math.Min(this.Width * 2, 3), mustDeploy: false);
map.Agents.Add(child);
}
}
// Get new random seed
sample = random.NextDouble();
// Check a s c e n d probability
if (sample < this.ProbAscend)
{
sample = random.NextDouble();
int verticalDistance = random.Next(1, Math.Min(this.Height, this.MaxVerticalDrop));
int polarity = sample > 0.5 ? verticalDistance : -verticalDistance;
this.Z += polarity;
}
else
{
// Update location
switch (this.Direction)
{
case AlifeDirection.East:
this.X++;
break;
case AlifeDirection.North:
this.Y++;
break;
case AlifeDirection.West:
this.X--;
break;
case AlifeDirection.South:
this.Y--;
break;
case AlifeDirection.Up:
this.Z++;
break;
case AlifeDirection.Down:
this.Z--;
break;
}
}
// Mark location
// Nasty nested four loop to handle the added spaces from the height and width
bool vertical = this.Direction == AlifeDirection.North || this.Direction == AlifeDirection.South;
for (int x = this.X; x