Skip to content

Commit

Permalink
Refactored game interaction using player classes
Browse files Browse the repository at this point in the history
  • Loading branch information
kigster committed May 18, 2012
1 parent c988917 commit e61319b
Show file tree
Hide file tree
Showing 15 changed files with 224 additions and 180 deletions.
9 changes: 7 additions & 2 deletions Classes/AI/AlphaBetaPruner.m
Expand Up @@ -14,7 +14,7 @@ @implementation AlphaBetaPruner
@synthesize maxDepth;
@synthesize computerPlayer;

#define DEPTH 2
#define DEPTH 3

-(AlphaBetaPruner *)initWithBoard: (Board *) thisBoard {
populate_threat_matrix();
Expand All @@ -40,13 +40,18 @@ -(AlphaBetaPruner *)initWithBoard: (Board *) thisBoard
*/
-(MyBest *)chooseMove {
if (board.moveCount < 4) {
MyBest *best = [MyBest alloc];
if (board.moveCount == 0) {
best.move = [[Move alloc] initWithX:(board.size / 2) andY:(board.size / 2)];
return best;
}

int x, y;
pick_next_move(board.matrix,
board.size,
computerPlayer, // next move is by X
&x,
&y);
MyBest *best = [MyBest alloc];
best.move = [[Move alloc] initWithX:x andY:y];
return best;
}
Expand Down
22 changes: 22 additions & 0 deletions Classes/AIPlayer.h
@@ -0,0 +1,22 @@
//
// UIPlayer.h
// gomoku
//
// Created by Konstantin Gredeskoul on 5/3/10.
// Copyright 2010 Konstantin Gredeskoul, shared under MIT license. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Player.h"
#import "Game.h"
#import "Move.h"

@interface AIPlayer : NSObject <Player> {
Game *game;
}

-(AIPlayer *)initWithGame:(Game *)thisGame;

@property(nonatomic, strong) Game *game;

@end
43 changes: 43 additions & 0 deletions Classes/AIPlayer.m
@@ -0,0 +1,43 @@
//
// UIPlayer.m
// gomoku
//
// Created by Konstantin Gredeskoul on 5/3/10.
// Copyright 2010 Konstantin Gredeskoul, shared under MIT license. All rights reserved.
//

#import "AIPlayer.h"
#import "AlphaBetaPruner.h"
#import "MyBest.h"

@implementation AIPlayer

@synthesize game;

-(AIPlayer *)initWithGame:(Game *) thisGame {
if (self = [super init]) {
self.game = thisGame;
}
return self;
}

- (void) beginTurn {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
AlphaBetaPruner *ai = [[AlphaBetaPruner alloc] initWithBoard:self.game.board];
MyBest *myBest = [ai chooseMove];
if (myBest != nil) {
NSLog(@"AI made move [%@]", myBest);
dispatch_async(dispatch_get_main_queue(), ^{
[[self game] makeMove: myBest.move];
});
} else {
NSLog(@"AI failed and returned a nil move");
}
});

}




@end
6 changes: 3 additions & 3 deletions Classes/Game.h
Expand Up @@ -25,7 +25,7 @@
NSMutableArray *players;
NSMutableArray *moves;
NSMutableArray *redoMoves;
int currentPlayerIndex; // first player: 0, second player 1, etc.
int currentPlayerIndex; // first player: 0, second player 1, etc.
Board *board;
Config *config;
@private
Expand All @@ -43,13 +43,13 @@

- (Game *) initGameWithConfig: (Config *)config;
- (void) addPlayer:(id <Player>) player;
- (id<Player>) player:(int) index;
- (id<Player>) currentPlayer;
- (void) makeMove: (Move *) move;
- (MoveByPlayer *) lastMove;
- (NSMutableArray *) moveHistory;
- (void) undoLastMove;
- (BOOL) isMoveValid: (Move *) move;
- (void) startGame;
- (BOOL) startGame;
- (void) stopGame;
- (int) otherPlayerIndex;
- (void) advanceToNextPlayer ;
Expand Down
79 changes: 36 additions & 43 deletions Classes/Game.m
Expand Up @@ -6,7 +6,7 @@
//

#import "Game.h"
#import "UIPlayer.h"
#import "Player.h"
#import "basic_ai.h"


Expand Down Expand Up @@ -41,26 +41,23 @@ - (Game *) initGameWithConfig: (Config *)gameConfig {
- (void) addPlayer:(id <Player>) player{
if ([self.players count] < GOMOKU_PLAYERS) {
[self.players addObject:player];
} else {
NSLog(@"already have enough players!");
}
}
}

