home    family    work    school    resume



Code


Truth --- Code --- Results --- Discussion --- Downloads

Below is the code for the main program, honesty.c
Standard comments to the code are in red.  Further analysis is in green.



#include <stdio.h>
#include <math.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>


/*Definitions */
#define NUM_PREY 400
#define NUM_PRED 100
#define PRED_ATTRIBS 3
#define PREY_ATTRIBS 4
#define ENERGY 100
#define TRANSFER_VALUE 1.0 /*amount of energy taken from prey is a random
                            value between upper and lower value multiplied by this*/
#define GAUSS_DIVIDE 100 /*amount to divide Gauss with mean of 1 by */


int upper_value = 0;
int lower_value = 0;
float cost_to_build = 0;
float cost_to_attack = 0;
float aging_prey = 0;
float aging_pred = 0;
float batt_factor = 0;
int prey_reproductions = 0;
int pred_reproductions = 0;


/*This data structure will hold the values for individuals representing preys.
  'call_with' is a percentage chance that the prey will call when battlements have
  been built.  'call_wo' is a percentage chance that the prey will call when it
  has not built battlements (this can be construed as "lying", assuming the prey
  is using calling to indicate battlements have been built).  'build' is a percantage
  representing the the chance that the prey will build battlements durring an
  interaction.  "Battlements" is a convention used to represent any action a prey
  may undertake to make itself less desirable to the predator.  In our model when
  battlements are built it costs the predator more to attack, and the predator gets
  less from the prey. */
typedef struct {
  double call_with;
  double call_wo;
  double build;
  short energy;
} Prey;


Prey pr[NUM_PREY]; /*An array of Preys */


/*This structure is for representing individuals within the predator population.
  'attack_call' is a percentage value representing the likliehood the predator will
  attack if a call has been given by the prey.  'attack_no_call' is a percentage
  value representing the likliehood of a predator attack given there is no call made
  by the prey. */
typedef struct {
  double attack_call;
  double attack_no_call;
  short energy;
} Predator;


Predator prd[NUM_PRED];


/*=============================================================== */
/*Functions */
void initialize ();
int interact ();
void preyreproduce (int subject);
void predreproduce (int subject);
int energypred (int subject, int amount);
int energyprey (int subject, int amount);
void record (int loop);
void aging();
int collectvariables();
int attack(int pry, int pd, int batt, int situation);
double frand ();
double irand (double max);
double rgauss ();


/*============================================================== */
int
main()
{
  int i, j, k, epochs, sweeps, records;
  FILE *data_ptr; /*data_ptr = data file pointer */
  if((data_ptr = fopen("data", "w"))==NULL)
    printf("File Could not be opened.\n");
  printf("How man interactions before aging cycle? : ");
  scanf("%d", &epochs);
  printf("How man aging cycles before sweep? : ");
  scanf("%d", &sweeps);
  printf("How man records? : ");
  scanf("%d", &records);
  if (collectvariables() == 0)
    {
      printf("problems with variable file\n");
      exit(0);
    }
  initialize();
  for (i = 0; i < records; i++)
    {
      record(i);
      for (j = 0; j < sweeps; j++)
 {
   for (k = 0; k < epochs; k ++)
     interact();
   aging();
 }
    }
  printf("number of prey which died: %d \nnumber of predators which died: %d \n", /
         prey_reproductions, pred_reproductions);
  exit(0);
}


/*==============================================================*/
/* Initialize both the predator and prey populations, filling the
attributes with random values from 0 to 1 and the Energy value being set to 100 */


void initialize ()
{
  int i = 0;
  int j = 0;
  for (i = 0; i < NUM_PRED; i++)
    {
    for (j = 0; j < PRED_ATTRIBS; j++)
      {
 if (j == 0)
   prd[i].attack_call = frand(); /*attack with call */
 if (j == 1)
   prd[i].attack_no_call = frand(); /*attack without call*/
 if (j == 2)
   prd[i].energy = irand(ENERGY);  /*starting energy */
      }
    }
  for (i = 0; i < NUM_PREY; i++)
    {
      for (j = 0; j < PREY_ATTRIBS; j++)
 {
   if (j == 0){
     pr[i].call_with = frand(); /*call with battlements */
   }
   if (j == 1){
     pr[i].call_wo = frand(); /*call with out battlements (bluff) */
   }
   if (j == 2){
     pr[i].build = frand(); /*make battlements */
   }
   if (j == 3){
     pr[i].energy = irand(ENERGY);
   }
 }
    }
}


