This is Chess.m in view mode; [Download] [Up]
#include <stdio.h> #include <ctype.h> #include <sys/param.h> #include <sys/times.h> #include <sys/file.h> #include <pwd.h> #import <appkit/appkit.h> #import "chess_strings.h" #import "Chess.h" #import "gnuchess.h" #import "gnuglue.h" #import "Clock.h" #import "Board.h" #import "Board3D.h" #import "ResponseMeter.h" extern id NXWait, NXArrow; extern short PieceList[2][16]; extern short PieceCnt[2]; extern gnuchess_main_init(); extern NewGame(); extern algbr(); /* extern getsectdata(); */ extern VerifyMove(); extern SelectMoveStart(); extern SelectMoveEnd(); extern SelectLoop(); short GameQueens[240]; #ifdef NeXT_DEBUG #define chess_debug(x) { printf x; } #else #define chess_debug(x) #endif @implementation Chess static void Counter(); + initialize { gnuchess_main_init(); } + new { self = [super new]; pwen = getpwuid( getuid() ); pref.time_control_minutes = 5; pref.time_control_moves = 60; pref.opponent = white; pref.computer = black; pref.bothsides = false; pref.cheat = YES; pref.white_name = pwen->pw_gecos; pref.black_name = (char *)COMPUTER; return self; } /* Get InterfaceBuilder outlets. */ - setClockWindow: anObject { clockWindow = anObject; } - clockWindow { return clockWindow; } - setWhiteSideMatrix: anObject { whiteSideMatrix = anObject; } - setBlackSideMatrix: anObject { blackSideMatrix = anObject; } - setForceButton: anObject { forceButton = anObject; } - setStartButton: anObject { startButton = anObject; } - setSetButton: anObject { setButton = anObject; } - setWhiteName: anObject { whiteName = anObject; } - setBlackName: anObject { blackName = anObject; } - setInfoPanel: anObject { infoPanel = anObject; } - setInfoScroll: anObject { infoScroll = anObject; } - setWhiteClock: anObject { whiteClock = anObject; } - whiteClock { return whiteClock; } - setBlackClock: anObject { blackClock = anObject; } - blackClock { return blackClock; } - setWhiteClockText: anObject { whiteClockText = anObject; } - setBlackClockText: anObject { blackClockText = anObject; } - setBoardWindow: anObject { boardWindow = anObject; } - setLevelText: anObject { levelText = anObject; } - setWhiteMeter: anObject { whiteMeter = anObject; } - whiteMeter { return whiteMeter; } - setBlackMeter: anObject { blackMeter = anObject; } - blackMeter { return blackMeter; } - setLevelSlider: anObject { levelSlider = anObject; } - setBoard3D: anObject { gameBoard = board3D = anObject; } - setBoard2D: anObject { board2D = anObject; [board2D removeFromSuperview]; } /* Action methods for InterfaceBuilder objects. */ - print: sender { [gameBoard printPSCode: sender]; return self; } - (int) openFile:(char const *)s ok:(int *)flag { GetGame( s ); *flag = YES; return 0; } - plastic: sender { id plastic; if( gameBoard == board2D ) return self; plastic = [Bitmap findBitmapFor: "3d_plastic.tiff"]; [gameBoard setBackgroundBitmap: plastic]; [gameBoard display]; } - granite: sender { id granite; if( gameBoard == board2D ) return self; granite = [Bitmap findBitmapFor: "3d_board.tiff"]; [gameBoard setBackgroundBitmap: granite]; [gameBoard display]; } - gameBoard { return gameBoard; } - view2D: sender { NXRect b; id v; if( gameBoard == board2D ) return self; v = [gameBoard superview]; [v getBounds: &b]; [v lockFocus]; PSgsave(); PSsetgray( NX_BLACK ); PSrectfill( 0, 0, b.size.width, b.size.height ); PSgrestore(); [v unlockFocus]; [gameBoard removeFromSuperview]; [v addSubview: board2D]; gameBoard = board2D; [gameBoard layoutBoard: board color: color]; [gameBoard display]; NXPing(); } - view3D: sender { id v; if( gameBoard == board3D ) return self; v = [gameBoard superview]; [gameBoard removeFromSuperview]; [v addSubview: board3D]; gameBoard = board3D; [gameBoard layoutBoard: board color: color]; [gameBoard display]; NXPing(); } - levelSliding: sender /* Change the text displayed below the level slider to indicate what the level means. */ { char buf[32]; int moves, minutes; Level = [levelSlider intValue]; switch (Level){ case 1 : moves = 60; minutes = 5; break; case 2 : moves = 60; minutes = 15; break; case 3 : moves = 60; minutes = 30; break; case 4 : moves = 40; minutes = 30; break; case 5 : moves = 40; minutes = 60; break; case 6 : moves = 40; minutes = 120; break; case 7 : moves = 40; minutes = 240; break; case 8 : moves = 1; minutes = 15; break; case 9 : moves = 1; minutes = 60; break; case 10 : moves = 1; minutes = 600; break; } if( moves > 1 ) sprintf( buf, "%d moves in %d minutes", moves, minutes ); else sprintf( buf, "%d move in %d minutes", moves, minutes ); [levelText setStringValue: buf]; } - setPreferences: sender /* Actually set the preferences. */ { int whiteSide = [whiteSideMatrix selectedRow]; int blackSide = [blackSideMatrix selectedRow]; int change = NO; int button; button = NXRunAlertPanel( 0, "Start a new game with these Preferences?", "Yes", "No", 0 ); switch( (Level = [levelSlider intValue]) ){ case 1 : pref.time_control_moves = 60; pref.time_control_minutes = 5; break; case 2 : pref.time_control_moves = 60; pref.time_control_minutes = 15; break; case 3 : pref.time_control_moves = 60; pref.time_control_minutes = 30; break; case 4 : pref.time_control_moves = 40; pref.time_control_minutes = 30; break; case 5 : pref.time_control_moves = 40; pref.time_control_minutes = 60; break; case 6 : pref.time_control_moves = 40; pref.time_control_minutes = 120; break; case 7 : pref.time_control_moves = 40; pref.time_control_minutes = 240; break; case 8 : pref.time_control_moves = 1; pref.time_control_minutes = 15; break; case 9 : pref.time_control_moves = 1; pref.time_control_minutes = 60; break; case 10 : pref.time_control_moves = 1; pref.time_control_minutes = 600; break; } if( whiteSide == 0 && blackSide == 0 ){ pref.bothsides = 1; pref.opponent = white; pref.computer = black; } else if( whiteSide == 1 && blackSide == 0 ){ pref.bothsides = 0; pref.opponent = white; pref.computer = black; } else if( whiteSide == 0 && blackSide == 1 ){ pref.bothsides = 0; pref.opponent = black; pref.computer = white; } else chess_debug(( "Unsupported combination\n" )); pref.white_name = (char *)[whiteName stringValue]; pref.black_name = (char *)[blackName stringValue]; if ( button == NX_ALERTDEFAULT ) { [self newGame: self]; } } - usePreferences /* Use current preferences */ { TCmoves = pref.time_control_moves; TCminutes = pref.time_control_minutes; TCflag = (TCmoves > 1); SetTimeControl(); bothsides = pref.bothsides; opponent = pref.opponent; computer = pref.computer; if( bothsides ){ [startButton setEnabled: YES]; [startButton display]; } else{ [startButton setEnabled: NO]; [startButton display]; } [self setWhiteName: pref.white_name blackName: pref.black_name]; } - openGame: sender /* Read a saved game. */ { id op = [OpenPanel new]; const char *types[2]; types[0] = "chess"; types[1] = 0; finished = 0; [op setRequiredFileType: "chess"]; if( [op runModalForTypes: types] ){ if( filename ) free( filename ); filename = (char *)malloc( strlen( [op filename] ) + 1 ); strcpy( filename, [op filename] ); GetGame( filename ); } } - saveAsGame: sender /* Save a game. */ { id sp = [SavePanel new]; [sp setRequiredFileType: "chess"]; if( [sp runModal] ){ if( filename ) free( filename ); filename = (char *)malloc( strlen( [sp filename] ) + 1 ); strcpy( filename, [sp filename] ); SaveGame( filename ); } } - saveGame: sender { if( filename ) SaveGame( filename ); else [self saveAsGame: sender]; } - listGame: sender /* Save a game. */ { id sp = [SavePanel new]; [sp setRequiredFileType: 0]; if( [sp runModal] ) ListGame( [sp filename] ); } - newGame: sender /* Start a new game. */ { forceCount = hintCount = undoCount = 0; finished = 0; NewGame(); [self setTitle]; [self usePreferences]; if( bothsides ){ [startButton setEnabled: YES]; [startButton display]; } else{ [startButton setEnabled: NO]; [startButton display]; if( computer == white && !mate && !quit ) [self selectMove: computer iop: 1]; } } - chooseSide: sender /* Set the text fields next to the side matrices. */ { int whiteSide = [whiteSideMatrix selectedRow]; int blackSide = [blackSideMatrix selectedRow]; if( whiteSide == 1 && blackSide == 0 ){ [whiteName setStringValue: pwen->pw_gecos]; [blackName setStringValue: "Computer"]; } else if( whiteSide == 0 && blackSide == 1 ){ [blackName setStringValue: pwen->pw_gecos]; [whiteName setStringValue: "Computer"]; } else if( whiteSide == 1 && blackSide == 1 ){ [blackName setStringValue: pwen->pw_gecos]; [whiteName setStringValue: pwen->pw_gecos]; } else{ [blackName setStringValue: "Computer"]; [whiteName setStringValue: "Computer"]; } return self; } -forceMove: sender { timeout = true; } BOOL playing = NO; - startGame: sender { id menuList = [[self mainMenu] itemList]; int i, r, c; [menuList getNumRows: &r numCols: &c]; if( [sender state] == 1 && playing == NO ){ quit = false; playing = YES; /* This is the loop that makes the computer play. It can be terminated */ /* by several conditions. The "Stop" button may be clicked, cmd-. may */ /* be pressed, or the game may end. */ while( !mate && !quit && !finished && playing ) [self selectMove: player iop: 1]; quit = true; timeout = true; playing = NO; for( i = 0; i < r; i++ ) [[menuList cellAt: i :0] setEnabled: YES]; [[self mainMenu] display]; [sender setState: 0]; } else if( [sender state] == 0 && playing == YES ){ quit = true; timeout = true; playing = NO; for( i = 0; i < r; i++ ) [[menuList cellAt: i :0] setEnabled: YES]; [[self mainMenu] display]; } } - hint: sender /* Give the player a hint. */ { short from = hint>>8; short to = hint & 0xff; int row, col; if( hint ){ algbr( (short)(hint>>8), (short)(hint & 0xff), false ); chess_debug(( "hint: %s\n", mvstr1 )); hintCount++; row = (int)(from / 8); col = (int)(from % 8); [gameBoard highlightSquareAt: row : col]; row = (int)(to / 8); col = (int)(to % 8); [gameBoard highlightSquareAt: row : col]; [self setTitle]; } else NXRunAlertPanel( 0, "I don't have a hint.", 0, 0, 0 ); } - undoMove: sender /* Undo last two half moves. */ { if( GameCnt >= 0 ){ Undo(); Undo(); undoCount++; // mate = false; /* Glenn Reid (NeXT) Mon Apr 16 00:39:35 PDT 1990 */ [self setTitle]; } else NXRunAlertPanel( 0, "No more moves to undo.", 0, 0, 0 ); } - info: sender { char *copyright; int copy_size; NXStream *copy_stream; id text; copyright = (char *)getsectdata( "__COPYRIGHT", "COPYING", ©_size); if( copyright != NULL ){ copy_stream = NXOpenMemory( copyright, copy_size, NX_READONLY ); text = [infoScroll docView]; [text readText: copy_stream]; [text sizeToFit]; [text setFont: [Font newFont: "Times" size: 14.0]]; [infoScroll display]; } [infoPanel makeKeyAndOrderFront: sender]; } /* Support methods. */ - setFinished: (int) f { finished = f; [self finishedAlert]; return self; } - (int)finished { return finished; } - (int)bothsides { return pref.bothsides; } - storePosition: (int) row : (int) col { currentRow = row; currentCol = col; } - showPosition: sender { [gameBoard highlightSquareAt: currentRow : currentCol]; [gameBoard flashSquareAt: currentRow : currentCol]; return self; } - finishedAlert { printf( "opponent %d, computer %d\n", opponent, computer ); switch( finished ){ case DRAW_GAME: NXRunAlertPanel( 0, "The game is a draw.", 0, 0, 0 ); break; case WHITE_MATE: NXRunAlertPanel( 0, "The game is over. Black wins.", 0, 0, 0 ); break; case BLACK_MATE: NXRunAlertPanel( 0, "The game is over. White wins.", 0, 0, 0 ); break; case OPPONENT_MATE: NXRunAlertPanel( 0, "The game is over.\nCongratulations, you win.", 0, 0, 0 ); break; default: break; } } - (int)makeMoveFrom: (int)r1 : (int)c1 to: (int)r2 : (int)c2 { unsigned short mv; char *move; short oldguy, newguy; oldguy = [gameBoard typeAt: r1 : c1]; move = convert_rc( r1, c1, r2, c2, [gameBoard typeAt: r1 : c1] ); player = opponent; if( !VerifyMove( move, 0, &mv ) ){ ShowMessage( "Illegal move" ); NXBeep(); return( 0 ); } else { /* if your pawn is promoted to queen and then you Undo, the queen should turn back into a pawn. Glenn Reid (NeXT) Mon Apr 16 00:49:26 PDT 1990 */ newguy = [gameBoard typeAt: r2 : c2]; if ( (newguy == queen) && (oldguy == pawn) ) { fprintf ( stderr, "pawn becomes queen...\n" ); GameQueens[GameCnt] = oldguy; } else { GameQueens[GameCnt] = 0; } chess_debug(( "opponent move time %d move %s\n", GameList[GameCnt].time, move )); [self updateClocks: opponent]; InCheck(); NXPing(); [gameBoard layoutBoard: board color: color]; [gameBoard display]; NXPing(); Sdepth = 0; ft = 0; if( !(quit || mate || force) ) [self selectMove: computer iop: 1]; } return( 1 ); } - selectMove: (int)side iop: (int)iop { id menuList = [[self mainMenu] itemList]; int i, r, c; if( side == black ) { ShowMessage( "Black's move" ); } else { ShowMessage( "White's move" ); } [forceButton setEnabled: YES]; [forceButton display]; NXPing(); [menuList getNumRows: &r numCols: &c]; for( i = 0; i < r-1; i++ ) [[menuList cellAt: i :0] setEnabled: NO]; [[self mainMenu] display]; if( !bothsides ) [setButton setEnabled: NO]; [gameBoard setEnabled: NO]; bzero( &move_info, sizeof( struct MoveInfo ) ); move_info.iop = iop; move_info.side = side; Sdepth = 0; SelectMoveStart( &move_info ); while (!timeout && Sdepth < MaxSearchDepth) SelectLoop( &move_info ); [self selectMoveEnd]; [self setTitle]; InCheck(); NXPing(); return self; } - selectMoveEnd { id menuList = [[self mainMenu] itemList]; int i, r, c; SelectMoveEnd( &move_info ); [self updateClocks: computer]; chess_debug(("computer move time %d, move %s\n", GameList[GameCnt].time, mvstr1 )); InCheck(); NXPing(); [menuList getNumRows: &r numCols: &c]; if( !bothsides ) for( i = 0; i < r; i++ ) [[menuList cellAt: i :0] setEnabled: YES]; [[self mainMenu] display]; [setButton setEnabled: YES]; [gameBoard setEnabled: YES]; NXPing(); [forceButton setEnabled: NO]; [forceButton display]; NXPing(); return; } - setWhiteName: (char *)wname blackName: (char *)bname { [whiteClockText setStringValue: wname]; [blackClockText setStringValue: bname]; if( [whiteSideMatrix selectedRow] == 1 ){ [whiteName setStringValue: wname]; } else{ [whiteName setStringValue: COMPUTER]; } if( [blackSideMatrix selectedRow] == 1 ){ [blackName setStringValue: bname]; } else{ [blackName setStringValue: COMPUTER]; } } - (int)whiteTime { return wtime; } - (int)blackTime { return btime; } - updateClocks: (int)side { if( !blackClock || !whiteClock ) return self; if( side == white ){ wtime += GameList[GameCnt].time; if( [clockWindow isVisible] ){ [whiteClock setSeconds: wtime]; [whiteClock display]; } } else{ btime += GameList[GameCnt].time; if( [clockWindow isVisible] ){ [blackClock setSeconds: wtime]; [blackClock display]; } } } - updateClocks: (int)side seconds: (int) seconds { if( side == white ){ if( [clockWindow isVisible] ){ [whiteClock setSeconds: wtime]; [whiteClock display]; } } else{ if( [clockWindow isVisible] ){ [blackClock setSeconds: wtime]; [blackClock display]; } } } - setTitle /* Change the board windows title to display the number of cheat commands issued. */ { char buf[64]; if( undoCount || hintCount ){ sprintf( buf, "Chess: " ); if( undoCount ){ if( undoCount == 1 ) sprintf( buf+strlen(buf), "1 Undo " ); else sprintf( buf+strlen(buf), "%d Undos ", undoCount ); } if( hintCount ){ if( hintCount == 1 ) sprintf( buf+strlen(buf), "1 Hint" ); else sprintf( buf+strlen(buf), "%d Hints", hintCount ); } } else sprintf( buf, "Chess" ); [boardWindow setTitle: buf]; } - setTitleMessage: (char *)m { char *om; char buf[128]; [self setTitle]; om = (char *)[boardWindow title]; strcpy( buf, om ); strcat( buf, " : " ); strcat( buf, m ); [boardWindow setTitle: buf]; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.