home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-07-10 | 28.0 KB | 1,136 lines |
- /*
- GNU GO - the game of Go (Wei-Chi)
- Version 1.1 last revised 3-1-89
- Copyright (C) Free Software Foundation, Inc.
- written by Man L. Li
- modified by Wayne Iba
- documented by Bob Webber
- NeXT version by John Neil
- */
- /*
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation - version 1.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License in file COPYING for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Please report any bug/fix, modification, suggestion to
-
- mail address: Man L. Li
- Dept. of Computer Science
- University of Houston
- 4800 Calhoun Road
- Houston, TX 77004
-
- e-mail address: manli@cs.uh.edu (Internet)
- coscgbn@uhvax1.bitnet (BITNET)
- 70070,404 (CompuServe)
-
- For the NeXT version, please report any bug/fix, modification, suggestion to
-
- mail address: John Neil
- Mathematics Department
- Portland State University
- PO Box 751
- Portland, OR 97207
-
- e-mail address: neil@math.mth.pdx.edu (Internet)
- neil@psuorvm.bitnet (BITNET)
- */
-
- #import "Board.h"
- #import "gnugo.h"
-
- #import <libc.h>
- #import <math.h>
- #import <dpsclient/wraps.h> // PSxxx functions
- #import <appkit/color.h> // For background colors of images
- #import <defaults/defaults.h> // For writing/reading high score
- #import <appkit/Application.h> // For NXApp
- #import <appkit/Button.h>
- #import <appkit/Control.h>
- #import <appkit/NXImage.h>
- #import <appkit/OpenPanel.h>
- #import <appkit/Panel.h>
- #import <appkit/Window.h>
- #import <appkit/Menu.h>
- #import <appkit/Matrix.h>
-
- #define EMPTY 0
- #define WHITESTONE 1
- #define BLACKSTONE 2
- #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 100.0
-
- #define gameSize bounds.size
-
- #define PSLine(a, b, x, y) PSmoveto(a, b); PSlineto(x, y)
-
- float stoneX, stoneY;
-
- 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
-
- - initFrame:(const NXRect *)frm
- {
- NXSize stoneSize;
-
- stoneSize.width = STONEWIDTH;
- stoneSize.height = STONEHEIGHT;
-
- [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];
-
- 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;
- }
-
- // The following method will initialize all the variables for a new game.
-
- - startNewGame
- {
- int i, j;
-
- gameRunning = NO;
- finished = NO;
-
- blackCaptured = whiteCaptured = 0;
-
- seed(&rd);
-
- for (i = 0; i < MAXX; i++)
- for (j = 0; j < MAXY; j++)
- p[i][j] = 0;
-
- for (i = 0; i < 9; i++)
- opn[i] = 1;
- opn[4] = 0;
-
- 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"];
-
- if (bothSides)
- [passButton setEnabled: NO];
- else
- [passButton setEnabled: YES];
- [passButton display];
-
- if (neitherSide) {
- [startButton setEnabled: NO];
- [stopButton setEnabled: NO];
- [startButton display];
- [stopButton display];
- } else {
- [startButton setEnabled: YES];
- [stopButton setEnabled: YES];
- [startButton display];
- [stopButton display];
- }
-
- if (((currentStone == BLACKSTONE) && (blackSide == 1)) ||
- ((currentStone == WHITESTONE) && (whiteSide == 1)))
- [gameMessage2 setStringValue:"Press START to begin..."];
- else
- [gameMessage2 setStringValue:"You move first..."];
-
- return self;
- }
-
- // The stop method will pause a running game. The go method will start it up
- // again.
-
- - go:sender
- {
- if ((gameRunning == 0) && (finished == 0)) {
- gameRunning = YES;
- [self step];
- }
- return self;
- }
-
- - stop:sender
- {
- id menuList = [mainMenu itemList];
- int i, r, c;
-
- if (gameRunning) {
- [menuList getNumRows: &r numCols: &c];
- for( i = 0; i < r; i++ )
- [[menuList cellAt: i :0] setEnabled: YES];
- [mainMenu display];
- gameRunning = NO;
- }
- return self;
- }
-
- - mouseDown:(NXEvent *)event
- {
- NXPoint pickedP;
-
- if (((currentStone == BLACKSTONE) && (blackSide == 1)) ||
- ((currentStone == WHITESTONE) && (whiteSide == 1)))
- return self;
-
- if ((!gameRunning) && (!finished))
- gameRunning = YES;
-
- if (!finished) {
- 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] == 0) && (!suicide(x,y))) {
- p[x][y] = currentStone;
- if (currentStone == BLACKSTONE)
- blackPassed = 0;
- else
- whitePassed = 0;
-
- setStoneLoc(x,y);
- // stoneX = BASEBOARDX - RADIUS + (x*STONEWIDTH);
- // stoneY = BASEBOARDY - RADIUS + ((18 - y)*STONEHEIGHT);
-
- // sprintf(s,"%d %d: %f %f",x,y,pickedP.x,pickedP.y);
- // [gameMessage setStringValue:s];
-
- [self lockFocus];
-
- switch (p[x][y]) {
- case WHITESTONE: [self showWhiteStone];
- break;
- case BLACKSTONE: [self showBlackStone];
- break;
- default: break;
- }
-
- [self unlockFocus];
- [self updateInfo];
- if (!neitherSide)
- [self step];
-
- }
- } else {
- [self go:self];
- }
-
- return self;
- }
-
- - passMove
- {
- if (((currentStone == BLACKSTONE) && (blackSide == 1)) ||
- ((currentStone == WHITESTONE) && (whiteSide == 1)))
- return self;
-
- if (currentStone == BLACKSTONE)
- blackPassed = 1;
- else
- whitePassed = 1;
-
- [self updateInfo];
- if (!neitherSide)
- [self step];
-
- return self;
- }
-
- - updateInfo
- {
- char s[35], s2[150];
- int oldBlackPrisoners, oldWhitePrisoners;
-
- oldBlackPrisoners = blackCaptured;
- oldWhitePrisoners = 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"];
- }
-
- sprintf(s,"%d",blackCaptured);
- [blackPrisoners setStringValue:s];
-
- sprintf(s,"%d",whiteCaptured);
- [whitePrisoners setStringValue:s];
-
- if ((oldBlackPrisoners != blackCaptured) ||
- (oldWhitePrisoners != whiteCaptured))
- {
- [self lockFocus];
- [[self window] flushWindow];
- [self drawSelf:&bounds :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)) {
- [self lockFocus];
- [[self window] flushWindow];
- [gameMessage setStringValue:"Scoring Game, Please Wait"];
- [gameMessage2 setStringValue:"Removing Dead Groups..."];
- [self display];
- [self unlockFocus];
- finished = 1;
- [self scoreGame];
- black_Score = (float)blackTerritory - (float)blackCaptured;
- white_Score = (float)whiteTerritory - (float)whiteCaptured;
- white_Score += (handicap == 0)?KOMI:0.5;
- if (black_Score > white_Score)
- sprintf(s, "Black has won by %3.1f points.", black_Score - white_Score);
- if (white_Score > black_Score)
- sprintf(s, "White has won by %3.1f points.", white_Score - black_Score);
- if (black_Score == white_Score)
- sprintf(s, "The game was a tie.");
- [gameMessage2 setStringValue:s];
- [gameMessage setStringValue:"Game Over"];
- [self lockFocus];
- [self display];
- [self unlockFocus];
- sprintf(s2, "Scoring: Territory - Captured + Komi = Score\nBlack %5d %5d %3.1f %3.1f\nWhite %5d %5d %3.1f %3.1f", blackTerritory, blackCaptured, 0.0, black_Score, whiteTerritory, whiteCaptured, (handicap == 0)?KOMI:0.5, white_Score);
- NXRunAlertPanel("Scoring Summary", s2, "OK", NULL, NULL);
- }
-
- 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] = 0;
- [self flashStone:k:l];
- num_in_pattern++;
- }
-
- find_owner();
-
- if ((ownermat[i][j] != -1) && (ownermat[i][j] != tempmat[i][j]))
- {
- if (tempmat[i][j] == 2)
- blackCaptured += num_in_pattern;
- else
- whiteCaptured += num_in_pattern;
- changes++;
- [self lockFocus];
- [[self window] flushWindow];
- [self drawSelf:&bounds :0];
- [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++;
- if (ownermat[i][j] == WHITESTONE)
- whiteTerritory++;
- if (ownermat[i][j] == -1)
- [self flashStone:i:j];
- }
- [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-SHADOWOFFSET/2, RADIUS+SHADOWOFFSET/2,
- RADIUS-SHADOWOFFSET-3.0, 170.0, 100.0);
- PSarc (RADIUS-SHADOWOFFSET/2, RADIUS+SHADOWOFFSET/2,
- RADIUS-SHADOWOFFSET-2.0, 100.0, 170.0);
- PSsetgray (NX_DKGRAY);
- PSfill ();
- PSarcn (RADIUS-SHADOWOFFSET/2, RADIUS+SHADOWOFFSET/2,
- RADIUS-SHADOWOFFSET-2.0, 350.0, 280.0);
- PSarc (RADIUS-SHADOWOFFSET/2, RADIUS+SHADOWOFFSET/2,
- 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-SHADOWOFFSET/2, RADIUS+SHADOWOFFSET/2,
- RADIUS-SHADOWOFFSET-3.0, 170.0, 100.0);
- PSarc (RADIUS-SHADOWOFFSET/2, RADIUS+SHADOWOFFSET/2,
- RADIUS-SHADOWOFFSET-2.0, 100.0, 170.0);
- PSsetgray (NX_LTGRAY);
- PSfill ();
- PSarcn (RADIUS-SHADOWOFFSET/2, RADIUS+SHADOWOFFSET/2,
- RADIUS-SHADOWOFFSET-2.0, 350.0, 280.0);
- PSarc (RADIUS-SHADOWOFFSET/2, RADIUS+SHADOWOFFSET/2,
- 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-SHADOWOFFSET/2, RADIUS+SHADOWOFFSET/2,
- RADIUS-SHADOWOFFSET-3.0, 170.0, 100.0);
- PSarc (RADIUS-SHADOWOFFSET/2, RADIUS+SHADOWOFFSET/2,
- RADIUS-SHADOWOFFSET-2.0, 100.0, 170.0);
- PSsetgray (NX_LTGRAY);
- PSfill ();
- PSarcn (RADIUS-SHADOWOFFSET/2, RADIUS+SHADOWOFFSET/2,
- RADIUS-SHADOWOFFSET-2.0, 350.0, 280.0);
- PSarc (RADIUS-SHADOWOFFSET/2, RADIUS+SHADOWOFFSET/2,
- 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;
-
- [self drawBackground:(rects ? rects : &bounds)];
-
- for (xcnt = 0; xcnt < MAXX; xcnt++) {
- for (ycnt = 0; ycnt < MAXY; ycnt++) {
- setStoneLoc(xcnt, ycnt);
- // stoneX = BASEBOARDX - RADIUS + (xcnt*STONEWIDTH);
- // stoneY = BASEBOARDY - RADIUS + ((18 - ycnt)*STONEHEIGHT);
- switch (p[xcnt][ycnt]) {
- case EMPTY: [self showBackgroundPiece: xcnt: ycnt];
- break;
- case WHITESTONE: [self showWhiteStone];
- break;
- case BLACKSTONE: [self showBlackStone];
- break;
- default: break;
- }
- }
- }
-
- return self;
- }
-
- - print:sender
- {
- return [self printPSCode:sender];
- }
-
- - step
- {
- id menuList = [mainMenu itemList];
- int i, r, c;
-
- if (neitherSide)
- return self;
-
- if (((currentStone == BLACKSTONE) && (blackSide == 0)) ||
- ((currentStone == WHITESTONE) && (whiteSide == 0)))
- return self;
-
- if (bothSides) {
- while ((gameRunning) && (!finished)) {
- [self selectMove];
- NXPing();
- [self updateInfo];
- }
-
- NXPing();
-
- [menuList getNumRows: &r numCols: &c];
- for( i = 0; i < r; i++ )
- [[menuList cellAt: i :0] setEnabled: YES];
- [mainMenu display];
- } else {
- [passButton setEnabled: NO];
- [passButton display];
- [self selectMove];
- [self updateInfo];
- [passButton setEnabled: YES];
- [passButton display];
- }
- return self;
- }
-
- - selectMove
- {
- id menuList = [mainMenu itemList];
- int i, j, r, c;
-
- NXPing();
-
- [menuList getNumRows: &r numCols: &c];
- for( i = 0; i < r-1; i++ )
- [[menuList cellAt: i :0] setEnabled: NO];
- [mainMenu display];
- if( !bothSides )
- [stopButton setEnabled: NO];
- else
- [stopButton setEnabled: YES];
-
- genmove( &i, &j );
- if (i >= 0)
- {
- p[i][j] = currentStone;
- [self flashStone: i: j];
- }
-
- [self selectMoveEnd];
-
- if (i >= 0)
- {
- [self lockFocus];
- if (currentStone == BLACKSTONE)
- [self showBlackStone];
- else
- [self showWhiteStone];
- [self unlockFocus];
- }
-
- NXPing();
- return self;
- }
-
- - selectMoveEnd
- {
- id menuList = [mainMenu itemList];
- int i, r, c;
- NXEvent peek_ev, *get_ev;
-
- NXPing();
-
- [menuList getNumRows: &r numCols: &c];
- if( !bothSides )
- for( i = 0; i < r; i++ )
- [[menuList cellAt: i :0] setEnabled: YES];
- [mainMenu display];
- [startButton setEnabled: YES];
- [stopButton setEnabled: YES];
- if( [NXApp peekNextEvent: NX_MOUSEDOWNMASK into: &peek_ev] ){
- get_ev = [NXApp getNextEvent: NX_MOUSEDOWNMASK];
- [NXApp sendEvent: get_ev];
- }
- NXPing();
-
- return self;
- }
-
- - flashStone: (int)x :(int)y
- {
-
- setStoneLoc(x, y);
- // stoneX = BASEBOARDX - RADIUS + (x*STONEWIDTH);
- // stoneY = BASEBOARDY - RADIUS + ((18 - y)*STONEHEIGHT);
-
- [self lockFocus];
- [self showGrayStone];
- [self unlockFocus];
-
- return self;
- }
-
-
- @end
-
-