/*================================================================= */
/*Interactions between prey and predator, assuming the two see each other */
int
interact ()
{
  int pry, pd; /*represent prey and predator */
  int didbuild = 0, didcall = 0; /*1 is yes, 0 is no */
  int enexchange = 0;
  pry = irand(NUM_PREY - 1); /*assign a random (unlucky) prey */
  pd = irand(NUM_PRED - 1);
  /*assign a random predator
    first the prey will decide whether or not to build battlements
    this will be decided by generating a random value and comparing
    it to the trait, choosing the higher */
  if(pr[pry].build > frand())
    {
      didbuild = 1;
      if(0 == energyprey(pry, cost_to_build))/*prey gives up energy for building */
 return(0);
      if(pr[pry].call_with > frand())
 /*having built battlements */
 didcall = 1;
    }
  else
    {
      if(pr[pry].call_wo > frand()) /*call w/o battlements */
 didcall = 1;
    }
  attack(pry, pd, didbuild, didcall);
  return(1);
}


/*=================================================================*/
/*An asexual reproduction function */
/* The function takes a single prey or predator that has died, and replaces
   that prey or predator with a new one.  The new replacement has its values
   selected by comparing two randomly selected individuals and the individual
   with the higher energy level will be the prototype from which the new
   replacement is made. */


void
preyreproduce (int subject)
{
  int i;
  int j;
  prey_reproductions += 1;
  /*First reproduce Prey by taking two prey, and allowing the one with */
  /*higher energy to reproduce */
  i = irand (NUM_PREY - 1);
  j = irand (NUM_PREY - 1);
  if (i == j)
    i = (i % 11) + 3; /*set i to new value if it is the same as j*/
  if (pr[i].energy >= pr[j].energy) /*Compare energy values */
    {
      pr[subject].call_with = (pr[i].call_with + (rgauss ()));
      if(pr[subject].call_with > 1.0) pr[subject].call_with = 1.0;
      if(pr[subject].call_with < 0.00) pr[subject].call_with = 0.0;
 
 
      pr[subject].call_wo = (pr[i].call_wo + (rgauss ())); /*rgauss "jiggles" */
      /*rgauss is a function which will add some value to the new individuals
        value corresponding to a Gaussian distribution ranging from .01 to -.01
        In effect, this acts as a slight mutation to the individual being
        reproduced to allow for evolution to select for individuals whos values
        "jiggle" in the more beneficial direction */


      if(pr[subject].call_wo > 1.0) pr[subject].call_wo = 1.0;
      if(pr[subject].call_wo < 0.00) pr[subject].call_wo = 0.0;


      pr[subject].build = (pr[i].build + (rgauss ()));
      if(pr[subject].build > 1.0) pr[subject].build = 1.0;
      if(pr[subject].build < 0.00) pr[subject].build = 0.0;


      pr[subject].energy = ENERGY;
    }
  if (pr[j].energy > pr[i].energy) /*Compare energy values*/
    {
      pr[subject].call_with = (pr[j].call_with + (rgauss ()));
      if(pr[subject].call_with > 1.0) pr[subject].call_with = 1.0;
      if(pr[subject].call_with < 0.00) pr[subject].call_with = 0.0;
 
      pr[subject].call_wo = (pr[j].call_wo + (rgauss ()));
      if(pr[subject].call_wo > 1.0) pr[subject].call_wo = 1.0;
      if(pr[subject].call_wo < 0.00) pr[subject].call_wo = 0.0;
 
      pr[subject].build = (pr[j].build + (rgauss ()));
      if(pr[subject].build > 1.0) pr[subject].build = 1.0;
      if(pr[subject].build < 0.00) pr[subject].build = 0.0;
 
      pr[subject].energy = ENERGY;
    }
}


