#import "Mousetrap.h"

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

extern id  grid, worldSchedule;

extern unsigned  numTriggered;

@implementation Mousetrap

+ create: aZone setXCoord: (int)x setYCoord: (int)y
{
  Mousetrap  *newTrap;

  newTrap = [self create: aZone];
  newTrap->xCoord = x;
  newTrap->yCoord = y;
  return newTrap;
}

- (void) trigger
{
  int       n, xTrigger, yTrigger;
  unsigned  bits, xbits, ybits, tbits, currentTick, triggerTick;

  if ( ! triggered ) {

    currentTick = getCurrentTime();
    if ( printTriggerEvents ) {
      printf( "mousetrap at x: %.2d, y: %.2d triggered at time: %d\n",
              xCoord, yCoord, currentTick );
    }
    // nelson hacks
    // [displayWidget drawPointX: xCoord Y: yCoord Color: 2];
    numTriggered++;

    bits = rand();
    if ( ( ( bits & 0xff ) ) < triggerLikelihood ) {
      triggered = 1;

      for ( n = numberOutputTriggers; n > 0; n-- ) {
        bits = rand();
        xbits = bits & 0xff;
        ybits = bits >> 8 & 0xff;
        bits = rand();
        tbits = bits & 0xff;
        bits >>= 8;

	if ( bits & 1 ) {
	  xTrigger = ( xCoord + ( xbits & ( maxTriggerDistance - 1 ) ) )
                     % gridSize;
	} else {
	  xTrigger = ( xCoord - ( xbits & ( maxTriggerDistance - 1 ) )
                       + gridSize ) % gridSize;
	}
	if ( bits & 2 ) {
	  yTrigger = ( yCoord + ( ybits & (maxTriggerDistance - 1) ) )
                     % gridSize;
	} else {
	  yTrigger = ( yCoord - ( ybits & (maxTriggerDistance - 1) )
                       + gridSize ) % gridSize;
	}
        triggerTick = currentTick + ( tbits & (maxTriggerTime - 1) );

        if ( printSameTickTriggers && triggerTick == currentTick )
          printf( "triggering mousetrap at same timestep at time: %d\n",
                  currentTick );

	[worldSchedule at: triggerTick
          createActionTo: [grid atX: xTrigger atY: yTrigger]
          message: M( trigger )];
      }
    }
  }
}

- (int) getXCoord
{
  return xCoord;
}

- (int) getYCoord
{
  return yCoord;
}

- (BOOL) getTriggered
{
  return triggered;
}

- (void) printTriggered
{
  timeval_t  currentTime;

  currentTime = getCurrentTime();
  printf( "trigger status of mousetrap at x: %.2d, y: %.2d at time: %u is %d\n",
             xCoord, yCoord, currentTime, triggered );
}

/*
- setDisplayWidget: w {
  displayWidget = w;
}
*/

@end


@implementation Grid2D

+ create: aZone setGridSize: (int)size
{
  Grid2D  *newGrid;

  newGrid = [aZone allocIVars: self];
  newGrid->gridSize = size;
  newGrid->cells = [aZone allocBlock:
                      newGrid->gridSize * newGrid->gridSize * sizeof (id)];
  return newGrid;
}

- (int) getGridSize
{
  return gridSize;
}

- atX: (int)xCoord atY: (int)yCoord
{
  return cells[ xCoord + yCoord * gridSize];
}

- (void) atX: (int)xCoord atY: (int)yCoord put: anObject
{
  cells[ xCoord + yCoord * gridSize] = anObject;
}

@end
