Neale Pickett
·
2011-10-13
master.c
1/*
2 * Hero movement commands
3 *
4 * @(#)master.c 4.49 (Berkeley) 02/05/99
5 */
6
7#include <curses.h>
8#include <ctype.h>
9#include "netprot.h"
10
11/*
12 * Used to hold the new Hero position
13 */
14
15coord nh;
16
17/*
18 * do_run:
19 * Start the hero running
20 */
21void
22do_run(char ch)
23{
24 Running = TRUE;
25 After = FALSE;
26 Runch = ch;
27}
28
29/*
30 * do_move:
31 * Check to see that a move is legal. If it is handle the
32 * consequences (fighting, picking up, etc.)
33 */
34void
35do_move(int dy, int dx)
36{
37 char ch, fl;
38
39 Firstmove = FALSE;
40 if (No_move)
41 {
42 No_move--;
43 msg("you are still stuck in the bear trap");
44 return;
45 }
46 /*
47 * Do a confused move (maybe)
48 */
49 if (on(Player, ISHUH) && rnd(5) != 0)
50 {
51 nh = *rndmove(&Player);
52 if (ce(nh, Hero))
53 {
54 After = FALSE;
55 Running = FALSE;
56 To_death = FALSE;
57 return;
58 }
59 }
60 else
61 {
62over:
63 nh.y = Hero.y + dy;
64 nh.x = Hero.x + dx;
65 }
66
67 /*
68 * Check if he tried to move off the screen or make an illegal
69 * diagonal move, and stop him if he did.
70 */
71 if (nh.x < 0 || nh.x >= NUMCOLS || nh.y <= 0 || nh.y >= NUMLINES - 1)
72 goto hit_bound;
73 if (!diag_ok(&Hero, &nh))
74 {
75 After = FALSE;
76 Running = FALSE;
77 return;
78 }
79 if (Running && ce(Hero, nh))
80 After = Running = FALSE;
81 fl = flat(nh.y, nh.x);
82 ch = winat(nh.y, nh.x);
83 if (!(fl & F_REAL) && ch == FLOOR)
84 {
85 if (!on(Player, ISLEVIT))
86 {
87 chat(nh.y, nh.x) = ch = TRAP;
88 flat(nh.y, nh.x) |= F_REAL;
89 }
90 }
91 else if (on(Player, ISHELD) && ch != 'F')
92 {
93 msg("you are being held");
94 return;
95 }
96 switch (ch)
97 {
98 case ' ':
99 case '|':
100 case '-':
101hit_bound:
102 if (Passgo && Running && (Proom->r_flags & ISGONE)
103 && !on(Player, ISBLIND))
104 {
105 bool b1, b2;
106
107 switch (Runch)
108 {
109 case 'h':
110 case 'l':
111 b1 = (Hero.y != 1 && turn_ok(Hero.y - 1, Hero.x));
112 b2 = (Hero.y != NUMLINES - 2 && turn_ok(Hero.y + 1, Hero.x));
113 if (!(b1 ^ b2))
114 break;
115 if (b1)
116 {
117 Runch = 'k';
118 dy = -1;
119 }
120 else
121 {
122 Runch = 'j';
123 dy = 1;
124 }
125 dx = 0;
126 turnref();
127 goto over;
128 case 'j':
129 case 'k':
130 b1 = (Hero.x != 0 && turn_ok(Hero.y, Hero.x - 1));
131 b2 = (Hero.x != NUMCOLS - 1 && turn_ok(Hero.y, Hero.x + 1));
132 if (!(b1 ^ b2))
133 break;
134 if (b1)
135 {
136 Runch = 'h';
137 dx = -1;
138 }
139 else
140 {
141 Runch = 'l';
142 dx = 1;
143 }
144 dy = 0;
145 turnref();
146 goto over;
147 }
148 }
149 Running = FALSE;
150 After = FALSE;
151 break;
152 case DOOR:
153 Running = FALSE;
154 if (flat(Hero.y, Hero.x) & F_PASS)
155 enter_room(&nh);
156 goto move_stuff;
157 case TRAP:
158 ch = be_trapped(&nh);
159 if (ch == T_DOOR || ch == T_TELEP)
160 return;
161 goto move_stuff;
162 case PASSAGE:
163 /*
164 * when you're in a corridor, you don't know if you're in
165 * a maze room or not, and there ain't no way to find out
166 * if you're leaving a maze room, so it is necessary to
167 * always recalculate Proom.
168 */
169 Proom = roomin(&Hero);
170 goto move_stuff;
171 case FLOOR:
172 if (!(fl & F_REAL))
173 be_trapped(&Hero);
174 goto move_stuff;
175 case STAIRS:
176 Seenstairs = TRUE;
177 /* FALLTHROUGH */
178 default:
179 Running = FALSE;
180 if (isupper(ch) || moat(nh.y, nh.x))
181 fight(&nh, Cur_weapon, FALSE);
182 else
183 {
184 if (ch != STAIRS)
185 Take = ch;
186move_stuff:
187 mvaddch(Hero.y, Hero.x, floor_at());
188 if ((fl & F_PASS) && chat(Oldpos.y, Oldpos.x) == DOOR)
189 leave_room(&nh);
190 Hero = nh;
191 }
192 }
193}
194
195/*
196 * turn_ok:
197 * Decide whether it is legal to turn onto the given space
198 */
199bool
200turn_ok(int y, int x)
201{
202 PLACE *pp;
203
204 pp = INDEX(y, x);
205 return (pp->p_ch == DOOR
206 || (pp->p_flags & (F_REAL|F_PASS)) == (F_REAL|F_PASS));
207}
208
209/*
210 * turnref:
211 * Decide whether to refresh at a passage turning or not
212 */
213void
214turnref(void)
215{
216 PLACE *pp;
217
218 pp = INDEX(Hero.y, Hero.x);
219 if (!(pp->p_flags & F_SEEN))
220 {
221 if (Jump)
222 {
223 leaveok(stdscr, TRUE);
224 refresh();
225 leaveok(stdscr, FALSE);
226 }
227 pp->p_flags |= F_SEEN;
228 }
229}
230
231/*
232 * door_open:
233 * Called to illuminate a room. If it is dark, remove anything
234 * that might move.
235 */
236void
237door_open(struct room *rp)
238{
239 THING *mp;
240 int y, x;
241
242 if (!(rp->r_flags & ISGONE))
243 for (y = rp->r_pos.y; y < rp->r_pos.y + rp->r_max.y; y++)
244 for (x = rp->r_pos.x; x < rp->r_pos.x + rp->r_max.x; x++)
245 if (isupper(winat(y, x)))
246 wake_monster(y, x);
247}
248
249/*
250 * be_trapped:
251 * The guy stepped on a trap.... Make him pay.
252 */
253char
254be_trapped(coord *tc)
255{
256 PLACE *pp;
257 THING *arrow;
258 char tr;
259
260 if (on(Player, ISLEVIT))
261 return T_RUST; /* anything that's not a door or teleport */
262 Running = FALSE;
263 Count = FALSE;
264 pp = INDEX(tc->y, tc->x);
265 pp->p_ch = TRAP;
266 tr = pp->p_flags & F_TMASK;
267 pp->p_flags |= F_SEEN;
268 switch (tr)
269 {
270 when T_DOOR:
271 Level++;
272 new_level();
273 msg("you fell into a trap!");
274 when T_BEAR:
275 No_move += BEARTIME;
276 msg("you are caught in a bear trap");
277 when T_SLEEP:
278 No_command += SLEEPTIME;
279 Player.t_flags &= ~ISRUN;
280 msg("a strange white mist envelops you and you fall asleep");
281 when T_ARROW:
282 if (swing(Pstats.s_lvl - 1, Pstats.s_arm, 1))
283 {
284 Pstats.s_hpt -= roll(1, 6);
285 if (Pstats.s_hpt <= 0)
286 {
287 msg("an arrow killed you");
288 death('a');
289 }
290 else
291 msg("oh no! An arrow shot you");
292 }
293 else
294 {
295 arrow = new_item();
296 init_weapon(arrow, ARROW);
297 arrow->o_count = 1;
298 arrow->o_pos = Hero;
299 fall(arrow, FALSE);
300 msg("an arrow shoots past you");
301 }
302 when T_TELEP:
303 /*
304 * since the hero's leaving, look() won't put a TRAP
305 * down for us, so we have to do it ourself
306 */
307 teleport();
308 mvaddch(tc->y, tc->x, TRAP);
309 when T_DART:
310 if (!swing(Pstats.s_lvl+1, Pstats.s_arm, 1))
311 msg("a small dart whizzes by your ear and vanishes");
312 else
313 {
314 Pstats.s_hpt -= roll(1, 4);
315 if (Pstats.s_hpt <= 0)
316 {
317 msg("a poisoned dart killed you");
318 death('d');
319 }
320 if (!ISWEARING(R_SUSTSTR) && !save(VS_POISON))
321 chg_str(-1);
322 msg("a small dart just hit you in the shoulder");
323 }
324 when T_RUST:
325 msg("a gush of water hits you on the head");
326 rust_armor(Cur_armor);
327 }
328 flush_type();
329 return tr;
330}
331
332/*
333 * rndmove:
334 * Move in a random direction if the monster/person is confused
335 */
336coord *
337rndmove(THING *who)
338{
339 THING *obj;
340 int x, y;
341 char ch;
342 coord ret; /* what we will be returning */
343
344 y = ret.y = who->t_pos.y + rnd(3) - 1;
345 x = ret.x = who->t_pos.x + rnd(3) - 1;
346 /*
347 * Now check to see if that's a legal move. If not, don't move.
348 * (I.e., bump into the wall or whatever)
349 */
350 if (y == who->t_pos.y && x == who->t_pos.x)
351 return &ret;
352 if (!diag_ok(&who->t_pos, &ret))
353 goto bad;
354 else
355 {
356 ch = winat(y, x);
357 if (!step_ok(ch))
358 goto bad;
359 if (ch == SCROLL)
360 {
361 for (obj = Lvl_obj; obj != NULL; obj = next(obj))
362 if (y == obj->o_pos.y && x == obj->o_pos.x)
363 break;
364 if (obj != NULL && obj->o_which == S_SCARE)
365 goto bad;
366 }
367 }
368 return &ret;
369
370bad:
371 ret = who->t_pos;
372 return &ret;
373}
374
375/*
376 * rust_armor:
377 * Rust the given armor, if it is a legal kind to rust, and we
378 * aren't wearing a magic ring.
379 */
380void
381rust_armor(THING *arm)
382{
383 if (arm == NULL || arm->o_type != ARMOR || arm->o_which == LEATHER ||
384 arm->o_arm >= 9)
385 return;
386
387 if ((arm->o_flags & ISPROT) || ISWEARING(R_SUSTARM))
388 {
389 if (!To_death)
390 msg("the rust vanishes instantly");
391 }
392 else
393 {
394 arm->o_arm++;
395 if (!Terse)
396 msg("your armor appears to be weaker now. Oh my!");
397 else
398 msg("your armor weakens");
399 }
400}