void
predreproduce (int subject)
{
  int i;
  int j;
  pred_reproductions += 1;
  i = irand (NUM_PRED - 1);
  j = irand (NUM_PRED - 1);
  if (i == j)
    i = (i % 11) + 3; /*set i to knew value if it is the same as j */
  if (prd[i].energy >= prd[j].energy) /*Compare energy values */
    {
      prd[subject].attack_call = (prd[i].attack_call + (rgauss ()));
      if(prd[subject].attack_call > 1.0) prd[subject].attack_call = 1.0;
      if(prd[subject].attack_call < 0.00) prd[subject].attack_call = 0.0;
 
      prd[subject].attack_no_call = (prd[i].attack_no_call + (rgauss ()));
      if(prd[subject].attack_no_call > 1.0) prd[subject].attack_no_call = 1.0;
      if(prd[subject].attack_no_call < 0.00) prd[subject].attack_no_call = 0.0;


      prd[subject].energy = ENERGY;
    }
  if (prd[j].energy > prd[i].energy) /*Compare energy values*/
    {
      prd[subject].attack_call = (prd[j].attack_call + (rgauss ()));
      if(prd[subject].attack_call > 1.0) prd[subject].attack_call = 1.0;
      if(prd[subject].attack_call < 0.00) prd[subject].attack_call = 0.0;


      prd[subject].attack_no_call = (prd[j].attack_no_call + (rgauss ())); /*rgauss "jiggles"*/
      if(prd[subject].attack_no_call > 1.0) prd[subject].attack_no_call = 1.0;
      if(prd[subject].attack_no_call < 0.00) prd[subject].attack_no_call = 0.0;


      prd[subject].energy = ENERGY;
    }
}


/*===============================================================*/
/*Getting old is such a drag */
/*This function goes through the entire population and for each prey
  and for each predator it calls the energy functions and either takes
  away or adds to the individuals energy.  The amount taken or given
  is defined with the make_config executable. */


void
aging()
{
  int i;
  for(i = 0; i < NUM_PREY; i++)
    energyprey(i, aging_prey);
  for(i = 0; i < NUM_PRED; i++)
    energypred(i, aging_pred);
}




/*================================================================*/
/*record averages for populations of predator and prey*/
/*Loop is simply the number passed to the argument to define how many times
  the record function will take place.  The loop value is set in the
  make_config executable. */


void
record (int loop)
{
  int i;
  double callbatt = 0.0, callnobatt = 0.0, build = 0.0, preyen = 0.0;
  double attackcall = 0.0, attacknocall = 0.0, preden = 0.0;
  FILE *data_ptr;
  if ((data_ptr = fopen("data", "a+")) == NULL)
    printf("File could not be opened.\n");
  else {
    for (i = 0; i < NUM_PREY; i++)
      {
      callbatt += pr[i].call_with;
      callnobatt += pr[i].call_wo;
      build += pr[i].build;
      preyen += pr[i].energy;
      }
    callbatt = callbatt/NUM_PREY;
    callnobatt = callnobatt/NUM_PREY;
    build = build/NUM_PREY;
    preyen = preyen/NUM_PREY;


    fprintf(data_ptr, "%d %.3f %.3f %.3f %.3g ", loop, callbatt, callnobatt, build, preyen);
    for (i = 0; i < NUM_PRED; i++)
      {
 attackcall += prd[i].attack_call;
 attacknocall += prd[i].attack_no_call;
 preden += prd[i].energy;
      }
    attackcall = attackcall/NUM_PRED;
    attacknocall = attacknocall/NUM_PRED;
    preden = preden/NUM_PRED;


    fprintf(data_ptr, "%.3f %.3f %.3g\n", attackcall, attacknocall, preden);
 
    fclose(data_ptr);
  }
}


/*================================================================*/
/*energy exchange for prey and predator*/
/*This function will take a subject, some individual, and an amount,
  some amount of energy, positive or negative which the subject will
  will have added to their energy.  If the energy value goes below 0
  after the exchange then the reproduce function is called because
  the subject is dead. */


int
energypred (int subject, int amount)
{
  prd[subject].energy = prd[subject].energy + amount;
  if(prd[subject].energy > 100) /*don't allow energy above 100*/
    prd[subject].energy = 100;
  if(prd[subject].energy < 0) /*if energy below 100, dead!*/
    {
    predreproduce(subject);
    return(0);
    }
  else return(1);
}


int
energyprey (int subject, int amount)
{
  pr[subject].energy = pr[subject].energy + amount;
  if(pr[subject].energy > 100)
    pr[subject].energy = 100;
  if(pr[subject].energy < 0)
    {
    preyreproduce(subject);
    return (0);
    }
  else return(1);
}


