Mercurial > hg > early-roguelike
comparison arogue5/new_level.c @ 63:0ed67132cf10
Import Advanced Rogue 5.8 from the Roguelike Restoration Project (r1490)
| author | elwin |
|---|---|
| date | Thu, 09 Aug 2012 22:58:48 +0000 |
| parents | |
| children | 56e748983fa8 |
comparison
equal
deleted
inserted
replaced
| 62:0ef99244acb8 | 63:0ed67132cf10 |
|---|---|
| 1 /* | |
| 2 * new_level: Dig and draw a new level | |
| 3 * | |
| 4 * Advanced Rogue | |
| 5 * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T | |
| 6 * All rights reserved. | |
| 7 * | |
| 8 * Based on "Rogue: Exploring the Dungeons of Doom" | |
| 9 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman | |
| 10 * All rights reserved. | |
| 11 * | |
| 12 * See the file LICENSE.TXT for full copyright and licensing information. | |
| 13 */ | |
| 14 | |
| 15 #include "curses.h" | |
| 16 #include "rogue.h" | |
| 17 #define TERRASAVE 3 | |
| 18 | |
| 19 new_level(ltype) | |
| 20 LEVTYPE ltype; /* designates type of level to create */ | |
| 21 { | |
| 22 register int rm = 0, i, cnt; | |
| 23 register char ch; | |
| 24 register struct linked_list *item; | |
| 25 register struct thing *tp; | |
| 26 register struct object *obj; | |
| 27 int waslit = 0; /* Was the previous outside level lit? */ | |
| 28 int starty = 0, startx = 0, deltay = 0, deltax = 0; | |
| 29 bool fresh=TRUE, vert = 0, top; | |
| 30 struct room *rp; | |
| 31 struct linked_list *nitem, *savmonst=NULL, *savitems=NULL; | |
| 32 coord stairs = { 0, 0 }; | |
| 33 | |
| 34 if (wizard) { | |
| 35 msg("Turns: %d", turns); /* Number of turns for last level */ | |
| 36 mpos = 0; | |
| 37 } | |
| 38 | |
| 39 /* Start player off right */ | |
| 40 turn_off(player, ISHELD); | |
| 41 turn_off(player, ISFLEE); | |
| 42 extinguish(suffocate); | |
| 43 hold_count = 0; | |
| 44 trap_tries = 0; | |
| 45 | |
| 46 /* Are we just entering a dungeon? If so, how big is it? */ | |
| 47 if (ltype != OUTSIDE && nfloors < 0) nfloors = HARDER+10 + rnd(11); | |
| 48 | |
| 49 if (level > max_level) | |
| 50 max_level = level; | |
| 51 | |
| 52 /* Are we starting a new outside level? */ | |
| 53 if (ltype == OUTSIDE) { | |
| 54 register int i, j; | |
| 55 | |
| 56 /* Save some information prior to clearing the screen */ | |
| 57 if (level == -1 || mvinch(hero.y, hero.x) == '-') vert = TRUE; | |
| 58 else vert = FALSE; | |
| 59 | |
| 60 if (level == -1) { | |
| 61 fresh = TRUE; | |
| 62 starty = 2; | |
| 63 startx = 1; | |
| 64 deltay = deltax = 1; | |
| 65 level = 0; /* Restore the level */ | |
| 66 } | |
| 67 else { /* Copy several lines of the terrain to the other end */ | |
| 68 char cch; /* Copy character */ | |
| 69 | |
| 70 /* Was the area dark (not magically lit)? */ | |
| 71 if (!(rooms[0].r_flags & ISDARK)) waslit = 1; | |
| 72 | |
| 73 fresh = FALSE; | |
| 74 if ((vert && hero.y == 1) || (!vert && hero.x == 0)) top = TRUE; | |
| 75 else top = FALSE; | |
| 76 for (i=0; i<TERRASAVE; i++) { | |
| 77 if (vert) | |
| 78 for (j=1; j<COLS-1; j++) { | |
| 79 if (top) { | |
| 80 cch = CCHAR( mvinch(i+2, j) ); | |
| 81 mvaddch(LINES-6+i, j, cch); | |
| 82 } | |
| 83 else { | |
| 84 cch = CCHAR( mvinch(LINES-4-i, j) ); | |
| 85 mvaddch(4-i, j, cch); | |
| 86 } | |
| 87 } | |
| 88 else | |
| 89 for (j=2; j<LINES-3; j++) { | |
| 90 if (top) { | |
| 91 cch = CCHAR( mvinch(j, i+1) ); | |
| 92 mvaddch(j, COLS-4+i, cch); | |
| 93 } | |
| 94 else { | |
| 95 cch = CCHAR( mvinch(j, COLS-2-i) ); | |
| 96 mvaddch(j, 3-i, cch); | |
| 97 } | |
| 98 } | |
| 99 } | |
| 100 | |
| 101 if (vert) { | |
| 102 startx = deltax = 1; | |
| 103 if (top) { | |
| 104 starty = LINES-4-TERRASAVE; | |
| 105 deltay = -1; | |
| 106 } | |
| 107 else { | |
| 108 starty = TERRASAVE + 2; | |
| 109 deltay = 1; | |
| 110 } | |
| 111 } | |
| 112 else { | |
| 113 starty = 2; | |
| 114 deltay = 1; | |
| 115 if (top) { | |
| 116 startx = COLS-2-TERRASAVE; | |
| 117 deltax = -1; | |
| 118 } | |
| 119 else { | |
| 120 deltax = 1; | |
| 121 startx = TERRASAVE + 1; | |
| 122 } | |
| 123 } | |
| 124 | |
| 125 /* Check if any monsters should be saved */ | |
| 126 for (item = mlist; item != NULL; item = nitem) { | |
| 127 nitem = next(item); | |
| 128 tp = THINGPTR(item); | |
| 129 if (vert) { | |
| 130 if (top) { | |
| 131 if (tp->t_pos.y < TERRASAVE + 2) | |
| 132 tp->t_pos.y += LINES - 5 - TERRASAVE; | |
| 133 else continue; | |
| 134 } | |
| 135 else { | |
| 136 if (tp->t_pos.y > LINES - 4 - TERRASAVE) | |
| 137 tp->t_pos.y += 5 + TERRASAVE - LINES; | |
| 138 else continue; | |
| 139 } | |
| 140 } | |
| 141 else { | |
| 142 if (top) { | |
| 143 if (tp->t_pos.x < TERRASAVE + 1) | |
| 144 tp->t_pos.x += COLS - 2 - TERRASAVE; | |
| 145 else continue; | |
| 146 } | |
| 147 else { | |
| 148 if (tp->t_pos.x > COLS - 2 - TERRASAVE) | |
| 149 tp->t_pos.x += 2 + TERRASAVE - COLS; | |
| 150 else continue; | |
| 151 } | |
| 152 } | |
| 153 detach(mlist, item); | |
| 154 attach(savmonst, item); | |
| 155 } | |
| 156 | |
| 157 /* Check if any treasure should be saved */ | |
| 158 for (item = lvl_obj; item != NULL; item = nitem) { | |
| 159 nitem = next(item); | |
| 160 obj = OBJPTR(item); | |
| 161 if (vert) { | |
| 162 if (top) { | |
| 163 if (obj->o_pos.y < TERRASAVE + 2) | |
| 164 obj->o_pos.y += LINES - 5 - TERRASAVE; | |
| 165 else continue; | |
| 166 } | |
| 167 else { | |
| 168 if (obj->o_pos.y > LINES - 4 - TERRASAVE) | |
| 169 obj->o_pos.y += 5 + TERRASAVE - LINES; | |
| 170 else continue; | |
| 171 } | |
| 172 } | |
| 173 else { | |
| 174 if (top) { | |
| 175 if (obj->o_pos.x < TERRASAVE + 1) | |
| 176 obj->o_pos.x += COLS - 2 - TERRASAVE; | |
| 177 else continue; | |
| 178 } | |
| 179 else { | |
| 180 if (obj->o_pos.x > COLS - 2 - TERRASAVE) | |
| 181 obj->o_pos.x += 2 + TERRASAVE - COLS; | |
| 182 else continue; | |
| 183 } | |
| 184 } | |
| 185 detach(lvl_obj, item); | |
| 186 attach(savitems, item); | |
| 187 } | |
| 188 } | |
| 189 } | |
| 190 | |
| 191 | |
| 192 wclear(cw); | |
| 193 wclear(mw); | |
| 194 if (fresh) clear(); | |
| 195 /* | |
| 196 * check to see if he missed a UNIQUE, If he did then put it back | |
| 197 * in the monster table for next time | |
| 198 */ | |
| 199 for (item = mlist; item != NULL; item = next(item)) { | |
| 200 tp = THINGPTR(item); | |
| 201 if (on(*tp, ISUNIQUE)) | |
| 202 monsters[tp->t_index].m_normal = TRUE; | |
| 203 } | |
| 204 /* | |
| 205 * Free up the monsters on the last level | |
| 206 */ | |
| 207 t_free_list(monst_dead); | |
| 208 t_free_list(mlist); | |
| 209 o_free_list(lvl_obj); /* Free up previous objects (if any) */ | |
| 210 for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) | |
| 211 t_free_list(rp->r_exit); /* Free up the exit lists */ | |
| 212 | |
| 213 levtype = ltype; | |
| 214 foods_this_level = 0; /* food for hero this level */ | |
| 215 if (ltype == POSTLEV) { | |
| 216 do_post(); /* do post stuff */ | |
| 217 } | |
| 218 else if (ltype == MAZELEV) { | |
| 219 do_maze(); | |
| 220 no_food++; | |
| 221 put_things(ltype); /* Place objects (if any) */ | |
| 222 } | |
| 223 else if (ltype == OUTSIDE) { | |
| 224 init_terrain(); | |
| 225 do_terrain(starty, startx, deltay, deltax, (bool) (fresh || !vert)); | |
| 226 no_food++; | |
| 227 put_things(ltype); | |
| 228 | |
| 229 /* Should we magically light this area? */ | |
| 230 if (waslit) rooms[0].r_flags &= ~ISDARK; | |
| 231 } | |
| 232 else { | |
| 233 do_rooms(); /* Draw rooms */ | |
| 234 do_passages(); /* Draw passages */ | |
| 235 no_food++; | |
| 236 put_things(ltype); /* Place objects (if any) */ | |
| 237 } | |
| 238 /* | |
| 239 * Place the staircase down. Only a small chance for an outside stairway. | |
| 240 */ | |
| 241 if (ltype != OUTSIDE || roll(1, 4) == 4) { | |
| 242 cnt = 0; | |
| 243 do { | |
| 244 rm = rnd_room(); | |
| 245 rnd_pos(&rooms[rm], &stairs); | |
| 246 } until (mvinch(stairs.y, stairs.x) == FLOOR || cnt++ > 5000); | |
| 247 addch(STAIRS); | |
| 248 } | |
| 249 /* | |
| 250 * maybe add a trading post | |
| 251 */ | |
| 252 if (level > 5 && rnd(11) == 7 && ltype == NORMLEV) { | |
| 253 cnt = 0; | |
| 254 do { | |
| 255 rm = rnd_room(); | |
| 256 if (rooms[rm].r_flags & ISTREAS) | |
| 257 continue; | |
| 258 rnd_pos(&rooms[rm], &stairs); | |
| 259 } until (winat(stairs.y, stairs.x) == FLOOR || cnt++ > 5000); | |
| 260 addch(POST); | |
| 261 } | |
| 262 if (ltype != POSTLEV) { /* Add monsters that fell through */ | |
| 263 nitem = tlist; | |
| 264 while (nitem != NULL) { | |
| 265 item = nitem; | |
| 266 nitem = next(item); /* because detach and attach mess up ptrs */ | |
| 267 tp = THINGPTR(item); | |
| 268 cnt = 0; | |
| 269 do { | |
| 270 rm = rnd_room(); | |
| 271 rnd_pos(&rooms[rm], &tp->t_pos); | |
| 272 } until (cnt++ > 5000 || winat(tp->t_pos.y, tp->t_pos.x) == FLOOR); | |
| 273 mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type); | |
| 274 tp->t_oldch = CCHAR( mvwinch(cw, tp->t_pos.y, tp->t_pos.x) ); | |
| 275 | |
| 276 /* | |
| 277 * If it has a fire, mark it | |
| 278 */ | |
| 279 if (on(*tp, HASFIRE)) { | |
| 280 register struct linked_list *fire_item; | |
| 281 | |
| 282 fire_item = creat_item(); | |
| 283 ldata(fire_item) = (char *) tp; | |
| 284 attach(rooms[rm].r_fires, fire_item); | |
| 285 rooms[rm].r_flags |= HASFIRE; | |
| 286 } | |
| 287 turn_off(*tp, ISELSEWHERE); | |
| 288 detach(tlist, item); | |
| 289 attach(mlist, item); | |
| 290 } | |
| 291 } | |
| 292 | |
| 293 /* Restore any saved monsters */ | |
| 294 for (item = savmonst; item != NULL; item = nitem) { | |
| 295 nitem = next(item); | |
| 296 tp = THINGPTR(item); | |
| 297 mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type); | |
| 298 tp->t_oldch = CCHAR( mvwinch(cw, tp->t_pos.y, tp->t_pos.x) ); | |
| 299 | |
| 300 /* | |
| 301 * If it has a fire, mark it | |
| 302 */ | |
| 303 if (on(*tp, HASFIRE)) { | |
| 304 register struct linked_list *fire_item; | |
| 305 | |
| 306 fire_item = creat_item(); | |
| 307 ldata(fire_item) = (char *) tp; | |
| 308 attach(rooms[rm].r_fires, fire_item); | |
| 309 rooms[rm].r_flags |= HASFIRE; | |
| 310 } | |
| 311 | |
| 312 detach(savmonst, item); | |
| 313 attach(mlist, item); | |
| 314 } | |
| 315 | |
| 316 /* Restore any saved objects */ | |
| 317 for(item = savitems; item != NULL; item = nitem) { | |
| 318 nitem = next(item); | |
| 319 obj = OBJPTR(item); | |
| 320 mvaddch(obj->o_pos.y, obj->o_pos.x, obj->o_type); | |
| 321 detach(savitems, item); | |
| 322 attach(lvl_obj, item); | |
| 323 } | |
| 324 | |
| 325 | |
| 326 /* | |
| 327 * Place the traps (except for trading post) | |
| 328 */ | |
| 329 ntraps = 0; /* No traps yet */ | |
| 330 if (levtype == NORMLEV) { | |
| 331 if (rnd(10) < vlevel) { | |
| 332 ntraps = rnd(vlevel/4)+1; | |
| 333 if (ntraps > MAXTRAPS) | |
| 334 ntraps = MAXTRAPS; | |
| 335 i = ntraps; | |
| 336 while (i--) | |
| 337 { | |
| 338 cnt = 0; | |
| 339 do { | |
| 340 rm = rnd_room(); | |
| 341 if (rooms[rm].r_flags & ISTREAS) | |
| 342 continue; | |
| 343 rnd_pos(&rooms[rm], &stairs); | |
| 344 } until (winat(stairs.y, stairs.x) == FLOOR || cnt++ > 5000); | |
| 345 | |
| 346 traps[i].tr_flags = 0; | |
| 347 | |
| 348 /* If we are at the bottom, we can't set a trap door */ | |
| 349 if (level >= nfloors) ch = (char) rnd(7) + 1; | |
| 350 else ch = (char) rnd(8); | |
| 351 | |
| 352 switch((int) ch) { | |
| 353 case 0: ch = TRAPDOOR; | |
| 354 when 1: ch = BEARTRAP; | |
| 355 when 2: ch = SLEEPTRAP; | |
| 356 when 3: ch = ARROWTRAP; | |
| 357 when 4: ch = TELTRAP; | |
| 358 when 5: ch = DARTTRAP; | |
| 359 when 6: ch = POOL; | |
| 360 traps[i].tr_flags = ISFOUND; | |
| 361 when 7: ch = MAZETRAP; | |
| 362 } | |
| 363 addch(ch); | |
| 364 traps[i].tr_type = ch; | |
| 365 traps[i].tr_show = FLOOR; | |
| 366 traps[i].tr_pos = stairs; | |
| 367 } | |
| 368 } | |
| 369 } | |
| 370 if (fresh) { /* A whole new picture */ | |
| 371 cnt = 0; | |
| 372 do { | |
| 373 rm = rnd_room(); | |
| 374 if (rooms[rm].r_flags & ISTREAS) | |
| 375 continue; | |
| 376 rnd_pos(&rooms[rm], &hero); | |
| 377 } until( cnt++ > 5000 || | |
| 378 |
