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