Mercurial > hg > early-roguelike
comparison rogue5/move.c @ 33:f502bf60e6e4
Import Rogue 5.4 from the Roguelike Restoration Project (r1490)
author | elwin |
---|---|
date | Mon, 24 May 2010 20:10:59 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
32:2dcd75e6a736 | 33:f502bf60e6e4 |
---|---|
1 /* | |
2 * hero movement commands | |
3 * | |
4 * @(#)move.c 4.49 (Berkeley) 02/05/99 | |
5 * | |
6 * Rogue: Exploring the Dungeons of Doom | |
7 * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman | |
8 * All rights reserved. | |
9 * | |
10 * See the file LICENSE.TXT for full copyright and licensing information. | |
11 */ | |
12 | |
13 #include <curses.h> | |
14 #include <ctype.h> | |
15 #include "rogue.h" | |
16 | |
17 /* | |
18 * used to hold the new hero position | |
19 */ | |
20 | |
21 | |
22 /* | |
23 * do_run: | |
24 * Start the hero running | |
25 */ | |
26 | |
27 void | |
28 do_run(int ch) | |
29 { | |
30 running = TRUE; | |
31 after = FALSE; | |
32 runch = ch; | |
33 } | |
34 | |
35 /* | |
36 * do_move: | |
37 * Check to see that a move is legal. If it is handle the | |
38 * consequences (fighting, picking up, etc.) | |
39 */ | |
40 | |
41 void | |
42 do_move(int dy, int dx) | |
43 { | |
44 int ch, fl; | |
45 coord nh; | |
46 | |
47 firstmove = FALSE; | |
48 if (no_move) | |
49 { | |
50 no_move--; | |
51 msg("you are still stuck in the bear trap"); | |
52 return; | |
53 } | |
54 /* | |
55 * Do a confused move (maybe) | |
56 */ | |
57 if (on(player, ISHUH) && rnd(5) != 0) | |
58 { | |
59 nh = rndmove(&player); | |
60 if (ce(nh, hero)) | |
61 { | |
62 after = FALSE; | |
63 running = FALSE; | |
64 to_death = FALSE; | |
65 return; | |
66 } | |
67 } | |
68 else | |
69 { | |
70 over: | |
71 nh.y = hero.y + dy; | |
72 nh.x = hero.x + dx; | |
73 } | |
74 | |
75 /* | |
76 * Check if he tried to move off the screen or make an illegal | |
77 * diagonal move, and stop him if he did. | |
78 */ | |
79 if (nh.x < 0 || nh.x >= NUMCOLS || nh.y <= 0 || nh.y >= NUMLINES - 1) | |
80 goto hit_bound; | |
81 if (!diag_ok(&hero, &nh)) | |
82 { | |
83 after = FALSE; | |
84 running = FALSE; | |
85 return; | |
86 } | |
87 if (running && ce(hero, nh)) | |
88 after = running = FALSE; | |
89 fl = flat(nh.y, nh.x); | |
90 ch = winat(nh.y, nh.x); | |
91 if (!(fl & F_REAL) && ch == FLOOR) | |
92 { | |
93 if (!on(player, ISLEVIT)) | |
94 { | |
95 chat(nh.y, nh.x) = ch = TRAP; | |
96 flat(nh.y, nh.x) |= F_REAL; | |
97 } | |
98 } | |
99 else if (on(player, ISHELD) && ch != 'F') | |
100 { | |
101 msg("you are being held"); | |
102 return; | |
103 } | |
104 switch (ch) | |
105 { | |
106 case ' ': | |
107 case '|': | |
108 case '-': | |
109 hit_bound: | |
110 if (passgo && running && (proom->r_flags & ISGONE) | |
111 && !on(player, ISBLIND)) | |
112 { | |
113 int b1, b2; | |
114 | |
115 switch (runch) | |
116 { | |
117 case 'h': | |
118 case 'l': | |
119 b1 = (hero.y != 1 && turn_ok(hero.y - 1, hero.x)); | |
120 b2 = (hero.y != NUMLINES - 2 && turn_ok(hero.y + 1, hero.x)); | |
121 if (!(b1 ^ b2)) | |
122 break; | |
123 if (b1) | |
124 { | |
125 runch = 'k'; | |
126 dy = -1; | |
127 } | |
128 else | |
129 { | |
130 runch = 'j'; | |
131 dy = 1; | |
132 } | |
133 dx = 0; | |
134 turnref(); | |
135 goto over; | |
136 case 'j': | |
137 case 'k': | |
138 b1 = (hero.x != 0 && turn_ok(hero.y, hero.x - 1)); | |
139 b2 = (hero.x != NUMCOLS - 1 && turn_ok(hero.y, hero.x + 1)); | |
140 if (!(b1 ^ b2)) | |
141 break; | |
142 if (b1) | |
143 { | |
144 runch = 'h'; | |
145 dx = -1; | |
146 } | |
147 else | |
148 { | |
149 runch = 'l'; | |
150 dx = 1; | |
151 } | |
152 dy = 0; | |
153 turnref(); | |
154 goto over; | |
155 } | |
156 } | |
157 running = FALSE; | |
158 after = FALSE; | |
159 break; | |
160 case DOOR: | |
161 running = FALSE; | |
162 if (flat(hero.y, hero.x) & F_PASS) | |
163 enter_room(&nh); | |
164 goto move_stuff; | |
165 case TRAP: | |
166 ch = be_trapped(&nh); | |
167 if (ch == T_DOOR || ch == T_TELEP) | |
168 return; | |
169 goto move_stuff; | |
170 case PASSAGE: | |
171 /* | |
172 * when you're in a corridor, you don't know if you're in | |
173 * a maze room or not, and there ain't no way to find out | |
174 * if you're leaving a maze room, so it is necessary to | |
175 * always recalculate proom. | |
176 */ | |
177 proom = roomin(&hero); | |
178 goto move_stuff; | |
179 case FLOOR: | |
180 if (!(fl & F_REAL)) | |
181 be_trapped(&hero); | |
182 goto move_stuff; | |
183 case STAIRS: | |
184 seenstairs = TRUE; | |
185 /* FALLTHROUGH */ | |
186 default: | |
187 running = FALSE; | |
188 if (isupper(ch) || moat(nh.y, nh.x)) | |
189 fight(&nh, cur_weapon, FALSE); | |
190 else | |
191 { | |
192 if (ch != STAIRS) | |
193 take = ch; | |
194 move_stuff: | |
195 mvaddch(hero.y, hero.x, floor_at()); | |
196 if ((fl & F_PASS) && chat(oldpos.y, oldpos.x) == DOOR) | |
197 leave_room(&nh); | |
198 hero = nh; | |
199 } | |
200 } | |
201 } | |
202 | |
203 /* | |
204 * turn_ok: | |
205 * Decide whether it is legal to turn onto the given space | |
206 */ | |
207 int | |
208 turn_ok(int y, int x) | |
209 { | |
210 PLACE *pp; | |
211 | |
212 pp = INDEX(y, x); | |
213 return (pp->p_ch == DOOR | |
214 || (pp->p_flags & (F_REAL|F_PASS)) == (F_REAL|F_PASS)); | |
215 } | |
216 | |
217 /* | |
218 * turnref: | |
219 * Decide whether to refresh at a passage turning or not | |
220 */ | |
221 | |
222 void | |
223 turnref(void) | |
224 { | |
225 PLACE *pp; | |
226 | |
227 pp = INDEX(hero.y, hero.x); | |
228 if (!(pp->p_flags & F_SEEN)) | |
229 { | |
230 if (jump) | |
231 { | |
232 leaveok(stdscr, TRUE); | |
233 refresh(); | |
234 leaveok(stdscr, FALSE); | |
235 } | |
236 pp->p_flags |= F_SEEN; | |
237 } | |
238 } | |
239 | |
240 /* | |
241 * door_open: | |
242 * Called to illuminate a room. If it is dark, remove anything | |
243 * that might move. | |
244 */ | |
245 | |
246 void | |
247 door_open(const struct room *rp) | |
248 { | |
249 int y, x; | |
250 | |
251 if (!(rp->r_flags & ISGONE)) | |
252 for (y = rp->r_pos.y; y < rp->r_pos.y + rp->r_max.y; y++) | |
253 for (x = rp->r_pos.x; x < rp->r_pos.x + rp->r_max.x; x++) | |
254 if (isupper(winat(y, x))) | |
255 wake_monster(y, x); | |
256 } | |
257 | |
258 /* | |
259 * be_trapped: | |
260 * The guy stepped on a trap.... Make him pay. | |
261 */ | |
262 int | |
263 be_trapped(const coord *tc) | |
264 { | |
265 PLACE *pp; | |
266 THING *arrow; | |
267 int tr; | |
268 | |
269 if (on(player, ISLEVIT)) | |
270 return T_RUST; /* anything that's not a door or teleport */ | |
271 running = FALSE; | |
272 count = FALSE; | |
273 pp = INDEX(tc->y, tc->x); | |
274 pp->p_ch = TRAP; | |
275 tr = pp->p_flags & F_TMASK; | |
276 pp->p_flags |= F_SEEN; | |
277 switch (tr) | |
278 { | |
279 case T_DOOR: | |
280 level++; | |
281 new_level(); | |
282 msg("you fell into a trap!"); | |
283 when T_BEAR: | |
284 no_move += BEARTIME; | |
285 msg("you are caught in a bear trap"); | |
286 when T_MYST: | |
287 switch(rnd(11)) | |
288 { | |
289 case 0: msg("you are suddenly in a parallel dimension"); | |
290 when 1: msg("the light in here suddenly seems %s", rainbow[rnd(cNCOLORS)]); | |
291 when 2: msg("you feel a sting in the side of your neck"); | |
292 when 3: msg("multi-colored lines swirl around you, then fade"); | |
293 when 4: msg("a %s light flashes in your eyes", rainbow[rnd(cNCOLORS)]); | |
294 when 5: msg("a spike shoots past your ear!"); | |
295 when 6: msg("%s sparks dance across your armor", rainbow[rnd(cNCOLORS)]); | |
296 when 7: msg("you suddenly feel very thirsty"); | |
297 when 8: msg("you feel time speed up suddenly"); | |
298 when 9: msg("time now seems to be going slower"); | |
299 when 10: msg("you pack turns %s!", rainbow[rnd(cNCOLORS)]); | |
300 } | |
301 when T_SLEEP: | |
302 no_command += SLEEPTIME; | |
303 player.t_flags &= ~ISRUN; | |
304 msg("a strange white mist envelops you and you fall asleep"); | |
305 when T_ARROW: | |
306 if (swing(pstats.s_lvl - 1, pstats.s_arm, 1)) | |
307 { | |
308 pstats.s_hpt -= roll(1, 6); | |
309 if (pstats.s_hpt <= 0) | |
310 { | |
311 msg("an arrow killed you"); | |
312 death('a'); | |
313 } | |
314 else | |
315 msg("oh no! An arrow shot you"); | |
316 } | |
317 else | |
318 { | |
319 arrow = new_item(); | |
320 init_weapon(arrow, ARROW); | |
321 arrow->o_count = 1; | |
322 arrow->o_pos = hero; | |
323 fall(arrow, FALSE); | |
324 msg("an arrow shoots past you"); | |
325 } | |
326 when T_TELEP: | |
327 /* | |
328 * since the hero's leaving, look() won't put a TRAP | |
329 * down for us, so we have to do it ourself | |
330 */ | |
331 teleport(); | |
332 mvaddch(tc->y, tc->x, TRAP); | |
333 when T_DART: | |
334 if (!swing(pstats.s_lvl+1, pstats.s_arm, 1)) | |
335 msg("a small dart whizzes by your ear and vanishes"); | |
336 else | |
337 { | |
338 pstats.s_hpt -= roll(1, 4); | |
339 if (pstats.s_hpt <= 0) | |
340 { | |
341 msg("a poisoned dart killed you"); | |
342 death('d'); | |
343 } | |
344 if (!ISWEARING(R_SUSTSTR) && !save(VS_POISON)) | |
345 chg_str(-1); | |
346 msg("a small dart just hit you in the shoulder"); | |
347 } | |
348 when T_RUST: | |
349 msg("a gush of water hits you on the head"); | |
350 rust_armor(cur_armor); | |
351 } | |
352 flush_type(); | |
353 return tr; | |
354 } | |
355 | |
356 /* | |
357 * rndmove: | |
358 * Move in a random direction if the monster/person is confused | |
359 */ | |
360 coord | |
361 rndmove(const THING *who) | |
362 { | |
363 THING *obj; | |
364 int x, y; | |
365 int ch; | |
366 coord ret; /* what we will be returning */ | |
367 | |
368 y = ret.y = who->t_pos.y + rnd(3) - 1; | |
369 x = ret.x = who->t_pos.x + rnd(3) - 1; | |
370 /* | |
371 * Now check to see if that's a legal move. If not, don't move. | |
372 * (I.e., bump into the wall or whatever) | |
373 */ | |
374 if (y == who->t_pos.y && x == who->t_pos.x) | |
375 return ret; | |
376 if (!diag_ok(&who->t_pos, &ret)) | |
377 goto bad; | |
378 else | |
379 { | |
380 ch = winat(y, x); | |
381 if (!step_ok(ch)) | |
382 goto bad; | |
383 if (ch == SCROLL) | |
384 { | |
385 for (obj = lvl_obj; obj != NULL; obj = next(obj)) |