/*================================================================*/
/*Attack function*/
/*This function takes a predator and a prey, a battlement value and
  a situation value.  The battlement value is 1 or 0, 1 representing
  that battlements have been built by the prey, 0 representing they
  have not.  The situation value is a 0 or 1 with 0 meaning the prey
  did not call and 1 meaning it did. */


int
attack(int pry, int pd, int batt, int situation)
{
  double enexchange = irand(upper_value) + lower_value;
  if ((situation == 1 && prd[pd].attack_call > frand()) || \
      (situation == 0 && prd[pd].attack_no_call > frand()))
    {
      if(batt == 1)
 {
   if(energypred (pd, cost_to_attack) == 0)
     return(0);/*costs too much to attack and pred dies*/
   if(pr[pry].energy < (batt_factor * enexchange))
     {
       /*predator only gets what the pr has left*/
       energypred(pd, pr[pry].energy);
       preyreproduce(pry); /* Prey Dies */
       return(0);
     }
   energypred(pd, (batt_factor * enexchange));
   energyprey(pry, (batt_factor * -enexchange * TRANSFER_VALUE));
 }
      else if (batt == 0) /*could just say 'else' here*/
 {
   if(pr[pry].energy < enexchange)
     {/*predator only gets what the prey has left*/
       energypred(pd, pr[pry].energy);
       preyreproduce(pry);
       return(0);
     }
   energypred(pd, enexchange);
   energyprey(pry, (-enexchange * TRANSFER_VALUE));
 }
    }


  else if(frand() > .95)
    {/*random action by predator*/
      if(batt == 1)
 {
   if(energypred (pd, cost_to_attack) == 0)
     return(0);/*costs to much to attack and pred dies*/
   if(pr[pry].energy < (batt_factor * enexchange))
     {/*predator only gets what the prey has left*/
       energypred(pd, pr[pry].energy);
       preyreproduce(pry);
       return(0);
     }
   energypred(pd, (batt_factor * enexchange));
   energyprey(pry, (batt_factor * -enexchange * TRANSFER_VALUE));
 }
      else if (batt == 0) /*could just say 'else' here */
 {
   if(pr[pry].energy < enexchange)
     {/*predator only gets what the prey has left*/
       energypred(pd, pr[pry].energy);
       preyreproduce(pry);
       return(0);
     }
   energypred(pd, enexchange);
   energyprey(pry, (-enexchange * TRANSFER_VALUE));
 }
    }
}


/*================================================================*/
/*Collect all variables from a file*/
int
collectvariables()
{
  FILE *cvPtr;
 
  if((cvPtr = fopen("config.honesty", "r")) == NULL)
    return(0);
  else {
    fscanf(cvPtr, "%d %d %f %f %f %f %f", &upper_value, &lower_value, \
        &cost_to_build, &cost_to_attack, &aging_prey, &aging_pred, &batt_factor);
  }
  printf("%d %d %f %f %f %f %f\n", upper_value, lower_value, cost_to_build, \
        cost_to_attack, aging_prey, aging_pred, batt_factor);
  fclose(cvPtr);
  return (1);
}


/*=================================================================*/
/*Math stuff*/


double
frand ()
{
  return ((double) rand () / RAND_MAX);
}


double
irand (double max)
{
  return ((double) floor (fabs (max) * frand ()));
}
/*======================================================*/
/*Gaussian distributed random numbers, from Prof. Batali */
static int rgauss_iset = 0;
 
static void reset_rgauss (void)
{
  rgauss_iset = 0;
}
 
double
rgauss ()
{
  static double gset;
  double fac, r, v1, v2, p;
  if (frand () > 0.5)
    p = 1.0;
  else p = -1.0;
  if (rgauss_iset == 0) {
    do {
      v1 = frand ();
      v2 = frand ();
      r = v1*v1 + v2*v2;
    }
    while (r >= 1.0);
    fac = sqrt(-2.0*log(r)/r);
    gset= v1*fac;
    rgauss_iset = 1;
    return(p*v2*fac/GAUSS_DIVIDE);
  }
  else {
    rgauss_iset = 0;
    return(p*gset/GAUSS_DIVIDE);
  }
}
/*==========================================================*/
Truth --- Code --- Results --- Discussion --- Downloads