- (void) startGame {
- (BOOL) startGame {
if ([self.players count] != GOMOKU_PLAYERS) {
NSLog(@"not enough players added!");
return;
return NO;
}
self.gameStarted = YES;
NSLog(@"starting %@", self);
// call first player
id<Player> p = [self.players objectAtIndex:self.currentPlayerIndex];
[p beginTurn];
return YES;
}

- (id<Player>) player:(int) index {
if (index < [self.players count])
return [self.players objectAtIndex:index];
else
return nil;
- (id<Player>) currentPlayer {
return [self.players objectAtIndex:currentPlayerIndex];
}

- (MoveByPlayer *) lastMove {
Expand Down Expand Up @@ -102,40 +99,36 @@ - (void) undoLastMove {
}

- (void) makeMove: (Move *) move {
if (self.gameStarted != YES) {
NSLog(@"game is not started, can't make this move %@", move);
if (gameStarted == NO) {
NSLog(@"game not started yo");
return;
}

if ([self isMoveValid:move] == YES) {
[delegate aboutToMakeMove];
MoveByPlayer *playerMove;
if (![move isKindOfClass:[MoveByPlayer class]]) {
playerMove = [[MoveByPlayer alloc] initWithMove:move andPlayerIndex:currentPlayerIndex];
} else {
playerMove = (MoveByPlayer *) move;
playerMove.playerIndex = currentPlayerIndex;
}

// add move to the history
[[moves objectAtIndex:currentPlayerIndex] addObject:playerMove];

// update the game board state
[board makeMove:playerMove];

// change current player
[self advanceToNextPlayer];

// update the UI
[delegate didMakeMove];
if ([self isMoveValid:move] == NO) {
NSLog(@"move %@ is NOT valid, ignoring...", move);
return;
}

if ([board isGameOver]) {
[delegate gameOver];
self.gameStarted = NO;
}
} else {
NSLog(@"move %@ is NOT valid, ignored", move);
[delegate aboutToMakeMove];

MoveByPlayer *playerMove = [[MoveByPlayer alloc] initWithMove:move andPlayerIndex:currentPlayerIndex];
// add move to the history
[[moves objectAtIndex:currentPlayerIndex] addObject:playerMove];
// update the game board state
[board makeMove:playerMove];
// change current player
[self advanceToNextPlayer];
// update the UI
[delegate didMakeMove];

if ([board isGameOver]) {
[delegate gameOver];
self.gameStarted = NO;
return;
}

[[self currentPlayer] beginTurn];

return;
}

Expand All @@ -158,8 +151,8 @@ - (void) stopGame {

- (NSString *)description {
return [NSString stringWithFormat:@"game: player1:%@, player2:%@, board:%@",
[self player:0],
[self player:1],
[self.players objectAtIndex:0],
[self.players objectAtIndex:1],
self.board];
}

Expand Down
4 changes: 2 additions & 2 deletions Classes/UIPlayer.h → Classes/HumanPlayer.h
Expand Up @@ -10,11 +10,11 @@
#import "Player.h"
#import "Game.h"

@interface UIPlayer : NSObject <Player> {
@interface HumanPlayer : NSObject <Player> {
Game *game;
}

-(UIPlayer *)initWithGame:(Game *)thisGame;
-(HumanPlayer *)initWithGame:(Game *)thisGame;

@property(nonatomic, strong) Game *game;

Expand Down
21 changes: 21 additions & 0 deletions Classes/HumanPlayer.m
@@ -0,0 +1,21 @@

#import "HumanPlayer.h"

@implementation HumanPlayer

@synthesize game;

-(HumanPlayer *)initWithGame:(Game *) thisGame {
if (self = [super init]) {
self.game = thisGame;
}
return self;
}

- (void) beginTurn {
}




@end
7 changes: 2 additions & 5 deletions Classes/Player.h
Expand Up @@ -10,11 +10,8 @@
#import "Move.h"


@protocol Player
@protocol Player <NSObject>

- (void) startThinking;
- (void) stopThinking;
- (void) makeMove: (Move *) move;
- (void) game;
- (void) beginTurn;

@end
38 changes: 0 additions & 38 deletions Classes/UIPlayer.m

This file was deleted.

8 changes: 5 additions & 3 deletions Classes/controllers/GomokuViewController.h
Expand Up @@ -8,7 +8,10 @@
#import <UIKit/UIKit.h>
#import "GameBoardViewController.h"
#import "Game.h"
#import "MoveByPlayer.h"
#import "Move.h"
#import "Player.h"
#import "AIPlayer.h"
#import "HumanPlayer.h"

@interface GomokuViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate>{
GameBoardViewController* gameBoardController;
Expand All @@ -24,10 +27,9 @@
@property(strong, nonatomic) NSMutableArray *boardSizes;
@property(strong, nonatomic) IBOutlet UIPickerView *pickerView;

- (IBAction) startSinglePlayerGame:(id) sender;
- (IBAction) startTwoPlayerGame:(id) sender;
- (void) startGameWithPlayers: (int) playerCount;
- (void) makeMove: (MoveByPlayer *) move;
- (void) makeMove: (Move *) move;

@end

0 comments on commit e61319b

Please sign in to comment.