#import "Mousetrap.h"
#import <activity/Activity.h>

#define __USE_FIXED_PROTOTYPES__   // for gcc headers
#include <stdio.h>


int gridSize              = 40;
int printTriggerEvents    = 1;
int printSameTickTriggers = 0;


// simulation parameters (these need to be a power of 2)

int triggerLikelihood    = 256;
int numberOutputTriggers = 2;
int maxTriggerDistance   = 4;
int maxTriggerTime       = 16;

// data from the mousetrap world

unsigned numTriggered = 0;

id grid, worldSchedule;

static void testTerminate( void )
{
  int  remainingCount;

  remainingCount = [worldSchedule getCount];
  if ( ! [worldSchedule getCount] ) [getTopLevelActivity() terminate];
}

int main(int argc, char ** argv)
{
  id   aZone, aMousetrap, subschedType, subgroup;
  id   displaySchedule, observerSwarm, observerActivity;
  id   worldSwarm, worldActivity;
  int  x, y, stepCount;

  initModule( activity );

  aZone = globalZone;

  // put a mousetrap on every grid point

  grid = [Grid2D create: aZone setGridSize: gridSize];
  for ( y = 0; y < gridSize; y ++ ) {
    for ( x = 0; x < gridSize; x++ ) {
      aMousetrap = [Mousetrap create: aZone setXCoord: x setYCoord: y];
      [grid atX: x atY: y put: aMousetrap];
    }
  }

  // create the mousetrap world schedule and schedule its first action

  subschedType = [Schedule customizeBegin: aZone];
  [subschedType setAutoDrop: 1];
  subschedType = [subschedType customizeEnd];

  worldSchedule = [Schedule createBegin: aZone];
  [worldSchedule setAutoDrop: 1];
  [worldSchedule setConcurrentGroupType: subschedType];
  worldSchedule = [worldSchedule createEnd];

  aMousetrap = [grid atX: gridSize/2 atY: gridSize/2];
  subgroup = [worldSchedule insertGroup: (id)0];
  [subgroup at: 0 createActionTo: aMousetrap message: M(trigger)];

  // create display schedule and schedule the display events

  displaySchedule = [Schedule createBegin: aZone];
  [displaySchedule setRepeatInterval: 1];
  displaySchedule = [displaySchedule createEnd];

  [displaySchedule at: 0 createActionTo:
    [grid atX: (gridSize + gridSize/2)/(gridSize/2) atY: gridSize/2]
    message: M(printTriggered)];
  [displaySchedule at: 0 createActionCall: (func_t)testTerminate];

  // create a swarm to combine the display schedule and the world swarm

  observerSwarm = [GenericSwarm create: aZone];
  observerActivity = [observerSwarm activateIn: nil];
  [displaySchedule activateIn: observerSwarm];

  worldSwarm = [GenericSwarm create: aZone];
  worldActivity = [worldSwarm activateIn: observerSwarm];
  subgroup = [worldSchedule activateIn: worldSwarm];

  // [observerActivity run];
  for ( stepCount = 0; [observerActivity step] == Stopped; stepCount++ );
  printf( "number of steps: %d\n", stepCount );
  printf( "total number of mousetraps triggered: %d\n", numTriggered );
  return 0;
}
