home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Education Sampler 1992 [NeXTSTEP]
/
Education_1992_Sampler.iso
/
NeXT
/
GnuSource
/
Chess-9
/
Board3D.m
< prev
next >
Wrap
Text File
|
1992-03-07
|
16KB
|
658 lines
#import <c.h>
#include <sys/types.h>
#include <sys/time.h>
#import <appkit/appkit.h>
#import "chess_strings.h"
#import "Chess.h"
#import "gnuchess.h"
#import "Board3D.h"
#import "Square3D.h"
#define PIECE_WIDTH_3D 55
#define BACK_STORE_WIDTH 80
#define PIECE_HEIGHT_3D 95
#define BACK_STORE_HEIGHT 110
extern PSWtrapezoid ();
/* Each set of points describes the vertical lines along the board. */
struct NXLine {
NXPoint a,b;
};
#define BASE_X 89
struct NXLine vertical[] = {
{{BASE_X,122},{BASE_X+61,467}},
{{BASE_X+71,122},{BASE_X+111,467}},
{{BASE_X+135,122},{BASE_X+162,467}},
{{BASE_X+200,122},{BASE_X+212,467}},
{{BASE_X+265,122},{BASE_X+265,467}},
{{BASE_X+330,122},{BASE_X+316,467}},
{{BASE_X+393,122},{BASE_X+367,467}},
{{BASE_X+459,122},{BASE_X+419,467}},
{{BASE_X+524,122},{BASE_X+469,467}}
};
/* Each coordinate describes the y value of each line of the board. */
#define BASE_Y 132
NXCoord horizontal[] = {
BASE_Y, BASE_Y+54, BASE_Y+106, BASE_Y+153,
BASE_Y+196, BASE_Y+237, BASE_Y+277, BASE_Y+312, BASE_Y+345
};
id pieces3D;
void convert_point( NXPoint *p, int *r, int *c );
@implementation Board3D
+ newFrame: (const NXRect *)f
{
int r, c, i;
self = [super newFrame: f];
[self allocateGState];
background = [NXImage newFromSection: "3d_board.tiff"];
[background setFlipped: NO];
pieces3D = [NXImage newFromSection: "3d_pieces.tiff"];
[pieces3D setFlipped: NO];
backBitmap = [Bitmap newSize: BACK_STORE_WIDTH: BACK_STORE_HEIGHT
type: NX_UNIQUEBITMAP];
[backBitmap setFlip: NO];
for( r = 0; r < 8; r++ )
for( c = 0; c < 8; c++ )
square[r][c] = [Square3D new];
[self setupPieces];
return self;
}
- setBackgroundBitmap: sender
{
background = sender;
[background setFlipped: NO];
}
- backgroundBitmap {return pieces3D;}
- setupPieces
{
[self layoutBoard: Stboard color:Stcolor];
}
- layoutBoard: (short *)b color: (short *)c
{
int sq, row, col;
PSgsave();
PSrotate ( 10.0 );
for (sq = 0; sq < 64; sq++){
row = sq / 8;
col = sq % 8;
[self placePiece: b[sq] at: row: col color: c[sq]];
}
PSgrestore();
}
squareOrigin( int r, int c, NXCoord *x, NXCoord *y )
{
NXCoord dx,m,b;
*y = horizontal[r];
dx = (vertical[c].a.x-vertical[c].b.x);
m = (vertical[c].a.y - vertical[c].b.y) / dx;
b = vertical[c].b.y - (m*vertical[c].b.x);
*x = dx ? (horizontal[r] - b)/m : vertical[c].a.x;
}
squareBounds( int r, int c, NXPoint *p1, NXPoint *p2, NXPoint *p3, NXPoint *p4 )
/*
(p2)----(p4)
| |
| |
(p1)----(p3)
*/
{
NXCoord dx,m,b;
dx = (vertical[c].a.x-vertical[c].b.x);
m = (vertical[c].a.y - vertical[c].b.y) / dx;
b = vertical[c].b.y - (m*vertical[c].b.x);
p1->y = floor( horizontal[r] );
p1->x = floor( dx ? (horizontal[r] - b)/m : vertical[c].a.x );
p2->y = floor( horizontal[r+1] );
p2->x = floor( dx ? (horizontal[r+1] - b)/m : vertical[c].a.x );
dx = (vertical[c+1].a.x-vertical[c+1].b.x);
m = (vertical[c+1].a.y - vertical[c+1].b.y) / dx;
b = vertical[c+1].b.y - (m*vertical[c+1].b.x);
p3->y = floor( horizontal[r] );
p3->x = floor( dx ? (horizontal[r] - b)/m : vertical[c+1].a.x );
p4->y = floor( horizontal[r+1] );
p4->x = floor( dx ? (horizontal[r+1] - b)/m : vertical[c+1].a.x );
}
- slidePieceFrom: (int)r1 : (int)c1 to: (int)r2 : (int)c2
{
NXPoint p, backP, centerP, endP;
NXRect backR;
int controlGState, type, color, increments, dr, dc, i;
NXRect newLocation, oldLocation;
NXCoord incX, incY;
[self lockFocus];
type = [square[r1][c1] type];
color = [square[r1][c1] colorVal];
oldLocation = *[square[r1][c1] location];
if( !type )
return self;
squareOrigin( r2, c2, &endP.x, &endP.y );
/* Remove piece and then save background */
[square[r1][c1] setType: 0 color: 0];
[self drawSelf: 0 : 0];
squareOrigin( r1, c1, &backP.x, &backP.y );
controlGState = [self gState];
[backBitmap lockFocus];
PSgsave();
PScomposite( backP.x, backP.y, BACK_STORE_WIDTH, BACK_STORE_HEIGHT,
controlGState,
0.0, 0.0, NX_COPY);
PSgrestore();
[backBitmap unlockFocus];
[square[r1][c1] setType: type color: color];
[square[r1][c1] drawInside: 0 inView: self];
[square[r1][c1] setMoving: YES];
PSflushgraphics();
NXPing();
incX = endP.x - backP.x;
incY = endP.y - backP.y;
increments = (int) MAX( ABS(incX), ABS(incY) ) / 7; // was 5 gcr
incX = incX / increments;
incY = incY / increments;
for( i = 0; i < increments; i++ ){
/* Restore old background */
[self lockFocus];
[backBitmap composite:NX_COPY toPoint: &backP];
[self unlockFocus];
backP.x += incX;
backP.y += incY;
convert_point( &backP, &dr, &dc );
/* Save new background */
[backBitmap lockFocus];
// PSgsave();
PScomposite( backP.x, backP.y,
BACK_STORE_WIDTH, BACK_STORE_HEIGHT,
controlGState,
0.0, 0.0, NX_COPY);
// PSgrestore();
[backBitmap unlockFocus];
/* Draw piece at new location. */
[square[r1][c1] setRow: dr];
newLocation.origin = backP;
newLocation.size.width = PIECE_WIDTH_3D;
newLocation.size.height = PIECE_HEIGHT_3D;
[square[r1][c1] setLocation: &newLocation];
[square[r1][c1] drawInside: 0 inView: self];
PSflushgraphics();
NXPing();
}
[square[r1][c1] setMoving: NO];
[self unlockFocus];
}
- placePiece: (int)p at: (int)r : (int)c color: (int)col
{
NXRect l;
NXCoord m,b,dx,x;
[square[r][c] setType: p color: col];
[square[r][c] setRow: r];
l.origin.y = horizontal[r];
dx = (vertical[c].a.x-vertical[c].b.x);
m = (vertical[c].a.y - vertical[c].b.y) / dx;
b = vertical[c].b.y - (m*vertical[c].b.x);
x = dx ? (horizontal[r] - b)/m : vertical[c].a.x;
l.origin.x = x;
dx = (vertical[c+1].a.x-vertical[c+1].b.x);
m = (vertical[c+1].a.y - vertical[c+1].b.y) / dx;
b = vertical[c+1].b.y - (m*vertical[c+1].b.x);
x = dx ? (horizontal[r] - b)/m : vertical[c+1].a.x;
l.size.width = x - l.origin.x;
l.size.height = 99999;
[square[r][c] setLocation: &l];
}
- (int)typeAt: (int)r : (int)c
{
return( (r>=0 && c>=0) ? [square[r][c] type] : 0 );
}
- (int)colorAt: (int)r : (int)c
{
return( (r>=0 && c>=0) ? [square[r][c] colorVal] : 0 );
}
- drawRows: (int)r from: (int)c
{
while( r >= 0 ){
if( [self typeAt: r : c] && ![square[r][c] moving] )
[square[r][c] drawInside: 0 inView: self];
r--;
}
}
- unhighlightSquareAt: (int)r : (int) c
{
NXPoint p1,p2,p3,p4,to;
NXRect backR;
squareBounds( r, c, &p1, &p2, &p3, &p4 );
p1.x = p1.x - 3;
p1.y = p1.y - 3;
p2.x = p2.x - 3;
p2.y = p2.y + 3;
p3.x = p3.x + 3;
p3.y = p3.y - 3;
p4.x = p4.x + 3;
p4.y = p4.y + 3;
to.y = p1.y;
to.x = MIN(p1.x,p2.x);
backR.origin = to;
backR.size.width = MAX(p3.x,p4.x) - to.x;
backR.size.height = p2.y - p1.y;
[self lockFocus];
PSgsave();
PSsetlinewidth( 3.0 );
PSsetgray( 1.0 );
PSnewpath();
PSmoveto( p1.x, p1.y );
PSlineto( p2.x, p2.y );
PSlineto( p4.x, p4.y );
PSlineto( p3.x, p3.y );
PSlineto( p1.x, p1.y );
PSclosepath;
PSclip();
[background composite: NX_COPY fromRect: &backR toPoint: &to];
PSgrestore();
if( [self typeAt:r :c] || ( r > 0 && [self typeAt:r-1 :c]) )
[self drawRows: r from: c];
PSflushgraphics();
NXPing();
[self unlockFocus];
}
- highlightSquareAt: (int)r : (int) c
{
struct timeval timeout;
NXPoint p1,p2,p3,p4;
short idx;
float color = 0.0;
squareBounds( r, c, &p1, &p2, &p3, &p4 );
[self lockFocus];
PSgsave();
PSsetlinewidth( 3.0 );
PSmoveto( p1.x, p1.y );
PSlineto( p2.x, p2.y );
PSlineto( p4.x, p4.y );
PSlineto( p3.x, p3.y );
PSlineto( p1.x, p1.y );
PSclosepath();
/* flash 2 times */
for ( idx=1; idx <= 3; idx++ ) {
color = 1.0 - color;
PSsetgray( color );
PSgsave();
PSstroke();
PSgrestore();
if( [self typeAt:r :c] || ( r > 0 && [self typeAt:r-1 :c]) )
[self drawRows: r from: c];
PSflushgraphics();
NXPing();
if( ![square[r][c] moving] ){
timeout.tv_sec = 0;
timeout.tv_usec = 15000;
select( 0, 0, 0, 0, &timeout );
}
}
PSgrestore();
/****
PSgsave();
PSsetlinewidth( 3.0 );
PSsetgray( 0.0 );
PSnewpath();
PSmoveto( p1.x, p1.y );
PSlineto( p2.x, p2.y );
PSlineto( p4.x, p4.y );
PSlineto( p3.x, p3.y );
PSlineto( p1.x, p1.y );
PSclosepath;
PSstroke();
PSgrestore();
if( [self typeAt:r :c] || ( r > 0 && [self typeAt:r-1 :c]) )
[self drawRows: r from: c];
PSflushgraphics();
NXPing();
if( ![square[r][c] moving] ){
timeout.tv_sec = 0;
timeout.tv_usec = 150000;
select( 0, 0, 0, 0, &timeout );
}
PSgsave();
PSsetlinewidth( 3.0 );
PSsetgray( 1.0 );
PSnewpath();
PSmoveto( p1.x, p1.y );
PSlineto( p2.x, p2.y );
PSlineto( p4.x, p4.y );
PSlineto( p3.x, p3.y );
PSlineto( p1.x, p1.y );
PSclosepath;
PSstroke();
PSgrestore();
if( [self typeAt:r :c] || ( r > 0 && [self typeAt:r-1 :c]) )
[self drawRows: r from: c];
PSflushgraphics();
NXPing();
if( ![square[r][c] moving] ){
timeout.tv_sec = 0;
timeout.tv_usec = 150000;
select( 0, 0, 0, 0, &timeout );
}
******/
[self unhighlightSquareAt: r : c];
[self unlockFocus];
}
- flashSquareAt: (int)r : (int) c
{
NXPoint p1,p2,p3,p4;
squareBounds( r, c, &p1, &p2, &p3, &p4 );
[self lockFocus];
PSgsave();
PSsetlinewidth( 3.0 );
PSsetgray( 1.0 );
PSnewpath();
PSmoveto( p1.x, p1.y );
PSlineto( p2.x, p2.y );
PSlineto( p4.x, p4.y );
PSlineto( p3.x, p3.y );
PSlineto( p1.x, p1.y );
PSclosepath;
PSstroke();
PSgrestore();
if( [self typeAt:r :c] || ( r > 0 && [self typeAt:r-1 :c]) )
[self drawRows: r from: c];
[self unlockFocus];
}
- printPSCode: sender
{
id pi = [NXApp printInfo];
const NXRect *pr;
NXCoord lm, rm, tm, bm;
pr = [pi paperRect];
lm = rm = (pr->size.width - frame.size.width) / 2.0;
tm = bm = (pr->size.height - frame.size.height) / 2.0;
[pi setMarginLeft: lm right: rm top: tm bottom: bm];
[self lockFocus];
NXSizeBitmap( &bounds, &print_size, &print_pwide, &print_phigh,
&print_bps, &print_ssp, &print_config, &print_mask );
print_image = (void *)malloc( print_size );
NXReadBitmap( &bounds, print_pwide, print_phigh, print_bps, print_ssp,
print_config, print_mask, print_image, 0, 0, 0, 0 );
[super printPSCode: self];
free( print_image );
[self unlockFocus];
return self;
}
- drawSelf:(const NXRect *)f :(int)rectCount;
{
int r, c;
NXRect cr;
NXPoint p;
p.x = p.y = 0.0;
if( NXDrawingStatus == NX_DRAWING ){
PSgsave();
[background composite: NX_COPY toPoint: &p];
for( r = 7; r >= 0; r-- ){
for( c = 7; c >= 0; c-- ){
[square[r][c] drawSelf: &cr inView: self];
}
}
PSgrestore();
}
else{
NXImageBitmap( &bounds, print_pwide, print_phigh, print_bps, print_ssp,
print_config, print_mask, print_image, 0, 0, 0, 0 );
}
}
- mouseDown: (NXEvent *)event
{
NXPoint p, pickedP, backP, centerP;
NXHandler handler;
NXRect pieceRect, backR;
int r, c, r2, c2, mask, controlGState, t, col;
unsigned short mv;
NXRect newLocation, oldLocation;
NXCoord x, y;
int hi_r = -1, hi_c = -1;
if ( [NXApp bothsides] ) {
NXBeep();
return self;
}
if( [NXApp finished] ){
[NXApp finishedAlert];
handler.code = 0;
[window addToEventMask: NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
NX_DURING
while (event->type != NX_MOUSEUP){
event = [NXApp getNextEvent:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
}
NX_HANDLER
handler = NXLocalHandler;
NX_ENDHANDLER
return self;
}
pickedP = event->location;
[self convertPoint:&pickedP fromView:nil];
backP = pickedP;
r = -1;
c = -1;
convert_point( &pickedP, &r, &c );
if( r == -1 || c == -1 )
return self;
[self lockFocus];
t = [square[r][c] type];
col = [square[r][c] colorVal];
oldLocation = *[square[r][c] location];
if( t ){
[square[r][c] setType: 0 color: 0];
[self drawSelf: 0 : 0];
[self flashSquareAt: r : c];
hi_r = r; hi_c = c;
/* Save background */
squareOrigin( r, c, &x, &y );
backP.x = x;
backP.y = y;
controlGState = [self gState];
[backBitmap lockFocus];
PSgsave();
PScomposite( backP.x, backP.y, BACK_STORE_WIDTH, BACK_STORE_HEIGHT,
controlGState,
0.0, 0.0, NX_COPY);
PSgrestore();
[backBitmap unlockFocus];
[square[r][c] setType: t color: col];
[square[r][c] drawInside: 0 inView: self];
[square[r][c] setMoving: YES];
PSflushgraphics();
NXPing();
pickedP.x = floor( pickedP.x - x );
pickedP.y = floor( pickedP.y - y );
}
r2 = 0; c2 = 0;
handler.code = 0;
[window addToEventMask: NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
NX_DURING
while (event->type != NX_MOUSEUP){
event = [NXApp getNextEvent:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
if( !t )
continue;
p = event->location;
[self convertPoint:&p fromView:nil];
/* Restore old background */
[self lockFocus];
[backBitmap composite:NX_COPY toPoint: &backP];
[self unlockFocus];
backP.x = p.x - pickedP.x;
backP.y = p.y - pickedP.y;
/* Un/highlight square */
centerP.y = backP.y + PIECE_HEIGHT_3D/4.0;
centerP.x = backP.x + PIECE_WIDTH_3D/2.0;
convert_point( ¢erP, &r2, &c2);
if( r2 != hi_r || c2 != hi_c ){
if( hi_r != -1 && hi_c != -1 )
[self unhighlightSquareAt: hi_r : hi_c];
hi_r = r2; hi_c = c2;
[self flashSquareAt: r2 : c2];
}
/* Save new background */
[backBitmap lockFocus];
PSgsave();
PScomposite( backP.x, backP.y,
BACK_STORE_WIDTH, BACK_STORE_HEIGHT,
controlGState,
0.0, 0.0, NX_COPY);
PSgrestore();
[backBitmap unlockFocus];
/* Draw piece at new location. */
[square[r][c] setRow: r2];
newLocation.origin.x = p.x - pickedP.x;
newLocation.origin.y = p.y - pickedP.y;
newLocation.size.width = PIECE_WIDTH_3D;
newLocation.size.height = PIECE_HEIGHT_3D;
[square[r][c] setLocation: &newLocation];
[square[r][c] drawInside: 0 inView: self];
PSflushgraphics();
NXPing();
}
NX_HANDLER
handler = NXLocalHandler;
NX_ENDHANDLER
if( t ){
[square[r][c] setMoving: NO];
if( r2 != r || c2 != c ){
if( ![NXApp makeMoveFrom: r : c to: r2 : c2] ){
[square[r][c] setLocation: &oldLocation];
[square[r][c] setType: t color: col];
[square[r][c] setRow: r];
}
}
else{
[square[r][c] setLocation: &oldLocation];
[square[r][c] setType: t color: col];
[square[r][c] setRow: r];
}
[self display];
PSflushgraphics();
NXPing();
}
[self unlockFocus];
if (handler.code) {
NX_RAISE(handler.code, handler.data1, handler.data2);
}
}
NXCoord
check_point( struct NXLine *l, NXPoint *p )
{
NXCoord dx,dy,dx1,dy1;
dx = l->a.x - l->b.x;
dy = l->a.y - l->b.y;
dx1 = p->x - l->a.x;
dy1 = p->y - l->a.y;
return( dx*dy1 - dy*dx1 );
}
void
convert_point( NXPoint *p, int *r, int *c )
{
NXCoord dx,dy,dx1,dy1,m;
int i;
for( i = 0; i < 8; i++ )
if( p->y >= horizontal[i] && p->y <= horizontal[i+1] ){
*r = i;
break;
}
for( i = 0; i < 8; i++ ){
NXCoord m1,m2;
m1 = check_point( &vertical[i], p );
m2 = check_point( &vertical[i+1], p );
if( m1 > 0 && m2 < 0 ){
*c = i;
break;
}
}
}
@end