//#import #import #import #import #import #import #import // NSBeep #import #import // NSZeroPoint #import // MAX, ABS #import #include // own interface #import "Board.h" // messaging objects #import "Square.h" #import "Chess.h" // NSApp // portability layer #import "gnuglue.h" // floor_value // square colors #define BLACK_SQUARE_COLOR (0.5) #define WHITE_SQUARE_COLOR (5.0 / 6.0) // private functions static NSString *whitePiece( p ) short p; { switch( p ) { case PAWN: return @"white_pawn"; case ROOK: return @"white_rook"; case KNIGHT: return @"white_knight"; case BISHOP: return @"white_bishop"; case KING: return @"white_king"; case QUEEN: return @"white_queen"; default: break; } return nil; } static NSString *blackPiece( p ) short p; { switch( p ) { case PAWN: return @"black_pawn"; case ROOK: return @"black_rook"; case KNIGHT: return @"black_knight"; case BISHOP: return @"black_bishop"; case KING: return @"black_king"; case QUEEN: return @"black_queen"; default: break; } return nil; } // Board implementations @implementation Board - (id)initWithFrame: (NSRect) f { self = [super initWithFrame: f]; if( self ) { int r, c; NSSize size; [self allocateGState]; size.width = f.size.width / 8.0; size.height = f.size.height / 8.0; backBitmap = [[NSImage alloc] initWithSize: size]; for( r = 0; r < 8; r++ ) { for( c = 0; c < 8; c++ ) { Square *aSquare; BOOL even; float bk; aSquare = [[Square alloc] init]; even = ( ! ((r + c) % 2) ); bk = ( even ) ? BLACK_SQUARE_COLOR : WHITE_SQUARE_COLOR; [aSquare setBackground: bk]; square[r][c] = aSquare; } } [self setupPieces]; return self; } return nil; } - (void) setupPieces { short *pieces = default_pieces(); short *colors = default_colors(); [self layoutBoard: pieces color: colors]; return; } - (void) layoutBoard: (short *)p color: (short *)c { int sq; for( sq = 0; sq < SQUARE_COUNT; sq++ ) { int row = sq / 8; int col = sq % 8; [self placePiece: p[sq] at: row: col color: c[sq]]; } return; } - (void) placePiece: (short)p at: (int)row : (int)col color: (short)c { Square *theSquare = square[row][col]; NSString *piece = ( c == WHITE ) ? whitePiece( p ) : blackPiece( p ); NSImage *image = ( piece ) ? [NSImage imageNamed: piece] : nil; [theSquare setImage: image]; return; } - (void) slidePieceFrom: (int)row1 : (int)col1 to: (int)row2 : (int)col2 { Square *theSquare; NSString *icon; int controlGState; NSRect pieceRect; NSPoint backP, endP, winP, roundedBackP; float incX, incY; int i, increments; theSquare = square[row1][col1]; //icon = [[theSquare image] name]; icon = [theSquare imageName]; if( [icon isEqual: @""] ) icon = nil; // ? if( ! icon ) return; controlGState = [self gState]; pieceRect.size.width = (float)floor_value( (double)([self frame].size.width / 8.0) ); pieceRect.size.height = (float)floor_value( (double)([self frame].size.height / 8.0) ); backP.x = ( (float)col1 * pieceRect.size.width ); backP.y = ( (float)row1 * pieceRect.size.height ); endP.x = ( (float)col2 * pieceRect.size.width ); endP.y = ( (float)row2 * pieceRect.size.height ); [self lockFocus]; PSgsave(); /* Draw over the piece we are moving. */ pieceRect.origin.x = col1 * pieceRect.size.width; pieceRect.origin.y = row1 * pieceRect.size.height; [theSquare drawBackground: pieceRect inView: self]; /* Save background */ [backBitmap lockFocus]; PSgsave(); roundedBackP.x = floor(backP.x); roundedBackP.y = floor(backP.y); winP = [[self superview] convertPoint: roundedBackP fromView: self]; PScomposite( winP.x, winP.y, pieceRect.size.width, pieceRect.size.height, controlGState, (float)0.0, (float)0.0, NSCompositeCopy ); PSgrestore(); [backBitmap unlockFocus]; incX = endP.x - backP.x; incY = endP.y - backP.y; increments = (int) MAX( ABS(incX), ABS(incY) ) / 7; incX = incX / increments; incY = incY / increments; for( i = 0; i < increments; i++ ){ /* Restore old background */ [self lockFocus]; [backBitmap compositeToPoint: backP operation: NSCompositeCopy]; [self unlockFocus]; [[self window] flushWindow]; /* Save new background */ backP.x += incX; backP.y += incY; [backBitmap lockFocus]; PSgsave(); roundedBackP.x = floor(backP.x); roundedBackP.y = floor(backP.y); pieceRect.origin = roundedBackP; winP = [[self superview] convertPoint: roundedBackP fromView: self]; PScomposite( winP.x, winP.y, pieceRect.size.width, pieceRect.size.height, controlGState, (float)0.0, (float)0.0, NSCompositeCopy ); PSgrestore(); [backBitmap unlockFocus]; /* Draw piece at new location. */ [theSquare drawInteriorWithFrame: pieceRect inView: self]; [[self window] flushWindow]; PSsetgray( NSBlack ); PSsetlinewidth( (float)2.0 ); PSclippath(); PSstroke(); [[self window] flushWindow]; } PSgrestore(); [self unlockFocus]; return; } - (int) pieceAt: (int)row : (int)col { if( row >= 0 && col >= 0 ) { Square *theSquare = square[row][col]; return( [theSquare pieceType] ); } return (int)NO_PIECE; } - (void) highlightSquareAt: (int)row : (int)col { NSRect cr; Square *theSquare = square[row][col]; [self lockFocus]; cr.size.width = [self frame].size.width / 8.0; cr.size.height = [self frame].size.height / 8.0; cr.origin.x = col * cr.size.width; cr.origin.y = row * cr.size.height; [theSquare highlight: cr inView: self]; PSsetgray( NSBlack ); PSsetlinewidth( (float)2.0 ); PSclippath(); PSstroke(); [[self window] flushWindow]; [self unlockFocus]; return; } - (void) unhighlightSquareAt: (int)row : (int)col { return; } - (void) flashSquareAt: (int)row : (int)col { return; } - (void) print: (id)sender { NSPrintInfo *pi = [NSPrintInfo sharedPrintInfo]; NSSize ps = [pi paperSize]; NSSize fs = [self frame].size; float hm = (ps.width - fs.width) / 2.0; float vm = (ps.height - fs.height) / 2.0; [pi setLeftMargin: hm]; [pi setRightMargin: hm]; [pi setTopMargin: vm]; [pi setBottomMargin: vm]; [self lockFocus]; printImage = [[NSBitmapImageRep alloc] initWithFocusedViewRect: [self bounds]]; [self unlockFocus]; [super print: sender]; [printImage release]; printImage = nil; return; } - (void) drawRect: (NSRect)f { if( ! printImage ) { int r, c; NSRect cr; PSgsave(); cr.size.width = f.size.width / 8.0; cr.size.height = f.size.height / 8.0; for( r = 0; r < 8; r++ ) { cr.origin.y = r * cr.size.height; for( c = 0; c < 8; c++ ) { Square *theSquare = square[r][c]; cr.origin.x = c * cr.size.width; [theSquare drawWithFrame: cr inView: self]; } } PSsetgray( NSBlack ); PSsetlinewidth( (float)2.0 ); PSclippath(); PSstroke(); PSgrestore(); } else { [printImage draw]; } return; } - (void) mouseDown: (NSEvent *)event { NSException *exception = nil; if ( [NSApp bothsides] ) { NSBeep(); } else if( [NSApp finished] ) { [NSApp finishedAlert]; [[self window] setAcceptsMouseMovedEvents: YES]; NS_DURING while( [event type] != NSLeftMouseUp ) { unsigned int mask = (NSLeftMouseUpMask | NSLeftMouseDraggedMask); event = [[self window] nextEventMatchingMask: mask]; } NS_HANDLER exception = localException; NS_ENDHANDLER } else { NSPoint pickedP, backP, roundedBackP, winP; NSRect pieceRect, backR; int r, c; Square *theSquare; int controlGState; NSString *icon; NSPoint p; pickedP = [event locationInWindow]; pickedP = [self convertPoint: pickedP fromView: nil]; backP = pickedP; //pieceRect.origin = NSZeroPoint; pieceRect.size.width = [self frame].size.width / 8.0; pieceRect.size.height = [self frame].size.height / 8.0; r = floor_value( (double)(pickedP.y / pieceRect.size.height) ); c = floor_value( (double)(pickedP.x / pieceRect.size.width) ); pieceRect.size.width =(float)floor_value((double)pieceRect.size.width); pieceRect.size.height=(float)floor_value((double)pieceRect.size.height); backR.origin = NSZeroPoint; backR.size = pieceRect.size; pickedP.x = pickedP.x - (((float)c) * pieceRect.size.width); pickedP.y = pickedP.y - (((float)r) * pieceRect.size.height); theSquare = square[r][c]; //icon = [[theSquare image] name]; icon = [theSquare imageName]; if( [icon isEqual: @""] ) icon = nil; // ? if( icon && [self isEnabled] ) { controlGState = [self gState]; if( ! controlGState ) { [self allocateGState]; controlGState = [self gState]; } [self lockFocus]; PSgsave(); /* Draw over the piece we are moving. */ pieceRect.origin.x = c * pieceRect.size.width; pieceRect.origin.y = r * pieceRect.size.height; [theSquare drawBackground: pieceRect inView: self]; /* Save background */ [backBitmap lockFocus]; PSgsave(); roundedBackP.x = floor(backP.x); roundedBackP.y = floor(backP.y); winP = [[self superview] convertPoint: roundedBackP fromView: self]; PScomposite( winP.x, winP.y, backR.size.width, backR.size.height, controlGState, (float)0.0, (float)0.0, NSCompositeCopy ); PSgrestore(); [backBitmap unlockFocus]; } [[self window] setAcceptsMouseMovedEvents: YES]; NS_DURING while ([event type] != NSLeftMouseUp) { unsigned int mask = (NSLeftMouseUpMask | NSLeftMouseDraggedMask); event = [[self window] nextEventMatchingMask: mask]; p = [event locationInWindow]; p = [self convertPoint: p fromView: nil]; if( icon && [self isEnabled] ) { /* Restore old background */ [self lockFocus]; [backBitmap compositeToPoint:roundedBackP operation:NSCompositeCopy]; [self unlockFocus]; /* Save new background */ backP.x = pieceRect.origin.x = p.x - pickedP.x; backP.y = pieceRect.origin.y = p.y - pickedP.y; [backBitmap lockFocus]; PSgsave(); roundedBackP.x = floor(backP.x); roundedBackP.y = floor(backP.y); winP = [[self superview] convertPoint: roundedBackP fromView: self]; PScomposite( winP.x, winP.y, backR.size.width, backR.size.height, controlGState, (float)0.0, (float)0.0, NSCompositeCopy ); PSgrestore(); [backBitmap unlockFocus]; /* Draw piece at new location. */ [theSquare drawInteriorWithFrame: pieceRect inView: self]; PSsetgray( NSBlack ); PSsetlinewidth( (float)2.0 ); PSclippath(); PSstroke(); [[self window] flushWindow]; } } NS_HANDLER exception = localException; NS_ENDHANDLER if( icon && [self isEnabled] ) { NSSize frame = [self frame].size; int r2 = floor_value( (double)(p.y / (frame.height / 8.0)) ); int c2 = floor_value( (double)(p.x / (frame.width / 8.0)) ); if( r2 != r || c2 != c ) { if( ! [NSApp makeMoveFrom: r : c to: r2 : c2] ) { PSWait(); } } [self display]; PSgrestore(); [self unlockFocus]; } } if( exception ) [exception raise]; return; } @end // Local Variables: // tab-width: 8 // End: