Mercurial > hg > early-roguelike
comparison rogue3/move.c @ 0:527e2150eaf0
Import Rogue 3.6 from the Roguelike Restoration Project (r1490)
author | edwarj4 |
---|---|
date | Tue, 13 Oct 2009 13:33:34 +0000 |
parents | |
children | d9e44e18eeec |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:527e2150eaf0 |
---|---|
1 /* | |
2 * Hero movement commands | |
3 * | |
4 * @(#)move.c 3.26 (Berkeley) 6/15/81 | |
5 * | |
6 * Rogue: Exploring the Dungeons of Doom | |
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 void | |
29 do_run(int 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 void | |
43 do_move(int dy, int dx) | |
44 { | |
45 int 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 void | |
141 light(coord *cp) | |
142 { | |
143 struct room *rp; | |
144 int j, k; | |
145 int ch; | |
146 int rch; | |
147 struct linked_list *item; | |
148 | |
149 if ((rp = roomin(cp)) != NULL && !on(player, ISBLIND)) | |
150 { | |
151 for (j = 0; j < rp->r_max.y; j++) | |
152 { | |
153 for (k = 0; k < rp->r_max.x; k++) | |
154 { | |
155 ch = show(rp->r_pos.y + j, rp->r_pos.x + k); | |
156 wmove(cw, rp->r_pos.y + j, rp->r_pos.x + k); | |
157 /* | |
158 * Figure out how to display a secret door | |
159 */ | |
160 if (ch == SECRETDOOR) | |
161 { | |
162 if (j == 0 || j == rp->r_max.y - 1) | |
163 ch = '-'; | |
164 else | |
165 ch = '|'; | |
166 } | |
167 /* | |
168 * If the room is a dark room, we might want to remove | |
169 * monsters and the like from it (since they might | |
170 * move) | |
171 */ | |
172 if (isupper(ch)) | |
173 { | |
174 item = wake_monster(rp->r_pos.y+j, rp->r_pos.x+k); | |
175 if (((struct thing *) ldata(item))->t_oldch == ' ') | |
176 if (!(rp->r_flags & ISDARK)) | |
177 ((struct thing *) ldata(item))->t_oldch = | |
178 mvwinch(stdscr, rp->r_pos.y+j, rp->r_pos.x+k); | |
179 } | |
180 if (rp->r_flags & ISDARK) | |
181 { | |
182 rch = mvwinch(cw, rp->r_pos.y+j, rp->r_pos.x+k); | |
183 switch (rch) | |
184 { | |
185 case DOOR: | |
186 case STAIRS: | |
187 case TRAP: | |
188 case '|': | |
189 case '-': | |
190 case ' ': | |
191 ch = rch; | |
192 when FLOOR: | |
193 ch = (on(player, ISBLIND) ? FLOOR : ' '); | |
194 otherwise: | |
195 ch = ' '; | |
196 } | |
197 } | |
198 mvwaddch(cw, rp->r_pos.y+j, rp->r_pos.x+k, ch); | |
199 } | |
200 } | |
201 } | |
202 } | |
203 | |
204 /* | |
205 * show: | |
206 * returns what a certain thing will display as to the un-initiated | |
207 */ | |
208 | |
209 int | |
210 show(int y, int x) | |
211 { | |
212 int ch = winat(y, x); | |
213 struct linked_list *it; | |
214 struct thing *tp; | |
215 | |
216 if (ch == TRAP) | |
217 return (trap_at(y, x)->tr_flags & ISFOUND) ? TRAP : FLOOR; | |
218 else if (ch == 'M' || ch == 'I') | |
219 { | |
220 if ((it = find_mons(y, x)) == NULL) | |
221 fatal("Can't find monster in show"); | |
222 tp = (struct thing *) ldata(it); | |
223 if (ch == 'M') | |
224 ch = tp->t_disguise; | |
225 /* | |
226 * Hide invisible monsters | |
227 */ | |
228 else if (off(player, CANSEE)) | |
229 ch = mvwinch(stdscr, y, x); | |
230 } | |
231 return ch; | |
232 } | |
233 | |
234 /* | |
235 * be_trapped: | |
236 * The guy stepped on a trap.... Make him pay. | |
237 */ | |
238 | |
239 int | |
240 be_trapped(coord *tc) | |
241 { | |
242 struct trap *tp; | |
243 int ch; | |
244 | |
245 tp = trap_at(tc->y, tc->x); | |
246 count = running = FALSE; | |
247 mvwaddch(cw, tp->tr_pos.y, tp->tr_pos.x, TRAP); | |
248 tp->tr_flags |= ISFOUND; | |
249 switch (ch = tp->tr_type) | |
250 { | |
251 case TRAPDOOR: | |
252 level++; | |
253 new_level(); | |
254 msg("You fell into a trap!"); | |
255 when BEARTRAP: | |
256 no_move += BEARTIME; | |
257 msg("You are caught in a bear trap"); | |
258 when SLEEPTRAP: | |
259 no_command += SLEEPTIME; | |
260 msg("A strange white mist envelops you and you fall asleep"); | |
261 when ARROWTRAP: | |
262 if (swing(pstats.s_lvl-1, pstats.s_arm, 1)) | |
263 { | |
264 msg("Oh no! An arrow shot you"); | |
265 if ((pstats.s_hpt -= roll(1, 6)) <= 0) | |
266 { | |
267 msg("The arrow killed you."); | |
268 death('a'); | |
269 } | |
270 } | |
271 else | |
272 { | |
273 struct linked_list *item; | |
274 struct object *arrow; | |
275 | |
276 msg("An arrow shoots past you."); | |
277 item = new_item(sizeof *arrow); | |
278 arrow = (struct object *) ldata(item); | |
279 arrow->o_type = WEAPON; | |
280 arrow->o_which = ARROW; | |
281 init_weapon(arrow, ARROW); | |
282 arrow->o_count = 1; | |
283 arrow->o_pos = hero; | |
284 arrow->o_hplus = arrow->o_dplus = 0; /* "arrow bug" FIX */ | |
285 fall(item, FALSE); | |
286 } | |
287 when TELTRAP: | |
288 teleport(); | |
289 when DARTTRAP: | |
290 if (swing(pstats.s_lvl+1, pstats.s_arm, 1)) | |
291 { | |
292 msg("A small dart just hit you in the shoulder"); | |
293 if ((pstats.s_hpt -= roll(1, 4)) <= 0) | |
294 { | |
295 msg("The dart killed you."); | |
296 death('d'); | |
297 } | |
298 if (!ISWEARING(R_SUSTSTR)) | |
299 chg_str(-1); | |
300 } | |
301 else | |
302 msg("A small dart whizzes by your ear and vanishes."); | |
303 } | |
304 flush_type(); /* flush typeahead */ | |
305 return(ch); | |
306 } | |
307 | |
308 /* | |
309 * trap_at: | |
310 * find the trap at (y,x) on screen. | |
311 */ | |
312 | |
313 struct trap * | |
314 trap_at(int y, int x) | |
315 { | |
316 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(struct thing *who) | |
337 { | |
338 int x, y; | |
339 int ch; | |
340 int ex, ey, nopen = 0; | |
341 struct linked_list *item; | |
342 struct object *obj; | |
343 static coord ret; /* what we will be returning */ | |
344 static coord dest; | |
345 | |
346 ret = who->t_pos; | |
347 /* | |
348 * Now go through the spaces surrounding the player and | |
349 * set that place in the array to true if the space can be | |
350 * moved into | |
351 */ | |
352 ey = ret.y + 1; | |
353 ex = ret.x + 1; | |
354 for (y = who->t_pos.y - 1; y <= ey; y++) | |
355 if (y >= 0 && y < LINES) | |
356 for (x = who->t_pos.x - 1; x <= ex; x++) | |
357 { | |
358 if (x < 0 || x >= COLS) | |
359 continue; | |
360 ch = winat(y, x); | |
361 if (step_ok(ch)) | |
362 { | |
363 dest.y = y; | |
364 dest.x = x; | |
365 if (!diag_ok(&who->t_pos, &dest)) | |
366 continue; | |
367 if (ch == SCROLL) | |
368 { | |
369 item = NULL; | |
370 for (item = lvl_obj; item != NULL; item = next(item)) | |
371 { | |
372 obj = (struct object *) ldata(item); | |
373 if (y == obj->o_pos.y && x == obj->o_pos.x) | |
374 break; | |
375 } | |
376 if (item != NULL && obj->o_which == S_SCARE) | |
377 continue; | |
378 } | |
379 if (rnd(++nopen) == 0) | |
380 ret = dest; | |
381 } | |
382 } | |
383 return &ret; | |
384 } |