Codebase list gridlock.app / run/7a88808b-69aa-4130-a8f5-ec42250fed0a/main DiagonalsGame.m
run/7a88808b-69aa-4130-a8f5-ec42250fed0a/main

Tree @run/7a88808b-69aa-4130-a8f5-ec42250fed0a/main (Download .tar.gz)

DiagonalsGame.m @run/7a88808b-69aa-4130-a8f5-ec42250fed0a/mainraw · history · blame

//
//  DiagonalsGame.m
//  Gridlock
//
//  Created by Brian on Sat Jul 10 2004.
//  Copyright (c) 2004 __MyCompanyName__. All rights reserved.
//

#import "DiagonalsGame.h"


@implementation DiagonalsGame

idAccessor(preparedMove, setPreparedMove)

-(void)reset {
  [super reset];  
  [self setGrid:[DCHypergrid gridWithRows:[[[self configurationInfo] objectForKey:@"rows"] intValue]
                                  columns:[[[self configurationInfo] objectForKey:@"cols"] intValue]]];
  p1Score = p2Score = 0;
  [self setPreparedMove:nil];
}

-(BOOL)prepareMoveSequence:(NSArray *)positions {
  [self setPreparedMove:[positions lastObject]];
  return YES;
}  

-(NSArray *)positionsOfAllChangingCells {
  return [[self preparedMove] arrayWithSelf_];
}

-(int)futureValueAtPosition:(DCHypergridPosition *)pos {
  if ([pos isEqual:[self preparedMove]]) return [self currentPlayerNumber];
  else return [self valueAtPosition:pos];
}

-(int)scoreForDiagonalFromPosition:(id)pos northEast:(BOOL)ne {
  int score = 1; // count position moved to
  BOOL longerThan1 = NO; // corners don't count
  int pnum = [self valueAtPosition:pos];

  // go forward diagonally until we hit the edge or an empty cell
  int r = [pos row];
  int c = [pos column];
  int dc = ne ? 1 : -1;
  while ([self isValidRow:r+1 column:c+dc]) {
    int val = [self valueAtRow:r+1 column:c+dc];
    if (val==0) return 0; // not a full diagonal
    if (val==pnum) score++;
    longerThan1 = YES;
    r++; 
    c+=dc;
  }
  // repeat in opposite direction
  r = [pos row];
  c = [pos column];
  while ([self isValidRow:r-1 column:c-dc]) {
    int val = [self valueAtRow:r-1 column:c-dc];
    if (val==0) return 0; // not a full diagonal
    if (val==pnum) score++;
    longerThan1 = YES;
    r--; 
    c-=dc;
  }
  return (longerThan1) ? score : 0;
}

-(int)scoreForDiagonalsFromPosition:(id)pos {
  return [self scoreForDiagonalFromPosition:pos northEast:YES] + [self scoreForDiagonalFromPosition:pos northEast:NO];
}

-(void)updateFromPreparedMove {
  id pos = [self preparedMove];
  
  [super updateFromPreparedMove];
  // check for completed diagonals
  int score = [self scoreForDiagonalsFromPosition:pos];
  if ([self currentPlayerNumber]==1) {
    p1Score += score;
  }
  else {
    p2Score += score;
  }
}

-(NSArray *)allValidMoveSequences {
  return [[[self grid] allPositionsWithValue:0] valuesByObjectsPerformingSelector:@selector(arrayWithSelf_)];
}

-(BOOL)showScores {
  return YES;
}

-(int)scoreForPlayer:(int)pnum {
  return (pnum==1) ? p1Score : p2Score;
}

-(BOOL)isGameOver {
  return !([[self grid] hasCellWithValue:0]);
}

// these methods deal with the score ivars (since they can't be derived from the state of the board)
-(Game *)copy {
  DiagonalsGame *newGame = (DiagonalsGame *)[super copy];
  newGame->p1Score = p1Score;
  newGame->p2Score = p2Score;
  return newGame;
}

-(void)copyValuesToGame:(DiagonalsGame *)newGame {
  [super copyValuesToGame:newGame];
  newGame->p1Score = p1Score;
  newGame->p2Score = p2Score;
}

-(id)propertyList {
  id plist = [super propertyList];
  // assume mutable?
  [plist setObject:[[NSNumber numberWithInt:p1Score] stringValue] forKey:@"p1Score"];
  [plist setObject:[[NSNumber numberWithInt:p2Score] stringValue] forKey:@"p2Score"];
  return plist;
}

-(void)updateFromPropertyList:(id)plist {
  [super updateFromPropertyList:plist];
  p1Score = [[plist objectForKey:@"p1Score"] intValue];
  p2Score = [[plist objectForKey:@"p2Score"] intValue];
}

@end