/** * <summary> * Step function for roomer. Checks if less than half of the spaces are occupied, and if not, creates a room. * <author>1upD</author> * </summary> */ public override void Step(AlifeMap map) { try { // Mark to discard this._completed = true; // Local variables int spacesOccupied = 0; int total = 0; List <Tuple <int, int, int> > locationsToMark = new List <Tuple <int, int, int> >(); for (int z = this.Z; z < this.Z + this.Height; z++) { for (int x = this.X + this._x2; x < this.X + this._x1; x++) { for (int y = this.Y + this._y2; y < this.Y + this._y1; y++) { locationsToMark.Add(new Tuple <int, int, int>(x, y, z)); bool isSpaceOccupied = map.GetLocation(x, y, z) != null && map.GetLocation(x, y, z) != ""; spacesOccupied += isSpaceOccupied ? 1 : 0; total++; } } } if (spacesOccupied < total / 2 && MustDeploy) { log.Debug(string.Format("Roomer deployed: {0} spaces occupied, {1} total.", spacesOccupied, total)); log.Debug(string.Format("Roomer deployed at x: {0} y: {1} z: {2}", this.X, this.Y, this.Z)); foreach (var tuple in locationsToMark) { map.MarkLocation(this.Style, tuple.Item1, tuple.Item2, tuple.Item3); } } else { log.Debug(string.Format("Roomer did not deploy. {0} spaces occupied, {1} total.", spacesOccupied, total)); } } catch (Exception e) { log.Error("Error in Roomer Step function: ", e); } }
/** * <summary> * 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. * <author>1upD</author> * </summary> * */ 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 <= (vertical ? this.X + this.Width : this.X); x++) { for (int y = this.Y; y <= (vertical ? this.Y : this.Y + this.Width); y++) { for (int z = this.Z; z <= this.Z + this.Height; z++) { map.MarkLocation(this.Style, x, y, z); } } } if (this.Lifetime == 1 && this.SpawnRoomerOnDeath) { log.Debug(string.Format("Tunneler died at {0}, {1}, {2}.", this.X, this.Y, this.Z)); // Add a roomer 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)); map.Agents.Add(child); } this.Lifetime--; } catch (Exception e) { log.Error("Error in Tunneler Step function: ", e); } }