@agent Resident {
  @uses ;		// We need this Swarm package
  					// as we are using lists here
    
  @var: int color, age, maxAge;
  @var: int posX, posY;
  @var: float limit;

    @sub: (void) setX: (int) x Y: (int) y {
      posX = x;
      posY = y;
      [model->city putObject: self atX: posX Y: posY];
    }

    @sub: (void) setColor: (int) c maxAge: (int) a AndLimit: (float) l {
      color = c;
      age = 0;
      maxAge = a;
      limit = l;
    }

    @sub: (void) step {
    int i, j, num, numOfOK, numOfEmpties;
    float level;
    Resident *dummy;		// The neighbor under observation
    id emptyX, emptyY;		// List of possible locations to go
    				// (X and Y coordinates separately).
    
    emptyX = [List create: [self getZone]];
    emptyY = [List create: [self getZone]];

      num = numOfOK = 0;
      for (i=-1; i<2; i++)
        for(j=-1; j<2; j++) {
        
          // If the location is not ours
          if ((i!=0) || (j!=0)) {
          
            dummy = [model->city getObjectAtX: 
                                  ((posX+i+model->citySize) % model->citySize)
                                            Y: 
                                  ((posY+j+model->citySize) % model->citySize)];

            if (dummy != nil) {
              num++;
              if (dummy->color == color)  
                numOfOK++;
            }
            else {	// otherwise do the statistics of emptyIsOK
              if (model->emptyIsOK) {
                numOfOK++;
                num++;
              }
              
              // And append the location to the 'emptyLoc' list
              [emptyX addFirst: (id) ((posX+i+model->citySize) % model->citySize)];
              [emptyY addFirst: (id) ((posY+j+model->citySize) % model->citySize)];
            }
          }
        }
          
      // Calculating the current ratio
      level = (float) numOfOK / (float) num;
      numOfEmpties = [emptyX getCount];

      // If we have to move and there is place to move to, let's move
      if ((level < limit) && (numOfEmpties > 0) ) {
      
        // If there is only 1 place, then we set it frankly
        if (numOfEmpties == 1)
          i = 0;
        else	// otherwise we select randomly
          i = [uniformIntRand getIntegerWithMin: 0 withMax: (numOfEmpties-1)];
          
        // Clear the current location, and set the new one
        [model->city putObject: nil atX: posX Y: posY];
        [self setX: (int) [emptyX atOffset: i]
                 Y: (int) [emptyY atOffset: i]
        ]; 
      }

      // Clear the lists
      [emptyX removeAll];
      [emptyY removeAll];
      [emptyX drop];      
      [emptyY drop];

      // Increment the age
      age++;
      
      // If its time to die, then do so.
      // (That is, create a new resident at a random location).
      if (age > maxAge) {
        [model->city putObject: nil atX: posX Y: posY];
        [model createNewResident: self];
      }
    }
}
----

ButtonReturn to Contents of this issue

© Copyright Journal of Artificial Societies and Social Simulation, 1999