/*********************************************/ /* 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 #include #include "xbd.h" void blink(i, j) int i, j; { field[i][j].changed = TRUE; } void move_cell(i, j, ii, jj) int i, j, ii, jj; { field[ii][jj] = field[i][j]; field[ii][jj].speed = 1; field[ii][jj].changed = TRUE; field[ii][jj].dir = ((ii - i) == 1) ? S : ((i - ii) == 1) ? N : ((jj - j) == 1) ? E : W; set_cell(i, j, SPACE); } void explode(a, b, stage) int a, b, stage; { if (field[a][b].content != STEEL) { set_cell(a, b, EXPLOSION); field[a][b].stage = stage;/* dirty fix, not what stage was meant for */ } } Bool move_nucbal(i, j, t) int i, j, t; { ii = (!t) ? (i + y - 1) % y : i; if (!t) jj = j; else switch (field[i][j].dir) { case E: jj = (t == 1) ? (j + x - 1) % x : (j + 1) % x; break; case W: default: jj = (t == 2) ? (j + x - 1) % x : (j + 1) % x; break; } switch (field[ii][jj].content) { case SPACE: move_cell(i, j, ii, jj); return (TRUE); case NUCBAL: explode(i, j, DIAEXPLO); explode(ii, jj, DIAEXPLO); return (TRUE); default: if (field[i][j].dir == N) field[i][j].dir = E; else field[i][j].dir = ((field[i][j].dir + 2) % 4); return (FALSE); } } Bool move_monster(content, direction) char content, direction; { switch (direction) { case N: ii = (i + y - 1) % y; jj = j; break; case E: jj = (j + 1) % x; ii = i; break; case S: ii = (i + 1) % y; jj = j; break; default: jj = (j + x - 1) % x; ii = i; break; /* default must be SOMEthing, West */ } switch (field[ii][jj].content) { case SPACE: if (!field[ii][jj].changed) { move_cell(i, j, ii, jj); field[ii][jj].dir = direction; return (TRUE); } else return (FALSE); break; case BOULDER: case DIAMOND: if ((direction == N) && (field[ii][jj].speed != 0)) if (content == RMONSTER) { explode(i, j, DIAEXPLO); return (TRUE); } else if (content == LMONSTER) { explode(i, j, SPACEEXPLO); return (TRUE); } else return (FALSE); else return (FALSE); break; default: return (FALSE); break; } return (FALSE); } Bool search_destroy(content) char content; { ii = (i + y - 1) % y; jj = (j + x - 1) % x; if (field[i][jj].content == PLAYER || field[i][jj].content == BLOB) { set_cell(i, j, SPACE); if (field[i][jj].content == PLAYER) { lives--; scoreobs = TRUE; } if (content == RMONSTER) explode(i, jj, DIAEXPLO); else explode(i, jj, SPACEEXPLO); return (TRUE); } else if (field[ii][j].content == PLAYER || field[ii][j].content == BLOB) { set_cell(i, j, SPACE); if (field[ii][j].content == PLAYER) { lives--; scoreobs = TRUE; } if (content == RMONSTER) explode(ii, j, DIAEXPLO); else explode(ii, j, SPACEEXPLO); return (TRUE); } else { ii = (i + 1) % y; jj = (j + 1) % x; if (field[i][jj].content == PLAYER || field[i][jj].content == BLOB) { set_cell(i, j, SPACE); if (field[i][jj].content == PLAYER) { lives--; scoreobs = TRUE; } if (content == RMONSTER) explode(i, jj, DIAEXPLO); else explode(i, jj, SPACEEXPLO); return (TRUE); } else if (field[ii][j].content == PLAYER || field[ii][j].content == BLOB) { set_cell(i, j, SPACE); if (field[ii][j].content == PLAYER) { lives--; scoreobs = TRUE; } if (content == RMONSTER) explode(ii, j, DIAEXPLO); else explode(ii, j, SPACEEXPLO); return (TRUE); } else return (FALSE); } } void propagate(i, j, dias) int i, j; Bool dias; { int t, it, jt; if (dias) set_cell(i, j, DIAMOND); else { field[i][j].checked = PROPAGATED; field[i][j].caught = TRUE; } for (t = 0; (t < 4); ++t) { it = (t == 1) ? (i + y - 1) % y : (t == 3) ? (i + 1) % y : i; jt = (t == 2) ? (j + x - 1) % x : (t == 0) ? (j + 1) % x : j; switch (field[it][jt].content) { case BLOB: if (field[it][jt].checked != PROPAGATED) propagate(it, jt, dias); break; case SPACE: case GRASS: if (!(rand() % (blobbreak + 1))) { set_cell(it, jt, BLOB); field[it][jt].checked = PROPAGATED; field[it][jt].caught = TRUE; } break; default: break; } } } Bool caught(i, j) int i, j; { Bool Free; int t, it, jt; field[i][j].checked = 1; Free = FALSE; for (t = 0; ((t < 4) && !Free); ++t) { it = (t == 1) ? (i + y - 1) % y : (t == 3) ? (i + 1) % y : i; jt = (t == 2) ? (j + x - 1) % x : (t == 0) ? (j + 1) % x : j; switch (field[it][jt].content) { case SPACE: case GRASS: case RMONSTER: case LMONSTER: case EATER: Free = TRUE; break; case BLOB: Free = (Free || ((field[it][jt].checked == 1) ? !field[i][j].caught : !caught(it, jt))); break; default: break; } } field[i][j].caught != Free; return (!Free); } void diaboulderproc(i, j) int i, j; { if (field[i][j].content == DIAMOND) blink(i, j); ii = (ii + 1) % y; field[i][j].dir = NODIR; switch (field[ii][j].content) { case SPACE: /* directly underneath */ move_cell(i, j, ii, j); field[ii][j].speed = 1; break; case PLAYER: if (field[i][j].speed) { set_cell(i, j, SPACE); explode(ii, j, SPACEEXPLO); lives--; scoreobs = TRUE; } break; case LMONSTER: case EATER: if (field[i][j].speed) { set_cell(i, j, SPACE); explode(ii, j, SPACEEXPLO); } break; case RMONSTER: if (field[i][j].speed) { set_cell(i, j, SPACE); explode(ii, j, DIAEXPLO); } break; case TINKLE: if (field[i][j].speed) { tinkact = TRUE; field[ii][j].stage = field[i][j].content; field[ii][j].speed = 1; set_cell(i, j, SPACE); break; } break; case WALL: case BOULDER: case DIAMOND: case EXPLOSION: jj = (j + 1) % x; if (field[i][jj].content == SPACE && field[ii][jj].content == SPACE) { move_cell(i, j, i, jj); field[i][jj].speed = 0; } else { jj = (j - 1) % x; if (field[i][jj].content == SPACE && field[ii][jj].content == SPACE) { move_cell(i, j, i, jj); field[i][jj].speed = 0; } else field[i][j].speed = 0; } break; default: field[i][j].speed = 0; break; } } void calculate_field() { players = 0; /* Iterate through each horizontal line */ if (!curtime) curorder = KILL; for (i = y - 1; i >= 0; --i) { for (j = 0; j < x; ++j) { if (!(field[i][j].changed)) { ii = i; jj = j; switch (field[i][j].content) { case PLAYER: players++; switch (curorder) { case STAND: break; case UP: ii = (i + y - 1) % y; break; case DOWN: ii = (i + 1) % y; break; case LEFT: jj = (j + x - 1) % x; break; case RIGHT: jj = (j + 1) % x; break; } if (!(curorder == STAND) && !(field[i][j].changed)) { if (curorder == KILL) { set_cell(i, j, EXPLOSION); lives--; scoreobs = TRUE; break; } switch (field[ii][jj].content) { case SPACE: case GRASS: case DIAMOND: if (field[ii][jj].content == DIAMOND) { if (curorder == UP && field[ii][jj].speed) break; score += diapoints; if (diareq) diareq--; scoreobs = TRUE; } if (steal) set_cell(ii, jj, SPACE); else move_cell(i, j, ii, jj); break; case BOULDER: jjj = (2 * jj - j + x) % x; if (field[i][jjj].content == SPACE && ((rand() % 2) == 0) && !(field[ii][jj].dir == E)) { move_cell(i, jj, i, jjj); field[i][jjj].speed = 0; if (!steal) { move_cell(i, j, i, jj); } } break; case EXIT: if (diareq < 1) { if (!steal) move_cell(i, j, ii, jj); else set_cell(ii, jj, SPACE); if (!levincreased) { levelnum++; lives++; levincreased = TRUE; for (jj = curtime / 10; jj > 0; --jj) { score += 10; draw_score(); } } gamestop = TRUE; stoplevel = TRUE; } break; } } blink(i, j); break; case DIAMOND: case BOULDER: diaboulderproc(i, j); break; case EATER: if (!field[i][j].speed) { for (jjj = 0; ((!field[i][j].changed) && (jjj < 4)); ++jjj) { ii = (jjj == 2) ? (i + 1) % y : (jjj == 0) ? (i + y - 1) % y : i; jj = (jjj == 1) ? (j + 1) % x : (jjj == 3) ? (j + x - 1) % x : j; switch (field[ii][jj].content) { case PLAYER: lives--; scoreobs = TRUE; case DIAMOND: if (field[ii][jj].speed && (ii == i - 1) && (jj == j)) break; case BLOB: case LMONSTER: case RMONSTER: case NUCBAL: move_cell(i, j, ii, jj); break; default: break; } } } else { jjj = field[i][j].dir; ii = (jjj == 2) ? (i + 1) % y : (jjj == 0) ? (i + y - 1) % y : i; jj = (jjj == 1) ? (j + 1) % x : (jjj == 3) ? (j + x - 1) % x : j; switch (field[ii][jj].content) { case LMONSTER: case BLOB: case SPACE: case GRASS: case DIAMOND: case RMONSTER: case PLAYER: case NUCBAL: if (field[ii][jj].content == PLAYER) { lives--; scoreobs = TRUE; } move_cell(i, j, ii, jj); break; case BOULDER: jjj = (2 * jj - j + x) % x; if (field[i][jjj].content == SPACE && ((rand() % 2) == 0) && !(field[ii][jj].dir == E)) { move_cell(i, jj, i, jjj); move_cell(i, j, i, jj); } else field[i][j].speed = 0; break; default: field[i][j].speed = 0; break; } } blink(i, j); break; case RMONSTER: blink(i, j); if (search_destroy(RMONSTER)) break; jjj = 3; while (jjj >= 0 && !move_monster(RMONSTER, (field[i][j].dir + jjj + 2) % 4)) jjj--; break; case LMONSTER: blink(i, j); if (search_destroy(LMONSTER)) break; jjj = 0; while (jjj <= 4 && !move_monster(LMONSTER, (field[i][j].dir + jjj + 3) % 4)) jjj++; break; case EXPLOSION: jjj = field[i][j].stage; if (!(jjj % 5)) { jjj++; /* use jjj for setting new stage */ ii = (i + 1) % y; jj = (j + 1) % x; explode(i, j, jjj); explode(i, jj, jjj); explode(ii, j, jjj); explode(ii, jj, jjj); ii = (i + y - 1) % y; explode(ii, j, jjj); explode(ii, jj, jjj); jj = (j + x - 1) % x; explode(ii, jj, jjj); explode(i, jj, jjj); ii = (i + 1) % y; explode(ii, jj, jjj); } else { if (jjj % 10 < 3) field[i][j].stage++; else if (jjj > DIAEXPLO) { set_cell(i, j, DIAMOND); } else if (jjj > BOULDEXPLO) { set_cell(i, j, BOULDER); } else if (jjj > SPACEEXPLO) { set_cell(i, j, SPACE); } else field[i][j].stage++; } break; case EXIT: blink(i, j); break; case BLOB: blobcells++; if (blobcollapse) set_cell(i, j, BOULDER); else { if (blobcells > critical) blobcollapse = TRUE; else { if (!field[i][j].checked) { if (caught(i, j)) propagate(i, j, DIAMOND); else propagate(i, j, FALSE); } field[i][j].checked = FALSE; field[i][j].caught = TRUE; } } blink(i, j); break; case NUCBAL: for (jjj = 0; ((jjj < 3) && !move_nucbal(i, j, jjj)); ++jjj); blink(i, j); break; case MAGICWALL: jj = (j + x - 1) % x; if (field[i][jj].content == SPACE) set_cell(i, jj, MAGICWALL); jj = (j + 1) % x; if (field[i][jj].content == SPACE) set_cell(i, jj, MAGICWALL); break; case TINKLE: if (tinkact) { blink(i, j); if (tinkdur > 0) { switch (field[i][j].stage) { case BOULDER: { field[i][j].content = DIAMOND; diaboulderproc(i, j); break; } case DIAMOND: { field[i][j].content = BOULDER; diaboulderproc(i, j); break; } default: break; } } } set_cell(i, j, TINKLE); /* reset to empty tinkle wall */ break; default: break; } } } } curorder = STAND; /* reset orders */ blobcells = 0; pgc = (pgc == pgc1) ? ((rand() % 22) == 0) ? pgc2 : pgc1 : pgc1; dgc = (dgc == dgc1) ? dgc2 : dgc1; lgc = (lgc == lgc1) ? lgc2 : lgc1; rgc = (rgc == rgc1) ? rgc2 : rgc1; egc = (egc == egc1) ? egc2 : egc1; Bgc = (Bgc == Bgc1) ? Bgc2 : Bgc1; if (tinkact) tgc = (tgc == tgc1) ? tgc2 : tgc1; if (!diareq) { Egc = (Egc == Egc1) ? Egc2 : Egc1; if (diareq == 0) { diapoints = extradiapoints; scoreobs = TRUE; } } }