home *** CD-ROM | disk | FTP | other *** search
-
- #import <stdio.h>
- #import <libc.h>
- #import "Maze.h"
- #import "PacManGameBrain.h"
- #import <appkit/appkit.h>
-
- @implementation Maze
-
- - init
- {
- char *appPath, *slashPos;
- int i, j, k;
- FILE *fp;
-
- [super init];
-
- // load image
- mazeParts[1] = [NXImage findImageNamed:"Maze.tiff"];
- mazeParts[2] = [NXImage findImageNamed:"MazeBig.tiff"];
-
- scale = 1;
-
- // get the path to the app wrapper (to find the maze file)
- appPath = (char *)malloc(1024);
- strcpy(appPath, NXArgv[0]);
- if (slashPos = strrchr(appPath, '/')) {
- slashPos[1] = '\0';
- } else {
- strcpy(appPath, "./");
- }
- strcat(appPath, "mazes");
-
- // read in the maze data
- fp = fopen(appPath, "r");
- if (fp == NULL) fprintf(stderr, "PacMan: Cannot read maze data!\n");
- for (i=0; i<MAZES; i++) {
- for (j=BLOCK_HEIGHT-1; j>=0; j--) {
- for (k=0; k<BLOCK_WIDTH; k++) {
- mazes[i][k][j] = getc(fp);
- switch(mazes[i][k][j]) { // handle special cases
- case 'D' : { mazes[i][k][j] = 5; // Door
- break; }
- case '>' : { mazes[i][k][j] = 26; // door cap
- break; }
- case '<' : { mazes[i][k][j] = 27; // door cap
- break; }
- case ']' : { mazes[i][k][j] = 33; // end cap
- break; }
- case '[' : { mazes[i][k][j] = 32; // end cap
- break; }
- case ' ' : { mazes[i][k][j] = 28; // dot
- break; }
- case 'O' : { mazes[i][k][j] = 29; // power dot
- break; }
- case '|' : { mazes[i][k][j] = 31; // vert wall
- break; }
- case '-' : { mazes[i][k][j] = 30; // horiz wall
- break; }
- case '^' : { mazes[i][k][j] = 34; // end cap
- break; }
- case 'P' : { mazes[i][k][j] = 7; // player (blank image)
- break; }
- case 'G' : { mazes[i][k][j] = 10; // ghost (blank image)
- break; }
- case '+' : { mazes[i][k][j] = 8; // blank (inside cage)
- break; }
- default : { mazes[i][k][j] -= 'a'; // get index
- break; }
- }
- }
- getc(fp);
- }
- }
- fclose(fp);
-
- // initizlize other instance vars.
- [self makeMaze:1];
- powerDotShown = YES;
- visibleMaze = YES;
-
- return self;
- }
-
-
- - render:(NXRect *)rect at:(NXPoint *)pos // used to render in another view
- {
- int j, k;
- NXRect from, check;
- NXPoint pos2;
-
- if (!visibleMaze) return self;
- for (j=0; j<BLOCK_HEIGHT; j++) {
- pos2.y = j * GHOST_SIZE * scale + pos->y;
- for (k=0; k<BLOCK_WIDTH; k++) {
- if ((maze[k][j] != POWER) || powerDotShown) { // if power dot
- // blinked off, we don't render it.
- NXSetRect(&check, k * GHOST_SIZE, j * GHOST_SIZE,
- GHOST_SIZE, GHOST_SIZE);
- if (NXIntersectsRect(&check, rect)) { // only draw maze bits
- // in the rects that intersect the rect passed to us
- NXSetRect(&from,
- (maze[k][j] % PER_ROW) * GHOST_SIZE * scale,
- (maze[k][j] / PER_ROW) * GHOST_SIZE * scale,
- GHOST_SIZE * scale, GHOST_SIZE * scale);
- pos2.x = k * GHOST_SIZE * scale + pos->x;
- [mazeParts[scale] composite:NX_SOVER
- fromRect:&from toPoint:&pos2];
- } } } }
- return self;
-
- }
-
-
- - makeMaze:(int)num
- { // build a maze from the template; fill it with dots, set up new player and
- // ghost positions, etc.
- int j, k;
- int ghost = 0;
- int pdot = 0;
-
- dots = 0;
- if ((num >= 0) && (num < MAZES)) { // make sure in range
- mazeNum = num;
- player[0] = -32; player[1] = -32; // sum is neg if no player spot found
- // set up player/ghost/power dot position, etc. for maze.
- for (j=0; j<BLOCK_HEIGHT; j++) {
- for (k=0; k<BLOCK_WIDTH; k++) {
- maze[k][j] = mazes[num][k][j];
- switch (maze[k][j]) {
- case GHDOOR : { door[0] = k; // door for ghosts
- door[1] = j; break; }
- case PLAYER : { player[0] = k; // Player
- player[1] = j;
- maze[k][j] = EMPTY; break; }
- case GHOST : { ghosts[ghost * 2] = k; // Ghost
- ghosts[ghost * 2 + 1] = j;
- maze[k][j] = EMPTY;
- if (++ghost > MAX_GHOSTS) { fprintf(stderr,
- "Maze %d has too many ghosts.\n", num); }
- break; }
- case POWER : { power[pdot * 2] = k; // Power Dot
- power[pdot * 2 + 1] = j; dots++;
- if (++pdot > MAX_POWER_DOTS) { fprintf(stderr,
- "Maze %d has too many power dots.\n", num); }
- break; }
- case DOT : { dots++; // Normal Dot
- break; }
- default : { break; } // do nothing
- }
- }
- }
- if (!ghost) { fprintf(stderr, "Maze %d has no ghosts.\n", num); }
- if (!pdot) { fprintf(stderr, "Maze %d has no power dots.\n", num); }
- if (player[0]+player[1] < 0) {
- fprintf(stderr, "Maze %d has no player.\n", num); }
- }
- return self;
- }
-
-
- - playerPosition:(int *)x :(int *)y // return x, y of player/fruit
- {
- *x = player[0] * GHOST_SIZE; *y = player[1] * GHOST_SIZE;
- return self;
- }
-
-
- - doorPosition:(int *)x :(int *)y // return x, y of door to ghost chamber
- {
- *x = door[0] * GHOST_SIZE; *y = door[1] * GHOST_SIZE;
- return self;
- }
-
-
- - (const int *)powerDot // return pointer to power array
- {
- return power;
- }
-
-
- - (const int *)ghosts // return pointer to ghosts array
- {
- return ghosts;
- }
-
-
- - (BOOL)powerDotAt:(int)x :(int)y // return YES if power dot in block
- {
- // only have to be 1/2 way into block to eat dot:
- int basex = x / GHOST_SIZE + ((x % GHOST_SIZE) > (GHOST_SIZE / 2));
- int basey = y / GHOST_SIZE + ((y % GHOST_SIZE) > (GHOST_SIZE / 2));
-
- if (maze[basex][basey] == POWER) { // munch power dot
- [[[NXApp delegate] scoreKeeper] addToScore:POWERDOTPOINTS];
- maze[basex][basey] = EMPTY;
- dots--;
- dotx = basex; doty = basey; // save them away
- return YES;
- }
- return NO;
- }
-
- - (BOOL)eatDotAt:(int)x :(int)y // return YES if OK, NO if no dot was there
- {
- int basex = x / GHOST_SIZE;
- int basey = y / GHOST_SIZE;
- int dx = x % GHOST_SIZE;
- int dy = y % GHOST_SIZE;
-
- if (!dx) { // in a vertical column or corner/junction
- if (dy > GHOST_SIZE / 2) basey++;
- } else { // on a horiz. row
- if (dx > GHOST_SIZE / 2) basex++;
- }
-
- if (maze[basex][basey] == DOT) { // munch dot
- [[[NXApp delegate] scoreKeeper] addToScore:DOTPOINTS];
- maze[basex][basey] = EMPTY;
- dots--;
- dotx = basex; doty = basey; // save them away
- return YES;
- }
- return NO;
- }
-
- - (int)dots // return the number of dots left in maze
- {
- return dots;
- }
-
- - lastDot:(int *)xx :(int *)yy
- {
- *xx = dotx * GHOST_SIZE;
- *yy = doty * GHOST_SIZE;
- return self;
- }
-
- - (BOOL)playerWall:(float)x :(float)y // YES if player can't be in block
- {
- int mazex = x / GHOST_SIZE;
- int mazey = y / GHOST_SIZE;
-
- if ((maze[mazex][mazey] == EMPTY) ||
- (maze[mazex][mazey] == DOT) ||
- (maze[mazex][mazey] == POWER)) return NO;
- return YES;
- }
-
- - (BOOL)monsterWall:(float)x :(float)y // YES if ghost can't be in block
- {
- int mazex = x / GHOST_SIZE;
- int mazey = y / GHOST_SIZE;
-
- if ((maze[mazex][mazey] == EMPTY) ||
- (maze[mazex][mazey] == DOT) ||
- (maze[mazex][mazey] == GHDOOR) ||
- (maze[mazex][mazey] == POWER)) return NO;
- return YES;
- }
-
- - blinkPowerDot // toggle ON/OFF state of power dots
- {
- powerDotShown = !powerDotShown;
- return self;
- }
-
- - visible:(BOOL)flag // used to tell us if the maze is visible
- {
- visibleMaze = flag;
- return self;
- }
-
- - (BOOL)isVisible; // used to tell others if maze is visible
- { return visibleMaze; }
-
- - (int)scale
- {
- return scale;
- }
-
- - setScale:(int)newScale
- {
- if ((newScale < 1) || (newScale > 2)) return self;
- scale = newScale;
- return self;
- }
-
-
- @end
-