1 /*
2  * new_level:
3  *	Dig and draw a new level
4  *
5  * new_level.c	1.4 (A.I. Design) 12/13/84
6  */
7 
8 #include "rogue.h"
9 #include "curses.h"
10 
11 #define TREAS_ROOM 20	/* one chance in TREAS_ROOM for a treasure room */
12 #define MAXTREAS 10	/* maximum number of treasures in a treasure room */
13 #define MINTREAS 2	/* minimum number of treasures in a treasure room */
14 
15 
16 new_level()
17 {
18     register int rm, i;
19     THING *tp;
20     byte *fp;
21     THING **mp;
22     int index;
23     coord stairs;
24 
25     player.t_flags &= ~ISHELD;	/* unhold when you go down just in case */
26     /*
27      * Monsters only get displayed when you move
28      * so start a level by having the poor guy rest
29      * God forbid he lands next to a monster!
30      */
31     if (level > max_level)
32 		max_level = level;
33 #ifdef PROTECTED
34 	one_tick();
35 	if (level > 1 && csum() != cksum)
36 		_halt();
37 #endif
38     /*
39      * Clean things off from last level
40      */
41     wsetmem(_level, ((MAXLINES-3)*MAXCOLS) >> 1,'  ');
42     setmem(_flags, (MAXLINES-3)*MAXCOLS, F_REAL);
43     /*
44      * Free up the monsters on the last level
45      */
46     for (tp = mlist; tp != NULL; tp = next(tp))
47 		free_list(tp->t_pack);
48     free_list(mlist);
49     /*
50      * just in case we left some flytraps behind
51      */
52     f_restor();
53     /*
54      * Throw away stuff left on the previous level (if anything)
55      */
56     free_list(lvl_obj);
57     do_rooms();				/* Draw rooms */
58     if (max_level == 1) {
59 		extern int svwin_ds;
60 
61     	reinit = TRUE;
62 		if (svwin_ds == -1) {
63 			move(maxrow, 0);
64 			clrtoeol();
65 		} else
66 			clear();
67 	}
68     implode();
69     status();
70     do_passages();			/* Draw passages */
71     no_food++;
72     put_things();			/* Place objects (if any) */
73     /*
74      * Place the staircase down.
75      */
76     i = 0;
77     do {
78         rm = rnd_room();
79 	rnd_pos(&rooms[rm], &stairs);
80 	index = INDEX(stairs.y, stairs.x);
81 	if (i++ > 100)
82 	{
83 	    i = 0;
84 	    seed = srand();
85 	}
86     } while (!isfloor(_level[index]));
87     _level[index] = STAIRS;
88     /*
89      * Place the traps
90      */
91     if (rnd(10) < level) {
92 		ntraps = rnd(level / 4) + 1;
93 		if (ntraps > MAXTRAPS)
94 		    ntraps = MAXTRAPS;
95 		i = ntraps;
96 		while (i--) {
97 		    do {
98 				rm = rnd_room();
99 				rnd_pos(&rooms[rm], &stairs);
100 				index = INDEX(stairs.y, stairs.x);
101 		    } while (!isfloor(_level[index]));
102 		    fp = &_flags[index];
103 		    *fp &= ~F_REAL;
104 		    *fp |= rnd(NTRAPS);
105 		}
106     }
107     do {
108 		rm = rnd_room();
109 		rnd_pos(&rooms[rm], &hero);
110 		index = INDEX(hero.y, hero.x);
111     } while (!(isfloor(_level[index]) && (_flags[index] & F_REAL)
112 				&& moat(hero.y, hero.x) == NULL));
113 
114     mpos = 0;
115     enter_room(&hero);
116     mvaddch(hero.y, hero.x, PLAYER);
117     bcopy(oldpos,hero);
118     oldrp = proom;
119     if (on(player, SEEMONST))
120 		turn_see(FALSE);
121 }
122 
123 /*
124  * rnd_room:
125  *	Pick a room that is really there
126  */
127 rnd_room()
128 {
129     register int rm;
130 
131     do
132 	rm = rnd(MAXROOMS);
133     while (!((rooms[rm].r_flags & ISGONE)==0||(rooms[rm].r_flags & ISMAZE)));
134     return rm;
135 }
136 
137 /*
138  * put_things:
139  *	Put potions and scrolls on this level
140  */
141 put_things()
142 {
143     register int i = 0;
144     register THING *cur;
145     register int rm;
146     coord tp;
147 
148     /*
149      * Once you have found the amulet, the only way to get new stuff is
150      * go down into the dungeon.
151      * This is real unfair - I'm going to allow one thing, that way
152      * the poor guy will get some food.
153      */
154     if (saw_amulet && level < max_level)
155 		i = MAXOBJ - 1;
156     else {
157 		/*
158 		 * If he is really deep in the dungeon and he hasn't found the
159 		 * amulet yet, put it somewhere on the ground
160 		 * Check this first so if we are out of memory the guy has a
161 		 * hope of getting the amulet
162 		 */
163 		if (level >= AMULETLEVEL && !saw_amulet) {
164 		    if ((cur = new_item()) != NULL) {
165 				attach(lvl_obj, cur);
166 				cur->o_hplus = cur->o_dplus = 0;
167 				cur->o_damage = cur->o_hurldmg = "0d0";
168 				cur->o_ac = 11;
169 				cur->o_type = AMULET;
170 				/*
171 				 * Put it somewhere
172 				 */
173 				do {
174 					rm = rnd_room();
175 					rnd_pos(&rooms[rm], &tp);
176 				} while (!isfloor(winat(tp.y, tp.x)));
177 				chat(tp.y, tp.x) = AMULET;
178 				bcopy(cur->o_pos,tp);
179 		    }
180 		}
181         /*
182          * check for treasure rooms, and if so, put it in.
183          */
184         if (rnd(TREAS_ROOM) == 0)
185 		    treas_room();
186     }
187     /*
188      * Do MAXOBJ attempts to put things on a level
189      */
190     for (;i < MAXOBJ; i++)
191 		if (total < MAXITEMS && rnd(100) < 35) {
192 		    /*
193 		     * Pick a new object and link it in the list
194 		     */
195 		    cur = new_thing();
196 		    attach(lvl_obj, cur);
197 		    /*
198 		     * Put it somewhere
199 		     */
200 		    do {
201 				rm = rnd_room();
202 				rnd_pos(&rooms[rm], &tp);
203 		    } while (!isfloor(chat(tp.y, tp.x)));
204 		    chat(tp.y, tp.x) = cur->o_type;
205 		    bcopy(cur->o_pos,tp);
206 		}
207 }
208 
209 /*
210  * treas_room:
211  *	Add a treasure room
212  */
213 #define MAXTRIES 10	/* max number of tries to put down a monster */
214 
215 treas_room()
216 {
217     int nm, index;
218     register THING *tp;
219     register struct room *rp;
220     int spots, num_monst;
221     coord mp;
222 
223     rp = &rooms[rnd_room()];
224     spots = (rp->r_max.y - 2) * (rp->r_max.x - 2) - MINTREAS;
225     if (spots > (MAXTREAS - MINTREAS))
226 	spots = (MAXTREAS - MINTREAS);
227     num_monst = nm = rnd(spots) + MINTREAS;
228     while (nm-- && total < MAXITEMS)
229     {
230 	do
231 	{
232 	    rnd_pos(rp, &mp);
233 	    index = INDEX(mp.y, mp.x);
234 	} while (!isfloor(_level[index]));
235 	tp = new_thing();
236 	bcopy(tp->o_pos,mp);
237 	attach(lvl_obj, tp);
238 	_level[index] = tp->o_type;
239     }
240 
241     /*
242      * fill up room with monsters from the next level down
243      */
244 
245     if ((nm = rnd(spots) + MINTREAS) < num_monst + 2)
246 	nm = num_monst + 2;
247     spots = (rp->r_max.y - 2) * (rp->r_max.x - 2);
248     if (nm > spots)
249 	nm = spots;
250     level++;
251     while (nm--)
252     {
253 	for (spots = 0; spots < MAXTRIES; spots++)
254 	{
255 	    rnd_pos(rp, &mp);
256 	    index = INDEX(mp.y, mp.x);
257 	    if (isfloor(_level[index]) && moat(mp.y, mp.x) == NULL)
258 	    	break;
259 	}
260 	if (spots != MAXTRIES)
261 	{
262 	    if ((tp = new_item()) != NULL)
263 	    {
264 	        new_monster(tp, randmonster(FALSE), &mp);
265 #ifdef TEST
266 	        if (bailout && me())
267 				msg("treasure rm bailout");
268 #endif TEST
269 	        tp->t_flags |= ISMEAN;	/* no sloughers in THIS room */
270 	        give_pack(tp);
271 	    }
272 	}
273     }
274     level--;
275 }
276 