/*********************************************/ /* you just keep on pushing my luck over the */ /* BOULDER DASH */ /* */ /* Jeroen Houttuin, ETH Zurich, 1990 */ /* */ /* */ /* PC-VGA version from : */ /* */ /* Herve SOULARD, Paris, 1990 */ /* */ /*********************************************/ #include #include #include "xbd.h" #define HEIGHT 16 #define WIDTH 16 #define MAXPGM 23 char curchar; char allPgms[NB_EDIT_PGM]; Bool kbdHit(void) { if (*kbdPtrRead == *kbdPtrWrite) return(FALSE); else return(TRUE); } void getKbd(byte *TT,byte *T) { *T = *(kbdBuffer + *kbdPtrRead); if (*T == 0x00 || *T == 0xE0) { *T = *(kbdBuffer + *kbdPtrRead + 1); *TT = 'F'; } else *TT = 'T'; *kbdPtrRead += 2; if (*kbdPtrRead == 0x3E) *kbdPtrRead = 0x1E; } void init_vars() { levelnum = -1; xin = 0; yin = 0; } /* Save the current level back into a file. The global variable */ /* filename is used to determine the file name. */ void save_level() { FILE *levelfile; char buf[300]; register int i, j; /* Open the data file */ levelfile = fopen(filename, "w"); if (levelfile == NULL) { exit(1); } /* Write out the size of the level. Normal text is used so that */ /* levels can be easily copied across architectures. */ fprintf(levelfile, "%d %d %d %d %d %d %d %d %d %s\n", y, x, speed, diareq, diapoints, extradiapoints, blobbreak, tinkdur, curtime, levname); /* Terminate the lines for writing out the horizontal level lines */ buf[x] = '\n'; buf[x + 1] = '\0'; /* Iterate through each vertical position */ for (i = 0; i < y; ++i) { /* Copy each horizontal line into the output buffer */ for (j = 0; j < x; ++j) buf[j] = field[i][j].content; /* Write the line out to the file */ fputs(buf, levelfile); } /* Close the data file */ fclose(levelfile); } int getIndex(char c) { int i=0; while (allPgms[i] != c && i < NB_EDIT_PGM) i++; if (i == NB_EDIT_PGM) return (-1); else return(i); } void setCursor(xC,yC) int xC,yC; { int x,y; _setcolor(15); y = yC * HEIGHT; x = xC * WIDTH; _rectangle(_GBORDER, x, y, x + WIDTH -1, y + HEIGHT-1); _setcolor(0); _rectangle(_GBORDER, x+1, y+1, x + WIDTH-2, y + HEIGHT-2); } void unsetCursor(xC,yC) int xC,yC; { switch (field[yC][xC].content) { case GRASS: drawPgm((xC << 1), (yC << 4), ggc, _GPSET); break; case SPACE: drawPgm((xC << 1), (yC << 4), sgc, _GPSET); break; case PLAYER: drawPgm((xC << 1), (yC << 4), pgc, _GPSET); break; case WALL: drawPgm((xC << 1), (yC << 4), wgc, _GPSET); break; case MAGICWALL: drawPgm((xC << 1), (yC << 4), Wgc, _GPSET); break; case DIAMOND: drawPgm((xC << 1), (yC << 4), dgc, _GPSET); break; case BOULDER: drawPgm((xC << 1), (yC << 4), bgc, _GPSET); break; case EXPLOSION: drawPgm((xC << 1), (yC << 4), xgc, _GPSET); break; case LMONSTER: drawPgm((xC << 1), (yC << 4), lgc, _GPSET); break; case RMONSTER: drawPgm((xC << 1), (yC << 4), rgc, _GPSET); break; case NUCBAL: drawPgm((xC << 1), (yC << 4), ngc, _GPSET); break; case BLOB: drawPgm((xC << 1), (yC << 4), Bgc, _GPSET); break; case TINKLE: drawPgm((xC << 1), (yC << 4), tgc, _GPSET); break; case EATER: drawPgm((xC << 1), (yC << 4), egc, _GPSET); break; case EXIT: drawPgm((xC << 1), (yC << 4), Egc, _GPSET); break; case STEEL: drawPgm((xC << 1), (yC << 4), Sgc, _GPSET); break; } } void showLocPgm(int xC, int yC) { char c; int i; c = field[yC][xC].content; i = getIndex(c); _setcolor(15); _rectangle(_GFILLINTERIOR, 625, 22+(i*20), 635, 26+(i*20)); } void unShowLocPgm(int xC, int yC) { char c; int i; c = field[yC][xC].content; i = getIndex(c); _setcolor(0); _rectangle(_GFILLINTERIOR, 625, 22+(i*20), 635, 26+(i*20)); } void drawAllPgm() { drawPgm(75, 16, pgc, _GPSET); allPgms[0] = PLAYER; drawPgm(75, 36, sgc, _GPSET); allPgms[1] = SPACE; drawPgm(75, 56, lgc, _GPSET); allPgms[2] = LMONSTER; drawPgm(75, 76, rgc, _GPSET); allPgms[3] = RMONSTER; drawPgm(75, 96, ggc, _GPSET); allPgms[4] = GRASS; drawPgm(75,116, wgc, _GPSET); allPgms[5] = WALL; drawPgm(75,136, Wgc, _GPSET); allPgms[6] = MAGICWALL; drawPgm(75,156, dgc, _GPSET); allPgms[7] = DIAMOND; drawPgm(75,176, Sgc, _GPSET); allPgms[8] = STEEL; drawPgm(75,196, bgc, _GPSET); allPgms[9] = BOULDER; drawPgm(75,216, xgc, _GPSET); allPgms[10] = EXPLOSION; drawPgm(75,236, Egc, _GPSET); allPgms[11] = EXIT; drawPgm(75,256, egc, _GPSET); allPgms[12] = EATER; drawPgm(75,276, ngc, _GPSET); allPgms[13] = NUCBAL; drawPgm(75,296, Bgc, _GPSET); allPgms[14] = BLOB; drawPgm(75,316, tgc, _GPSET); allPgms[15] = TINKLE; } /* Main routine for editing levels */ void main(argc, argv) int argc; char **argv; { register int i, j; int tmp; char buf[50]; int pX = 0, pY = 0; int curPgm = 0; Bool end = FALSE; byte keyhit; byte keytype; init_vars(); /* Read in command line options */ for (i = 1; i < argc; ++i) { if (argv[i][0] == '-') { /* -w sets the level width */ if (argv[i][1] == 'w') { if (argv[i][2] == '\0' && i + 1 < argc) { sscanf(argv[i + 1], "%d", &xin); i++; } else sscanf(argv[i] + 2, "%d", &xin); } /* -h sets the level height */ else if (argv[i][1] == 'h') { if (argv[i][2] == '\0' && i + 1 < argc) { sscanf(argv[i + 1], "%d", &yin); i++; } else sscanf(argv[i] + 2, "%d", &yin); } /* -l sets the level number */ else if (argv[i][1] == 'l') { if (argv[i][2] == '\0' && i + 1 < argc) { sscanf(argv[i + 1], "%d", &levelnum); i++; } else sscanf(argv[i] + 2, "%d", &levelnum); } else { printf("usage: xbde [-h ] [-w ] -l \n"); exit(1); } } } /* Make sure some value was chosen for the level number. This */ /* discourages everybody editing the same level all the time. */ if (levelnum == -1) { printf("usage: xbde [-h ] [-w ] -l \n"); exit(1); } /* Load in level data from file. */ init_level(levelnum); /* Start up X windows and create all graphics cursors */ xstart(); load(); make_gcs(); Egc = Egc2; Wgc = Wgc2; tgc = tgc3; draw_field(TRUE); drawAllPgm(); _setcolor(15); _rectangle(_GFILLINTERIOR, 580, 22+(curPgm*20), 590, 26+(curPgm*20)); showLocPgm(pX,pY); /* Main event loop */ while (!end) { setCursor(pX, pY); if (kbdHit()) { getKbd(&keytype,&keyhit); if (keytype == 'T') { switch (keyhit) { /* C erases the entire level */ case K_C : case K_c : /* Replace level contents with space */ for (i = 0; i < y; ++i) for (j = 0; j < x; ++j) if ((i == 0) || (i == y - 1) || (j == 0) || (j == x - 1)) set_cell(i, j, STEEL); else set_cell(i, j, SPACE); /* Redraw empty level */ draw_field(FALSE); showLocPgm(pX,pY); break; case K_U : case K_u : save_level(); break; case K_ESC : end = TRUE; break; case K_SPACE : unShowLocPgm(pX,pY); set_cell(pY, pX, allPgms[curPgm]); showLocPgm(pX,pY); break; default : curchar = keyhit; break; } } else { switch (keyhit) { case K_PGUP : _setcolor(0); _rectangle(_GFILLINTERIOR, 580, 22+(curPgm*20), 590, 26+(curPgm*20)); if (--curPgm < 0) curPgm = NB_EDIT_PGM - 1; _setcolor(15); _rectangle(_GFILLINTERIOR, 580, 22+(curPgm*20), 590, 26+(curPgm*20)); break; case K_PGDOWN : _setcolor(0); _rectangle(_GFILLINTERIOR, 580, 22+(curPgm*20), 590, 26+(curPgm*20)); if (++curPgm >= NB_EDIT_PGM) curPgm = 0; _setcolor(15); _rectangle(_GFILLINTERIOR, 580, 22+(curPgm*20), 590, 26+(curPgm*20)); break; case K_LEFT : unsetCursor(pX,pY); unShowLocPgm(pX,pY); if (--pX < 0) pX = x-1; setCursor(pX,pY); showLocPgm(pX,pY); break; case K_RIGHT : unsetCursor(pX,pY); unShowLocPgm(pX,pY); if (++pX >= x) pX = 0; setCursor(pX,pY); showLocPgm(pX,pY); break; case K_UP : unsetCursor(pX,pY); unShowLocPgm(pX,pY); if (--pY < 0) pY = y-1; setCursor(pX,pY); showLocPgm(pX,pY); break; case K_DOWN : unShowLocPgm(pX,pY); unsetCursor(pX,pY); if (++pY >= y) pY = 0; showLocPgm(pX,pY); setCursor(pX,pY); break; } } } unsetCursor(pX, pY); /* If the mouse moves with the button pressed, or the button is */ /* pressed, draw the current block at that position */ /* else if (xev.type == MotionNotify) { if (xev.xmotion.state & Button3Mask) set_cell(xev.xmotion.y >> 5, xev.xmotion.x >> 5, SPACE); else if (xev.xmotion.state & Button1Mask) set_cell(xev.xmotion.y >> 5, xev.xmotion.x >> 5, curchar); } else if (xev.type == ButtonPress) { if (xev.xbutton.button == Button3) set_cell(xev.xbutton.y >> 5, xev.xbutton.x >> 5, SPACE); else set_cell(xev.xbutton.y >> 5, xev.xbutton.x >> 5, curchar); } draw_field(FALSE); XFlush(disp); */ } xend(); exit(0); }