Hunters
Implementation Details

 Site maintained by: Andrew Schlei Last updated: 22 June 2003 Table of Contents: Agent-Based Computational Economics (ACE) Website ACE/CAS Interactive Computer Demos Site

Hunter Rules [top]
The Hunter agents have rules that determine their behavior during the simulation. These rules are the same for all agents, but the outcome of following these rules depends on the agents' data. Following is a description of the rules that govern how the agents act during the simulation.

Movement:
The movement rule determines how agents move around in their two-dimensional world. The rule is as follows:
• Look in each of the four principal directions as far as vision and world boundaries allow, and record a total score for each path by adding together the scores for each grid square along that path. The following table is used to determine the score for an individual grid square:

 Cell Contains Agent is Attacking Agent is Sharing Agent is Hoarding Other Agent 4 4 0 Food 5 5 5 Nothing 0 0 0

• If one direction had a higher score than all the others, then attempt to move in that direction, otherwise choose a random direction to move in, which includes staying in the same square.
• If it is possible to move in the chosen direction (the first space in that direction is empty), then move in that direction. Otherwise continue choosing random directions until a safe direction is found (staying still is always safe, so a safe direction will always be found).
Food Gathering:
The food gathering rule determines how agents collect food. The rule is as follows:
• Look one square in each of the four principal directions.
• If there is food in a square, gather it.
Interaction:
The interaction rule determines how agents find others to interact with and what actions they choose. The interaction rule also determines the outcome of the interaction, including strength adjustments. The rule is as follows:
• Look one square in each of the four principal directions.
• If another hunter is found, interact with it.
• Choose the action with the highest associated strength. The other agent will also choose an action based on it's own strengths.
• If either hunter chooses to attack, a battle will be fought. The agent with the higher power wins the battle. If they have equal power, a winner is determined randomly. The winner of the battle steals half of the loser's food. Any agent that attacks loses food equal to the material cost of attacking.
• If both agents choose to share, they each take half of their food and pool it together. Each agent then takes half of the food pool. If the amount of food does not divide evenly in half, one of the agents is chosen randomly to receive the extra food.
• Adjust action strengths according to the following table:
 Hunter 1 Hunter 2 Adjust A1 Adjust S1 Adjust H1 Adjust A2 Adjust S2 Adjust H2 Attacked Attacked + difference 0 0 + difference 0 0 Attacked Shared + difference 0 0 +/- 1 0 0 Attacked Hoarded + difference 0 0 +/- 1 0 + difference Shared Shared 0 + difference 0 0 + difference 0 Shared Hoarded 0 0 0 0 0 0 Hoarded Hoarded 0 0 0 0 0 0
Hunter 1 and Hunter 2 are two Hunter agents that are interacting. Which hunter is number 1 and which is number 2 is not important. The adjust columns refer to the strengths to be adjusted. Adjust A1 is the adjustment to Hunter 1's attack strength, Adjust S2 is the adjustment to Hunter 2's share strength, and so on. An entry of "0" means that no adjustment takes place. An entry of "+ difference" means to adjust the hunter's strength by the difference between the hunter's current food supply and its food supply before the interaction (note that this can be negative), and then add the utility offset for the action the hunter performed. An entry of "+/- 1" means to increment the strength by one if the agent won the battle, or decrement it by one if the agent lost the battle.
• Adjust interaction arrays to reflect interactions that occurred.
• Remove any ties for the highest action strength by randomly incrementing one of the strengths tied for highest.

Evolution:
The evolution rule determines how dead hunters are replaced with new hunters. The rule is as follows:

• Gather a list of all of the agents that survived the current generation.
• Scan through the entire list of agents, looking for dead ones.
• For every dead agent found, replace it by choosing two "parents" at random from the list of living agents (it is possible for a single agent to act as both parents). Change the dead agent's data so that its power and action strengths are now the average of those of its parents. For example, consider that the first chosen parent has a power of 20, an attack strength of 10, a share strength of 2, and a hoard strength of 0, while the other parent has a power of 10, an attack strength of 0, a share strength of 4, and a hoard strength of 0. The dead agent's data would be changed as follows: power would be set to 15, attack strength would be set to 5, share strength would be set to 3, and hoard strength would be set to 0.

The Hunter Class [top]
The Hunter class defines the agents used in this simulation. This class contains variables, methods, and non-member functions. The class serves as a container for agent data, and contains the implementation for agent functions.

Private Variables:

