This is Board.m in view mode; [Download] [Up]
/* * Board * description: the object that stores the state of a Splat Board * history: * 2/14/93 [Erik Kay] - created * < I wasn't keeping track of my changes here > * 6/8/93 [Erik Kay] - added bycopy support */ #import "Board.h" @implementation Board // initialization - initCols:(int)c Rows:(int)r { [super init]; maxRow = r; maxCol = c; numone = 0; numtwo = 0; board = malloc (sizeof (int *) * (maxCol + 1) * (maxRow + 1)); filename = NULL; return self; } - init { [self initCols:8 Rows:8]; [self clearBoard]; filename = NULL; return self; } - free { free(board); free(filename); [super free]; return self; } // loading a .board file + newFromFile:(const char *)fname { int maxr, maxc; char line[256]; id newb; FILE *f; if ((f = fopen(fname,"r")) == NULL) return nil; fgets (line, 255, f); maxc = strlen(line)/2; maxr = 0; do { if (strlen(line)/2 != maxc) { return nil; } maxr++; } while (fgets(line, 255, f)); fclose(f); newb = [[Board alloc] initCols:maxc Rows:maxr]; [newb setFilename:fname]; [newb clearBoard]; [newb reloadFromFile]; return newb; } - reloadFromFile { int r, c; char line[256]; FILE *f; if (!filename || ((f = fopen(filename,"r")) == NULL)) return nil; r = c = 0; fseek(f,0,SEEK_SET); while (fgets(line, 255, f)) { for (c = 0; c < maxCol; c++) { switch (line[c*2]) { case '+': [self setPiece:SQUARE_BLOCKED at:c :(maxRow -1 - r)]; break; case '1': [self setPiece:SQUARE_ONE at:c :(maxRow -1 - r)]; break; case '2': [self setPiece:SQUARE_TWO at:c :(maxRow -1 - r)]; break; default: [self setPiece:SQUARE_EMPTY at:c :(maxRow -1 - r)]; break; } } r++; } fclose(f); return self; } - setFilename:(const char *)f { filename = malloc(strlen(f) + 1); strcpy (filename,f); return self; } - (const char *)filename { return (const char *)filename; } //! NOT FINISHED - should be able to archive to a .board file - writeToFile:(const char *)filename { return self; } // board utilities - clearBoard { int i; for (i = 0; i < maxCol * maxRow; i++) board[i] = SQUARE_EMPTY; numone = numtwo = 0; return self; } // used by the game over code to fill all empty squares with a given piece - fillEmptyWith:(square_state)type { int i, c; for (i = 0, c = 0; i < maxCol * maxRow; i++) if (board[i] == SQUARE_EMPTY) { board[i] = type; c++; } if (type == SQUARE_ONE) numone += c; else if (type == SQUARE_TWO) numtwo += c; return self; } - trueCopy { int i, c; square_state *from, *to; Board *newb = [[Board alloc] initCols:maxCol Rows:maxRow]; from = board; to = newb->board; c = maxCol * maxRow; for (i = 0; i < c; i++) *to++ = *from++; newb->numone = numone; newb->numtwo = numtwo; newb->currentMove = currentMove; [newb setFilename:filename]; return newb; } // individually addressing board squares // we keep track of how many pieces there are on a board // This is very useful to most of the computer players that use a greedy-like // strategy. It speeds things up quite a bit. - setPiece:(square_state)value at:(int)col :(int)row { int i; if ((col >= maxCol) || (row >= maxRow) || (col < 0) || (row < 0)) return self; i = col + (row * maxCol); switch (value) { case SQUARE_ONE: numone++; break; case SQUARE_TWO: numtwo++; break; default: break; } switch (board[i]) { case SQUARE_ONE: numone--; break; case SQUARE_TWO: numtwo--; break; default: break; } board[i] = value; return self; } - setPiece:(square_state)value at:(location *)loc { return [self setPiece:value at:loc->col :loc->row]; } - clearPieceAt:(int)col :(int)row { return self; } - (square_state)pieceAt:(int)col :(int)row { if ((col >= maxCol) || (row >= maxRow) || (col < 0) || (row < 0)) return SQUARE_ERROR; return board[col + (row * maxCol)]; } - (square_state)pieceAt:(location *)loc { if ((loc->col >= maxCol) || (loc->row >= maxRow) || (loc->col < 0) || (loc->row < 0)) return SQUARE_ERROR; return board[loc->col + (loc->row * maxCol)]; } // querying other board information - (int)rows { return maxRow; } - (int)cols { return maxCol; } - (int)numberOfPiece:(square_state)type { unsigned int count = 0, i; switch (type) { case SQUARE_ONE: return numone; break; case SQUARE_TWO: return numtwo; break; default: for (i = 0; i < maxCol * maxRow; i++) { if (board[i] == type) count++; } break; } return count; } // return an array of all of the pieces of a given type (their locations) - (location *)pieces:(square_state)type { int count, current, i; location *pieces; count = [self numberOfPiece:type]; pieces = malloc(sizeof(location) * count); current = 0; for (i = 0; i < maxCol * maxRow; i++) { if (board[i] == type) { pieces[current].col = (i % maxCol); pieces[current].row = (i / maxCol); current++; } } return pieces; } // keep track of the last move - setCurrentMove:(move *)mv { currentMove = *mv; return self; } - (move *)currentMove { return ¤tMove; } // keep track of a 'score' or rating for the board - (int)score { return score; } - setScore:(int)s { score = s; return self; } /* * Transport protocol */ - encodeRemotelyFor:(NXConnection *)connection freeAfterEncoding:(BOOL *)flagp isBycopy:(BOOL)isBycopy { if (isBycopy) return self; else return [super encodeRemotelyFor:connection freeAfterEncoding:flagp isBycopy:NO]; } - encodeUsing:(id <NXEncoding>)portal { // char buf[10]; int count, i, val; // send the count first, so that the destination can allocate enough count = (maxRow + 1) * (maxCol + 1); [portal encodeData:&count ofType:"i"]; // can't send an enum across the wire, so we send it as a series of ints for (i = 0; i < count; i++) { val = board[i]; [portal encodeData:&val ofType:"i"]; } [portal encodeData:&maxRow ofType:"i"]; [portal encodeData:&maxCol ofType:"i"]; // can't send nested structs, so we send them individually [portal encodeData:¤tMove.from.col ofType:"i"]; [portal encodeData:¤tMove.from.row ofType:"i"]; [portal encodeData:¤tMove.to.col ofType:"i"]; [portal encodeData:¤tMove.to.row ofType:"i"]; [portal encodeData:&numone ofType:"i"]; [portal encodeData:&numtwo ofType:"i"]; [portal encodeData:&score ofType:"i"]; [portal encodeData:&filename ofType:"*"]; return self; } - decodeUsing:(id <NXDecoding>)portal { // char buf[10]; int count, i, val; // find out how many squares there are, and allocate accordingly [portal decodeData:&count ofType:"i"]; board = malloc(sizeof(int *) * count); // cast these ints into square_states for (i = 0; i < count; i++) { [portal decodeData:&val ofType:"i"]; board[i] = val; } [portal decodeData:&maxRow ofType:"i"]; [portal decodeData:&maxCol ofType:"i"]; [portal decodeData:¤tMove.from.col ofType:"i"]; [portal decodeData:¤tMove.from.row ofType:"i"]; [portal decodeData:¤tMove.to.col ofType:"i"]; [portal decodeData:¤tMove.to.row ofType:"i"]; [portal decodeData:&numone ofType:"i"]; [portal decodeData:&numtwo ofType:"i"]; [portal decodeData:&score ofType:"i"]; [portal decodeData:&filename ofType:"*"]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.