//
//  DaggerGame.m
//  Gridlock
//
//  Created by Brian on Sun Feb 29 2004.
//  Copyright (c) 2004 __MyCompanyName__. All rights reserved.
//

#import "DaggerGame.h"


@implementation DaggerGame

-(void)reset {
  [super reset];
  [self createGridFromConfiguration];
}  

-(int)ownerOfPosition:(DCHypergridPosition *)pos {
  return abs([self valueAtPosition:pos]);  
}
-(int)ownerOfRow:(int)r column:(int)c {
  return abs([self valueAtRow:r column:c]);
}

-(BOOL)isCrownAtPosition:(DCHypergridPosition *)pos {
  return ([self valueAtPosition:pos]<0);
}
-(BOOL)isCrownAtRow:(int)r column:(int)c {
  return ([self valueAtRow:r column:c]<0);
}

-(int)numberOfDaggersForPlayer:(int)pnum {
  return [[self grid] numberOfCellsWithValue:pnum];
}
-(int)numberOfCrownsForPlayer:(int)pnum{
  return [[self grid] numberOfCellsWithValue:-pnum];  
}


-(BOOL)prepareMoveSequence:(NSArray *)positions {
  [self resetFutureGrid];
  [[self futureGrid] setValue:0 atPosition:[positions objectAtIndex:0]];
  [[self futureGrid] setValue:[self valueAtPosition:[positions objectAtIndex:0]] atPosition:[positions objectAtIndex:1]];
  return YES;
}

-(int)winningPlayer {
  return [self nextPlayerNumber];
}

-(void)appendValidDaggerMovesFromPosition:(DCHypergridPosition *)pos forPlayer:(int)pnum intoArray:(NSMutableArray *)moves {
  int r = [pos row];
  int c = [pos column];
  // check diagonally uphill
  if ([self isValidRow:r+1 column:c-1] && [self ownerOfRow:r+1 column:c-1]!=pnum) {
    [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r+1 column:c-1], nil]];
  }
  if ([self isValidRow:r+1 column:c+1] && [self ownerOfRow:r+1 column:c+1]!=pnum) {
    [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r+1 column:c+1], nil]];
  }
  // check directly uphill, can't capture daggers
  if ([self isValidRow:r+1 column:c]) {
    int owner = [self ownerOfRow:r+1 column:c];
    if (owner==0 || (owner!=pnum && [self isCrownAtRow:r+1 column:c])) {
      [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r+1 column:c], nil]];
    }
  }
  // check downhill
  int dc;
  int i;
  for(dc=-1; dc<=+1; dc++) {
    BOOL done = NO;
    for(i=1; !done; i++) {
      int endr = r-i;
      int endc = c+i*dc;
      if ([self isValidRow:endr column:endc]) {
        int owner = [self ownerOfRow:endr column:endc];
        if (owner==0) {
          [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:endr column:endc], nil]];
        }
        else {
          // we hit another piece, capture if we can
          if (owner!=pnum && (dc!=0 || [self isCrownAtRow:endr column:endc])) {
            [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:endr column:endc], nil]];
          }
          done = YES;
        }
      }
      else done = YES;
    }
  }
}

-(void)appendValidCrownMovesFromPosition:(id)pos forPlayer:(int)pnum intoArray:(NSMutableArray *)moves {
  NSEnumerator *pe = [[[self grid] neighborsOfPosition:pos distance:1] objectEnumerator];
  id npos;
  while ((npos=[pe nextObject])) {
    if ([self ownerOfPosition:npos]!=pnum) {
      [moves addObject:[NSArray arrayWithObjects:pos,npos,nil]];
    }
  }
}

-(NSArray *)allValidMoveSequences {
  int pnum = [self currentPlayerNumber];
  NSMutableArray *moves = [NSMutableArray array];
  NSEnumerator *posEnum = [[self grid] positionEnumerator];
  id position;
  while ((position=[posEnum nextObject])) {
    int value = [self valueAtPosition:position];
    if (value==pnum) {
      [self appendValidDaggerMovesFromPosition:position forPlayer:pnum intoArray:moves];
    }
    else if (value==-pnum) {
      [self appendValidCrownMovesFromPosition:position forPlayer:pnum intoArray:moves];
    }
  }
  if ([moves count]==0) [moves addObject:[NSArray array]];
  return moves;
}

-(int)playerWithCrownAtLastRow {
  int c;
  int maxr = [self numberOfRows]-1;
  for(c=[self numberOfColumns]-1; c>=0; c--) {
    if ([self valueAtRow:0 column:c]==-2) return 2;
    if ([self valueAtRow:maxr column:c]==-1) return 1;
  }
  return 0;
}

-(BOOL)isGameOver {
  return [self numberOfCrownsForPlayer:1]<2 || [self numberOfCrownsForPlayer:2]<2 || [self playerWithCrownAtLastRow]>0;
}

@end
