Another 64 bit issue.
[rogue-pphs.git] / move.c
1 /*
2 * Hero movement commands
3 *
4 * @(#)move.c 3.26 (Berkeley) 6/15/81
5 *
6 * Rogue: Exploring the Cavern of Cuties
7 * Copyright (C) 1980, 1981 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 coord nh;
22
23 /*
24 * do_run:
25 * Start the hero running
26 */
27
28 do_run(ch)
29 char ch;
30 {
31 running = TRUE;
32 after = FALSE;
33 runch = ch;
34 }
35
36 /*
37 * do_move:
38 * Check to see that a move is legal. If it is handle the
39 * consequences (fighting, picking up, etc.)
40 */
41
42 do_move(dy, dx)
43 int dy, dx;
44 {
45 register char ch;
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 (rnd(100) < 80 && on(player, ISHUH))
58 nh = *rndmove(&player);
59 else
60 {
61 nh.y = hero.y + dy;
62 nh.x = hero.x + dx;
63 }
64
65 /*
66 * Check if he tried to move off the screen or make an illegal
67 * diagonal move, and stop him if he did.
68 */
69 if (nh.x < 0 || nh.x > COLS-1 || nh.y < 0 || nh.y > LINES - 1
70 || !diag_ok(&hero, &nh))
71 {
72 after = FALSE;
73 running = FALSE;
74 return;
75 }
76 if (running && ce(hero, nh))
77 after = running = FALSE;
78 ch = winat(nh.y, nh.x);
79 if (on(player, ISHELD) && ch != 'F')
80 {
81 msg("You are being held");
82 return;
83 }
84 switch(ch)
85 {
86 case ' ':
87 case '|':
88 case '-':
89 case SECRETDOOR:
90 after = running = FALSE;
91 return;
92 case TRAP:
93 ch = be_trapped(&nh);
94 if (ch == TRAPDOOR || ch == TELTRAP)
95 return;
96 goto move_stuff;
97 case GOLD:
98 case POTION:
99 case SCROLL:
100 case FOOD:
101 case WEAPON:
102 case ARMOR:
103 case RING:
104 case AMULET:
105 case STICK:
106 running = FALSE;
107 take = ch;
108 default:
109 move_stuff:
110 if (ch == PASSAGE && winat(hero.y, hero.x) == DOOR)
111 light(&hero);
112 else if (ch == DOOR)
113 {
114 running = FALSE;
115 if (winat(hero.y, hero.x) == PASSAGE)
116 light(&nh);
117 }
118 else if (ch == STAIRS)
119 running = FALSE;
120 else if (isupper(ch))
121 {
122 running = FALSE;
123 fight(&nh, ch, cur_weapon, FALSE);
124 return;
125 }
126 ch = winat(hero.y, hero.x);
127 wmove(cw, unc(hero));
128 waddch(cw, ch);
129 hero = nh;
130 wmove(cw, unc(hero));
131 waddch(cw, PLAYER);
132 }
133 }
134
135 /*
136 * Called to illuminate a room.
137 * If it is dark, remove anything that might move.
138 */
139
140 light(cp)
141 coord *cp;
142 {
143 register struct room *rp;
144 register int j, k;
145 register char ch, rch;
146 register struct linked_list *item;
147
148 if ((rp = roomin(cp)) != NULL && !on(player, ISBLIND))
149 {
150 for (j = 0; j < rp->r_max.y; j++)
151 {
152 for (k = 0; k < rp->r_max.x; k++)
153 {
154 ch = show(rp->r_pos.y + j, rp->r_pos.x + k);
155 wmove(cw, rp->r_pos.y + j, rp->r_pos.x + k);
156 /*
157 * Figure out how to display a secret door
158 */
159 if (ch == SECRETDOOR)
160 {
161 if (j == 0 || j == rp->r_max.y - 1)
162 ch = '-';
163 else
164 ch = '|';
165 }
166 /*
167 * If the room is a dark room, we might want to remove
168 * monsters and the like from it (since they might
169 * move)
170 */
171 if (isupper(ch))
172 {
173 item = wake_monster(rp->r_pos.y+j, rp->r_pos.x+k);
174 if (((struct thing *) ldata(item))->t_oldch == ' ')
175 if (!(rp->r_flags & ISDARK))
176 ((struct thing *) ldata(item))->t_oldch =
177 mvwinch(stdscr, rp->r_pos.y+j, rp->r_pos.x+k);
178 }
179 if (rp->r_flags & ISDARK)
180 {
181 rch = mvwinch(cw, rp->r_pos.y+j, rp->r_pos.x+k);
182 switch (rch)
183 {
184 case DOOR:
185 case STAIRS:
186 case TRAP:
187 case '|':
188 case '-':
189 case ' ':
190 ch = rch;
191 when FLOOR:
192 ch = (on(player, ISBLIND) ? FLOOR : ' ');
193 otherwise:
194 ch = ' ';
195 }
196 }
197 mvwaddch(cw, rp->r_pos.y+j, rp->r_pos.x+k, ch);
198 }
199 }
200 }
201 }
202
203 /*
204 * show:
205 * returns what a certain thing will display as to the un-initiated
206 */
207
208 show(y, x)
209 register int y, x;
210 {
211 register char ch = winat(y, x);
212 register struct linked_list *it;
213 register struct thing *tp;
214
215 if (ch == TRAP)
216 return (trap_at(y, x)->tr_flags & ISFOUND) ? TRAP : FLOOR;
217 else if (ch == 'M' || ch == 'I')
218 {
219 if ((it = find_mons(y, x)) == NULL)
220 fatal("Can't find monster in show");
221 tp = (struct thing *) ldata(it);
222 if (ch == 'M')
223 ch = tp->t_disguise;
224 /*
225 * Hide invisible monsters
226 */
227 else if (off(player, CANSEE))
228 ch = mvwinch(stdscr, y, x);
229 }
230 return ch;
231 }
232
233 /*
234 * be_trapped:
235 * The guy stepped on a trap.... Make him pay.
236 */
237
238 be_trapped(tc)
239 register coord *tc;
240 {
241 register struct trap *tp;
242 register char ch;
243
244 tp = trap_at(tc->y, tc->x);
245 count = running = FALSE;
246 mvwaddch(cw, tp->tr_pos.y, tp->tr_pos.x, TRAP);
247 tp->tr_flags |= ISFOUND;
248 switch (ch = tp->tr_type)
249 {
250 case TRAPDOOR:
251 level++;
252 new_level();
253 msg("You fell into a trap!");
254 when BEARTRAP:
255 no_move += BEARTIME;
256 msg("You are caught in a bear trap");
257 when SLEEPTRAP:
258 no_command += SLEEPTIME;
259 msg("A strange white mist envelops you and you fall asleep");
260 when ARROWTRAP:
261 if (swing(pstats.s_lvl-1, pstats.s_arm, 1))
262 {
263 msg("Oh no! An arrow shot you");
264 if ((pstats.s_hpt -= roll(1, 6)) <= 0)
265 {
266 msg("The arrow killed you.");
267 death('a');
268 }
269 }
270 else
271 {
272 register struct linked_list *item;
273 register struct object *arrow;
274
275 msg("An arrow shoots past you.");
276 item = new_item(sizeof *arrow);
277 arrow = (struct object *) ldata(item);
278 arrow->o_type = WEAPON;
279 arrow->o_which = ARROW;
280 init_weapon(arrow, ARROW);
281 arrow->o_count = 1;
282 arrow->o_pos = hero;
283 arrow->o_hplus = arrow->o_dplus = 0; /* "arrow bug" FIX */
284 fall(item, FALSE);
285 }
286 when TELTRAP:
287 teleport();
288 when DARTTRAP:
289 if (swing(pstats.s_lvl+1, pstats.s_arm, 1))
290 {
291 msg("A small dart just hit you in the shoulder");
292 if ((pstats.s_hpt -= roll(1, 4)) <= 0)
293 {
294 msg("The dart killed you.");
295 death('d');
296 }
297 if (!ISWEARING(R_SUSTSTR))
298 chg_str(-1);
299 }
300 else
301 msg("A small dart whizzes by your ear and vanishes.");
302 }
303 flush_type(); /* flush typeahead */
304 return(ch);
305 }
306
307 /*
308 * trap_at:
309 * find the trap at (y,x) on screen.
310 */
311
312 struct trap *
313 trap_at(y, x)
314 register int y, x;
315 {
316 register struct trap *tp, *ep;
317
318 ep = &traps[ntraps];
319 for (tp = traps; tp < ep; tp++)
320 if (tp->tr_pos.y == y && tp->tr_pos.x == x)
321 break;
322 if (tp == ep)
323 {
324 sprintf(prbuf, "Trap at %d,%d not in array", y, x);
325 fatal(prbuf);
326 }
327 return tp;
328 }
329
330 /*
331 * rndmove:
332 * move in a random direction if the monster/person is confused
333 */
334
335 coord *
336 rndmove(who)
337 struct thing *who;
338 {
339 register int x, y;
340 register char ch;
341 register int ex, ey, nopen = 0;
342 register struct linked_list *item;
343 register struct object *obj;
344 static coord ret; /* what we will be returning */
345 static coord dest;
346
347 ret = who->t_pos;
348 /*
349 * Now go through the spaces surrounding the player and
350 * set that place in the array to true if the space can be
351 * moved into
352 */
353 ey = ret.y + 1;
354 ex = ret.x + 1;
355 for (y = who->t_pos.y - 1; y <= ey; y++)
356 if (y >= 0 && y < LINES)
357 for (x = who->t_pos.x - 1; x <= ex; x++)
358 {
359 if (x < 0 || x >= COLS)
360 continue;
361 ch = winat(y, x);
362 if (step_ok(ch))
363 {
364 dest.y = y;
365 dest.x = x;
366 if (!diag_ok(&who->t_pos, &dest))
367 continue;
368 if (ch == SCROLL)
369 {
370 item = NULL;
371 for (item = lvl_obj; item != NULL; item = next(item))
372 {
373 obj = (struct object *) ldata(item);
374 if (y == obj->o_pos.y && x == obj->o_pos.x)
375 break;
376 }
377 if (item != NULL && obj->o_which == S_SCARE)
378 continue;
379 }
380 if (rnd(++nopen) == 0)
381 ret = dest;
382 }
383 }
384 return &ret;
385 }