Mercurial > hg > early-roguelike
comparison urogue/move.c @ 256:c495a4f288c6
Import UltraRogue from the Roguelike Restoration Project (r1490)
author | John "Elwin" Edwards |
---|---|
date | Tue, 31 Jan 2017 19:56:04 -0500 |
parents | |
children | e52a8a7ad4c5 |
comparison
equal
deleted
inserted
replaced
253:d9badb9c0179 | 256:c495a4f288c6 |
---|---|
1 /* | |
2 move.c - Hero movement commands | |
3 | |
4 UltraRogue: The Ultimate Adventure in the Dungeons of Doom | |
5 Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong | |
6 All rights reserved. | |
7 | |
8 Based on "Advanced Rogue" | |
9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka | |
10 All rights reserved. | |
11 | |
12 Based on "Rogue: Exploring the Dungeons of Doom" | |
13 Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman | |
14 All rights reserved. | |
15 | |
16 See the file LICENSE.TXT for full copyright and licensing information. | |
17 */ | |
18 | |
19 #include <stdlib.h> | |
20 #include <ctype.h> | |
21 #include "rogue.h" | |
22 | |
23 /* | |
24 do_run() | |
25 Start the hero running | |
26 */ | |
27 | |
28 void | |
29 do_run(char ch) | |
30 { | |
31 running = TRUE; | |
32 after = FALSE; | |
33 runch = ch; | |
34 | |
35 if (doorstop && !on(player, ISBLIND)) | |
36 { | |
37 door_stop = TRUE; | |
38 firstmove = TRUE; | |
39 } | |
40 } | |
41 | |
42 /* | |
43 step_ok() | |
44 returns true if it is ok for type to step on ch flgptr will be | |
45 NULL if we don't know what the monster is yet! | |
46 */ | |
47 | |
48 int | |
49 step_ok(int y, int x, int can_on_monst, struct thing *flgptr) | |
50 { | |
51 struct linked_list *item; | |
52 char ch; | |
53 | |
54 /* What is here? Don't check monster window if MONSTOK is set */ | |
55 | |
56 if (can_on_monst == MONSTOK) | |
57 ch = CCHAR( mvinch(y, x) ); | |
58 else | |
59 ch = winat(y, x); | |
60 | |
61 switch (ch) | |
62 { | |
63 case ' ': | |
64 case '|': | |
65 case '-': | |
66 case SECRETDOOR: | |
67 if (flgptr && on(*flgptr, CANINWALL)) | |
68 return(TRUE); | |
69 | |
70 return(FALSE); | |
71 | |
72 case SCROLL: | |
73 /* | |
74 * If it is a scroll, it might be a scare monster scroll so | |
75 * we need to look it up to see what type it is. | |
76 */ | |
77 | |
78 if (flgptr && flgptr->t_ctype == C_MONSTER) | |
79 { | |
80 item = find_obj(y, x); | |
81 | |
82 if (item != NULL && (OBJPTR(item))->o_type == SCROLL | |
83 && (OBJPTR(item))->o_which == S_SCARE | |
84 && rnd(flgptr->t_stats.s_intel) < 12) | |
85 return(FALSE); /* All but smart ones are scared */ | |
86 } | |
87 return(TRUE); | |
88 | |
89 default: | |
90 return(!isalpha(ch)); | |
91 } | |
92 } | |
93 | |
94 /* | |
95 corr_move() | |
96 Check to see that a move is legal. If so, return correct | |
97 character. If not, if player came from a legal place, then try to turn | |
98 him. | |
99 */ | |
100 | |
101 void | |
102 corr_move(int dy, int dx) | |
103 { | |
104 char ch; | |
105 short legal = 0; /* Number of legal alternatives */ | |
106 int y = 0, x = 0; /* Holds legal new position */ | |
107 int *ny, *nx; /* Point to which direction to change */ | |
108 | |
109 /* New position */ | |
110 | |
111 player.t_nxtpos.y = hero.y + dy; | |
112 player.t_nxtpos.x = hero.x + dx; | |
113 | |
114 /* A bad diagonal move is illegal */ | |
115 | |
116 if (!diag_ok(&hero, &player.t_nxtpos, &player)) | |
117 return; | |
118 | |
119 /* If it is a legal move, just return */ | |
120 | |
121 if (player.t_nxtpos.x >= 0 && player.t_nxtpos.x < COLS && player.t_nxtpos.y > 0 && player.t_nxtpos.y < LINES - 2) | |
122 { | |
123 ch = winat(player.t_nxtpos.y, player.t_nxtpos.x); | |
124 | |
125 switch (ch) | |
126 { | |
127 case ' ': | |
128 case '|': | |
129 case '-': | |
130 break; | |
131 default: | |
132 return; | |
133 } | |
134 } | |
135 | |
136 /* Check the legal alternatives */ | |
137 | |
138 if (dy == 0) | |
139 { | |
140 ny = &dy; | |
141 nx = &dx; | |
142 } | |
143 else | |
144 { | |
145 ny = &dx; | |
146 nx = &dy; | |
147 } | |
148 | |
149 for (*nx = 0, *ny = -1; *ny < 2; *ny += 2) | |
150 { | |
151 /* New position */ | |
152 player.t_nxtpos.y = hero.y + dy; | |
153 player.t_nxtpos.x = hero.x + dx; | |
154 | |
155 if (player.t_nxtpos.x < 0 || player.t_nxtpos.x > COLS - 1 || player.t_nxtpos.y < 1 || player.t_nxtpos.y > LINES - 3) | |
156 continue; | |
157 | |
158 ch = winat(player.t_nxtpos.y, player.t_nxtpos.x); | |
159 | |
160 switch (ch) | |
161 { | |
162 case ' ': | |
163 case '|': | |
164 case '-': | |
165 break; | |
166 default: | |
167 legal++; | |
168 y = dy; | |
169 x = dx; | |
170 } | |
171 } | |
172 | |
173 /* If we have 2 legal moves, make no change */ | |
174 | |
175 if (legal != 1) | |
176 return; | |
177 | |
178 /* Make the change */ | |
179 | |
180 if (y == 0) /* Move horizontally */ | |
181 { | |
182 if (x == 1) | |
183 runch = 'l'; | |
184 else | |
185 runch = 'h'; | |
186 } | |
187 else /* Move vertically */ | |
188 { | |
189 if (y == 1) | |
190 runch = 'j'; | |
191 else | |
192 runch = 'k'; | |
193 } | |
194 | |
195 return; | |
196 } | |
197 | |
198 | |
199 /* | |
200 do_move() | |
201 Check to see that a move is legal. If it is handle the | |
202 consequences (fighting, picking up, etc.) | |
203 */ | |
204 | |
205 void | |
206 do_move(int dy, int dx) | |
207 { | |
208 char ch; | |
209 coord old_hero; | |
210 char hch; | |
211 | |
212 firstmove = FALSE; | |
213 | |
214 if (player.t_no_move) | |
215 { | |
216 player.t_no_move--; | |
217 msg("You are still stuck in the bear trap."); | |
218 return; | |
219 } | |
220 | |
221 /* Do a confused move (maybe) */ | |
222 | |
223 if ((rnd(100) < 80 && on(player, ISHUH)) || | |
224 (is_wearing(R_DELUSION) && rnd(100) < 25) || | |
225 on(player, STUMBLER) && rnd(40) == 0) | |
226 player.t_nxtpos = rndmove(&player); | |
227 else | |
228 { | |
229 player.t_nxtpos.y = hero.y + dy; | |
230 player.t_nxtpos.x = hero.x + dx; | |
231 } | |
232 | |
233 /* | |
234 * Check if he tried to move off the screen or make an illegal | |
235 * diagonal move, and stop him if he did. | |
236 */ | |
237 | |
238 if (player.t_nxtpos.x < 0 || player.t_nxtpos.x > COLS - 1 || player.t_nxtpos.y < 1 || player.t_nxtpos.y >= LINES - 2 | |
239 || !diag_ok(&hero, &player.t_nxtpos, &player)) | |
240 { | |
241 after = fighting = running = FALSE; | |
242 return; | |
243 } | |
244 | |
245 if (running && ce(hero, player.t_nxtpos)) | |
246 after = running = FALSE; | |
247 | |
248 ch = winat(player.t_nxtpos.y, player.t_nxtpos.x); | |
249 | |
250 if (isalpha(ch)) | |
251 debug("Moving onto monster %c",ch); | |
252 | |
253 /* Take care of hero trying to move close to something frightening */ | |
254 | |
255 if (on(player, ISFLEE)) | |
256 { | |
257 if (rnd(10) < 1) | |
258 { | |
259 turn_off(player, ISFLEE); | |
260 msg("You regain your composure."); | |
261 } | |
262 else if (DISTANCE(player.t_nxtpos, player.t_chasee->t_pos) < | |
263 DISTANCE(hero,player.t_chasee->t_pos)) | |
264 return; | |
265 } | |
266 | |
267 /* Take care of hero being held */ | |
268 | |
269 if (on(player, ISHELD) && !isalpha(ch)) | |
270 { | |
271 if (rnd(pstats.s_str) > 14) | |
272 { | |
273 msg("You break free of the hold."); | |
274 | |
275 if (--hold_count == 0) | |
276 turn_off(player, ISHELD); | |
277 } | |
278 else | |
279 { | |
280 msg("You are being held."); | |
281 return; | |
282 } | |
283 } | |
284 | |
285 /* Might lose disguise */ | |
286 | |
287 if (on(player, ISDISGUISE) && rnd(11 * pstats.s_dext) == 0) | |
288 { | |
289 extinguish_fuse(FUSE_UNDISGUISE); | |
290 undisguise(NULL); | |
291 } | |
292 | |
293 /* assume he's not in a wall */ | |
294 | |
295 if (!isalpha(ch)) | |
296 turn_off(player, ISINWALL); | |
297 | |
298 hch = CCHAR( mvinch(hero.y, hero.x) ); /* Where hero was */ | |
299 old_hero = hero; /* Save hero's old position */ | |
300 | |
301 switch (ch) | |
302 { | |
303 case ' ': | |
304 case '|': | |
305 case '-': | |
306 case SECRETDOOR: | |
307 if (off(player, CANINWALL)) | |
308 { | |
309 after = running = FALSE; | |
310 return; | |
311 } | |
312 else if (running) | |
313 { | |
314 after = running = FALSE; | |
315 return; | |
316 } | |
317 turn_on(player, ISINWALL); | |
318 break; | |
319 | |
320 case TRAPDOOR: | |
321 case TELTRAP: | |
322 case BEARTRAP: | |
323 case SLEEPTRAP: | |
324 case ARROWTRAP: | |
325 case DARTTRAP: | |
326 case POOL: | |
327 case MAZETRAP: | |
328 case FIRETRAP: | |
329 case POISONTRAP: | |
330 case LAIR: | |
331 case RUSTTRAP: | |
332 ch = be_trapped(&player, player.t_nxtpos); | |
333 | |
334 if (!is_wearing(R_LEVITATION) && off(player, CANFLY) && | |
335 (old_hero.x != hero.x || old_hero.y != hero.y | |
336 || pool_teleport)) | |
337 { | |
338 pool_teleport = FALSE; | |
339 return; | |
340 } | |
341 | |
342 break; | |
343 | |
344 case GOLD: | |
345 case POTION: | |
346 case SCROLL: | |
347 case FOOD: | |
348 case WEAPON: | |
349 case ARMOR: | |
350 case RING: | |
351 case ARTIFACT: | |
352 case STICK: | |
353 running = FALSE; | |
354 take = ch; | |
355 break; | |
356 | |
357 default: | |
358 break; | |
359 } | |
360 | |
361 if (ch == FIRETRAP) | |
362 light(&hero); | |
363 | |
364 hero = player.t_nxtpos; /* Move the hero */ | |
365 | |
366 /* adjust lighting */ | |
367 | |
368 if (roomin(hero) == NULL && (hch == '-' || hch == '|' || | |
369 hch == DOOR || hch == SECRETDOOR)) | |
370 { | |
371 /* Leaving a room -- darken it */ | |
372 struct room *rp = roomin(old_hero); | |
373 int is_lit = FALSE; | |
374 | |
375 if (!(rp->r_flags & ISDARK)) | |
376 is_lit = TRUE; | |
377 | |
378 rp->r_flags |= ISDARK; /* Fake darkness */ | |
379 light(&old_hero); | |
380 | |
381 if (is_lit) | |