Annotation of early-roguelike/arogue5/new_level.c, Revision 1.1.1.1
1.1 rubenllo 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: void put_things(LEVTYPE ltype);
20:
21: /* ltype designates type of level to create */
22: void
23: new_level(LEVTYPE ltype)
24: {
25: register int rm = 0, i, cnt;
26: register char ch;
27: register struct linked_list *item;
28: register struct thing *tp;
29: register struct object *obj;
30: int waslit = 0; /* Was the previous outside level lit? */
31: int starty = 0, startx = 0, deltay = 0, deltax = 0;
32: bool fresh=TRUE, vert = 0, top;
33: struct room *rp;
34: struct linked_list *nitem, *savmonst=NULL, *savitems=NULL;
35: coord stairs = { 0, 0 };
36:
37: if (wizard) {
38: msg("Turns: %d", turns); /* Number of turns for last level */
39: mpos = 0;
40: }
41:
42: /* Start player off right */
43: turn_off(player, ISHELD);
44: turn_off(player, ISFLEE);
45: extinguish(suffocate);
46: hold_count = 0;
47: trap_tries = 0;
48:
49: /* Are we just entering a dungeon? If so, how big is it? */
50: if (ltype != OUTSIDE && nfloors < 0) nfloors = HARDER+10 + rnd(11);
51:
52: if (level > max_level)
53: max_level = level;
54:
55: /* Are we starting a new outside level? */
56: if (ltype == OUTSIDE) {
57: register int i, j;
58:
59: /* Save some information prior to clearing the screen */
60: if (level == -1 || mvinch(hero.y, hero.x) == '-') vert = TRUE;
61: else vert = FALSE;
62:
63: if (level == -1) {
64: fresh = TRUE;
65: starty = 2;
66: startx = 1;
67: deltay = deltax = 1;
68: level = 0; /* Restore the level */
69: }
70: else { /* Copy several lines of the terrain to the other end */
71: char cch; /* Copy character */
72:
73: /* Was the area dark (not magically lit)? */
74: if (!(rooms[0].r_flags & ISDARK)) waslit = 1;
75:
76: fresh = FALSE;
77: if ((vert && hero.y == 1) || (!vert && hero.x == 0)) top = TRUE;
78: else top = FALSE;
79: for (i=0; i<TERRASAVE; i++) {
80: if (vert)
81: for (j=1; j<COLS-1; j++) {
82: if (top) {
83: cch = CCHAR( mvinch(i+2, j) );
84: mvaddch(LINES-6+i, j, cch);
85: }
86: else {
87: cch = CCHAR( mvinch(LINES-4-i, j) );
88: mvaddch(4-i, j, cch);
89: }
90: }
91: else
92: for (j=2; j<LINES-3; j++) {
93: if (top) {
94: cch = CCHAR( mvinch(j, i+1) );
95: mvaddch(j, COLS-4+i, cch);
96: }
97: else {
98: cch = CCHAR( mvinch(j, COLS-2-i) );
99: mvaddch(j, 3-i, cch);
100: }
101: }
102: }
103:
104: if (vert) {
105: startx = deltax = 1;
106: if (top) {
107: starty = LINES-4-TERRASAVE;
108: deltay = -1;
109: }
110: else {
111: starty = TERRASAVE + 2;
112: deltay = 1;
113: }
114: }
115: else {
116: starty = 2;
117: deltay = 1;
118: if (top) {
119: startx = COLS-2-TERRASAVE;
120: deltax = -1;
121: }
122: else {
123: deltax = 1;
124: startx = TERRASAVE + 1;
125: }
126: }
127:
128: /* Check if any monsters should be saved */
129: for (item = mlist; item != NULL; item = nitem) {
130: nitem = next(item);
131: tp = THINGPTR(item);
132: if (vert) {
133: if (top) {
134: if (tp->t_pos.y < TERRASAVE + 2)
135: tp->t_pos.y += LINES - 5 - TERRASAVE;
136: else continue;
137: }
138: else {
139: if (tp->t_pos.y > LINES - 4 - TERRASAVE)
140: tp->t_pos.y += 5 + TERRASAVE - LINES;
141: else continue;
142: }
143: }
144: else {
145: if (top) {
146: if (tp->t_pos.x < TERRASAVE + 1)
147: tp->t_pos.x += COLS - 2 - TERRASAVE;
148: else continue;
149: }
150: else {
151: if (tp->t_pos.x > COLS - 2 - TERRASAVE)
152: tp->t_pos.x += 2 + TERRASAVE - COLS;
153: else continue;
154: }
155: }
156: detach(mlist, item);
157: attach(savmonst, item);
158: }
159:
160: /* Check if any treasure should be saved */
161: for (item = lvl_obj; item != NULL; item = nitem) {
162: nitem = next(item);
163: obj = OBJPTR(item);
164: if (vert) {
165: if (top) {
166: if (obj->o_pos.y < TERRASAVE + 2)
167: obj->o_pos.y += LINES - 5 - TERRASAVE;
168: else continue;
169: }
170: else {
171: if (obj->o_pos.y > LINES - 4 - TERRASAVE)
172: obj->o_pos.y += 5 + TERRASAVE - LINES;
173: else continue;
174: }
175: }
176: else {
177: if (top) {
178: if (obj->o_pos.x < TERRASAVE + 1)
179: obj->o_pos.x += COLS - 2 - TERRASAVE;
180: else continue;
181: }
182: else {
183: if (obj->o_pos.x > COLS - 2 - TERRASAVE)
184: obj->o_pos.x += 2 + TERRASAVE - COLS;
185: else continue;
186: }
187: }
188: detach(lvl_obj, item);
189: attach(savitems, item);
190: }
191: }
192: }
193:
194:
195: wclear(cw);
196: wclear(mw);
197: if (fresh) clear();
198: /*
199: * check to see if he missed a UNIQUE, If he did then put it back
200: * in the monster table for next time
201: */
202: for (item = mlist; item != NULL; item = next(item)) {
203: tp = THINGPTR(item);
204: if (on(*tp, ISUNIQUE))
205: monsters[tp->t_index].m_normal = TRUE;
206: }
207: /*
208: * Free up the monsters on the last level
209: */
210: t_free_list(monst_dead);
211: t_free_list(mlist);
212: o_free_list(lvl_obj); /* Free up previous objects (if any) */
213: for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
214: t_free_list(rp->r_exit); /* Free up the exit lists */
215:
216: levtype = ltype;
217: foods_this_level = 0; /* food for hero this level */
218: if (ltype == POSTLEV) {
219: do_post(); /* do post stuff */
220: }
221: else if (ltype == MAZELEV) {
222: do_maze();
223: no_food++;
224: put_things(ltype); /* Place objects (if any) */
225: }
226: else if (ltype == OUTSIDE) {
227: init_terrain();
228: do_terrain(starty, startx, deltay, deltax, (bool) (fresh || !vert));
229: no_food++;
230: put_things(ltype);
231:
232: /* Should we magically light this area? */
233: if (waslit) rooms[0].r_flags &= ~ISDARK;
234: }
235: else {
236: do_rooms(); /* Draw rooms */
237: do_passages(); /* Draw passages */
238: no_food++;
239: put_things(ltype); /* Place objects (if any) */
240: }
241: /*
242: * Place the staircase down. Only a small chance for an outside stairway.
243: */
244: if (ltype != OUTSIDE || roll(1, 4) == 4) {
245: cnt = 0;
246: do {
247: rm = rnd_room();
248: rnd_pos(&rooms[rm], &stairs);
249: } until (mvinch(stairs.y, stairs.x) == FLOOR || cnt++ > 5000);
250: addch(STAIRS);
251: }
252: /*
253: * maybe add a trading post
254: */
255: if (level > 5 && rnd(11) == 7 && ltype == NORMLEV) {
256: cnt = 0;
257: do {
258: rm = rnd_room();
259: if (rooms[rm].r_flags & ISTREAS)
260: continue;
261: rnd_pos(&rooms[rm], &stairs);
262: } until (winat(stairs.y, stairs.x) == FLOOR || cnt++ > 5000);
263: addch(POST);
264: }
265: if (ltype != POSTLEV) { /* Add monsters that fell through */
266: nitem = tlist;
267: while (nitem != NULL) {
268: item = nitem;
269: nitem = next(item); /* because detach and attach mess up ptrs */
270: tp = THINGPTR(item);
271: cnt = 0;
272: do {
273: rm = rnd_room();
274: rnd_pos(&rooms[rm], &tp->t_pos);
275: } until (cnt++ > 5000 || winat(tp->t_pos.y, tp->t_pos.x) == FLOOR);
276: mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type);
277: tp->t_oldch = CCHAR( mvwinch(cw, tp->t_pos.y, tp->t_pos.x) );
278:
279: /*
280: * If it has a fire, mark it
281: */
282: if (on(*tp, HASFIRE)) {
283: register struct linked_list *fire_item;
284:
285: fire_item = creat_item();
286: ldata(fire_item) = (char *) tp;
287: attach(rooms[rm].r_fires, fire_item);
288: rooms[rm].r_flags |= HASFIRE;
289: }
290: turn_off(*tp, ISELSEWHERE);
291: detach(tlist, item);
292: attach(mlist, item);
293: }
294: }
295:
296: /* Restore any saved monsters */
297: for (item = savmonst; item != NULL; item = nitem) {
298: nitem = next(item);
299: tp = THINGPTR(item);
300: mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type);
301: tp->t_oldch = CCHAR( mvwinch(cw, tp->t_pos.y, tp->t_pos.x) );
302:
303: /*
304: * If it has a fire, mark it
305: */
306: if (on(*tp, HASFIRE)) {
307: register struct linked_list *fire_item;
308:
309: fire_item = creat_item();
310: ldata(fire_item) = (char *) tp;
311: attach(rooms[rm].r_fires, fire_item);
312: rooms[rm].r_flags |= HASFIRE;
313: }
314:
315: detach(savmonst, item);
316: attach(mlist, item);
317: }
318:
319: /* Restore any saved objects */
320: for(item = savitems; item != NULL; item = nitem) {
321: nitem = next(item);
322: obj = OBJPTR(item);
323: mvaddch(obj->o_pos.y, obj->o_pos.x, obj->o_type);
324: detach(savitems, item);
325: attach(lvl_obj, item);
326: }
327:
328:
329: /*
330: * Place the traps (except for trading post)
331: */
332: ntraps = 0; /* No traps yet */
333: if (levtype == NORMLEV) {
334: if (rnd(10) < vlevel) {
335: ntraps = rnd(vlevel/4)+1;
336: if (ntraps > MAXTRAPS)
337: ntraps = MAXTRAPS;
338: i = ntraps;
339: while (i--)
340: {
341: cnt = 0;
342: do {
343: rm = rnd_room();
344: if (rooms[rm].r_flags & ISTREAS)
345: continue;
346: rnd_pos(&rooms[rm], &stairs);
347: } until (winat(stairs.y, stairs.x) == FLOOR || cnt++ > 5000);
348:
349: traps[i].tr_flags = 0;
350:
351: /* If we are at the bottom, we can't set a trap door */
352: if (level >= nfloors) ch = (char) rnd(7) + 1;
353: else ch = (char) rnd(8);
354:
355: switch((int) ch) {
356: case 0: ch = TRAPDOOR;
357: when 1: ch = BEARTRAP;
358: when 2: ch = SLEEPTRAP;
359: when 3: ch = ARROWTRAP;
360: when 4: ch = TELTRAP;
361: when 5: ch = DARTTRAP;
362: when 6: ch = POOL;
363: traps[i].tr_flags = ISFOUND;
364: when 7: ch = MAZETRAP;
365: }
366: addch(ch);
367: traps[i].tr_type = ch;
368: traps[i].tr_show = FLOOR;
369: traps[i].tr_pos = stairs;
370: }
371: }
372: }
373: if (fresh) { /* A whole new picture */
374: cnt = 0;
375: do {
376: rm = rnd_room();
377: if (rooms[rm].r_flags & ISTREAS)
378: continue;
379: rnd_pos(&rooms[rm], &hero);
380: } until( cnt++ > 5000 ||
381: (winat(hero.y, hero.x) == FLOOR &&
382: DISTANCE(hero.y, hero.x, stairs.y, stairs.x) > 16));
383: }
384: else { /* We're extending into an adjacent outside plane */
385: rm = 0;
386: if (vert) {
387: if (hero.y == 1) hero.y = LINES - 3 - TERRASAVE; /* Top to bottom */
388: else hero.y = TERRASAVE + 1; /* Bottom to top */
389: }
390: else {
391: if (hero.x == 0) hero.x = COLS - 1 - TERRASAVE; /* Right to left */
392: else hero.x = TERRASAVE; /* Left to right */
393: }
394: }
395: oldrp = &rooms[rm]; /* Set the current room */
396: player.t_oldpos = player.t_pos; /* Set the current position */
397: if (ISWEARING(R_AGGR) ||
398: (cur_misc[WEAR_JEWEL] != NULL &&
399: cur_misc[WEAR_JEWEL]->o_which == MM_JEWEL))
400: aggravate();
401: light(&hero);
402: wmove(cw, hero.y, hero.x);
403: waddch(cw, PLAYER);
404:
405: if (level > cur_max)
406: cur_max = level;
407:
408: status(TRUE);
409: }
410:
411: /*
412: * Pick a room that is really there
413: */
414:
415: int
416: rnd_room(void)
417: {
418: register int rm;
419:
420: if (levtype != NORMLEV)
421: rm = 0;
422: else do
423: {
424: rm = rnd(MAXROOMS);
425: } while (rooms[rm].r_flags & ISGONE);
426: return rm;
427: }
428:
429: /*
430: * put_things:
431: * put potions and scrolls on this level
432: * ltype: designates type of level to create
433: */
434:
435: void
436: put_things(LEVTYPE ltype)
437: {
438: register int i, rm, cnt;
439: register struct object *cur;
440: register struct linked_list *item, *exitptr;
441: bool got_unique = FALSE;
442: int length, width;
443: coord tp, *exit;
444:
445: /*
446: * The only way to get new stuff is to go down into the dungeon.
447: */
448: if (level <= cur_max)
449: return;
450:
451: /*
452: * There is a chance that there is a treasure room on this level
453: * Increasing chance after level 9
454: */
455: if (ltype != MAZELEV && rnd(HARDER) < level - 8) {
456: register int j;
457: register struct room *rp;
458:
459: /* Count the number of free spaces */
460: i = 0; /* 0 tries */
461: do {
462: rp = &rooms[rnd_room()];
463: width = rp->r_max.y - 2;
464: length = rp->r_max.x - 2;
465: } until ((width*length >= MAXTREAS) || (i++ > MAXROOMS*4));
466:
467: /* Mark the room as a treasure room */
468: rp->r_flags |= ISTREAS;
469:
470: /* Make all the doors secret doors */
471: for (exitptr = rp->r_exit; exitptr; exitptr = next(exitptr)) {
472: exit = DOORPTR(exitptr);
473: move(exit->y, exit->x);
474: addch(SECRETDOOR);
475: }
476:
477: /*
478: * check to see if there are any monsters in room already
479: */
480: for (item = mlist; item != NULL; item = next(item)) {
481: register struct thing *tp;
482:
483: tp = THINGPTR(item);
484: if (rp == roomin(&tp->t_pos)) {
485: turn_on(*tp, ISMEAN);
486: if (off(*tp, CANINWALL)) {
487: tp->t_dest = &hero;
488: turn_on(*tp, ISRUN);
489: }
490: if (on(*tp, ISUNIQUE))
491: got_unique = TRUE;
492:
493: /* If it is a mimic, undisguise it */
494: if (on(*tp, ISDISGUISE))
495: turn_off(*tp, ISDISGUISE);
496: }
497: }
498:
499:
500: /* Put in the monsters and treasures */
501: for (j=1; j<rp->r_max.y-1; j++)
502: for (i=1; i<rp->r_max.x-1; i++) {
503: coord trp;
504:
505: trp.y = rp->r_pos.y+j;
506: trp.x = rp->r_pos.x+i;
507:
508: /* Monsters */
509: if ((rnd(100) < (MAXTREAS*100)/(width*length)) &&
510: (mvwinch(mw, rp->r_pos.y+j, rp->r_pos.x+i) == ' ')) {
511: register struct thing *tp;
512:
513: /* Make a monster */
514: item = new_item(sizeof *tp);
515: tp = THINGPTR(item);
516:
517: /*
518: * Put it there and aggravate it (unless it can escape)
519: * only put one UNIQUE per treasure room at most
520: */
521: if (got_unique)
522: new_monster(item,randmonster(FALSE, TRUE),&trp,TRUE);
523: else
524: new_monster(item,randmonster(FALSE, FALSE),&trp,TRUE);
525: if (on(*tp, ISUNIQUE)) {
526: got_unique = TRUE;
527: carry_obj(tp, monsters[tp->t_index].m_carry);
528: }
529: turn_on(*tp, ISMEAN);
530: if (off(*tp, CANINWALL)) {
531: tp->t_dest = &hero;
532: turn_on(*tp, ISRUN);
533: }
534:
535: /* If it is a mimic, undisguise it */
536: if (on(*tp, ISDISGUISE))
537: turn_off(*tp, ISDISGUISE);
538:
539: if (on(*tp, HASFIRE)) {
540: register struct linked_list *fire_item;
541:
542: fire_item = creat_item();
543: ldata(fire_item) = (char *) tp;
544: attach(rp->r_fires, fire_item);
545: rp->r_flags |= HASFIRE;
546: }
547: }
548:
549: /* Treasures */
550: if ((rnd(100) < (MAXTREAS*100)/(width*length)) &&
551: (mvinch(rp->r_pos.y+j, rp->r_pos.x+i) == FLOOR)) {
552: item = new_thing(ALL);
553: attach(lvl_obj, item);
554: cur = OBJPTR(item);
555:
556: mvaddch(trp.y, trp.x, cur->o_type);
557: cur->o_pos = trp;
558: }
559: }
560: }
561:
562: /*
563: * Do MAXOBJ attempts to put things on a level
564: */
565: for (i = 0; i < MAXOBJ; i++)
566: if (rnd(100) < 45) {
567: /*
568: * Pick a new object and link it in the list
569: */
570: item = new_thing(ALL);
571: attach(lvl_obj, item);
572: cur = OBJPTR(item);
573: /*
574: * Put it somewhere
575: */
576: cnt = 0;
577: do {
578: rm = rnd_room();
579: rnd_pos(&rooms[rm], &tp);
580: } until (winat(tp.y, tp.x) == FLOOR || cnt++ > 500);
581: mvaddch(tp.y, tp.x, cur->o_type);
582: cur->o_pos = tp;
583: }
584: }
CVSweb