
#import "Opponent.h"
#import "random.h"
#import "RuleControl.h"
#import "RuleType.h"

@implementation Opponent

int type;

- init
{
  long t;
  int seed;

  type = 0; // no opponent
  
  time(&t);
  seed = (int) t; /* is time-based! */
  
  srandom(seed);
  
  return self;
}


- move:sender
{
  switch (type)
  {
    case 0:
      [self tactic_0];
      return self;
      break;
    case 1:
      [self tactic_1];
      return self;
      break;
    case 2:
      [self tactic_2];
      return self;
      break;
    case 3:
      [self tactic_3];
      return self;
      break;
  }
  return self;
}


- setType:sender
{
  char msg[128];
  type = [sender selectedRow];
  sprintf(msg, "Tactics type is now %d", type);
  [statusLine setStringValue:msg];
  
  return self;
}


- (int) minColor
{
  int i,x,y,istart;
  int n[5]; // color frequencies; include blue here
  int mincol, nmincol;
  Rule currRule;
  
  for (i=0; i<5; i++) 
    n[i] = 0;
  
  // count colors:  
  for (y=0; y<5; y++) // runs top-->down
  for (x=0; x<5; x++) // from left to right
  {
    currRule = [ruleControl ruleAt:x:y];
    n[currRule.leftColor]++;
    n[currRule.rightColor]++;
  }
  
  // search minimum:
  istart = 0;
  while(n[i] == 0) istart++; // don't use vanished colors
  mincol = istart;
  nmincol = n[mincol];
  for (i=istart; i<=3; i++) 
  if ((n[i] < nmincol) && (n[i] > 0))
  {
    nmincol = n[i];
    mincol = i;
  }
  
  return mincol;
}


- (int) maxColor
{
  int i,x,y,istart;
  int n[5]; // color frequencies; include blue here
  int maxcol, nmaxcol;
  Rule currRule;
  
  for (i=0; i<5; i++) 
    n[i] = 0;
  
  // count colors:  
  for (y=0; y<5; y++) // runs top-->down
  for (x=0; x<5; x++) // from left to right
  {
    currRule = [ruleControl ruleAt:x:y];
    n[currRule.leftColor]++;
    n[currRule.rightColor]++;
  }
  
  // search maximum:
  istart = 0;
  while(n[i] == 0) istart++; // don't use vanished colors
  maxcol = istart;
  nmaxcol = n[maxcol];
  for (i=istart; i<=3; i++) 
  if ((n[i] > nmaxcol))
  {
    nmaxcol = n[i];
    maxcol = i;
  }
  
  return maxcol;
}


- (int) ranColor
{
  return (int) floor(randomVal(0.0, 3.99999999999999)); 
}


// get a rule with the color col 
- (Rule) ruleWith:(int)color
{
  int x,y;
  Rule currRule;
    
  // seek exemplar:
  for (y=0; y<5; y++) // runs top-->down
  for (x=0; x<5; x++) // from left to right
  {
    currRule = [ruleControl ruleAt:x:y];
    if (currRule.leftColor == color)
      return currRule ;
    if (currRule.rightColor == color)
      return currRule ;
  }
  
  return currRule;
}


- tactic_0
{
  char msg[128];

  sprintf(msg, "Tactic %d did nothing.", type);
  [statusLine setStringValue:msg];
  
  return self;
}


// set random values:
- tactic_1 
{
  char msg[128];
  int rx, ry, rr, rc;
  Rule theRule;
  
  do {
    rx = (int) floor(randomVal(0.0, 4.99999999999999));
    ry = (int) floor(randomVal(0.0, 4.99999999999999));
  } while ((rx != 2) && (ry != 2));
  rr = (int) floor(randomVal(0.0, 1.99999999999999)); // right or left color?
   
  theRule = [ruleControl ruleAt:rx:ry];
  do { // change to an _other_ random color rc:
    rc = (int) floor(randomVal(0.0, 3.99999999999999));
  } while ((rc == theRule.leftColor) || (rc == theRule.rightColor));
   
  [ruleControl setRule:theRule];
  sprintf(msg, "rule [%d, %d] changed.", theRule.buttonX, theRule.buttonY);
  [statusLine setStringValue:msg];
  
  return self;
}


// decimate most abundant color:
- tactic_2
{
  char msg[128];
  int maxCol = [self maxColor];
  int randCol;
  Rule theRule = [self ruleWith:maxCol];
  
  if (theRule.leftColor == maxCol)
  {
    do { // change to an _other_ color:
      randCol = (int) floor(randomVal(0.0, 3.99999999999999));
    } while (randCol == theRule.leftColor);
    theRule.leftColor = randCol;
  }
  else
  {
    do { // change to an _other_ color:
      randCol = (int) floor(randomVal(0.0, 3.99999999999999));
    } while (randCol == theRule.rightColor);
    theRule.rightColor = randCol;
  }
  
  [ruleControl setRule:theRule];
  sprintf(msg, "rule [%d, %d] changed.", theRule.buttonX, theRule.buttonY);
  [statusLine setStringValue:msg];
  
  return self;
}


- tactic_3
{
  char msg[128];
  int minCol = [self minColor];
  int randCol;
  Rule theRule = [self ruleWith:minCol];
  
  if (theRule.leftColor == minCol)
  {
    do { // change to an _other_ color:
      randCol = (int) floor(randomVal(0.0, 3.99999999999999));
    } while (randCol == theRule.leftColor);
    theRule.leftColor = randCol;
  }
  else
  {
    do { // change to an _other_ color:
      randCol = (int) floor(randomVal(0.0, 3.99999999999999));
    } while (randCol == theRule.rightColor);
    theRule.rightColor = randCol;
  }
  
  [ruleControl setRule:theRule];
  sprintf(msg, "rule [%d, %d] changed.", theRule.buttonX, theRule.buttonY);
  [statusLine setStringValue:msg];
  
  return self;
}


@end
