Mercurial > hg > early-roguelike
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)) |
