/// <summary> /// When conditions are right, the BoyPig listens for a grunting GirlPig. /// When one is heard, the BoyPig tries to reach that GirlPig, /// which will only succeed when she is in an adjacent cell. /// /// If the BoyPig reaches a GirlPig, then they try to produce a baby pig. /// /// But if no GirlPig can be reached, then the BoyPig tries to move in the direction of the sound. /// (If there is no sound, then the BoyPig can move in any direction.) /// /// Overrides the LookForPig method in the base class, Pig. /// </summary> protected override void LookForPig() { // Do not modify, delete, or move the debugAnimalAction line below, // or the Debug Info will not show correctly in the GUI, and that could be confusing. debugAnimalAction = "LookForPig"; Direction direction = Listen(); // When no GirlPigs are grunting, this will be null. if (direction == null) { WanderAround(); } else { LifeForm lifeForm = Reach(direction); // Will be null when that direction's cell has no LifeForm occupant. if (lifeForm is GirlPig) { GirlPig girl = (GirlPig)lifeForm; if (!IsTired() && IsInTheMoodForLove()) { girl.TryToMakeBaby(this); UseEnergy(STOMACH_EMPTY_LEVEL); IncreaseTiredness(5); } } else { Move(direction); } } }
/// <summary> /// First the pig looks to see if there is any PigFood in its current Cell. /// If there is, the pig picks it up, eats it, and does nothing more. I.e. the pig stays where it is. /// Otherwise, the pig looks for the nearest PigFood, using the FindNearest method. /// If there isn't any food anywhere in the pigWorld, the pig does nothing. /// If there is food, then the pig (tries to) move one square in the direction /// of that food. If the move fails (e.g. because there's a wall in the way, /// or any other reason), then the pig simply remains where it is. /// </summary> public void LookForFood() { // Do not modify, delete, or move the debugAnimalAction line below, // or the Debug Info will not show correctly in the GUI, and that could be confusing. debugAnimalAction = "LookForFood"; bool pigFoodInCurrentCell = Cell.Exists(typeof(PigFood)); if (pigFoodInCurrentCell) { PigFood food = (PigFood)Cell.PickUp(typeof(PigFood)); Eat(food); } else { Echo nearestPigFood = FindNearest(typeof(PigFood)); if (nearestPigFood != null) { Cell targetCell = Cell.GetAdjacentCell(nearestPigFood.direction); if (targetCell != null) { LifeForm adjacentLifeForm = targetCell.LifeFormOccupant; if (adjacentLifeForm == null) { Move(targetCell); } } } } }
private double sweepAngle; // the current angle of the radar's sweep /// <summary> /// Constructs a new Radar. /// </summary> /// <param name="owner">A reference to the LifeForm that owns this radar. </param> /// <param name="targetType"> The type of object detected by this radar. </param> public Radar(LifeForm owner, Type targetType) { this.owner = owner; this.pigWorld = owner.PigWorld; this.targetType = targetType; sweepAngle = -1.0; // negative value ensures 0 degrees will be swept first. }
/// <summary> /// This method releases the current lifeFormOccupant from this Cell. If there is /// currently no lifeFormOccupant, then this method does nothing. /// </summary> /// <returns> the LifeForm that was released, or null if there was nothing /// occupying this Cell. </returns> private LifeForm Release() { LifeForm removed = lifeFormOccupant; if (lifeFormOccupant != null) { lifeFormOccupant = null; } return(removed); }
/// <summary> /// Tests whether there is room for the given LifeForm on this Cell. If /// there is already a LifeForm occupying this Cell, the answer is no /// (false). If the given LifeForm is a Plant and there are some /// nonLivingThings on this Cell, then the answer is also no. But apart from that, /// this method has no other reasons to return false and should return /// true in all other cases. /// </summary> /// <param name="lifeForm"> the LifeForm to test if there is any room for. </param> /// <returns> true if there is any room on this Cell for the given LifeForm, /// or false otherwise. </returns> public bool IsRoomFor(LifeForm lifeForm) { if (lifeFormOccupant != null) { return(false); } if (lifeForm is Plant && GetCountOfNonlivingThings() > 0) { return(false); } return(true); }
/// <summary> /// Constructs the LifeFormView. /// </summary> /// <param name="pigWorldView"> the view of the pigWorld. </param> /// <param name="lifeForm"> the LifeForm to view. </param> protected LifeFormView(PigWorldView pigWorldView, LifeForm lifeForm) { this.pigWorldView = pigWorldView; this.lifeForm = lifeForm; Position position = lifeForm.Cell.Position; CellView cellView = pigWorldView.GetCellViewFromPosition(position); this.containingCellView = cellView; this.lifeForm.lifeFormMovedEvent += LifeFormMovedEvent; }
/// <summary> /// This method steps through one unit of time in the pigWorld. It loops over /// every LifeForm in the pigWorld and calls the DoSomething() method on each /// LifeForm once. You can use the Step method while the pigWorld is stopped to /// see how the pigWorld changes after one unit of time. /// To make multiple steps, this method can be called repeatedly, /// e.g. by the periodic tick of a timer. /// </summary> public virtual void Step() { now += 1; // Make any sounds in the air dampen over time. if (now % 3 == 0) { for (int row = 0; row < numOfRows; row++) { for (int column = 0; column < numOfColumns; column++) { cells[row, column].Air.DecrementSoundLevel(); } } } // Update each Thing in the pigWorld, for this moment in time. // Items can be added to, and removed from, the list of Things as each LifeForm gets // its slice of time. E.g. pigs can be born, or eaten by a wolf. // To make sure that only existing Things get their time-slice on the current Step, // we make a copy of the list first. List <Thing> localListOfThings = new List <Thing>(Things); for (int i = 0; i < localListOfThings.Count; i++) { // The Things update themselves, so we can't use "foreach" here. Thing thing = localListOfThings[i]; if (thing is LifeForm) { LifeForm lifeForm = (LifeForm)thing; if (lifeForm.Exists()) { lifeForm.HandleTime(); } } else { // Refresh the display of NonlivingThings periodically. if (now % 6 == 0) { Cell cell = thing.Cell; if (cell != null) { cell.Pulse(); } } } } }
/// <summary> /// Removes every Thing from the pigWorld, but will leave the Walls in place. /// </summary> public void RemoveAllThings() { // Because the Delete method updates the list of Things, we make a copy of the list first. List <Thing> localListOfThings = new List <Thing>(Things); for (int i = 0; i < localListOfThings.Count; i++) { // The Things update themselves, so we can't use "foreach" here. Thing thing = localListOfThings[i]; if (!thing.Exists()) { continue; } thing.Delete(); } LifeForm.ResetAllIds(); }
/// <summary> /// If no LifeForm currently standing on this Cell, this method takes /// the LifeForm given in the parameter from its old Cell and places it onto /// this Cell to become the new lifeFormOccupant of this Cell. /// /// If a LifeForm is already on this Cell, then this method does /// nothing. /// </summary> /// <param name="newOccupant"> the new lifeFormOccupant of this Cell. </param> /// <returns> true if the newOccupant was successfully placed, or false otherwise. </returns> public bool AddLifeForm(LifeForm newOccupant) { LifeForm oldOccupant = lifeFormOccupant; if (!IsRoomFor(newOccupant)) { return(false); } Cell sourceCell = newOccupant.Cell; if (sourceCell != null) { sourceCell.Release(); } lifeFormOccupant = newOccupant; lifeFormOccupant.Cell = this; return(true); }
/// <summary> /// This method is called every unit of time by the PigWorld to give the Wolf /// a chance to do something. /// /// First the Wolf looks around for the nearest pig, using the /// method "FindNearest". If there isn't a pig, the Wolf does nothing. /// If there is, then the Wolf either: /// (1) tries to moves one cell/square in the direction of the nearest pig, or /// (2) if a pig is in fact only one move away, the wolf eats the pig. /// /// Note that if there is a wall between the Wolf and the nearest pig, /// then the Wolf won't move at all. /// </summary> protected override void DoSomething() { // This will detect any type of pig (both BoyPigs and GirlPigs). Echo nearestPig = FindNearest(typeof(Pig)); if (nearestPig != null) { Cell targetCell = Cell.GetAdjacentCell(nearestPig.direction); if (targetCell != null) { LifeForm adjacentLifeForm = targetCell.LifeFormOccupant; if (adjacentLifeForm == null) { Move(targetCell); } else if (adjacentLifeForm is Pig) { Eat(adjacentLifeForm); Move(targetCell); } } } }