public Campfire(int x, int y) : base(x, y, 10) { Size = 25; RenderMode = RenderContextMode.ObjectFirst; image = Utilities.GetResourceImage("campfirelit.png"); RenderContext.AddAccessory(new Halo(13, 13, 200)); FleeFromThisUtility = new ActionUtility(new FleeAction(this), new Tuple <Need, double>[] { ActionUtility.NewPair(Need.JobFullfilment, 0.0025) }); }
public override List <ActionUtility> GetAdvertisedActions(Entity entity, double mod) { List <ActionUtility> actionAds = new List <ActionUtility>(); if (entity is Person) { actionAds.Add(new ActionUtility(new GuardBaseAction(Position, 800), new Tuple <Need, double>[] { ActionUtility.NewPair(Need.JobFullfilment, DDeltaConfig.guardBaseDelta) })); } return(actionAds); }
public override List <ActionUtility> GetAdvertisedActions(Entity entity, double mod) { List <ActionUtility> actionUtilities = new List <ActionUtility>(); if (entity is Person person) { // males attack or run away from all animal types. females run away or ignore based on animal types. // entity can defeat this animal in combat or the animal can't fight back. if (person.Sex == Sex.Male) { if (this.Health / entity.Strength > person.GetHealth() / this.Strength || Type == AnimalType.Hog || Type == AnimalType.Goat) { actionUtilities.Add(AttackThisUtility); } else // Male runs away from scary animal. { actionUtilities.Add(FleeFromThisUtility); } } else { if (Type == AnimalType.Bear || Type == AnimalType.Wolf) { // Weak males and females should run away from the animal. actionUtilities.Add(FleeFromThisUtility); } } } else if (entity is Animal animal) { if (this.Type == AnimalType.Goat && animal.Type == AnimalType.Wolf) // Wolves will attack goats. { actionUtilities.Add(AttackThisUtility); } else if (this.Type == AnimalType.Wolf && animal.Type == AnimalType.Goat) // Goats will run from wolves. { actionUtilities.Add(FleeFromThisUtility); } else if (this.Type != AnimalType.Bear && this.Type == animal.Type) // All but bears will travel in packs. { actionUtilities.Add(new ActionUtility(new FollowAction(this, FollowDistance), new Tuple <Need, double>[] { ActionUtility.NewPair(Need.JobFullfilment, 0.002) })); } } return(actionUtilities); }
public override List <ActionUtility> GetAdvertisedActions(Entity entity, double mod) { List <ActionUtility> actionUtilities = new List <ActionUtility>(); if (entity is Person person) { if (appleCount > 0) { actionUtilities.Add(new ActionUtility(new HarvestAction(this), new Tuple <Need, double>[] { ActionUtility.NewPair(Need.JobFullfilment, DDeltaConfig.harvestPlantDelta) })); } } return(actionUtilities); }
public void DecideAction(Animal animal, List <GameObject> nearbyObjects) { List <ActionUtility> actionAds = nearbyObjects. Where(o => o != animal) .SelectMany(o => o.GetAdvertisedActions(animal, 0.0)).ToList(); actionAds.Add(new ActionUtility(animal.IdleAction, new Tuple <Need, double>[] { ActionUtility.NewPair(Need.JobFullfilment, 0.002) })); EntityAction attackerResponseAction; // Add actions to respond to the attacker being nearby. // Bears will always attack nearby entities, but wolves might not, and goats and hogs will not. if (animal.Attacker != null && nearbyObjects.Contains(animal.Attacker)) { if (animal.Type == AnimalType.Bear) { attackerResponseAction = new AttackAction(animal.Attacker); } // Wolves will fight back if it can win. I.e. it will take less ticks for the wolf to kill the attacker than for the // attacker to kill the wolf. else if (animal.Type == AnimalType.Wolf && animal.GetHealth() / animal.Attacker.Strength > animal.GetHealth() / animal.Strength) { attackerResponseAction = new AttackAction(animal.Attacker); } else { attackerResponseAction = new FleeAction(animal.Attacker); } actionAds.Add(new ActionUtility(attackerResponseAction, new Tuple <Need, double>[] { ActionUtility.NewPair(Need.JobFullfilment, DDeltaConfig.attackerResponseDelta) })); } EntityAction bestAction = utilityDecider.GetBestAction(animal, actionAds); if (!Utilities.AreSameBaseType(animal.Action, bestAction)) { animal.TrySetAction(bestAction); } }
private Animal(int x, int y, AnimalType type) : base(1.5, 10, x, y, GetBaseColor(type), 5) { Type = type; // Set all needs in the middle. These won't be updated right now, but they will be used for Animal decision making. Hunger = 0.5; Social = 0.5; Lust = 0.5; Tiredness = 0.5; Boredom = 0.5; JobFullfilment = 0.5; AttackThisUtility = new ActionUtility(AttackThisAction, new Tuple <Need, double>[] { ActionUtility.NewPair(Need.JobFullfilment, 0.04) }); FleeFromThisUtility = new ActionUtility(new FleeAction(this), new Tuple <Need, double>[] { ActionUtility.NewPair(Need.JobFullfilment, 0.0025) }); }
public PersonBrain(int personLimit, int desiredFoodCount, OrderedPair <int> housePosition, RectangleF houseBox) { this.personLimit = personLimit; this.desiredFoodCount = desiredFoodCount; this.housePosition = housePosition; houseRectangle = houseBox; Tasks = new List <Task>(); utilityDecider = new UtilityDecider <Need>(); utilityDecider.AddResponseFunction(Need.Hunger, x => x); utilityDecider.AddResponseFunction(Need.Social, x => x); utilityDecider.AddResponseFunction(Need.Lust, x => x); utilityDecider.AddResponseFunction(Need.Tiredness, x => x); utilityDecider.AddResponseFunction(Need.Boredom, x => x); utilityDecider.AddResponseFunction(Need.JobFullfilment, x => x); dropUtility = new ActionUtility(new DropAction(houseRectangle), new Tuple <Need, double>[] { ActionUtility.NewPair(Need.JobFullfilment, DDeltaConfig.dropFoodDelta) }); }
// Uses the person's needs and the list of GameObjects that are nearby public void DecideAction(Person person, List <GameObject> nearbyObjects, int personCount, int food, int mouseX, int mouseY) { //person.SetAction(new FollowMouseAction(mouseX, mouseY, housePosition, houseRectangle)); double personCountMod = (personCount == 0 ? 1.0 : food / (2 * personCount)); List <ActionUtility> actionAds = nearbyObjects .Where(o => o != person) // Kinda clunky but this will allow extra data to control action advertisements. .SelectMany(o => o is Person ? o.GetAdvertisedActions(person, personCountMod) : o.GetAdvertisedActions(person, 0.0)) .ToList(); //if (personCount >= personLimit) // actionAds = actionAds.Where(ad => !(ad.Action is MateAction)).ToList(); // Limit the number of people that can be present at one time. This would be more efficient as a check inside Person to prevent // people from advertising a mate action if their are too many people. if (personCount >= personLimit) { actionAds = actionAds.Where(au => !(au.Action is MateAction)).ToList(); } double deliverFoodDelta = person.GetItemCount(ItemType.Apple) / 2; // Return food to house. actionAds.Add(new ActionUtility(new DeliverFoodAction(houseRectangle), new Tuple <Need, double>[] { ActionUtility.NewPair(Need.JobFullfilment, deliverFoodDelta) })); // Wander around. actionAds.Add(new ActionUtility(person.IdleAction, new Tuple <Need, double>[] { ActionUtility.NewPair(Need.JobFullfilment, DDeltaConfig.idleActionAdvertisement) })); // Hunger need. if ((person.GetItemCount(ItemType.Apple) > 0 || food > 0) && person.Hunger <= 0.5) { actionAds.Add(new ActionUtility(new EatAction(), new Tuple <Need, double>[] { ActionUtility.NewPair(Need.Hunger, 1.0 - person.Hunger) })); } // Tiredness need. if ((person.Tiredness < 0.6 || person.Health < 50) && !person.AttackerInRange()) // Sleep required. ** Add check to see if attacker is nearby **. { actionAds.Add(new ActionUtility(new SleepAction(Person.sleepSeconds, true), new Tuple <Need, double>[] { ActionUtility.NewPair(Need.Tiredness, DDeltaConfig.sleepActionAdvertisement), ActionUtility.NewPair(Need.Health, DDeltaConfig.sleepHealthAdvertisement) })); } else // Napping optional. This should be picked more often unless there are a lot of other actions to pick. { actionAds.Add(new ActionUtility(new SleepAction(Person.napSeconds, false), new Tuple <Need, double>[] { ActionUtility.NewPair(Need.Tiredness, DDeltaConfig.napActionDelta) })); } if (person.GetRectangleF().IntersectsWith(houseRectangle)) { actionAds.Add(dropUtility); } EntityAction attackerResponseAction; if (person.Attacker != null && nearbyObjects.Contains(person.Attacker)) { if (person.Sex == Sex.Male && person.GetHealth() / person.Attacker.Strength > person.GetHealth() / person.Strength) { attackerResponseAction = new AttackAction(person.Attacker); } else { attackerResponseAction = new FleeAction(person.Attacker); } actionAds.Add(new ActionUtility(attackerResponseAction, new Tuple <Need, double>[] { ActionUtility.NewPair(Need.JobFullfilment, DDeltaConfig.attackerResponseDelta) })); } // *** Apply action ad filters here from EntitController's tasks *** ApplyTaskFilters(actionAds); // NOTE: Doesn't filter actions that give 0.0 delta or a negative! EntityAction bestAction = utilityDecider.GetBestAction(person, actionAds); if (!Utilities.AreSameBaseType(person.Action, bestAction)) { if (!(bestAction is WanderAction)) // Remove leftover velocity from a WanderAction. { person.Stop(); } person.TrySetAction(bestAction); } }