This is Board.m in view mode; [Download] [Up]
#include "comment.header"
/* $Id: Board.m,v 1.3 1997/07/06 19:37:55 ergo Exp $ */
/*
* $Log: Board.m,v $
* 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"
#include "MiscString.h"
#import <libc.h>
#import <math.h>
#import <sys/time.h>
#import <dpsclient/wraps.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 gameSize bounds.size
#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;
}
void TEHandler(DPSTimedEntry teNumber, double now, void* userdata) {
id obj = (id)userdata;
TimeStruct* ts = [obj ts];
char buf[256];
int myTime;
if ([obj startZeit] == 0.0)
[obj setStartZeit:now];
myTime = ts->time - (now - [obj startZeit]);
if (myTime < 0) {
if (ts->byo == -1 || /* player is in first byo-yomi time */
ts->byo == 25) { /* player is in byo-yomi but did */
/* not yet move */
myTime += [obj ByoTime] * 60;
ts->byo = 25;
}
}
sprintf(buf, "%d:%02d", myTime / 60, myTime % 60);
if (ts->byo != -1)
sprintf(buf, "%s, %d", buf, ts->byo);
[ts->timeToHandle setStringValue:buf];
[ts->timeToHandle display];
}
@implementation GoView
- initFrame:(const NXRect *)frm
{
NXSize stoneSize;
stoneSize.width = STONEWIDTH;
stoneSize.height = STONEHEIGHT;
te = 0;
startZeit = 0;
[super initFrame:frm];
[self allocateGState]; // For faster lock/unlockFocus
[(blackStone = [[NXImage allocFromZone:[self zone]] init]) setScalable:NO];
[blackStone useDrawMethod:@selector(drawBlackStone:) inObject:self];
[blackStone setSize:&stoneSize];
[(whiteStone = [[NXImage allocFromZone:[self zone]] init]) setScalable:NO];
[whiteStone useDrawMethod:@selector(drawWhiteStone:) inObject:self];
[whiteStone setSize:&stoneSize];
[(grayStone = [[NXImage allocFromZone:[self zone]] init]) setScalable:NO];
[grayStone useDrawMethod:@selector(drawGrayStone:) inObject:self];
[grayStone setSize:&stoneSize];
[(upperLeft = [[NXImage allocFromZone:[self zone]] init]) setScalable:NO];
[upperLeft useDrawMethod:@selector(drawUpperLeft:) inObject:self];
[upperLeft setSize:&stoneSize];
[(upperRight = [[NXImage allocFromZone:[self zone]] init]) setScalable:NO];
[upperRight useDrawMethod:@selector(drawUpperRight:) inObject:self];
[upperRight setSize:&stoneSize];
[(lowerLeft = [[NXImage allocFromZone:[self zone]] init]) setScalable:NO];
[lowerLeft useDrawMethod:@selector(drawLowerLeft:) inObject:self];
[lowerLeft setSize:&stoneSize];
[(lowerRight = [[NXImage allocFromZone:[self zone]] init]) setScalable:NO];
[lowerRight useDrawMethod:@selector(drawLowerRight:) inObject:self];
[lowerRight setSize:&stoneSize];
[(midLeft = [[NXImage allocFromZone:[self zone]] init]) setScalable:NO];
[midLeft useDrawMethod:@selector(drawMidLeft:) inObject:self];
[midLeft setSize:&stoneSize];
[(midRight = [[NXImage allocFromZone:[self zone]] init]) setScalable:NO];
[midRight useDrawMethod:@selector(drawMidRight:) inObject:self];
[midRight setSize:&stoneSize];
[(midTop = [[NXImage allocFromZone:[self zone]] init]) setScalable:NO];
[midTop useDrawMethod:@selector(drawMidTop:) inObject:self];
[midTop setSize:&stoneSize];
[(midBottom = [[NXImage allocFromZone:[self zone]] init]) setScalable:NO];
[midBottom useDrawMethod:@selector(drawMidBottom:) inObject:self];
[midBottom setSize:&stoneSize];
[(innerSquare = [[NXImage allocFromZone:[self zone]] init]) setScalable:NO];
[innerSquare useDrawMethod:@selector(drawInnerSquare:) inObject:self];
[innerSquare setSize:&stoneSize];
[(innerHandicap = [[NXImage allocFromZone:[self zone]] init]) setScalable:NO];
[innerHandicap useDrawMethod:@selector(drawInnerHandicap:) inObject:self];
[innerHandicap setSize:&stoneSize];
[self setBackgroundFile:NXGetDefaultValue([NXApp appName], "BackGround")
andRemember:NO];
[self startNewGame];
historyFont = [Font newFont:"Helvetica" size:9.0 matrix:NX_IDENTITYMATRIX];
blackTerrFont = [Font newFont:"Helvetica" size:25.0 matrix:NX_IDENTITYMATRIX];
whiteTerrFont = [Font newFont:"Helvetica" size:22.5 matrix:NX_IDENTITYMATRIX];
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.
- free {
[backGround free];
return [super free];
}
// 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 free];
backGround = [[NXImage allocFromZone:[self zone]] initSize:&gameSize];
if (fileName) {
[backGround useFromFile:fileName];
if (remember)
NXWriteDefault ([NXApp appName], "Background", fileName);
} else {
[backGround useFromSection:"Background.tiff"];
if (remember)
NXRemoveDefault ([NXApp appName], "Background");
}
[backGround setBackgroundColor:NX_COLORWHITE];
[backGround setScalable:NO];
[self display];
return self;
}
// The following two methods allow changing the background image from
// menu items or buttons.
- changeBackground:sender {
const char *const types[] = {"tiff", "eps", NULL};
if ([[OpenPanel new] runModalForTypes:types]) {
[self setBackgroundFile:[[OpenPanel new] filename] 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 == 1)) ||
((currentStone == WHITESTONE) && (whiteSide == 1)))
[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];
NXPing();
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];
NXPing();
}
if ((gameRunning == 0) && (finished == 0)) {
gameRunning = YES;
[self step];
}
return 0;
}
- stop:sender {
if (gameType == IGSGAME)
return self;
if (gameRunning)
gameRunning = NO;
return self;
}
- showLastMove:sender
{
int i;
if (SmartGoGameFlag)
return self;
if (finished)
{
NXRunAlertPanel("NeXTGo", "The game has concluded. The last move was\n\
the scoring.", "OK", 0, 0);
return self;
}
if (lastMove == 0)
{
NXRunAlertPanel("NeXTGo", "The game has not yet started.", "OK", 0, 0);
return self;
}
for (i = 0; i < gameMoves[lastMove-1].numchanges; i++)
{
if (gameMoves[lastMove-1].changes[i].x < 0)
{
NXRunAlertPanel("NeXTGo", "The last move was a pass.", "OK", 0, 0);
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];
NXPing();
[self lockFocus];
[[self window] flushWindow];
[self drawSelf:&bounds :0];
[self display];
[self unlockFocus];
NXPing();
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];
NXPing();
return self;
}
- toggleCoords:sender
{
[self lockFocus];
[self display];
[self unlockFocus];
return self;
}
- mouseDown:(NXEvent *)event
{
NXPoint pickedP;
if (gameType == LOCAL) {
if ((((currentStone == BLACKSTONE) && (blackSide == 1)) ||
((currentStone == WHITESTONE) && (whiteSide == 1))) &&
(!scoringGame) && (!manualScoring))
return self;
if (SmartGoGameFlag)
return self;
if ((!gameRunning) && (!finished))
gameRunning = YES;
if (!finished) {
int i, j, x, y;
pickedP = event->location;
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];
[self doClick];
[self updateInfo];
[self addMoveToGameMoves: currentStone: x: y];
if ([showHistFlag intValue]) {
NXRect tmpRect = {{floor(stoneX), floor(stoneY)},
{floor(STONEWIDTH), floor(STONEHEIGHT)}};
[self lockFocus];
[self drawSelf:&tmpRect :0];
[self unlockFocus];
}
if (!neitherSide)
[self step];
[self update];
}
}
else {
if ((scoringGame) && (manualScoring) && (!gameScored)) {
int x, y;
pickedP = event->location;
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 update];
}
}
}
}
else {
int x, y;
char s[50], n[50];
extern int observing, ingame;
if (observing || (ingame == -1)) {
NXRunAlertPanel("IGS Error", "You cannot make a move unless you are playing.", "OK", 0, 0);
return self;
}
pickedP = event->location;
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);
}
return self;
}
- passMove
{
if (gameType == LOCAL) {
if (((currentStone == BLACKSTONE) && (blackSide == 1)) ||
((currentStone == WHITESTONE) && (whiteSide == 1))) {
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 drawSelf:&bounds :0];
[self display];
[self unlockFocus];
NXPing();
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];
[self doClick];
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]) {
NXRect tmpRect = {{floor(stoneX), floor(stoneY)},
{floor(STONEWIDTH), floor(STONEHEIGHT)}};
[self lockFocus];
[self drawSelf:&tmpRect :0];
[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 update];
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
{
ts.caller = self;
if (bTime != -1) {
if (bTime < 0)
bTime = 0;
if (wTime < 0)
wTime = 0;
if (currentStone == WHITESTONE) { /* Black moved */
[self removeTE];
startZeit = 0.0;
ts.byo = bbyo;
ts.time = btime;
ts.timeToHandle = blackTime;
te = DPSAddTimedEntry(0.2, TEHandler, (void*)self,
NX_BASETHRESHOLD);
}
else { /* White moved */
[self removeTE];
startZeit = 0.0;
ts.byo = wbyo;
ts.time = wtime;
ts.timeToHandle = whiteTime;
te = DPSAddTimedEntry(0.2, TEHandler, (void*)self,
NX_BASETHRESHOLD);
}
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:bltime];
[blackTime display];
[whiteTime setStringValue:whtime];
[whiteTime display];
return self;
}
- setGameNumber: (int)n
{
[IGSGameNumber setIntValue:n];
[IGSGameNumber display];
return self;
}
- updateTitle {
id buf = [ [MiscString alloc] initString:[IGSBlackPlayer stringValue]];
[buf cat:" - "];
[buf cat:[IGSWhitePlayer stringValue]];
[[self window] setTitle:[buf stringValue]];
[buf free];
return self;
}
- setWhiteName: (char *)wname {
[IGSWhitePlayer setStringValue:wname];
[IGSWhitePlayer display];
[self updateTitle];
return self;
}
- setBlackName: (char *)bname {
[IGSBlackPlayer setStringValue:bname];
[IGSBlackPlayer display];
[self updateTitle];
return self;
}
- setIGSHandicap: (int)h
{
[IGShandicap setIntValue:h];
[IGShandicap display];
return self;
}
- setIGSKomi: (char *)k
{
[IGSkomi setStringValue: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])
{
NXRect tmpRect = {{floor(stoneX), floor(stoneY)},
{floor(STONEWIDTH), floor(STONEHEIGHT)}};
[self lockFocus];
[self drawSelf:&tmpRect :0];
[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: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 (NXDrawingStatus == NX_DRAWING) {
PSsetalpha (1.0);
}
// Draw the stone.
PSarc (RADIUS, RADIUS,
RADIUS, 0.0, 360.0);
PSsetgray (NX_BLACK);
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 (NX_DKGRAY);
PSfill ();
PSarcn (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-3.0, 350.0, 280.0);
PSarc (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-2.0, 280.0, 350.0);
PSsetgray (NX_LTGRAY);
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 (NXDrawingStatus == NX_DRAWING) {
PSsetalpha (1.0);
}
// Draw the stone.
PSarc (RADIUS, RADIUS,
RADIUS, 0.0, 360.0);
PSsetgray (NX_WHITE);
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 (NX_LTGRAY);
PSfill ();
PSarcn (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-3.0, 350.0, 280.0);
PSarc (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-2.0, 280.0, 350.0);
PSsetgray (NX_DKGRAY);
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 (NXDrawingStatus == NX_DRAWING) {
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 (NX_DKGRAY);
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 (NX_LTGRAY);
PSfill ();
PSarcn (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-3.0, 350.0, 280.0);
PSarc (RADIUS, RADIUS,
RADIUS-SHADOWOFFSET-2.0, 280.0, 350.0);
PSsetgray (NX_WHITE);
PSfill ();
return self;
}
- drawUpperLeft:imageRep
{
PSsetgray(NX_BLACK);
PSsetlinewidth(0.0);
if (NXDrawingStatus == NX_DRAWING) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(RADIUS, RADIUS);
PSlineto(bounds.size.width,RADIUS);
PSmoveto(RADIUS, RADIUS);
PSlineto(RADIUS, 0.0);
PSmoveto(RADIUS-SHADOWOFFSET, RADIUS+SHADOWOFFSET);
PSlineto(bounds.size.width, RADIUS+SHADOWOFFSET);
PSmoveto(RADIUS-SHADOWOFFSET, RADIUS+SHADOWOFFSET);
PSlineto(RADIUS-SHADOWOFFSET, 0.0);
PSstroke();
return self;
}
- drawUpperRight:imageRep
{
PSsetgray(NX_BLACK);
PSsetlinewidth(0.0);
if (NXDrawingStatus == NX_DRAWING) {
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(NX_BLACK);
PSsetlinewidth(0.0);
if (NXDrawingStatus == NX_DRAWING) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(RADIUS, RADIUS);
PSlineto(bounds.size.width,RADIUS);
PSmoveto(RADIUS, RADIUS);
PSlineto(RADIUS, bounds.size.height);
PSmoveto(RADIUS-SHADOWOFFSET, RADIUS-SHADOWOFFSET);
PSlineto(bounds.size.width, RADIUS-SHADOWOFFSET);
PSmoveto(RADIUS-SHADOWOFFSET, RADIUS-SHADOWOFFSET);
PSlineto(RADIUS-SHADOWOFFSET, bounds.size.height);
PSstroke();
return self;
}
- drawLowerRight:imageRep
{
PSsetgray(NX_BLACK);
PSsetlinewidth(0.0);
if (NXDrawingStatus == NX_DRAWING) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(RADIUS, RADIUS);
PSlineto(0.0,RADIUS);
PSmoveto(RADIUS, RADIUS);
PSlineto(RADIUS, bounds.size.height);
PSmoveto(RADIUS+SHADOWOFFSET, RADIUS-SHADOWOFFSET);
PSlineto(0.0, RADIUS-SHADOWOFFSET);
PSmoveto(RADIUS+SHADOWOFFSET, RADIUS-SHADOWOFFSET);
PSlineto(RADIUS+SHADOWOFFSET, bounds.size.height);
PSstroke();
return self;
}
- drawMidLeft:imageRep
{
PSsetgray(NX_BLACK);
PSsetlinewidth(0.0);
if (NXDrawingStatus == NX_DRAWING) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(RADIUS, RADIUS);
PSlineto(bounds.size.width,RADIUS);
PSmoveto(RADIUS, bounds.size.height);
PSlineto(RADIUS, 0.0);
PSmoveto(RADIUS-SHADOWOFFSET, bounds.size.height);
PSlineto(RADIUS-SHADOWOFFSET, 0.0);
PSstroke();
return self;
}
- drawMidRight:imageRep
{
PSsetgray(NX_BLACK);
PSsetlinewidth(0.0);
if (NXDrawingStatus == NX_DRAWING) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(RADIUS, RADIUS);
PSlineto(0.0,RADIUS);
PSmoveto(RADIUS, bounds.size.height);
PSlineto(RADIUS, 0.0);
PSmoveto(RADIUS+SHADOWOFFSET, bounds.size.height);
PSlineto(RADIUS+SHADOWOFFSET, 0.0);
PSstroke();
return self;
}
- drawMidTop:imageRep
{
PSsetgray(NX_BLACK);
PSsetlinewidth(0.0);
if (NXDrawingStatus == NX_DRAWING) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(RADIUS, RADIUS);
PSlineto(RADIUS,0.0);
PSmoveto(0.0, RADIUS);
PSlineto(bounds.size.width, RADIUS);
PSmoveto(0.0, RADIUS+SHADOWOFFSET);
PSlineto(bounds.size.width, RADIUS+SHADOWOFFSET);
PSstroke();
return self;
}
- drawMidBottom:imageRep
{
PSsetgray(NX_BLACK);
PSsetlinewidth(0.0);
if (NXDrawingStatus == NX_DRAWING) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(RADIUS, RADIUS);
PSlineto(RADIUS,bounds.size.height);
PSmoveto(0.0, RADIUS);
PSlineto(bounds.size.width, RADIUS);
PSmoveto(0.0, RADIUS-SHADOWOFFSET);
PSlineto(bounds.size.width, RADIUS-SHADOWOFFSET);
PSstroke();
return self;
}
- drawInnerSquare:imageRep
{
PSsetgray(NX_BLACK);
PSsetlinewidth(0.0);
if (NXDrawingStatus == NX_DRAWING) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(0.0, RADIUS);
PSlineto(bounds.size.width,RADIUS);
PSmoveto(RADIUS, bounds.size.height);
PSlineto(RADIUS, 0.0);
PSstroke();
return self;
}
- drawInnerHandicap:imageRep
{
PSsetgray(NX_BLACK);
PSsetlinewidth(0.0);
if (NXDrawingStatus == NX_DRAWING) {
PSsetalpha (1.0);
}
PSnewpath();
PSmoveto(0.0, RADIUS);
PSlineto(bounds.size.width,RADIUS);
PSmoveto(RADIUS, 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
{
NXRect tmpRect = {{floor(stoneX), floor(stoneY)},
{floor(STONEWIDTH), floor(STONEHEIGHT)}};
[blackStone composite:NX_SOVER toPoint:&tmpRect.origin];
return self;
}
- showWhiteStone
{
NXRect tmpRect = {{floor(stoneX), floor(stoneY)},
{floor(STONEWIDTH), floor(STONEHEIGHT)}};
[whiteStone composite:NX_SOVER toPoint:&tmpRect.origin];
return self;
}
- showGrayStone
{
NXRect tmpRect = {{floor(stoneX), floor(stoneY)},
{floor(STONEWIDTH), floor(STONEHEIGHT)}};
[grayStone composite:NX_SOVER toPoint:&tmpRect.origin];
return self;
}
- eraseStone
{
NXRect 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;
NXRect tmpRect = {{floor(stoneX), floor(stoneY)}, {floor(STONEWIDTH), floor(STONEHEIGHT)}};
if ((x == 0) && (y == 0))
[upperLeft composite:NX_SOVER toPoint:&tmpRect.origin];
if ((x == 0) && (y == MAXY - 1))
[lowerLeft composite:NX_SOVER toPoint:&tmpRect.origin];
if ((x == MAXX - 1) && (y == 0))
[upperRight composite:NX_SOVER toPoint:&tmpRect.origin];
if ((x == MAXX - 1) && (y == MAXY - 1))
[lowerRight composite:NX_SOVER toPoint:&tmpRect.origin];
if ((x == 0) && (y > 0) && (y < MAXY - 1))
[midLeft composite:NX_SOVER toPoint:&tmpRect.origin];
if ((x == MAXX - 1) && (y > 0) && (y < MAXY - 1))
[midRight composite:NX_SOVER toPoint:&tmpRect.origin];
if ((x > 0) && (x < MAXX - 1) && (y == 0))
[midTop composite:NX_SOVER toPoint:&tmpRect.origin];
if ((x > 0) && (x < MAXX - 1) && (y == MAXY - 1))
[midBottom composite:NX_SOVER toPoint:&tmpRect.origin];
if ((x > 0) && (x < MAXX - 1) && (y > 0) && (y < MAXY - 1))
[innerSquare composite:NX_SOVER toPoint:&tmpRect.origin];
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 composite:NX_SOVER toPoint:&tmpRect.origin];
return self;
}
- drawBackground:(NXRect *)rect
{
NXRect tmpRect = *rect;
NX_X(&tmpRect) = floor(NX_X(&tmpRect));
NX_Y(&tmpRect) = floor(NX_Y(&tmpRect));
if (NXDrawingStatus == NX_DRAWING) {
PSsetgray (NX_WHITE);
PScompositerect (NX_X(&tmpRect), NX_Y(&tmpRect),
NX_WIDTH(&tmpRect), NX_HEIGHT(&tmpRect), NX_COPY);
}
[backGround composite:NX_SOVER fromRect:&tmpRect toPoint:&tmpRect.origin];
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.
- drawSelf:(NXRect *)rects :(int)rectCount
{
int xcnt, ycnt;
char s[5], specialChar;
[self drawBackground:(rects ? rects : &bounds)];
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(NX_BLACK);
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(NX_WHITE);
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(NX_WHITE);
PSmoveto(stoneX+RADIUS/3, stoneY+RADIUS/3+2);
PSshow("W");
break;
case BLACK_TERR: [self showBackgroundPiece: xcnt: ycnt];
[blackTerrFont set];
PSsetgray(NX_DKGRAY);
PSmoveto(stoneX+RADIUS/3+1, stoneY+RADIUS/3);
PSshow("B");
break;
case SPECIAL_CHAR: [self showBackgroundPiece: xcnt: ycnt];
PSselectfont("Helvetica", 25.0);
PSsetgray(NX_DKGRAY);
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(NX_DKGRAY);
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(NX_DKGRAY);
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);
}
}
return self;
}
- print:sender
{
return [self printPSCode:sender];
}
- step
{
NXEvent peek_ev, *get_ev;
if (gameType == IGSGAME)
{
return self;
}
if (neitherSide)
return self;
if (((currentStone == BLACKSTONE) && (blackSide == 0)) ||
((currentStone == WHITESTONE) && (whiteSide == 0)))
return self;
if (bothSides) {
while ((gameRunning) && (!finished)) {
[self selectMove];
NXPing();
if( [NXApp peekNextEvent: NX_MOUSEDOWNMASK into: &peek_ev] ){
get_ev = [NXApp getNextEvent: NX_MOUSEDOWNMASK];
[NXApp sendEvent: get_ev];
}
}
NXPing();
} else {
[passButton setEnabled: NO];
[self selectMove];
NXPing();
NXPing();
[passButton setEnabled: YES];
NXPing();
}
return self;
}
- selectMove
{
int i, j;
NXPing();
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])
{
NXRect tmpRect = {{floor(stoneX), floor(stoneY)},
{floor(STONEWIDTH), floor(STONEHEIGHT)}};
[self lockFocus];
[self drawSelf:&tmpRect :0];
[self display];
[self unlockFocus];
}
NXPing();
return self;
}
- selectMoveEnd
{
NXPing();
[startButton setEnabled: YES];
[stopButton setEnabled: YES];
NXPing();
return self;
}
- flashStone: (int)x :(int)y
{
setStoneLoc(x, y);
[self lockFocus];
[self showGrayStone];
[self unlockFocus];
return self;
}
- setMess1:(char *)s
{
[gameMessage setStringValue:s];
[gameMessage display];
return self;
}
- setMess2:(char *)s
{
[gameMessage2 setStringValue: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;
}
- (float)startZeit {
return startZeit;
}
- setStartZeit:(float)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)
DPSRemoveTimedEntry(te);
te = 0;
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.