This is Board.m in view mode; [Download] [Up]
#include "comment.header"
/* $Id: Board.m,v 1.4 1997/11/04 16:49:20 ergo Exp $ */
/*
* $Log: Board.m,v $
* Revision 1.4 1997/11/04 16:49:20 ergo
* ported to OpenStep
*
* Revision 1.3 1997/07/06 19:37:55 ergo
* actual version
*
* Revision 1.5 1997/06/03 23:01:55 ergo
* *** empty log message ***
*
* Revision 1.4 1997/05/30 18:44:13 ergo
* Added an Inspector
*
* Revision 1.3 1997/05/04 18:56:50 ergo
* added time control for moves
*
*/
#import "Board.h"
#import "gnugo.h"
#include "igs.h"
#import <libc.h>
#import <math.h>
#import <sys/time.h>
#import <AppKit/psopsOpenStep.h> // PSxxx functions
#import <SoundKit/Sound.h>
#import <AppKit/AppKit.h>
#define EMPTY 0
#define WHITESTONE 1
#define BLACKSTONE 2
#define NEUTRAL_TERR 3
#define WHITE_TERR 4
#define BLACK_TERR 5
#define SPECIAL_CHAR 6
#define KOMI 5.5
// The following values are the default sizes for the various pieces.
#define RADIUS 14.5 // Stone radius
#define STONEWIDTH 29.0 // Stone width
#define STONEHEIGHT 29.0 // Stone height
// SHADOWOFFSET defines the amount the shadow is offset from the piece.
#define SHADOWOFFSET 2.0
#define BASEBOARDX 19.0
#define BASEBOARDY 19.0
#define WINDOWOFFSETX 12.0
#define WINDOWOFFSETY 12.0
#define PSLine(a, b, x, y) PSmoveto(a, b); PSlineto(x, y)
float stoneX, stoneY;
int blackStones, whiteStones;
char currentCharacter;
unsigned char oldBoard[19][19];
void setStoneLoc(int x, int y)
{
stoneX = ((19.0 - MAXX)/2.0)*STONEWIDTH + BASEBOARDX - RADIUS + (x*STONEWIDTH);
stoneY = BASEBOARDY - RADIUS + ((18 - y)*STONEHEIGHT) - ((19.0 - MAXY)/2.0)*STONEHEIGHT;
}
@implementation GoView
- initWithFrame:(NSRect)frm
{
NSSize stoneSize;
stoneSize.width = STONEWIDTH;
stoneSize.height = STONEHEIGHT;
te = 0;
startZeit = 0;
[super initWithFrame:frm];
[self allocateGState]; // For faster lock/unlockFocus
[(blackStone = [[NSImage allocWithZone:[self zone]] init]) setScalesWhenResized:NO];
[blackStone addRepresentation:[[[NSCustomImageRep alloc] initWithDrawSelector:@selector(drawBlackStone:) delegate:self] autorelease]];
[blackStone setSize:stoneSize];
[(whiteStone = [[NSImage allocWithZone:[self zone]] init]) setScalesWhenResized:NO];
[whiteStone addRepresentation:[[[NSCustomImageRep alloc] initWithDrawSelector:@selector(drawWhiteStone:) delegate:self] autorelease]];
[whiteStone setSize:stoneSize];
[(grayStone = [[NSImage allocWithZone:[self zone]] init]) setScalesWhenResized:NO];
[grayStone addRepresentation:[[[NSCustomImageRep alloc] initWithDrawSelector:@selector(drawGrayStone:) delegate:self] autorelease]];
[grayStone setSize:stoneSize];
[(upperLeft = [[NSImage allocWithZone:[self zone]] init]) setScalesWhenResized:NO];
[upperLeft addRepresentation:[[[NSCustomImageRep alloc] initWithDrawSelector:@selector(drawUpperLeft:) delegate:self] autorelease]];
[upperLeft setSize:stoneSize];
[(upperRight = [[NSImage allocWithZone:[self zone]] init]) setScalesWhenResized:NO];
[upperRight addRepresentation:[[[NSCustomImageRep alloc] initWithDrawSelector:@selector(drawUpperRight:) delegate:self] autorelease]];
[upperRight setSize:stoneSize];
[(lowerLeft = [[NSImage allocWithZone:[self zone]] init]) setScalesWhenResized:NO];
[lowerLeft addRepresentation:[[[NSCustomImageRep alloc] initWithDrawSelector:@selector(drawLowerLeft:) delegate:self] autorelease]];
[lowerLeft setSize:stoneSize];
[(lowerRight = [[NSImage allocWithZone:[self zone]] init]) setScalesWhenResized:NO];
[lowerRight addRepresentation:[[[NSCustomImageRep alloc] initWithDrawSelector:@selector(drawLowerRight:) delegate:self] autorelease]];
[lowerRight setSize:stoneSize];
[(midLeft = [[NSImage allocWithZone:[self zone]] init]) setScalesWhenResized:NO];
[midLeft addRepresentation:[[[NSCustomImageRep alloc] initWithDrawSelector:@selector(drawMidLeft:) delegate:self] autorelease]];
[midLeft setSize:stoneSize];
[(midRight = [[NSImage allocWithZone:[self zone]] init]) setScalesWhenResized:NO];
[midRight addRepresentation:[[[NSCustomImageRep alloc] initWithDrawSelector:@selector(drawMidRight:) delegate:self] autorelease]];
[midRight setSize:stoneSize];
[(midTop = [[NSImage allocWithZone:[self zone]] init]) setScalesWhenResized:NO];
[midTop addRepresentation:[[[NSCustomImageRep alloc] initWithDrawSelector:@selector(drawMidTop:) delegate:self] autorelease]];
[midTop setSize:stoneSize];
[(midBottom = [[NSImage allocWithZone:[self zone]] init]) setScalesWhenResized:NO];
[midBottom addRepresentation:[[[NSCustomImageRep alloc] initWithDrawSelector:@selector(drawMidBottom:) delegate:self] autorelease]];
[midBottom setSize:stoneSize];
[(innerSquare = [[NSImage allocWithZone:[self zone]] init]) setScalesWhenResized:NO];
[innerSquare addRepresentation:[[[NSCustomImageRep alloc] initWithDrawSelector:@selector(drawInnerSquare:) delegate:self] autorelease]];
[innerSquare setSize:stoneSize];
[(innerHandicap = [[NSImage allocWithZone:[self zone]] init]) setScalesWhenResized:NO];
[innerHandicap addRepresentation:[[[NSCustomImageRep alloc] initWithDrawSelector:@selector(drawInnerHandicap:) delegate:self] autorelease]];
[innerHandicap setSize:stoneSize];
[self setBackgroundFile:[[[NSUserDefaults standardUserDefaults] objectForKey:@"BackGround"] cString]
andRemember:NO];
[self startNewGame];
historyFont = [ [NSFont fontWithName:@"Helvetica" size:9.0] retain];
blackTerrFont = [ [NSFont fontWithName:@"Helvetica" size:25.0] retain];
whiteTerrFont = [ [NSFont fontWithName:@"Helvetica" size:22.5] retain];
#warning
stoneClick = [Sound findSoundFor:@"Pop"];
{
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
time = tp.tv_sec;
}
return self;
}
// free simply gets rid of everything we created for MainGoView, including
// the instance of MainGoView itself. This is how nice objects clean up.
- (void)dealloc {
[backGround release];
{ [super dealloc]; return; };
}
// This methods allows changing the file used to paint the background of the
// playing field. Set fileName to NULL to revert to the default. Set
// remember to YES if you wish the write the value out in the defaults.
- setBackgroundFile:(const char *)fileName andRemember:(BOOL)remember {
[backGround release];
if (fileName) {
backGround = [NSImage alloc];
[backGround initWithContentsOfFile:[NSString stringWithCString:fileName]];
[backGround setSize:[self bounds].size];
if (remember)
[[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithCString:fileName] forKey:@"Background"];
} else {
backGround = [ [NSImage imageNamed:@"Background.tiff"] retain];
[backGround setSize:[self bounds].size];
if (remember)
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"Background"];
}
[backGround setBackgroundColor:[NSColor whiteColor]];
[backGround setScalesWhenResized:NO];
[self display];
return self;
}
// The following two methods allow changing the background image from
// menu items or buttons.
- changeBackground:sender {
NSString *fileType1 = @"tiff",
*fileType2 = @"eps";
id fileTypes = [NSArray arrayWithObjects:fileType1, fileType2, nil];
if ([[NSOpenPanel new] runModalForTypes:fileTypes]) {
[self setBackgroundFile:[[[NSOpenPanel new] filename] cString] andRemember:YES];
[self display];
}
return self;
}
- revertBackground:sender
{
[self setBackgroundFile:NULL andRemember:YES];
[self display];
return self;
}
- resetButtons
{
if (SmartGoGameFlag)
{
[startButton setEnabled:NO];
[stopButton setEnabled:NO];
[passButton setEnabled:NO];
return self;
}
if (bothSides)
[passButton setEnabled:NO];
else
[passButton setEnabled:YES];
if (neitherSide)
{
[startButton setEnabled:NO];
[stopButton setEnabled:NO];
}
else
{
[startButton setEnabled:YES];
[stopButton setEnabled:YES];
}
return self;
}
// The following method will initialize all the variables for a new game.
- startNewGame {
int i, j;
gameRunning = NO;
finished = NO;
gameScored = NO;
resultsDisplayed = NO;
scoringGame = NO;
lastMove = 0;
blackCaptured = whiteCaptured = 0;
manualScoring = manScoreTemp;
seed(&rd);
for (i = 0; i < MAXX; i++)
for (j = 0; j < MAXY; j++)
oldBoard[i][j] = p[i][j] = hist[i][j] = 0;
for (i = 0; i < 9; i++)
opn[i] = 1;
opn[4] = 0;
if (gameType == LOCAL) {
sethand(handicap);
currentStone = (handicap == 0)?BLACKSTONE:WHITESTONE;
opposingStone = (currentStone == BLACKSTONE)?WHITESTONE:BLACKSTONE;
if (currentStone == BLACKSTONE)
[gameMessage setStringValue:@"Black's Turn"];
else
[gameMessage setStringValue:@"White's Turn"];
[self resetButtons];
if (((currentStone == BLACKSTONE) && blackSide) ||
((currentStone == WHITESTONE) && whiteSide))
[gameMessage2 setStringValue:@"Press START to begin..."];
else
[gameMessage2 setStringValue:@"You move first..."];
}
else {
[gameMessage2 setStringValue:@"Internet Go Server"];
[gameMessage setStringValue:@""];
[self setblacksPrisoners:0];
[self setwhitesPrisoners:0];
[passButton setEnabled:YES];
[startButton setEnabled:NO];
[stopButton setEnabled:NO];
[self removeTE];
{
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
time = tp.tv_sec;
}
}
[ScoringWindow close];
PSWait();
return self;
}
// The stop method will pause a running game. The go method will start it up
// again.
- go:sender
{
if (gameType == IGSGAME)
return self;
if ((scoringGame) && (manualScoring))
{
int i, j;
find_owner();
blackTerritory = 0;
whiteTerritory = 0;
for (i = 0; i < MAXX; i++)
for (j = 0; j < MAXY; j++)
{
if (ownermat[i][j] == BLACKSTONE)
{
blackTerritory++;
p[i][j] = BLACK_TERR;
}
if (ownermat[i][j] == WHITESTONE)
{
whiteTerritory++;
p[i][j] = WHITE_TERR;
}
if (ownermat[i][j] == NEUTRAL_TERR)
{
p[i][j] = NEUTRAL_TERR;
}
}
gameScored = YES;
[self displayScoringInfo];
PSWait();
}
if ((gameRunning == 0) && (finished == 0)) {
gameRunning = YES;
[self step];
}
return 0;
}
- (void)stop:(id)sender {
if (gameType == IGSGAME)
return;
if (gameRunning)
gameRunning = NO;
}
- showLastMove:sender
{
int i;
if (SmartGoGameFlag)
return self;
if (finished)
{
NSRunAlertPanel(@"NeXTGo", @"The game has concluded. The last move was\n\
the scoring.", @"OK", nil, nil);
return self;
}
if (lastMove == 0)
{
NSRunAlertPanel(@"NeXTGo", @"The game has not yet started.", @"OK", nil, nil);
return self;
}
for (i = 0; i < gameMoves[lastMove-1].numchanges; i++)
{
if (gameMoves[lastMove-1].changes[i].x < 0)
{
NSRunAlertPanel(@"NeXTGo", @"The last move was a pass.", @"OK", nil, nil);
return self;
}
}
[self lockFocus];
for (i = 0; i < gameMoves[lastMove-1].numchanges; i++)
{
if (gameMoves[lastMove-1].changes[i].added)
{
setStoneLoc(gameMoves[lastMove-1].changes[i].x,
gameMoves[lastMove-1].changes[i].y);
[self showGrayStone];
}
}
[self unlockFocus];
PSWait();
[self lockFocus];
[[self window] flushWindow];
[self drawRect:[self bounds]];
[self display];
[self unlockFocus];
PSWait();
return self;
}
- undo
{
int i, j, x, y;
if (finished)
return self;
if (lastMove == 1)
{
[self startNewGame];
[self display];
return self;
}
if (lastMove > 0)
{
lastMove--;
for (i = 0; i < MAXX; i++)
for (j = 0; j < MAXY; j++)
p[i][j] = oldBoard[i][j];
blackCaptured = gameMoves[lastMove].blackCaptured;
whiteCaptured = gameMoves[lastMove].whiteCaptured;
for (i = 0; i < gameMoves[lastMove-1].numchanges; i++)
{
x = gameMoves[lastMove-1].changes[i].x;
y = gameMoves[lastMove-1].changes[i].y;
if (gameMoves[lastMove-1].changes[i].added)
{
oldBoard[x][y] = EMPTY;
}
else
{
oldBoard[x][y] = gameMoves[lastMove-1].changes[i].color;
}
}
[self refreshIO];
currentStone = opposingStone;
opposingStone = (currentStone == BLACKSTONE)?WHITESTONE:BLACKSTONE;
if (gameType == LOCAL)
{
[gameMessage setStringValue:(currentStone == BLACKSTONE) ? @"Black's Turn" : @"White's Turn"];
if ((bothSides) || (((currentStone == BLACKSTONE) && (blackSide)) ||
((currentStone == WHITESTONE) && (whiteSide))))
{
[gameMessage2 setStringValue:@"Press START to continue..."];
gameRunning = 0;
}
else
[gameMessage2 setStringValue:@"Your move..."];
}
}
return self;
}
- undoLastMove:sender {
if (SmartGoGameFlag)
return self;
if (gameType == LOCAL) {
[self undo];
}
else {
sendstr("undo\n");
}
return self;
}
- toggleShowHistFlag:sender {
[self lockFocus];
[self display];
[self unlockFocus];
return self;
}
- toggleSound:sender {
return self;
}
- doClick {
if ([playSounds intValue])
[stoneClick play];
PSWait();
return self;
}
- toggleCoords:sender {
[self lockFocus];
[self display];
[self unlockFocus];
return self;
}
- (void)mouseDown:(NSEvent *)event
{
NSPoint pickedP;
if (gameType == LOCAL) {
if ((((currentStone == BLACKSTONE) && blackSide) ||
((currentStone == WHITESTONE) && whiteSide)) &&
(!scoringGame) && (!manualScoring))
return;
if (SmartGoGameFlag)
return;
if ((!gameRunning) && (!finished))
gameRunning = YES;
if (!finished) {
int i, j, x, y;
pickedP = [event locationInWindow];
x = floor((pickedP.x - ((19.0 - MAXX)/2.0)*STONEWIDTH - BASEBOARDX
- WINDOWOFFSETX + RADIUS)/STONEWIDTH);
y = 18 - floor((pickedP.y - BASEBOARDY - WINDOWOFFSETY + RADIUS +
((19.0 - MAXY)/2.0)*STONEHEIGHT)/STONEHEIGHT);
if (x < 0) x = 0;
if (x > MAXX - 1) x = MAXX - 1;
if (y < 0) y = 0;
if (y > MAXY - 1) y = MAXY - 1;
if ((p[x][y] == 0) && (!suicide(x,y))) {
for (i = 0; i < MAXX; i++)
for (j = 0; j < MAXY; j++)
oldBoard[i][j] = p[i][j];
p[x][y] = currentStone;
if (currentStone == BLACKSTONE)
blackPassed = 0;
else
whitePassed = 0;
setStoneLoc(x,y);
[self lockFocus];
switch (p[x][y]) {
case WHITESTONE:
[self showWhiteStone];
break;
case BLACKSTONE:
[self showBlackStone];
break;
default:
break;
}
[self unlockFocus];
// commented out because of double clicks [self doClick];
[self updateInfo];
[self addMoveToGameMoves: currentStone: x: y];
if ([showHistFlag intValue]) {
NSRect tmpRect = {{floor(stoneX), floor(stoneY)},
{floor(STONEWIDTH), floor(STONEHEIGHT)}};
[self lockFocus];
[self drawRect:tmpRect];
[self unlockFocus];
}
if (!neitherSide)
[self step];
[self setNeedsDisplay:YES];
}
}
else {
if ((scoringGame) && (manualScoring) && (!gameScored)) {
int x, y;
pickedP = [event locationInWindow];
x = floor((pickedP.x - ((19.0 - MAXX)/2.0)*STONEWIDTH - BASEBOARDX
- WINDOWOFFSETX + RADIUS)/STONEWIDTH);
y = 18 - floor((pickedP.y - BASEBOARDY - WINDOWOFFSETY + RADIUS +
((19.0 - MAXY)/2.0)*STONEHEIGHT)/STONEHEIGHT);
if (x < 0) x = 0;
if (x > MAXX - 1) x = MAXX - 1;
if (y < 0) y = 0;
if (y > MAXY - 1) y = MAXY - 1;
if (p[x][y] != EMPTY) {
int k, l;
currentStone = p[x][y];
find_pattern_in_board(x, y);
for (k = 0; k < MAXX; k++)
for (l = 0; l < MAXY; l++)
if (patternmat[k][l]) {
p[k][l] = EMPTY;
if (currentStone == BLACKSTONE)
blackCaptured++;
else
whiteCaptured++;
}
[self setblacksPrisoners:blackCaptured];
[self setwhitesPrisoners:whiteCaptured];
[self setNeedsDisplay:YES];
}
}
}
}
else {
int x, y;
char s[50], n[50];
extern int observing, ingame;
if (observing || (ingame == -1)) {
NSRunAlertPanel(@"IGS Error", @"You cannot make a move unless you are playing.", @"OK", nil, nil); return;
}
pickedP = [event locationInWindow];
x = floor((pickedP.x - ((19.0 - MAXX)/2.0)*STONEWIDTH - BASEBOARDX -
WINDOWOFFSETX + RADIUS)/STONEWIDTH);
y = 18 - floor((pickedP.y - BASEBOARDY - WINDOWOFFSETY + RADIUS +
((19.0 - MAXY)/2.0)*STONEHEIGHT)/STONEHEIGHT);
if (x < 0) x = 0;
if (x > MAXX - 1)
x = MAXX - 1;
if (y < 0) y = 0;
if (y > MAXY - 1)
y = MAXY - 1;
s[0] = x + 'a';
if (x > 7)
s[0] = x + 'b';
s[1] = 0;
sprintf(n, "%d", MAXY-y);
strcat(s, n);
{
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
time = tp.tv_sec - time;
}
sprintf(n, " %d", ingame);
strcat(s, n);
sprintf(n, " %ld", time);
strcat(s, n);
strcat(s, "\n");
sendstr(s);
}
}
- passMove {
if (gameType == LOCAL) {
if (((currentStone == BLACKSTONE) && blackSide) ||
((currentStone == WHITESTONE) && whiteSide)) {
return self;
}
if (currentStone == BLACKSTONE) {
blackPassed = 1;
if (AGAScoring) blackCaptured++;
}
else {
whitePassed = 1;
if (AGAScoring) whiteCaptured++;
}
[self updateInfo];
[self addMoveToGameMoves: currentStone: -1: -1];
if ((!neitherSide) && (!finished))
[self step];
}
else {
sendstr("pass\n");
}
return self;
}
- refreshIO {
[self setblacksPrisoners:blackCaptured];
[self setwhitesPrisoners:whiteCaptured];
[self lockFocus];
[[self window] flushWindow];
[self drawRect:[self bounds]];
[self display];
[self unlockFocus];
PSWait();
return self;
}
- addMoveToGameMoves: (int)color: (int)x: (int)y {
int i, j, k, numchanges;
numchanges = 0;
for (i = 0; i < MAXX; i++)
for (j = 0; j < MAXY; j++)
if (p[i][j] != oldBoard[i][j])
numchanges++;
if (x < 0 || y < 0)
numchanges++;
gameMoves[lastMove].numchanges = numchanges;
gameMoves[lastMove].changes = (struct change *)
malloc((size_t)sizeof(struct change)*numchanges);
k = 0;
if (x < 0 || y < 0) {
gameMoves[lastMove].changes[0].added = NO;
gameMoves[lastMove].changes[0].x = x;
gameMoves[lastMove].changes[0].y = y;
gameMoves[lastMove].changes[0].color = color;
k++;
}
for (i = 0; i < MAXX; i++)
for (j = 0; j < MAXY; j++)
if (p[i][j] != oldBoard[i][j]) {
gameMoves[lastMove].changes[k].x = i;
gameMoves[lastMove].changes[k].y = j;
if (p[i][j] != EMPTY) {
gameMoves[lastMove].changes[k].added = YES;
gameMoves[lastMove].changes[k].color = p[i][j];
}
else {
gameMoves[lastMove].changes[k].added = NO;
gameMoves[lastMove].changes[k].color = oldBoard[i][j];
}
k++;
}
gameMoves[lastMove].blackCaptured = blackCaptured;
gameMoves[lastMove].whiteCaptured = whiteCaptured;
lastMove++;
if (x >= 0)
hist[x][y] = lastMove;
return self;
}
- makeMove: (int)color: (int)x: (int)y {
int oldwhitesPrisoners, oldblacksPrisoners, i, j;
currentStone = color;
opposingStone = (currentStone == BLACKSTONE)?WHITESTONE:BLACKSTONE;
if ((x >= 0) && (y >= 0)) {
for (i = 0; i < MAXX; i++)
for (j = 0; j < MAXX; j++)
oldBoard[i][j] = p[i][j];
p[x][y] = color;
setStoneLoc(x,y);
[self lockFocus];
switch (p[x][y]) {
case WHITESTONE:
[self showWhiteStone];
break;
case BLACKSTONE:
[self showBlackStone];
break;
default:
break;
}
[self unlockFocus];
oldblacksPrisoners = blackCaptured;
oldwhitesPrisoners = whiteCaptured;
examboard(opposingStone);
[self setblacksPrisoners:blackCaptured];
[self setwhitesPrisoners:whiteCaptured];
if (((oldblacksPrisoners != blackCaptured) ||
(oldwhitesPrisoners != whiteCaptured))) {
[self lockFocus];
[self display];
[self unlockFocus];
}
if ([showHistFlag intValue]) {
NSRect tmpRect = {{floor(stoneX), floor(stoneY)},
{floor(STONEWIDTH), floor(STONEHEIGHT)}};
[self lockFocus];
[self drawRect:tmpRect];
[self display];
[self unlockFocus];
}
if (blackPassed) {
blackPassed = 0;
[gameMessage2 setStringValue:@""];
}
if (whitePassed) {
whitePassed = 0;
[gameMessage2 setStringValue:@""];
}
}
[self addMoveToGameMoves: color: x: y];
[gameMessage setStringValue:(opposingStone == BLACKSTONE) ? @"Black's Turn" : @"White's Turn"];
if ((-1 == x) && (-1 == y)) { /* opponent has passed */
if (currentStone == BLACKSTONE) {
blackPassed = 1;
[gameMessage2 setStringValue:@"Black has passed."];
}
else {
whitePassed = 1;
[gameMessage2 setStringValue:@"White has passed."];
}
}
{
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
time = tp.tv_sec;
}
[self doClick];
[self setNeedsDisplay:YES];
return self;
}
- makeMoveSilent: (int)color: (int)x: (int)y
{
int i, j;
if ((x >= 0) && (y >= 0))
{
for (i = 0; i < MAXX; i++)
for (j = 0; j < MAXY; j++)
oldBoard[i][j] = p[i][j];
p[x][y] = color;
currentStone = color;
opposingStone = (currentStone == BLACKSTONE)?WHITESTONE:BLACKSTONE;
examboard(opposingStone);
[self addMoveToGameMoves: color: x: y];
}
return self;
}
- setTimeAndByo: (int)btime: (int)bbyo: (int)wtime: (int)wbyo {
#ifdef DEBUG
printf("setTimeAndByo: BlackTime = %d, BlackByo = %d, WhitTime = %d, Whitebyo = %d\n", btime, bbyo, wtime, wbyo);
#endif
if (bTime != -1) {
if (bTime < 0)
bTime = 0;
if (wTime < 0)
wTime = 0;
[self removeTE];
startZeit = 0;
if (currentStone == WHITESTONE) { /* Black moved */
ts.byo = bbyo;
ts.time = btime;
ts.timeToHandle = blackTime;
}
else { /* White moved */
ts.byo = wbyo;
ts.time = wtime;
ts.timeToHandle = whiteTime;
}
te = [[NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(TEHandler:) userInfo:self repeats:YES] retain];
bTime = btime;
bByo = bbyo;
wTime = wtime;
wByo = wbyo;
}
return self;
}
- dispTime
{
char bltime[25], whtime[25];
sprintf(bltime, "%d:%02d", bTime / 60, bTime % 60);
if (bByo != -1)
sprintf(bltime, "%s, %d", bltime, bByo);
sprintf(whtime, "%d:%02d", wTime / 60, wTime % 60);
if (wByo != -1)
sprintf(whtime, "%s, %d", whtime, wByo);
[blackTime setStringValue:[NSString stringWithCString:bltime]];
[blackTime display];
[whiteTime setStringValue:[NSString stringWithCString:whtime]];
[whiteTime display];
return self;
}
- setGameNumber: (int)n
{
[IGSGameNumber setIntValue:n];
[IGSGameNumber display];
return self;
}
- updateTitle {
id buf = [ NSString stringWithString:[IGSBlackPlayer stringValue]];
buf = [buf stringByAppendingString:[NSString stringWithString:@" - "] ];
buf = [buf stringByAppendingString:[IGSWhitePlayer stringValue]];
[[self window] setTitle:buf];
return self;
}
- setWhiteName: (char *)wname {
[IGSWhitePlayer setStringValue:[NSString stringWithCString:wname]];
[IGSWhitePlayer display];
[self updateTitle];
return self;
}
- setBlackName: (char *)bname {
[IGSBlackPlayer setStringValue:[NSString stringWithCString:bname]];
[IGSBlackPlayer display];
[self updateTitle];
return self;
}
- setIGSHandicap: (int)h
{
[IGShandicap setIntValue:h];
[IGShandicap display];
return self;
}
- setIGSKomi: (char *)k
{
[IGSkomi setStringValue:[NSString stringWithCString:k]];
[IGSkomi display];
return self;
}
- setByoTime: (int)aByoTime {
ByoTime = aByoTime;
return self;
}
- (int) ByoTime {
return ByoTime;
}
- updateInfo {
int oldblacksPrisoners, oldwhitesPrisoners, i, j;
if (finished && gameScored && resultsDisplayed) {
[startButton setEnabled:NO];
[stopButton setEnabled:NO];
[passButton setEnabled:NO];
return self;
}
oldblacksPrisoners = blackCaptured;
oldwhitesPrisoners = whiteCaptured;
examboard(opposingStone);
if (currentStone == BLACKSTONE) {
opposingStone = BLACKSTONE;
currentStone = WHITESTONE;
[gameMessage setStringValue:@"White's Turn"];
}
else {
opposingStone = WHITESTONE;
currentStone = BLACKSTONE;
[gameMessage setStringValue:@"Black's Turn"];
}
[self setblacksPrisoners:blackCaptured];
[self setwhitesPrisoners:whiteCaptured];
if (((oldblacksPrisoners != blackCaptured) ||
(oldwhitesPrisoners != whiteCaptured))) {
[self lockFocus];
for (i = 0; i < MAXX; i++)
for (j = 0; j < MAXX; j++)
if ((oldBoard[i][j] != EMPTY) && (p[i][j] == EMPTY)) {
setStoneLoc(i, j);
[self eraseStone];
[self showBackgroundPiece: i: j];
}
[self unlockFocus];
}
if ([showHistFlag intValue]) {
NSRect tmpRect = {{floor(stoneX), floor(stoneY)},
{floor(STONEWIDTH), floor(STONEHEIGHT)}};
[self lockFocus];
[self drawRect:tmpRect];
[self display];
[self unlockFocus];
}
if ((blackPassed) && (opposingStone == BLACKSTONE))
[gameMessage2 setStringValue:@"Black has passed."];
if ((whitePassed) && (opposingStone == WHITESTONE))
[gameMessage2 setStringValue:@"White has passed."];
if ((!blackPassed) && (!whitePassed))
[gameMessage2 setStringValue:@""];
if ((blackPassed) && (whitePassed) && (!manualScoring) && (!gameScored)) {
[self lockFocus];
[[self window] flushWindow];
[gameMessage setStringValue:@"Scoring Game, Please Wait"];
[gameMessage2 setStringValue:@"Removing Dead Groups..."];
[self display];
[self unlockFocus];
finished = 1;
score_game();
// [self scoreGame];
manualScoring = 1;
}
if ((blackPassed) && (whitePassed) && (manualScoring) && (!gameScored)) {
[self lockFocus];
[[self window] flushWindow];
[gameMessage setStringValue:@"Please remove dead groups"];
[gameMessage2 setStringValue:@"When finished, press Start..."];
[self display];
[self unlockFocus];
[passButton setEnabled:NO];
[stopButton setEnabled:NO];
finished = 1;
scoringGame = YES;
}
return self;
}
- displayScoringInfo
{
char s[35];
int i, j;
if (gameScored)
{
resultsDisplayed = YES;
if (typeOfScoring == 0)
{
black_Score = (float)blackTerritory - (float)blackCaptured;
white_Score = (float)whiteTerritory - (float)whiteCaptured;
white_Score += (handicap == 0)?KOMI:0.5;
[TypeOfScoring setStringValue:@"Japanese Scoring Method"];
[BlackTerrString setStringValue:@"Territory"];
[WhiteTerrString setStringValue:@"Territory"];
[BlackTerrValue setIntValue:blackTerritory];
[WhiteTerrValue setIntValue:whiteTerritory];
[BlackPrisonString setStringValue:@"Prisoners"];
[WhitePrisonString setStringValue:@"Prisoners"];
[BlackPrisonValue setIntValue:blackCaptured];
[WhitePrisonValue setIntValue:whiteCaptured];
[BlackTotalValue setFloatValue:black_Score];
[WhiteTotalValue setFloatValue:white_Score];
}
else
{
blackStones = whiteStones = 0;
for (i = 0; i < MAXX; i++)
for (j = 0; j < MAXY; j++)
{
if (p[i][j] == BLACKSTONE) blackStones++;
if (p[i][j] == WHITESTONE) whiteStones++;
}
black_Score = (float)blackTerritory + (float)blackStones;
white_Score = (float)whiteTerritory + (float)whiteStones;
white_Score += (handicap == 0)?KOMI:0.5;
[TypeOfScoring setStringValue:@"Chinese Scoring Method"];
[BlackTerrString setStringValue:@"Territory"];
[WhiteTerrString setStringValue:@"Territory"];
[BlackTerrValue setIntValue:blackTerritory];
[WhiteTerrValue setIntValue:whiteTerritory];
[BlackPrisonString setStringValue:@"Stones"];
[WhitePrisonString setStringValue:@"Stones"];
[BlackPrisonValue setIntValue:blackStones];
[WhitePrisonValue setIntValue:whiteStones];
[BlackTotalValue setFloatValue:black_Score];
[WhiteTotalValue setFloatValue:white_Score];
}
if (black_Score > white_Score)
sprintf(s, "Result: Black wins by %3.1f points.", black_Score - white_Score);
if (white_Score > black_Score)
sprintf(s, "Result: White wins by %3.1f points.", white_Score - black_Score);
if (black_Score == white_Score)
sprintf(s, "Result: The game was a tie.");
[KomiValue setFloatValue:((handicap == 0)?KOMI:0.5)];
[GameResult setStringValue:[NSString stringWithCString:s]];
[ScoringWindow makeKeyAndOrderFront:self];
[gameMessage setStringValue:@"Game Over"];
[self lockFocus];
[self display];
[self unlockFocus];
}
return self;
}
- scoreGame
{
int i, j, k, l, changes = 1, num_in_pattern;
for (i = 0; i < MAXX; i++)
for (j = 0; j < MAXY; j++)
scoringmat[i][j] = 0;
while (changes)
{
changes = 0;
find_owner();
for (i = 0; i < MAXX; i++)
for (j = 0; j < MAXY; j++)
if ((p[i][j] != 0) && (scoringmat[i][j] == 0))
{
if (surrounds_territory(i, j))
{
find_pattern_in_board(i, j);
for (k = 0; k < MAXX; k++)
for (l = 0; l < MAXY; l++)
if (patternmat[k][l])
scoringmat[k][l] = p[k][l];
}
else
{
find_pattern_in_board(i, j);
set_temp_to_p();
num_in_pattern = 0;
for (k = 0; k < MAXX; k++)
for (l = 0; l < MAXY; l++)
if (patternmat[k][l])
{
p[k][l] = EMPTY;
[self flashStone:k:l];
num_in_pattern++;
}
find_owner();
if ((ownermat[i][j] != NEUTRAL_TERR) &&
(ownermat[i][j] != tempmat[i][j]))
{
if (tempmat[i][j] == BLACKSTONE)
blackCaptured += num_in_pattern;
else
whiteCaptured += num_in_pattern;
changes++;
[self lockFocus];
[self display];
[self unlockFocus];
}
else
{
set_p_to_temp();
find_owner();
}
}
}
}
/* blackTerritory = 0;
whiteTerritory = 0;
[self lockFocus];
for (i = 0; i < MAXX; i++)
for (j = 0; j < MAXY; j++)
{
if (ownermat[i][j] == BLACKSTONE)
{
blackTerritory++;
p[i][j] = BLACK_TERR;
}
if (ownermat[i][j] == WHITESTONE)
{
whiteTerritory++;
p[i][j] = WHITE_TERR;
}
if (ownermat[i][j] == NEUTRAL_TERR)
{
[self flashStone:i:j];
p[i][j] = NEUTRAL_TERR;
}
}
[self unlockFocus]; */
return self;
}
// The following methods draw the pieces.
- drawBlackStone:imageRep
{
// PSscale (1.0, 1.0);
// First draw the shadow under the stone.
// PSarc (RADIUS+SHADOWOFFSET/2, RADIUS-SHADOWOFFSET/2,
// RADIUS-SHADOWOFFSET, 0.0, 360.0);
// PSsetgray (NX_DKGRAY);
// if (NXDrawingStatus == NX_DRAWING) {
// PSsetalpha (0.666);
// }
// PSfill ();
if ([[NSDPSContext currentContext] isDrawingToScreen]) {
PSsetalpha (1.0);
}
// Draw the stone.
PSarc (RADIUS, RADIUS,
RADIUS, 0.0, 360.0);
PSsetgray (NSBlack);
PSfill ();
// And the lighter & darker spots on the stone...
PSarcn (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-3.0, 170.0, 100.0);
PSarc (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-2.0, 100.0, 170.0);
PSsetgray (NSDarkGray);
PSfill ();
PSarcn (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-3.0, 350.0, 280.0);
PSarc (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-2.0, 280.0, 350.0);
PSsetgray (NSLightGray);
PSfill ();
return self;
}
- drawWhiteStone:imageRep
{
// PSscale (1.0, 1.0);
// First draw the shadow under the stone.
// PSarc (RADIUS+SHADOWOFFSET/2, RADIUS-SHADOWOFFSET/2,
// RADIUS-SHADOWOFFSET, 0.0, 360.0);
// PSsetgray (NX_DKGRAY);
// if (NXDrawingStatus == NX_DRAWING) {
// PSsetalpha (0.666);
// }
// PSfill ();
if ([[NSDPSContext currentContext] isDrawingToScreen]) {
PSsetalpha (1.0);
}
// Draw the stone.
PSarc (RADIUS, RADIUS,
RADIUS, 0.0, 360.0);
PSsetgray (NSWhite);
PSfill ();
// And the lighter & darker spots on the stone...
PSarcn (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-3.0, 170.0, 100.0);
PSarc (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-2.0, 100.0, 170.0);
PSsetgray (NSLightGray);
PSfill ();
PSarcn (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-3.0, 350.0, 280.0);
PSarc (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-2.0, 280.0, 350.0);
PSsetgray (NSDarkGray);
PSfill ();
return self;
}
- drawGrayStone:imageRep
{
// PSscale (1.0, 1.0);
// First draw the shadow under the stone.
// PSarc (RADIUS+SHADOWOFFSET/2, RADIUS-SHADOWOFFSET/2,
// RADIUS-SHADOWOFFSET, 0.0, 360.0);
// PSsetgray (NX_DKGRAY);
// if (NXDrawingStatus == NX_DRAWING) {
// PSsetalpha (0.666);
// }
// PSfill ();
if ([[NSDPSContext currentContext] isDrawingToScreen]) {
PSsetalpha (1.0);
}
// Draw the stone.
// PSarc (RADIUS-SHADOWOFFSET/2, RADIUS+SHADOWOFFSET/2,
// RADIUS-SHADOWOFFSET, 0.0, 360.0);
PSarc (RADIUS, RADIUS,
RADIUS, 0.0, 360.0);
PSsetgray (NSDarkGray);
PSfill ();
// And the lighter & darker spots on the stone...
PSarcn (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-3.0, 170.0, 100.0);
PSarc (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-2.0, 100.0, 170.0);
PSsetgray (NSLightGray);
PSfill ();
PSarcn (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-3.0, 350.0, 280.0);
PSarc (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-2.0, 280.0, 350.0);
PSsetgray (NSWhite);
PSfill ();
return self;
}
- drawUpperLeft:imageRep
{
PSsetgray(NSBlack);
PSsetlinewidth(0.0);
if ([[NSDPSContext currentContext] isDrawingToScreen]) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(RADIUS, RADIUS);
PSlineto([self bounds].size.width,RADIUS);
PSmoveto(RADIUS, RADIUS);
PSlineto(RADIUS, 0.0);
PSmoveto(RADIUS-SHADOWOFFSET, RADIUS+SHADOWOFFSET);
PSlineto([self bounds].size.width, RADIUS+SHADOWOFFSET);
PSmoveto(RADIUS-SHADOWOFFSET, RADIUS+SHADOWOFFSET);
PSlineto(RADIUS-SHADOWOFFSET, 0.0);
PSstroke();
return self;
}
- drawUpperRight:imageRep
{
PSsetgray(NSBlack);
PSsetlinewidth(0.0);
if ([[NSDPSContext currentContext] isDrawingToScreen]) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(RADIUS, RADIUS);
PSlineto(0.0,RADIUS);
PSmoveto(RADIUS, RADIUS);
PSlineto(RADIUS, 0.0);
PSmoveto(RADIUS+SHADOWOFFSET, RADIUS+SHADOWOFFSET);
PSlineto(0.0, RADIUS+SHADOWOFFSET);
PSmoveto(RADIUS+SHADOWOFFSET, RADIUS+SHADOWOFFSET);
PSlineto(RADIUS+SHADOWOFFSET, 0.0);
PSstroke();
return self;
}
- drawLowerLeft:imageRep
{
PSsetgray(NSBlack);
PSsetlinewidth(0.0);
if ([[NSDPSContext currentContext] isDrawingToScreen]) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(RADIUS, RADIUS);
PSlineto([self bounds].size.width,RADIUS);
PSmoveto(RADIUS, RADIUS);
PSlineto(RADIUS, [self bounds].size.height);
PSmoveto(RADIUS-SHADOWOFFSET, RADIUS-SHADOWOFFSET);
PSlineto([self bounds].size.width, RADIUS-SHADOWOFFSET);
PSmoveto(RADIUS-SHADOWOFFSET, RADIUS-SHADOWOFFSET);
PSlineto(RADIUS-SHADOWOFFSET, [self bounds].size.height);
PSstroke();
return self;
}
- drawLowerRight:imageRep
{
PSsetgray(NSBlack);
PSsetlinewidth(0.0);
if ([[NSDPSContext currentContext] isDrawingToScreen]) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(RADIUS, RADIUS);
PSlineto(0.0,RADIUS);
PSmoveto(RADIUS, RADIUS);
PSlineto(RADIUS, [self bounds].size.height);
PSmoveto(RADIUS+SHADOWOFFSET, RADIUS-SHADOWOFFSET);
PSlineto(0.0, RADIUS-SHADOWOFFSET);
PSmoveto(RADIUS+SHADOWOFFSET, RADIUS-SHADOWOFFSET);
PSlineto(RADIUS+SHADOWOFFSET, [self bounds].size.height);
PSstroke();
return self;
}
- drawMidLeft:imageRep
{
PSsetgray(NSBlack);
PSsetlinewidth(0.0);
if ([[NSDPSContext currentContext] isDrawingToScreen]) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(RADIUS, RADIUS);
PSlineto([self bounds].size.width,RADIUS);
PSmoveto(RADIUS, [self bounds].size.height);
PSlineto(RADIUS, 0.0);
PSmoveto(RADIUS-SHADOWOFFSET, [self bounds].size.height);
PSlineto(RADIUS-SHADOWOFFSET, 0.0);
PSstroke();
return self;
}
- drawMidRight:imageRep
{
PSsetgray(NSBlack);
PSsetlinewidth(0.0);
if ([[NSDPSContext currentContext] isDrawingToScreen]) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(RADIUS, RADIUS);
PSlineto(0.0,RADIUS);
PSmoveto(RADIUS, [self bounds].size.height);
PSlineto(RADIUS, 0.0);
PSmoveto(RADIUS+SHADOWOFFSET, [self bounds].size.height);
PSlineto(RADIUS+SHADOWOFFSET, 0.0);
PSstroke();
return self;
}
- drawMidTop:imageRep
{
PSsetgray(NSBlack);
PSsetlinewidth(0.0);
if ([[NSDPSContext currentContext] isDrawingToScreen]) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(RADIUS, RADIUS);
PSlineto(RADIUS,0.0);
PSmoveto(0.0, RADIUS);
PSlineto([self bounds].size.width, RADIUS);
PSmoveto(0.0, RADIUS+SHADOWOFFSET);
PSlineto([self bounds].size.width, RADIUS+SHADOWOFFSET);
PSstroke();
return self;
}
- drawMidBottom:imageRep
{
PSsetgray(NSBlack);
PSsetlinewidth(0.0);
if ([[NSDPSContext currentContext] isDrawingToScreen]) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(RADIUS, RADIUS);
PSlineto(RADIUS,[self bounds].size.height);
PSmoveto(0.0, RADIUS);
PSlineto([self bounds].size.width, RADIUS);
PSmoveto(0.0, RADIUS-SHADOWOFFSET);
PSlineto([self bounds].size.width, RADIUS-SHADOWOFFSET);
PSstroke();
return self;
}
- drawInnerSquare:imageRep
{
PSsetgray(NSBlack);
PSsetlinewidth(0.0);
if ([[NSDPSContext currentContext] isDrawingToScreen]) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(0.0, RADIUS);
PSlineto([self bounds].size.width,RADIUS);
PSmoveto(RADIUS, [self bounds].size.height);
PSlineto(RADIUS, 0.0);
PSstroke();
return self;
}
- drawInnerHandicap:imageRep
{
PSsetgray(NSBlack);
PSsetlinewidth(0.0);
if ([[NSDPSContext currentContext] isDrawingToScreen]) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(0.0, RADIUS);
PSlineto([self bounds].size.width,RADIUS);
PSmoveto(RADIUS, [self bounds].size.height);
PSlineto(RADIUS, 0.0);
PSstroke();
PSarc(RADIUS, RADIUS, SHADOWOFFSET, 0.0, 360.0);
PSfill();
return self;
}
// The following methods show or erase the stones from the board.
- showBlackStone
{
NSRect tmpRect = {{floor(stoneX), floor(stoneY)},
{floor(STONEWIDTH), floor(STONEHEIGHT)}};
[blackStone compositeToPoint:tmpRect.origin operation:NSCompositeSourceOver];
return self;
}
- showWhiteStone
{
NSRect tmpRect = {{floor(stoneX), floor(stoneY)},
{floor(STONEWIDTH), floor(STONEHEIGHT)}};
[whiteStone compositeToPoint:tmpRect.origin operation:NSCompositeSourceOver];
return self;
}
- showGrayStone
{
NSRect tmpRect = {{floor(stoneX), floor(stoneY)},
{floor(STONEWIDTH), floor(STONEHEIGHT)}};
[grayStone compositeToPoint:tmpRect.origin operation:NSCompositeSourceOver];
return self;
}
- eraseStone
{
NSRect tmpRect = {{floor(stoneX), floor(stoneY)}, {floor(STONEWIDTH), floor(STONEHEIGHT)}};
return [self drawBackground:&tmpRect];
}
// drawBackground: just draws the specified piece of the background by
// compositing from the background image.
- showBackgroundPiece: (int)x: (int)y {
int q;
NSRect tmpRect = {{floor(stoneX), floor(stoneY)}, {floor(STONEWIDTH), floor(STONEHEIGHT)}};
if ((x == 0) && (y == 0))
[upperLeft compositeToPoint:tmpRect.origin operation:NSCompositeSourceOver];
if ((x == 0) && (y == MAXY - 1))
[lowerLeft compositeToPoint:tmpRect.origin operation:NSCompositeSourceOver];
if ((x == MAXX - 1) && (y == 0))
[upperRight compositeToPoint:tmpRect.origin operation:NSCompositeSourceOver];
if ((x == MAXX - 1) && (y == MAXY - 1))
[lowerRight compositeToPoint:tmpRect.origin operation:NSCompositeSourceOver];
if ((x == 0) && (y > 0) && (y < MAXY - 1))
[midLeft compositeToPoint:tmpRect.origin operation:NSCompositeSourceOver];
if ((x == MAXX - 1) && (y > 0) && (y < MAXY - 1))
[midRight compositeToPoint:tmpRect.origin operation:NSCompositeSourceOver];
if ((x > 0) && (x < MAXX - 1) && (y == 0))
[midTop compositeToPoint:tmpRect.origin operation:NSCompositeSourceOver];
if ((x > 0) && (x < MAXX - 1) && (y == MAXY - 1))
[midBottom compositeToPoint:tmpRect.origin operation:NSCompositeSourceOver];
if ((x > 0) && (x < MAXX - 1) && (y > 0) && (y < MAXY - 1))
[innerSquare compositeToPoint:tmpRect.origin operation:NSCompositeSourceOver];
if (MAXX < 13)
q = 2;
else
q = 3;
if (((x == q) && (y == q)) || ((x == q) && (y == MAXY/2)) ||
((x == q) && (y == MAXY-q-1)) || ((x == MAXX/2) && (y == q)) ||
((x == MAXX/2) && (y == MAXY/2)) || ((x == MAXX/2) && (y == MAXY-q-1)) ||
((x == MAXX-q-1) && (y == q)) || ((x == MAXX-q-1) && (y == MAXY/2)) ||
((x == MAXX-q-1) && (y == MAXY-q-1)))
[innerHandicap compositeToPoint:tmpRect.origin operation:NSCompositeSourceOver];
return self;
}
- drawBackground:(NSRect *)rect
{
NSRect tmpRect = *rect;
(&tmpRect)->origin.x = floor(NSMinX(tmpRect));
(&tmpRect)->origin.y = floor(NSMinY(tmpRect));
if ([[NSDPSContext currentContext] isDrawingToScreen]) {
PSsetgray (NSWhite);
PScompositerect (NSMinX(tmpRect), NSMinY(tmpRect),
NSWidth(tmpRect), NSHeight(tmpRect), NSCompositeCopy);
}
[backGround compositeToPoint:tmpRect.origin fromRect:tmpRect operation:NSCompositeSourceOver];
return self;
}
// drawSelf::, a method every decent View should have, redraws the game
// in its current state. This allows us to print the game very easily.
- (void)drawRect:(NSRect)rects {
int xcnt, ycnt;
char s[5], specialChar;
NSRect aRect = [self bounds];
[self drawBackground:(&rects ? &rects : &aRect)];
specialChar = 'a';
for (xcnt = 0; xcnt < MAXX; xcnt++)
{
for (ycnt = 0; ycnt < MAXY; ycnt++)
{
setStoneLoc(xcnt, ycnt);
switch (p[xcnt][ycnt])
{
case EMPTY: currentCharacter = 0;
[self showBackgroundPiece: xcnt: ycnt];
break;
case WHITESTONE: [self showWhiteStone];
if ([showHistFlag intValue])
{
char s[5];
[historyFont set];
PSsetgray(NSBlack);
PSmoveto(stoneX+RADIUS -
(floor(log(hist[xcnt][ycnt]+0.5)/log(10))+1.0)*3,
stoneY+RADIUS - 4);
if (hist[xcnt][ycnt] > 0)
{
sprintf(s, "%d", hist[xcnt][ycnt]);
PSshow(s);
}
else
{
PSmoveto(stoneX + RADIUS - 4, stoneY + RADIUS - 4);
PSshow("H");
}
}
break;
case BLACKSTONE: [self showBlackStone];
if ([showHistFlag intValue])
{
char s[5];
[historyFont set];
PSsetgray(NSWhite);
PSmoveto(stoneX+RADIUS -
(floor(log(hist[xcnt][ycnt]+0.5)/log(10))+1.0)*3,
stoneY+RADIUS - 4);
if (hist[xcnt][ycnt] > 0)
{
sprintf(s, "%d", hist[xcnt][ycnt]);
PSshow(s);
}
else
{
PSmoveto(stoneX + RADIUS - 4, stoneY + RADIUS - 4);
PSshow("H");
}
}
break;
case NEUTRAL_TERR: [self showGrayStone];
break;
case WHITE_TERR: [self showBackgroundPiece: xcnt: ycnt];
[whiteTerrFont set];
PSsetgray(NSWhite);
PSmoveto(stoneX+RADIUS/3, stoneY+RADIUS/3+2);
PSshow("W");
break;
case BLACK_TERR: [self showBackgroundPiece: xcnt: ycnt];
[blackTerrFont set];
PSsetgray(NSDarkGray);
PSmoveto(stoneX+RADIUS/3+1, stoneY+RADIUS/3);
PSshow("B");
break;
case SPECIAL_CHAR: [self showBackgroundPiece: xcnt: ycnt];
PSselectfont("Helvetica", 25.0);
PSsetgray(NSDarkGray);
PSmoveto(stoneX+RADIUS/3+1, stoneY+RADIUS/3);
sprintf(s,"%c",specialChar);
specialChar++;
PSshow(s);
break;
default: currentCharacter = 0;
[self showBackgroundPiece: xcnt: ycnt];
break;
}
}
}
if ([showCoords intValue])
{
for (xcnt = 0; xcnt < MAXX; xcnt++)
{
setStoneLoc(xcnt, 0);
[historyFont set];
PSsetgray(NSDarkGray);
PSmoveto(stoneX + RADIUS - 3, stoneY + RADIUS + 11);
s[0] = 'A' + xcnt;
if (xcnt > 7) s[0]++;
s[1] = 0;
PSshow(s);
setStoneLoc(xcnt, MAXY - 1);
PSmoveto(stoneX + RADIUS - 3, stoneY - 3);
PSshow(s);
}
for (ycnt = 0; ycnt < MAXX; ycnt++)
{
setStoneLoc(0, ycnt);
[historyFont set];
PSsetgray(NSDarkGray);
PSmoveto(stoneX - 4, stoneY + RADIUS - 4);
sprintf(s, "%d", MAXY-ycnt);
PSshow(s);
setStoneLoc(MAXX - 1, ycnt);
if (xcnt < 10)
{
PSmoveto(stoneX + STONEWIDTH, stoneY + RADIUS - 4);
}
else
{
PSmoveto(stoneX + STONEWIDTH - 6, stoneY + RADIUS - 4);
}
PSshow(s);
}
}
}
- step {
// NSEvent *peek_ev, *get_ev;
if (gameType == IGSGAME) {
return self;
}
if (neitherSide)
return self;
if (((currentStone == BLACKSTONE) && !blackSide) ||
((currentStone == WHITESTONE) && !whiteSide))
return self;
if (bothSides) {
while ((gameRunning) && (!finished)) {
[self selectMove];
PSWait();
/*
if( peek_ev = [NSApp nextEventMatchingMask:NSLeftMouseDownMask untilDate:[NSDate distantFuture] inMode:NSEventTrackingRunLoopMode dequeue:NO] ){
get_ev = [ [self window] nextEventMatchingMask:NSLeftMouseDownMask untilDate:[NSDate distantFuture] inMode:NSEventTrackingRunLoopMode dequeue:YES];
[NSApp sendEvent: get_ev];
}
*/
}
PSWait();
}
else {
[passButton setEnabled:NO];
[self selectMove];
PSWait();
PSWait();
[passButton setEnabled:YES];
PSWait();
}
return self;
}
- selectMove {
int i, j;
PSWait();
if( !bothSides )
[stopButton setEnabled:NO];
else
[stopButton setEnabled:YES];
for (i = 0; i < MAXX; i++)
for (j = 0; j < MAXY; j++)
oldBoard[i][j] = p[i][j];
genmove( &i, &j );
if (i >= 0)
{
p[i][j] = currentStone;
[self flashStone: i: j];
}
if (((i < 0) || (j < 0)) && (AGAScoring))
{
if (currentStone == BLACKSTONE)
blackCaptured++;
else
whiteCaptured++;
}
[self selectMoveEnd];
if (i >= 0)
{
[self lockFocus];
if (currentStone == BLACKSTONE)
[self showBlackStone];
else
[self showWhiteStone];
[self unlockFocus];
[self doClick];
}
[self updateInfo];
[self addMoveToGameMoves: currentStone: i: j];
if ([showHistFlag intValue])
{
NSRect tmpRect = {{floor(stoneX), floor(stoneY)},
{floor(STONEWIDTH), floor(STONEHEIGHT)}};
[self lockFocus];
[self drawRect:tmpRect];
[self display];
[self unlockFocus];
}
PSWait();
return self;
}
- selectMoveEnd
{
PSWait();
[startButton setEnabled:YES];
[stopButton setEnabled:YES];
PSWait();
return self;
}
- flashStone: (int)x :(int)y
{
setStoneLoc(x, y);
[self lockFocus];
[self showGrayStone];
[self unlockFocus];
return self;
}
- setMess1:(char *)s
{
[gameMessage setStringValue:[NSString stringWithCString:s]];
[gameMessage display];
return self;
}
- setMess2:(char *)s
{
[gameMessage2 setStringValue:[NSString stringWithCString:s]];
[gameMessage2 display];
return self;
}
- setblacksPrisoners:(int)bp
{
[blacksPrisoners setIntValue:bp];
[blacksPrisoners display];
return self;
}
- setwhitesPrisoners:(int)wp
{
[whitesPrisoners setIntValue:wp];
[whitesPrisoners display];
return self;
}
- (long)startZeit {
return startZeit;
}
- setStartZeit:(long)aTime {
startZeit = aTime;
return self;
}
- (int)bByo {
return bByo;
}
- (TimeStruct*)ts {
return &ts;
}
- gameCompleted {
[self removeTE];
[self setblacksPrisoners:0];
[self setwhitesPrisoners:0];
[IGSGameNumber setStringValue:@""];
[IGSBlackPlayer setStringValue:@""];
[IGSWhitePlayer setStringValue:@""];
[IGShandicap setStringValue:@""];
[IGSkomi setStringValue:@""];
[blackTime setStringValue:@""];
[whiteTime setStringValue:@""];
return self;
}
- removeTE {
if (te) {
[te invalidate];
[te release];
te = 0;
}
return self;
}
- (void) TEHandler:(NSTimer *)aTimer {
id obj;
NSString *buf;
int myTime, now;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
now = tp.tv_sec;
obj = [aTimer userInfo];
if ([obj startZeit] == 0L) {
[obj setStartZeit:now];
}
myTime = ts.time - (now - [obj startZeit]);
#ifdef TIMEDEBUG
printf("TEHandler: now = %ld, startZeit = %ld, ts.time = %d, myTime = %d\n", now, [obj startZeit], ts.time, myTime);
#endif
if (myTime < 0) {
if (ts.byo == -1 || /* player is in normal game time */
ts.byo == 25) { /* player is in byo-yomi but did */
/* not yet move */
myTime += [obj ByoTime] * 60;
ts.byo = 25;
}
}
buf = [NSString stringWithFormat:@"%d:%02d", myTime / 60, myTime % 60];
if (ts.byo != -1) {
buf = [buf stringByAppendingFormat:@", %d", ts.byo];
}
[ts.timeToHandle setStringValue:buf];
[ts.timeToHandle display];
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.