/* Draw the pawn */ void draw_pawn(int coord_x, int coord_y, char color) { if(color == 'w') { GrSetGCForeground(tuxchess_gc,GR_RGB(255,255,255)); GrFillEllipse(tuxchess_wid,tuxchess_gc,coord_x+6,coord_y+6,2,4); GrSetGCForeground(tuxchess_gc,GR_RGB(0,0,0)); GrEllipse(tuxchess_wid,tuxchess_gc,coord_x+6,coord_y+6,2,4); GrSetGCForeground(tuxchess_gc,GR_RGB(255,255,255)); GrFillRect(tuxchess_wid,tuxchess_gc,coord_x+3,coord_y+9,7,3); GrSetGCForeground(tuxchess_gc,GR_RGB(0,0,0)); GrRect(tuxchess_wid,tuxchess_gc,coord_x+3,coord_y+9,7,3); } else { GrSetGCForeground(tuxchess_gc,GR_RGB(0,0,0)); GrFillEllipse(tuxchess_wid,tuxchess_gc,coord_x+6,coord_y+6,2,4); GrSetGCForeground(tuxchess_gc,GR_RGB(160,160,160)); GrEllipse(tuxchess_wid,tuxchess_gc,coord_x+6,coord_y+6,2,4); GrSetGCForeground(tuxchess_gc,GR_RGB(0,0,0)); GrFillRect(tuxchess_wid,tuxchess_gc,coord_x+3,coord_y+9,7,3); GrSetGCForeground(tuxchess_gc,GR_RGB(160,160,160)); GrRect(tuxchess_wid,tuxchess_gc,coord_x+3,coord_y+9,7,3); } }
// create the circular status animation static void create_status() { int i; int xpie[] = { 0, 3, 6, 3, 0, -3, -6, -3 }; int ypie[] = { -6, -3, 0, 3, 6, 3, 0, -3 }; // we need 16 frames GrSetGCForeground (mandel_gc, appearance_get_color( CS_TITLEBG )); for (i=0;i<16;i++) { status_image[i] = GrNewPixmap(12, 12, NULL); GrFillRect(status_image[i],mandel_gc,0,0,12,12); } // the background for (i=1;i<8;i++) { GrSetGCForeground(mandel_gc, appearance_get_color(CS_TITLEFG)); GrFillEllipse(status_image[i],mandel_gc,6,6,6,6); GrSetGCForeground(mandel_gc, appearance_get_color(CS_TITLEBG)); GrArc(status_image[i],mandel_gc,6,6,6,6,0,-6,xpie[i],ypie[i],MWPIE); } // the foreground part GrSetGCForeground(mandel_gc, appearance_get_color(CS_TITLEFG)); GrFillEllipse(status_image[8],mandel_gc,6,6,6,6); for (i=9;i<16;i++) GrArc(status_image[i],mandel_gc,6,6,6,6,0,-6,xpie[i-8],ypie[i-8],MWPIE); }
/* Draw the pawn */ void draw_pawn(int coord_x, int coord_y, int color) { if(color == 0) { GrSetGCForeground(tuxchess_gc,WHITE); GrFillEllipse(tuxchess_wid,tuxchess_gc,coord_x+6,coord_y+6,2,4); GrSetGCForeground(tuxchess_gc,BLACK); GrEllipse(tuxchess_wid,tuxchess_gc,coord_x+6,coord_y+6,2,4); GrSetGCForeground(tuxchess_gc,WHITE); GrFillRect(tuxchess_wid,tuxchess_gc,coord_x+3,coord_y+9,7,3); GrSetGCForeground(tuxchess_gc,BLACK); GrRect(tuxchess_wid,tuxchess_gc,coord_x+3,coord_y+9,7,3); } else { GrSetGCForeground(tuxchess_gc,BLACK); GrFillEllipse(tuxchess_wid,tuxchess_gc,coord_x+6,coord_y+6,2,4); GrSetGCForeground(tuxchess_gc,LTGRAY); GrEllipse(tuxchess_wid,tuxchess_gc,coord_x+6,coord_y+6,2,4); GrSetGCForeground(tuxchess_gc,BLACK); GrFillRect(tuxchess_wid,tuxchess_gc,coord_x+3,coord_y+9,7,3); GrSetGCForeground(tuxchess_gc,LTGRAY); GrRect(tuxchess_wid,tuxchess_gc,coord_x+3,coord_y+9,7,3); } }
static void GrFillEllipseWrapper(void *r) { nxFillEllipseReq *req = r; GrFillEllipse(req->drawid, req->gcid, req->x, req->y, req->rx, req->ry); }
/* * Draw a bomb in a window using the specified GC. * The bomb is animated and the terminal is beeped if necessary. */ static void drawbomb(POS pos, GR_GC_ID gc, GR_BOOL animate) /*POS pos; position to draw bomb at */ /*GR_GC_ID gc; GC for drawing (red or green) */ /*GR_BOOL animate; TRUE to animate the bomb */ { GR_COORD x; GR_COORD y; GR_COUNT count; if (animate) write(1, "\007", 1); cellcenter(pos, &x, &y); count = (animate ? 8 : 1); for (;;) { GrFillEllipse(boardwid, gc, x, y, xp / 2 - 3, yp / 2 - 3); if (--count == 0) return; delay(); clearcell(pos); delay(); } }
void draw_set(char *name, int mode) { int x; int tw, th, tb; GR_POINT points[4]; GR_GC_ID gc = GrNewGC(); GrSetGCForeground(gc, WHITE); GrSetGCBackground(gc, GRAY); GrGetGCTextSize(gc, name, -1, GR_TFTOP, &tw, &th, &tb); x = g_x + (tw - 50) / 2; GrText(g_main, gc, g_x, 5, name, -1, GR_TFTOP); g_x += (tw + 10); GrSetGCFillMode(gc, mode); if (mode == GR_FILL_STIPPLE) GrSetGCForeground(gc, YELLOW); else { GrSetGCForeground(gc, WHITE); GrSetGCBackground(gc, BLUE); } if (mode == GR_FILL_TILE) { GrSetGCTile(gc, g_pixmap, 16, 16); } if (mode == GR_FILL_STIPPLE || mode == GR_FILL_OPAQUE_STIPPLE) GrSetGCStipple(gc, g_stipple2, 2, 2); GrFillRect(g_main, gc, x, 25, 50, 50); if (mode == GR_FILL_STIPPLE || mode == GR_FILL_OPAQUE_STIPPLE) GrSetGCStipple(gc, g_stipple1, 7, 7); GrFillEllipse(g_main, gc, x + 25, 105, 25, 25); if (mode == GR_FILL_STIPPLE || mode == GR_FILL_OPAQUE_STIPPLE) GrSetGCStipple(gc, g_stipple3, 3, 2); points[0].x = points[3].x = x; points[0].y = points[3].y = 165; points[1].x = x + 50; points[1].y = 165; points[2].x = x + 25; points[2].y = 215; GrFillPoly(g_main, gc, 4, points); GrDestroyGC(gc); }
/* draw a button to the screen at x,y using info from id */ void lights_draw_button( int x, int y, int id ) { int ls2 = lights_size/2; /* change color based on if it's lit or not */ if( lights_states[id] ) { if( lights_screen_info.bpp == 16 ) GrSetGCForeground( lights_gc, GR_RGB( 255, 100, 50 )); else GrSetGCForeground( lights_gc, GR_RGB(255,255,255) ); } else { GrSetGCForeground( lights_gc, GR_RGB(0,0,0) ); } GrFillEllipse( lights_bufwid, lights_gc, ls2+x, ls2+y, ls2-2, ls2-2 ); /* draw the container */ if( lights_screen_info.bpp == 16 ) GrSetGCForeground( lights_gc, GR_RGB( 102, 0, 0 )); else GrSetGCForeground( lights_gc, GR_RGB(80,80,80) ); GrEllipse( lights_bufwid, lights_gc, ls2+x, ls2+y, ls2-1, ls2-1 ); /* draw the cursor if applicable */ if( id == lights_curr && !lights_hold_engaged ) { if( lights_cursblink ) { if( lights_screen_info.bpp == 16 ) GrSetGCForeground( lights_gc, GR_RGB( 0, 255, 0 )); else GrSetGCForeground( lights_gc, GR_RGB(255,255,255) ); } else { GrSetGCForeground( lights_gc, GR_RGB(0,0,0) ); } GrEllipse( lights_bufwid, lights_gc, ls2+x, ls2+y, ls2, ls2 ); GrEllipse( lights_bufwid, lights_gc, ls2+x, ls2+y, ls2-1, ls2-1 ); GrEllipse( lights_bufwid, lights_gc, ls2+x, ls2+y, ls2-1, ls2 ); GrEllipse( lights_bufwid, lights_gc, ls2+x, ls2+y, ls2, ls2-1 ); if( lights_cursblink ) { GrSetGCForeground( lights_gc, GR_RGB(0,0,0) ); } else { if( lights_screen_info.bpp == 16 ) GrSetGCForeground( lights_gc, GR_RGB( 0, 255, 255 )); else GrSetGCForeground( lights_gc, GR_RGB(255,255,255) ); } GrEllipse( lights_bufwid, lights_gc, ls2+x, ls2+y, ls2-2, ls2-2 ); } }
/* Draw the king */ void draw_king(int coord_x, int coord_y, char color) { GrSetGCForeground(tuxchess_gc,GR_RGB(0,0,0)); GrLine(tuxchess_wid,tuxchess_gc,coord_x+6,coord_y+1,coord_x+6,coord_y+4); GrLine(tuxchess_wid,tuxchess_gc,coord_x+4,coord_y+2,coord_x+8,coord_y+2); if(color == 'w') GrSetGCForeground(tuxchess_gc,GR_RGB(255,255,255)); GrFillEllipse(tuxchess_wid,tuxchess_gc,coord_x+6,coord_y+8,4,4); GrSetGCForeground(tuxchess_gc,GR_RGB(0,0,0)); GrEllipse(tuxchess_wid,tuxchess_gc,coord_x+6,coord_y+8,4,4); }
/* Draw the king */ void draw_king(int coord_x, int coord_y, int color) { GrSetGCForeground(tuxchess_gc,BLACK); GrLine(tuxchess_wid,tuxchess_gc,coord_x+6,coord_y+1,coord_x+6,coord_y+4); GrLine(tuxchess_wid,tuxchess_gc,coord_x+4,coord_y+2,coord_x+8,coord_y+2); if(color == 0) GrSetGCForeground(tuxchess_gc,WHITE); GrFillEllipse(tuxchess_wid,tuxchess_gc,coord_x+6,coord_y+8,4,4); GrSetGCForeground(tuxchess_gc,BLACK); GrEllipse(tuxchess_wid,tuxchess_gc,coord_x+6,coord_y+8,4,4); }
/* * Here to do an idle task when nothing else is happening. * Just draw a randomly colored filled circle in the small window. */ void do_idle(void) { GR_COORD x; GR_COORD y; GR_SIZE rx; GR_SIZE ry; GR_COLOR color; x = rand() % 70; y = rand() % 40; rx = (rand() % 10) + 5; ry = (rx * si.ydpcm) / si.xdpcm; /* make it appear circular */ color = rand() % si.ncolors; GrSetGCForeground(gc3, MWPALINDEX(color)); GrFillEllipse(w2, gc3, x, y, rx, ry); }
/* * Here to do an idle task when nothing else is happening. * Just draw a randomly colored filled circle in the small window. */ void do_idle(void) { GR_COORD x; GR_COORD y; GR_SIZE rx; GR_SIZE ry; GR_PIXELVAL pixelval; x = rand() % 70; y = rand() % 40; rx = (rand() % 10) + 5; ry = (rx * si.ydpcm) / si.xdpcm; /* make it appear circular */ pixelval = rand() % si.ncolors; GrSetGCForegroundPixelVal(gc3, pixelval); GrFillEllipse(w2, gc3, x, y, rx, ry); }
/* Load the game file. */ int load_game_file(nbstate *state) { FILE *fp; int line = 1; level *l, *lev = NULL; char buf[256], *p; int inlevelblock = 0; /* Generate the full game file name including the directory: */ snprintf(buf, 256, "%s/%s", state->gamedir, state->gamefile); /* Try to open the game file: */ if(!(fp = fopen(buf, "r"))) { /* It failed, so print an error message and return "failure": */ GrError("Failed to open game file \"%s\": %s\n", buf, strerror(errno)); return 1; } /* Read the file one line at a time in a loop: */ while(fgets(buf, 256, fp)) { /* Look for the newline at the end of the line. */ if(!(p = strchr(buf, '\n'))) { /* There wasn't one, which probably means that the * line was longer than 255 characters. */ GrError("Too long line on line %d of game file " "\"%s\"\n", line, state->gamefile); return 1; } *p = 0; /* Get rid of the newline. */ /* Ignore comments and blank lines: */ if(*buf == '#' || *buf == 0) { /* Compare the line against each of the different keywords: */ } else if(!memcmp(buf, "TitleBackground ", 16)) { if(state->titlebackground) { redefinewarning("TitleBackground", line, state->gamefile); free(state->titlebackground); } if(!(state->titlebackground = strdup(buf + 16))) { oom(); goto err; } } else if(!memcmp(buf, "TitleBackgroundTiled ", 21)) { /* Check whether the parameter to TitleBackgroundTiled * is "Yes" (1), "No" (0), or something else (parse * error): */ if(!strcmp(buf + 21, "Yes")) state->backgroundtiled = 1; else if(!strcmp(buf + 21, "No")) state->backgroundtiled = 0; else goto parseerr; } else if(!memcmp(buf, "TitleSplash ", 12)) { if(state->titlesplash) { redefinewarning("TitleSplash", line, state->gamefile); free(state->titlesplash); } if(!(state->titlesplash = strdup(buf + 12))) { oom(); goto err; } } else if(!memcmp(buf, "GameWonSplash ", 14)) { if(state->gamewonsplash) { redefinewarning("GameWonSplash", line, state->gamefile); free(state->gamewonsplash); } if(!(state->gamewonsplash = strdup(buf + 14))) { oom(); goto err; } } else if(!memcmp(buf, "GameLostSplash ", 15)) { if(state->gamelostsplash) { redefinewarning("GameLostSplash", line, state->gamefile); free(state->gamelostsplash); } if(!(state->gamelostsplash = strdup(buf + 15))) { oom(); goto err; } } else if(!memcmp(buf, "NormalPoints ", 13)) { /* Convert the parameter to NormalPoints into a * number: */ state->normalpoints = strtol(buf + 13, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "SmallBonusPoints ", 17)) { state->smallbonuspoints = strtol(buf + 17, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "MediumBonusPoints ", 18)) { state->mediumbonuspoints = strtol(buf + 18, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "LargeBonusPoints ", 17)) { state->largebonuspoints = strtol(buf + 17, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "HugeBonusPoints ", 16)) { state->hugebonuspoints = strtol(buf + 16, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "PowerUpPoints ", 14)) { state->poweruppoints = strtol(buf + 14, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "PowerDownPoints ", 16)) { state->powerdownpoints = strtol(buf + 16, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "StartBalls ", 11)) { state->startballs = strtol(buf + 11, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "NewLevelBalls ", 14)) { state->newlevelballs = strtol(buf + 14, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "BallImage ", 10)) { /* If the ball sprite has already been defined, print * a warning and destroy the old sprite: */ if(state->ball.s) { redefinewarning("BallImage", line, state->gamefile); destroy_sprite(state, state->ball.s); } /* Try to load the ball sprite: */ if(!(state->ball.s = load_sprite(state, buf + 10, -1, -1))) { /* That failed so try to make an empty one: */ if(!(state->ball.s = make_empty_sprite(state, buf + 10, DEFAULT_BALL_SIZE, DEFAULT_BALL_SIZE))) { /* That failed too so print an error * message and give up: */ GrError("Couldn't create " "ball sprite on line " "%d of game file " "\"%s\"\n", line, state->gamefile); goto err; } /* Fill in the dummy sprite with a white * circle: */ GrSetGCForeground(state->gc, GR_COLOR_WHITE); GrFillEllipse(state->ball.s->p, state->gc, DEFAULT_BALL_SIZE / 2, DEFAULT_BALL_SIZE / 2, (DEFAULT_BALL_SIZE / 2) - 1, (DEFAULT_BALL_SIZE / 2) - 1); GrFillEllipse(state->ball.s->a, state->gc, DEFAULT_BALL_SIZE / 2, DEFAULT_BALL_SIZE / 2, (DEFAULT_BALL_SIZE / 2) - 1, (DEFAULT_BALL_SIZE / 2) - 1); } } else if(!memcmp(buf, "SlowBallVelocity ", 17)) { state->ball.sv = strtol(buf + 17, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "NormalBallVelocity ", 19)) { state->ball.nv = strtol(buf + 19, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "FastBallVelocity ", 17)) { state->ball.fv = strtol(buf + 17, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "BatVelocity ", 12)) { state->batv = strtol(buf + 12, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "PowerVelocity ", 14)) { state->powerv = strtol(buf + 14, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "AnimatePeriod ", 14)) { state->animateperiod = strtol(buf + 14, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "BrickWidth ", 11)) { state->brickwidth = strtol(buf + 11, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "BrickHeight ", 12)) { state->brickheight = strtol(buf + 12, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "Brick ", 6)) { /* Parse the brick line: */ if(parse_brick(state, inlevelblock, lev, line, buf + 6)) goto err; } else if(!memcmp(buf, "Width ", 6)) { if(lev) { GrError("Error: Width must be set " "before the first level is defined " "(see line %d of game file \"%s\")\n", line, state->gamefile); goto err; } state->width = strtol(buf + 6, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "Height ", 7)) { if(lev) { GrError("Error: Height must be set " "before the first level is defined " "(see line %d of game file \"%s\")\n", line, state->gamefile); goto err; } state->height = strtol(buf + 7, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "BatHeight ", 10)) { state->batheight = strtol(buf + 10, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "NormalBatWidth ", 15)) { state->batwidths[NORMALBAT] = strtol(buf + 15, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "SmallBatWidth ", 14)) { state->batwidths[SMALLBAT] = strtol(buf + 14, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "LargeBatWidth ", 14)) { state->batwidths[LARGEBAT] = strtol(buf + 14, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "NormalBat ", 10)) { if(state->bats[NORMALBAT]) { redefinewarning("NormalBat", line, state->gamefile); destroy_sprite(state, state->bats[NORMALBAT]); } if(!(state->bats[NORMALBAT] = load_sprite(state, buf + 10, state->batwidths[NORMALBAT], state->batheight))) { if(!(state->bats[NORMALBAT] = make_empty_sprite(state, buf + 10, state->batwidths[NORMALBAT], state->batheight))) { GrError("Couldn't create " "normal bat sprite on " "line %d of game file " "\"%s\"\n", line, state->gamefile); goto err; } GrSetGCForeground(state->gc, GR_COLOR_RED); GrFillRect(state->bats[NORMALBAT]->p, state->gc, 0, 0, state->batwidths[NORMALBAT], state->batheight); GrSetGCForeground(state->gc, GR_COLOR_WHITE); GrFillRect(state->bats[NORMALBAT]->a, state->gc, 0, 0, state->batwidths[NORMALBAT], state->batheight); } } else if(!memcmp(buf, "SmallBat ", 9)) { if(state->bats[SMALLBAT]) { redefinewarning("SmallBat", line, state->gamefile); destroy_sprite(state, state->bats[SMALLBAT]); } if(!(state->bats[SMALLBAT] = load_sprite(state, buf + 9, state->batwidths[SMALLBAT], state->batheight))) { if(!(state->bats[SMALLBAT] = make_empty_sprite(state, buf + 9, state->batwidths[SMALLBAT], state->batheight))) { GrError("Couldn't create " "small bat sprite on " "line %d of game file " "\"%s\"\n", line, state->gamefile); goto err; } GrSetGCForeground(state->gc, GR_COLOR_RED); GrFillRect(state->bats[SMALLBAT]->p, state->gc, 0, 0, state->batwidths[SMALLBAT], state->batheight); GrSetGCForeground(state->gc, GR_COLOR_WHITE); GrFillRect(state->bats[SMALLBAT]->a, state->gc, 0, 0, state->batwidths[SMALLBAT], state->batheight); } } else if(!memcmp(buf, "LargeBat ", 9)) { if(state->bats[LARGEBAT]) { redefinewarning("LargeBat", line, state->gamefile); destroy_sprite(state, state->bats[LARGEBAT]); } if(!(state->bats[LARGEBAT] = load_sprite(state, buf + 9, state->batwidths[LARGEBAT], state->batheight))) { if(!(state->bats[LARGEBAT] = make_empty_sprite(state, buf + 9, state->batwidths[LARGEBAT], state->batheight))) { GrError("Couldn't create " "large bat sprite on " "line %d of game file " "\"%s\"\n", line, state->gamefile); goto err; } GrSetGCForeground(state->gc, GR_COLOR_RED); GrFillRect(state->bats[LARGEBAT]->p, state->gc, 0, 0, state->batwidths[LARGEBAT], state->batheight); GrSetGCForeground(state->gc, GR_COLOR_WHITE); GrFillRect(state->bats[LARGEBAT]->a, state->gc, 0, 0, state->batwidths[LARGEBAT], state->batheight); } } else if(!memcmp(buf, "PowerSprite ", 12)) { /* Parse the PowerSprite line: */ if(parse_powersprite(state, buf + 12, line)) goto err; } else if(!memcmp(buf, "PowerUpTimeout ", 15)) { state->poweruptime = strtol(buf + 15, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "PowerDownTimeout ", 17)) { state->powerdowntime = strtol(buf + 17, &p, 10); if(*p) goto parseerr; } else if(!memcmp(buf, "FadeRate ", 9)) { state->faderate = strtol(buf + 9, &p, 10); if(*p) goto parseerr; if(state->faderate > 255 || state->faderate < 0) { GrError("Invalid fade rate on line " "%d of game file \"%s\"\n", line, state->gamefile); goto err; } } else if(!memcmp(buf, "SolidFloorCheat ", 16)) { if(state->cheats[SFCHEAT]) { redefinewarning("SolidFloorCheat", line, state->gamefile); free(state->cheats[SFCHEAT]); } if(!(state->cheats[SFCHEAT] = strdup(buf + 16))) { oom(); goto err; } if(strlen(state->cheats[SFCHEAT]) > MAXCHEATLEN) { GrError("Cheat sequence too long on " "line %d of game file \"%s\"\n", line, state->gamefile); goto err; } } else if(!memcmp(buf, "TeleportCheat ", 14)) { if(state->cheats[TPCHEAT]) { redefinewarning("TeleportCheat", line, state->gamefile); free(state->cheats[TPCHEAT]); } if(!(state->cheats[TPCHEAT] = strdup(buf + 14))) { oom(); goto err; } if(strlen(state->cheats[TPCHEAT]) > MAXCHEATLEN) { GrError("Cheat sequence too long on " "line %d of game file \"%s\"\n", line, state->gamefile); goto err; } } else if(!memcmp(buf, "NoBounceCheat ", 14)) { if(state->cheats[NBCHEAT]) { redefinewarning("NoBounceCheat", line, state->gamefile); free(state->cheats[NBCHEAT]); } if(!(state->cheats[NBCHEAT] = strdup(buf + 14))) { oom(); goto err; } if(strlen(state->cheats[NBCHEAT]) > MAXCHEATLEN) { GrError("Cheat sequence too long on " "line %d of game file \"%s\"\n", line, state->gamefile); goto err; } } else if(!memcmp(buf, "NoPowerDownCheat ", 17)) { if(state->cheats[NPDCHEAT]) { redefinewarning("NoPowerDownCheat", line, state->gamefile); free(state->cheats[NPDCHEAT]); } if(!(state->cheats[NPDCHEAT] = strdup(buf + 17))) { oom(); goto err; } if(strlen(state->cheats[NPDCHEAT]) > MAXCHEATLEN) { GrError("Cheat sequence too long on " "line %d of game file \"%s\"\n", line, state->gamefile); goto err; } } else if(!memcmp(buf, "NoPowerUpTimeoutCheat ", 22)) { if(state->cheats[NPUTOCHEAT]) { redefinewarning("NoPowerUpTimeoutCheat", line, state->gamefile); free(state->cheats[NPUTOCHEAT]); } if(!(state->cheats[NPUTOCHEAT] = strdup(buf + 22))) { oom(); goto err; } if(strlen(state->cheats[NPUTOCHEAT]) > MAXCHEATLEN) { GrError("Cheat sequence too long on " "line %d of game file \"%s\"\n", line, state->gamefile); goto err; } } else if(!memcmp(buf, "BeginLevel", 10)) { /* Check to make sure we haven't got another BeginLevel * line while already in a level definition block: */ if(inlevelblock) { GrError("Error: BeginLevel while " "already in a level block on line %d " "of game file \"%s\"\n", line, state->gamefile); goto err; } inlevelblock = 1; /* Allocate a new level structure: */ if(!(lev = malloc(sizeof(level)))) { oom(); goto err; } /* Fill in the structure members with some defaults: */ lev->bricks = NULL; lev->backgroundname = NULL; lev->backgroundtiled = DEFAULT_BACKGROUND_TILED; lev->numbricks = 0; lev->next = NULL; /* Allocate and initialise the level grid: */ if(!(lev->grid = newgrid(state))) { oom(); goto err; } /* Link the new level structure onto the end of the * levels list: */ if(!state->levels) state->levels = lev; else { for(l = state->levels; l->next; l = l->next); l->next = lev; } } else if(!memcmp(buf, "LevelBackground ", 16)) { if(!inlevelblock) { notinlevblockerr("LevelBackground", line, state->gamefile); goto err; } if(lev->backgroundname) { redefinewarning("LevelBackground", line, state->gamefile); free(lev->backgroundname); } if(!(lev->backgroundname = strdup(buf + 16))) { oom(); goto err; } } else if(!memcmp(buf, "LevelBackgroundTiled ", 21)) { if(!inlevelblock) { notinlevblockerr("LevelBackgroundTiled", line, state->gamefile); goto err; } if(!strcmp(buf + 21, "Yes")) lev->backgroundtiled = 1; else if(!strcmp(buf + 21, "No")) lev->backgroundtiled = 0; else goto parseerr; } else if(!memcmp(buf, "BeginRows", 9)) { if(!inlevelblock) { notinlevblockerr("BeginRows", line, state->gamefile); goto err; } /* Parse the rows block: */ if(parse_rows(state, lev, fp, &line)) goto err; } else if(!memcmp(buf, "EndRows", 7)) { /* We should never see an EndRows here in a valid * level file because parse_rows() consumes it. */ GrError("Error: EndRows without corresponding " "BeginRows on line %d of game file " "\"%s\"\n", line, state->gamefile); goto err; } else if(!memcmp(buf, "BeginPowers", 11)) { if(!inlevelblock) { notinlevblockerr("BeginPowers", line, state->gamefile); goto err; } if(parse_powers(state, lev, fp, &line)) goto err; } else if(!memcmp(buf, "EndPowers", 9)) { GrError("Error: EndPowers without " "corresponding BeginPowers on line %d " "of game file \"%s\"\n", line, state->gamefile); goto err; } else if(!memcmp(buf, "EndLevel", 8)) { if(!inlevelblock) { GrError("Error: EndLevel while not in " "in a level block on line %d of game " "file \"%s\"\n", line, state->gamefile); goto err; } inlevelblock = 0; state->numlevels++; } else { GrError("Unknown command \"%s\" on line %d " "of game file \"%s\"\n", buf, line, state->gamefile); } /* We keep a count of the line we're on so that errors and * warnings can print out the number of the bad line: */ line++; } /* Check if the reason fgets() failed was because of an I/O error * instead of simply reaching the end of the file: */ if(ferror(fp)) { GrError("Error reading from game file \"%s\" on line " "%d: %s\n", state->gamefile, line, strerror(errno)); goto err; } /* Allocate and initialise the current game grid: */ if(!(state->grid = newgrid(state))) { oom(); goto err; } fclose(fp); /* Close the game file. */ return 0; /* Success. */ parseerr: /* A parse error occured so print an error message: */ GrError("Parse error on line %d of game file \"%s\"\n", line, state->gamefile); err: /* Some other error occured and we've already printed the error message. */ fclose(fp); /* Close the game file (may fail but we don't care). */ return 1; /* Failure. */ }
void draw_screen(int full) { int bstart, bend; int x = 0, y = 0; GR_GC_ID gc = GrNewGC(); for(y = 0; y < YUNITS; y++) { bstart = -1; bend = 0; for(x = 0; x < XUNITS; x++) { if (playground[y][x] == PLAYGROUND_EMPTY) { if (bstart == -1) bend = bstart = x; else bend++; continue; } /* Draw the background block */ if (bstart != -1) { GrSetGCForeground(gc, WHITE); GrFillRect(offscreen, gc, (bstart * XUNITSIZE), (y * YUNITSIZE), (bend - bstart + 1) * XUNITSIZE, YUNITSIZE); skipped += (bend - bstart); bstart = -1; bend = 0; } if (!full && playground[y][x] == PLAYGROUND_BORDER) continue; switch(playground[y][x]) { case PLAYGROUND_BORDER: GrSetGCForeground(gc, GRAY); break; case PLAYGROUND_SNAKE: GrSetGCForeground(gc, BLACK); break; case PLAYGROUND_TAIL: GrSetGCForeground(gc, BLACK); break; case PLAYGROUND_NIBBLE: GrSetGCForeground(gc, GRAY); break; } GrFillRect(offscreen, gc, (x * XUNITSIZE), (y * YUNITSIZE), XUNITSIZE, YUNITSIZE); #ifdef NOTUSED if (playground[y][x] == PLAYGROUND_NIBBLE && nibble.active) { GR_POINT points[4]; points[0].x = (x * XUNITSIZE) + 1; points[0].y = points[2].y = (y * YUNITSIZE) + 1 + ((YUNITSIZE -2) / 2); points[1].x = points[3].x = (x * YUNITSIZE) + 1 + ((XUNITSIZE -2) / 2); points[1].y = (y * YUNITSIZE) + 1; points[2].x = points[0].x + (XUNITSIZE - 2); points[3].y = points[1].y + (YUNITSIZE - 2); GrFillPoly(offscreen, gc, 4, points); } #endif if (playground[y][x] == PLAYGROUND_NIBBLE && nibble.active) { int xpos = (x * XUNITSIZE) + (XUNITSIZE / 2); int ypos = (y * YUNITSIZE) + (YUNITSIZE / 2); GrSetGCForeground(gc, BLACK); GrFillEllipse(offscreen, gc, xpos, ypos, (XUNITSIZE / 2) - 1, (YUNITSIZE / 2) - 1); } } /* If we have background clear up to the edge, handle that here */ if (bstart != -1) { GrSetGCForeground(gc, WHITE); GrFillRect(offscreen, gc, (bstart * XUNITSIZE), (y * YUNITSIZE), (bend - bstart + 1) * XUNITSIZE, YUNITSIZE); bend = bstart = 0; } } GrDestroyGC(gc); }
// Advances the game, draws the frame, then checks to see if the ball hit a chasm wall. static void advance_and_check() { // Increment game time_t t1; int i; int y; QUEUENODE *node; GR_COLOR gr = GRAY; GR_COLOR wh = WHITE; GrSetGCForeground(tunnel_gc, WHITE); GrFillRect(temp_pixmap, tunnel_gc, 0, 0, screen_info.cols, (screen_info.rows - (HEADER_TOPLINE + 1))); (void) time(&t1); srandom((long)t1); i = random() % 3; if (i == 0 && tail->offset > 0) cycle_chasm_queue(tail->offset - 1, &head, &middle, &tail); else if (i == 1 && tail->offset + chasmWidth < wi.width) cycle_chasm_queue(tail->offset + 1, &head, &middle, &tail); else cycle_chasm_queue(tail->offset, &head, &middle, &tail); // Draw chasm if( screen_info.bpp >= 16 ) { gr = GR_RGB( 255, 128, 0 ); wh = GR_RGB( 128, 50, 0 ); } node = head; y = 0; while (node != NULL) { GrSetGCForeground(tunnel_gc, wh); GrFillRect(temp_pixmap, tunnel_gc, 0, y, screen_info.cols, 2); GrSetGCForeground(tunnel_gc, WHITE); GrFillRect(temp_pixmap, tunnel_gc, node->offset, y, chasmWidth, 2); GrSetGCForeground(tunnel_gc, BLACK); GrFillRect(temp_pixmap, tunnel_gc, node->offset-5, y, 5, 2); GrFillRect(temp_pixmap, tunnel_gc, node->offset + chasmWidth, y, 5, 2); GrSetGCForeground(tunnel_gc, gr); GrFillRect(temp_pixmap, tunnel_gc, node->offset-8, y, 3, 2); GrFillRect(temp_pixmap, tunnel_gc, node->offset + chasmWidth+5, y, 3, 2); node = node->next; y+=2; } // Draw ball GrSetGCForeground(tunnel_gc, BLACK); GrFillEllipse(temp_pixmap ,tunnel_gc, ball.x, wi.height / 2, ball.radius, ball.radius); // Map window GrCopyArea(tunnel_wid, tunnel_gc, 0, 0, screen_info.cols, (screen_info.rows - (HEADER_TOPLINE + 1)), temp_pixmap, 0, 0, MWROP_SRCCOPY); // Check for collisions. Stop game if one is found. if (middle->offset >= ball.x - ball.radius || middle->offset + chasmWidth < ball.x + ball.radius) { running = 0; GrDestroyTimer( timer_id ); running = 1; draw_result(); } // increment score score++; }