comparison xrogue/n_level.c @ 133:e6179860cb76

Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 21 Apr 2015 08:55:20 -0400
parents
children f54901b9c39b
comparison
equal deleted inserted replaced
124:d10fc4a065ac 133:e6179860cb76
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);