Mercurial > hg > early-roguelike
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); | |