• int xPos The hunter's x position, or horizontal position, increasing from left to right.
• int yPos The hunter's y position, or vertical position, increasing from top to bottom.
• int power The hunter's power. This is used to describe how strong an agent is, in terms of its ability to win a fight. Whenever two hunters do battle, their power is compared to determine the winner. Hunters with a higher power are considered stronger.
• int hID The hunter's ID number. This corresponds directly to its position in the array used to store the agents. Every agent must have their own, unique ID number.
• int foodCount The amount of food the hunter has. There is no limit to the amount of food that any hunter can carry with him.
• int costAttack The cost, in food, of attacking. Whenever an agent attacks another agent, it must consume this additional amount of food
• int vision The range of the hunter's vision. When a hunter is deciding which way to move, it looks as far as its vision allows in each of the four principal directions (north, east, south, and west). The hunter can only see in these four directions, and not diagonally.
• int metabolism The amount of food the hunter must consume each round in order to survive.
• bool alive The hunter's status as living or dead. True if the hunter is alive, false if it is dead. Hunters die when they have no food left to consume at the end of a round. It is possible for a hunter to drop below zero food and still survive, as long as it gets more food before the round ends. Once a hunter dies, it stays dead for the remainder of the current generation. An agent that is dead at the end of a generation will be replaced by the offspring of more successful hunters.
• bool* interactedWith This array keeps track of which other agents an agent has already interacted with in a given round. Any pair of agents is only allowed one interaction per round. Each hunter has his own interaction array, but all of the arrays correspond to one another. Thus, if two hunters have not yet interacted with each other in a given round, both hunters will agree that they have not interacted. After they interact for that round, both agents will agree that they have interacted.
• Action utility offsets: After two agents interact, their action strengths are adjusted. The amount of adjustment is determined by the actions each agent performed, and how much food each agent lost or gained. However, the loss or gain of food is offset by action utility variables. These action utility offsets can be used to encourage or discourage certain agent behaviors.
• int utilityAttack Attack utility offset
• int utilityShare Share utility offset
• int utilityHoard Hoard utility offset
• Action Strengths: When an agent interacts with another agent, it has the choice of attacking, sharing, or hoarding. The action it chooses depends on which action has the highest associated strength. In general, when an action is beneficial to an agent, the associated strength for that action increases. When an action is detrimental to an agent, the associated strength for that action decreases. Each agent has his own data for attack, share, and hoard strengths, and no two strengths can be tied for the highest.
• int strengthAttack Attack strength
• int strengthShare Share strength
• int strengthHoard Hoard strength

Methods:

