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))