• void setPos(int x, int y)
This method sets the x and y positions
pre: x and y are coordinates in the 2-D world, with x increasing from left to right and y increasing from top to bottom
post: xPos and yPos have changed to reflect the agent's new position
• void setPower(int pow)
inline
This method sets the agents's power
pre: pow is the number to set the agent's power to
post: power has been set to pow
• void setFoodCount(int fc)
inline
This method sets how much food an agent has
pre: fc is the amount of food the agent is to possess
post: foodCount has been set to fc
• void setID(int idNum)
inline
This method sets the agent's id number
pre: idNum is the agent's new id number
post: hID has been set to idNum
• void setAlive(bool a)
inline
This method sets the agent's alive status
pre: a is the agent's new status (true = alive, false = dead)
post: alive has been set to a
• void setStrengthAttack(int str)
inline
This method is used to set the agent's strength associated with attacking
pre: str is the new strength to be assigned to attacking
post: strengthAttack has been set to str
• void setStrengthShare(int str)
inline
This method is used to set the agent's strength associated with sharing
pre: str is the new strength to be assigned to sharing
post: strengthShare has been set to str
• void setStrengthHoard(int str)
inline
This method is used to set the agent's strength associated with hoarding
pre: str is the new strength to be assigned to hoarding
post: strengthHoard has been set to str
• void setCostAttack(int cost)
inline
This method sets the agent's material cost for attacking
pre: cost is the amount of food used up when attacking
post: costAttack has been set to cost
• void setUtilityAttack(int util)
inline
This method set the agent's utility offset for attacking
pre: util is the additional amount to adjust strength by when attacking
post: utilityAttack has been set to util
• void setUtilityShare(int util)
inline
This method set the agent's utility offset for sharing
pre: util is the additional amount to adjust strength by when sharing
post: utilityShare has been set to util
• void setUtilityHoard(int util)
inline
This method set the agent's utility offset for hoarding
pre: util is the additional amount to adjust strength by when hoarding
post: utilityHoard has been set to util
• void setVision(int vis)
inline
This method is used to set the agent's vision range
pre: vis is the desired vision range
post: vision has been set to vis
• void setMetabolism(int met)
inline
This method is used to set the agent's metabolism
pre: met is the desired metabolism
post: metabolism has been set to met
• void createInteract(int numHunters)
This method is used to create the interactedWith array
pre: numHunters is the number of hunter agents in the simulation
post: the agent's interactedWith array has been allocated
• void initInteract(int numHunters)
This method initializes the hunters interactedWith array
pre: numHunters is the number of hunter agents in the simulation
post: the agent's interactedWith array has been initialized to false
• void setInteracted(int i)
inline
This method is used to adjust the agent's interactedWith array to show that the agent has interacted with another hunter agent
pre: i is the id number of the agent that was interacted with
post: interactedWith[i] has been set to true, showing that the agent has interacted with agent i
• void move(int* worldMatrix, int WSX, int WSY, int EMPTY, int FOOD)
This method determines how the agents move
pre: worldMatrix is a pointer to a 1 dimensional array that represents the 2 dimensional world the hunter agents live in.
WSX is the world size in the x dimension (in cells).
WSY is the world size in the y dimension (in cells).
EMPTY is the number denoting an empty cell in worldMatrix.
FOOD is the number denoting food in worldMatrix
post: worldMatrix has been modified to reflect the new positions of the hunter agents. The agent's xPos and yPos coordinates have also been altered to reflect the agent's new position.
• int getScore(int* worldMatrix, int WSX, int EMPTY, int FOOD, int cellX, int cellY)
This method is used to find the score for a given cell, which agents use to determine how to move
pre: worldMatrix is a pointer to a 1 dimensional array that represents the 2 dimensional world the hunter agents live in.
WSX is the world size in the x dimension (in cells).
EMPTY is the number denoting an empty cell in worldMatrix.
FOOD is the number denoting food in worldMatrix.
cellX is the x coordinate of the cell to be examined.
cellY is the y coordinate of the cell to be examined
post: returns score for given cell
• void gather(int* worldMatrix, int WSX, int WSY, int EMPTY, int FOOD,int FOOD_VALUE)
this method is used by the agents to gather food
pre: worldMatrix is a pointer to a 1 dimensional array that represents the 2 dimensional world the hunter agents live in
WSX is the world size in the x dimension (in cells)
WSY is the world size in the y dimension (in cells)
EMPTY is the number denoting an empty cell in worldMatrix
FOOD is the nubmer denoting a cell containing food in worldMatrix
FOOD_VALUE is the amount of food gained from collecting from a food cell
post: The agent's foodCount has been adjusted to reflect any food gathered. worldMatrix has been modified to remove any food cells that were gathered (by setting them to EMPTY).
• void removeTies()
This method is used to remove any ties for the highest strength. If any strengths are tied for highest, it randomly selects one to increment by one.
pre: none
post: the agent's action strengths have been adjusted to remove any ties
• int getPower()
inline
pre: none
post: returns the agent's power
• int getFoodCount()
inline
pre: none
post: returns the agent's foodCount
• int getStrengthAttack()
inline
pre: none
post: returns the agent's strengthAttack
• int getStrengthShare()
inline
pre: none
post: returns the agent's strengthShare
• int getStrengthHoard()
inline
pre: none
post: returns the agent's strengthHoard
• int getY()
inline
pre: none
post: returns the agent's yPos
• int getX()
inline
pre: none
post: returns the agent's xPos
• int getCostAttack()
inline
pre: none
post: returns the agent's costAttack
• int getUtilityAttack()
inline
pre: none
post: returns the agent's utilityAttack
• int getUtilityShare()
inline
pre: none
post: returns the agent's utilityShare
• int getUtilityHoard()
inline
pre: none
post: returns the agent's utilityHoard
• int getVision()
inline
pre: none
post: returns the agent's vision range
• int getMetabolism()
inline
pre: none
post: returns the agent's metabolism
• bool isAlive()
inline
pre: none
post: returns the agent's alive status
• bool interacted(int i)
inline
pre: i is a hunter id number
post: returns true if the agent has interacted with agent i
• bool isAttacking()
This method is used to determine if the agent is currently in "attack mode"
pre: none
post: returns true if the the agent's strengthAttack is its highest strength
• bool isSharing()
This method is used to determine if the agent is currently in "share mode"
pre: none
post: returns true if the the agent's strengthShare is its highest strength
• bool isHoarding()
This method is used to determine if the agent is currently in "hoard mode"
pre: none
post: returns true if the the agent's strengthHoard is its highest strength

Non-Member Functions:

• void hunterInteraction(int* world,int WSY,int WSX,Hunter* hunters, int i, ofstream &log)
This function is used by hunter i to search for nearby hunters it can interact with. When it finds a hunter it has not yet interacted with, hunterInteractionResolver is called.
pre: worldMatrix is a pointer to a 1 dimensional array that represents the 2 dimensional world the hunter agents live in
WSX is the world size in the x dimension (in cells)
WSY is the world size in the y dimension (in cells)
hunters is a pointer to the array of hunter agents
i is the id number of the agent currently acting
log is an open output file stream
post: agent i will have interacted with any agents nearby if it hasn't already
• void hunterInteractionResolver(Hunter* hunters, int i, int target, ofstream &log)
This function is used to resolve interactions between hunters
pre: hunters is a pointer to the array of hunter agents
i is the id number of the agent currently acting
targetID is the id number of the agent being interacted with
logOutput is an open file output stream
post: An action between two agents has been resolved, including adjustments to action strengths, foodCounts, and the interactedWith arrays.
• void hunterEvolution(Hunter* hunters, int NUM_HUNTERS, int numAlive)
This function handles the evolution of the agents. First, the id numbers of all surviving agents are gathered. Then each dead agent is replaced with a new agent. The new agent is created by first choosing two "parents" from among the living agents and then averaging their power, stengthAttack, stengthShare, and strengthHoard member variables. It is possible for a single agent to be both "parents"
pre: hunters is a pointer to the array of hunter agents
NUM_HUNTERS is the total number of hunters in the simulation
numAlive is the number of agents currently "alive"
post: all dead hunter agents have been replaced with new agents, although they are still dead.

Feedback [top]
You may contact me at aschlei@hotmail.com. I would greatly appreciate your comments and suggestions.