Mercurial > hg > early-roguelike
comparison rogue4/move.c @ 12:9535a08ddc39
Import Rogue 5.2 from the Roguelike Restoration Project (r1490)
| author | edwarj4 |
|---|---|
| date | Sat, 24 Oct 2009 16:52:52 +0000 |
| parents | |
| children | 1b73a8641b37 |
comparison
equal
deleted
inserted
replaced
| 11:949d558c2162 | 12:9535a08ddc39 |
|---|---|
| 1 /* | |
| 2 * Hero movement commands | |
| 3 * | |
| 4 * @(#)move.c 4.24 (Berkeley) 5/12/82 | |
| 5 * | |
| 6 * Rogue: Exploring the Dungeons of Doom | |
| 7 * Copyright (C) 1980, 1981, 1982 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 do_run(ch) | |
| 28 char 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 do_move(dy, dx) | |
| 41 int dy, dx; | |
| 42 { | |
| 43 register char ch, fl; | |
| 44 | |
| 45 firstmove = FALSE; | |
| 46 if (no_move) | |
| 47 { | |
| 48 no_move--; | |
| 49 msg("you are still stuck in the bear trap"); | |
| 50 return; | |
| 51 } | |
| 52 /* | |
| 53 * Do a confused move (maybe) | |
| 54 */ | |
| 55 if (on(player, ISHUH) && rnd(5) != 0) | |
| 56 { | |
| 57 nh = *rndmove(&player); | |
| 58 if (ce(nh, hero)) | |
| 59 { | |
| 60 after = FALSE; | |
| 61 running = FALSE; | |
| 62 return; | |
| 63 } | |
| 64 } | |
| 65 else | |
| 66 { | |
| 67 over: | |
| 68 nh.y = hero.y + dy; | |
| 69 nh.x = hero.x + dx; | |
| 70 } | |
| 71 | |
| 72 /* | |
| 73 * Check if he tried to move off the screen or make an illegal | |
| 74 * diagonal move, and stop him if he did. | |
| 75 */ | |
| 76 if (nh.x < 0 || nh.x > COLS-1 || nh.y < 1 || nh.y > LINES - 2) | |
| 77 goto hit_bound; | |
| 78 if (!diag_ok(&hero, &nh)) | |
| 79 { | |
| 80 after = FALSE; | |
| 81 running = FALSE; | |
| 82 return; | |
| 83 } | |
| 84 if (running && ce(hero, nh)) | |
| 85 after = running = FALSE; | |
| 86 fl = flat(nh.y, nh.x); | |
| 87 ch = winat(nh.y, nh.x); | |
| 88 if (!(fl & F_REAL) && ch == FLOOR) | |
| 89 { | |
| 90 chat(nh.y, nh.x) = ch = TRAP; | |
| 91 flat(nh.y, nh.x) |= F_REAL; | |
| 92 } | |
| 93 else | |
| 94 if (on(player, ISHELD) && ch != 'F') | |
| 95 { | |
| 96 msg("you are being held"); | |
| 97 return; | |
| 98 } | |
| 99 switch (ch) | |
| 100 { | |
| 101 case ' ': | |
| 102 case '|': | |
| 103 case '-': | |
| 104 hit_bound: | |
| 105 if (passgo && running && (proom->r_flags & ISGONE) | |
| 106 && !on(player, ISBLIND)) | |
| 107 { | |
| 108 register bool b1, b2; | |
| 109 | |
| 110 switch (runch) | |
| 111 { | |
| 112 case 'h': | |
| 113 case 'l': | |
| 114 b1 = (((flat(hero.y - 1, hero.x) & F_PASS) || chat(hero.y - 1, hero.x) == DOOR) && hero.y != 1); | |
| 115 b2 = (((flat(hero.y + 1, hero.x) & F_PASS) || chat(hero.y + 1, hero.x) == DOOR) && hero.y != LINES - 2); | |
| 116 if (!(b1 ^ b2)) | |
| 117 break; | |
| 118 if (b1) | |
| 119 { | |
| 120 runch = 'k'; | |
| 121 dy = -1; | |
| 122 } | |
| 123 else | |
| 124 { | |
| 125 runch = 'j'; | |
| 126 dy = 1; | |
| 127 } | |
| 128 dx = 0; | |
| 129 turnref(); | |
| 130 goto over; | |
| 131 case 'j': | |
| 132 case 'k': | |
| 133 b1 = (((flat(hero.y, hero.x - 1) & F_PASS) || chat(hero.y, hero.x - 1) == DOOR) && hero.x != 0); | |
| 134 b2 = (((flat(hero.y, hero.x + 1) & F_PASS) || chat(hero.y, hero.x + 1) == DOOR) && hero.x != COLS - 1); | |
| 135 if (!(b1 ^ b2)) | |
| 136 break; | |
| 137 if (b1) | |
| 138 { | |
| 139 runch = 'h'; | |
| 140 dx = -1; | |
| 141 } | |
| 142 else | |
| 143 { | |
| 144 runch = 'l'; | |
| 145 dx = 1; | |
| 146 } | |
| 147 dy = 0; | |
| 148 turnref(); | |
| 149 goto over; | |
| 150 } | |
| 151 } | |
| 152 after = running = FALSE; | |
| 153 break; | |
| 154 case DOOR: | |
| 155 running = FALSE; | |
| 156 if (flat(hero.y, hero.x) & F_PASS) | |
| 157 enter_room(&nh); | |
| 158 goto move_stuff; | |
| 159 case TRAP: | |
| 160 ch = be_trapped(&nh); | |
| 161 if (ch == T_DOOR || ch == T_TELEP) | |
| 162 return; | |
| 163 goto move_stuff; | |
| 164 case PASSAGE: | |
| 165 goto move_stuff; | |
| 166 case FLOOR: | |
| 167 if (!(fl & F_REAL)) | |
| 168 be_trapped(&hero); | |
| 169 goto move_stuff; | |
| 170 default: | |
| 171 running = FALSE; | |
| 172 if (isupper(ch) || moat(nh.y, nh.x)) | |
| 173 fight(&nh, ch, cur_weapon, FALSE); | |
| 174 else | |
| 175 { | |
| 176 running = FALSE; | |
| 177 if (ch != STAIRS) | |
| 178 take = ch; | |
| 179 move_stuff: | |
| 180 mvaddch(hero.y, hero.x, chat(hero.y, hero.x)); | |
| 181 if ((fl & F_PASS) && chat(oldpos.y, oldpos.x) == DOOR) | |
| 182 leave_room(&nh); | |
| 183 hero = nh; | |
| 184 } | |
| 185 } | |
| 186 } | |
| 187 | |
| 188 /* | |
| 189 * turnref: | |
| 190 * Decide whether to refresh at a passage turning or not | |
| 191 */ | |
| 192 turnref() | |
| 193 { | |
| 194 register int index; | |
| 195 | |
| 196 index = INDEX(hero.y, hero.x); | |
| 197 if (!(_flags[index] & F_SEEN)) | |
| 198 { | |
| 199 if (jump) | |
| 200 { | |
| 201 leaveok(stdscr, TRUE); | |
| 202 refresh(); | |
| 203 leaveok(stdscr, FALSE); | |
| 204 } | |
| 205 _flags[index] |= F_SEEN; | |
| 206 } | |
| 207 } | |
| 208 | |
| 209 /* | |
| 210 * door_open: | |
| 211 * Called to illuminate a room. If it is dark, remove anything | |
| 212 * that might move. | |
| 213 */ | |
| 214 door_open(rp) | |
| 215 struct room *rp; | |
| 216 { | |
| 217 register int j, k; | |
| 218 register char ch; | |
| 219 register THING *item; | |
| 220 | |
| 221 if (!(rp->r_flags & ISGONE) && !on(player, ISBLIND)) | |
| 222 for (j = rp->r_pos.y; j < rp->r_pos.y + rp->r_max.y; j++) | |
| 223 for (k = rp->r_pos.x; k < rp->r_pos.x + rp->r_max.x; k++) | |
| 224 { | |
| 225 ch = winat(j, k); | |
| 226 move(j, k); | |
| 227 if (isupper(ch)) | |
| 228 { | |
| 229 item = wake_monster(j, k); | |
| 230 if (item->t_oldch == ' ' && !(rp->r_flags & ISDARK) | |
| 231 && !on(player, ISBLIND)) | |
| 232 item->t_oldch = chat(j, k); | |
| 233 } | |
| 234 } | |
| 235 } | |
| 236 | |
| 237 /* | |
| 238 * be_trapped: | |
| 239 * The guy stepped on a trap.... Make him pay. | |
| 240 */ | |
| 241 be_trapped(tc) | |
| 242 register coord *tc; | |
| 243 { | |
| 244 register char tr; | |
| 245 register int index; | |
| 246 | |
| 247 count = running = FALSE; | |
| 248 index = INDEX(tc->y, tc->x); | |
| 249 _level[index] = TRAP; | |
| 250 tr = _flags[index] & F_TMASK; | |
| 251 switch (tr) | |
| 252 { | |
| 253 case T_DOOR: | |
| 254 level++; | |
| 255 new_level(); | |
| 256 msg("you fell into a trap!"); | |
| 257 when T_BEAR: | |
| 258 no_move += BEARTIME; | |
| 259 msg("you are caught in a bear trap"); | |
| 260 when T_SLEEP: | |
| 261 no_command += SLEEPTIME; | |
| 262 player.t_flags &= ~ISRUN; | |
| 263 msg("a strange white mist envelops you and you fall asleep"); | |
| 264 when T_ARROW: | |
| 265 if (swing(pstats.s_lvl-1, pstats.s_arm, 1)) | |
| 266 { | |
| 267 pstats.s_hpt -= roll(1, 6); | |
| 268 if (pstats.s_hpt <= 0) | |
| 269 { | |
| 270 msg("an arrow killed you"); | |
| 271 death('a'); | |
| 272 } | |
| 273 else | |
| 274 msg("oh no! An arrow shot you"); | |
| 275 } | |
| 276 else | |
| 277 { | |
| 278 register THING *arrow; | |
| 279 | |
| 280 arrow = new_item(); | |
| 281 arrow->o_type = WEAPON; | |
| 282 arrow->o_which = ARROW; | |
| 283 init_weapon(arrow, ARROW); | |
| 284 arrow->o_count = 1; | |
| 285 arrow->o_pos = hero; | |
| 286 arrow->o_hplus = arrow->o_dplus = 0; | |
| 287 fall(arrow, FALSE); | |
| 288 msg("an arrow shoots past you"); | |
| 289 } | |
| 290 when T_TELEP: | |
| 291 teleport(); | |
| 292 mvaddch(tc->y, tc->x, TRAP); /* since the hero's leaving, look() | |
| 293 won't put it on for us */ | |
| 294 when T_DART: | |
| 295 if (swing(pstats.s_lvl+1, pstats.s_arm, 1)) | |
| 296 { | |
| 297 pstats.s_hpt -= roll(1, 4); | |
| 298 if (pstats.s_hpt <= 0) | |
| 299 { | |
| 300 msg("a poisoned dart killed you"); | |
| 301 death('d'); | |
| 302 } | |
| 303 if (!ISWEARING(R_SUSTSTR) && !save(VS_POISON)) | |
| 304 chg_str(-1); | |
| 305 msg("a small dart just hit you in the shoulder"); | |
| 306 } | |
| 307 else | |
| 308 msg("a small dart whizzes by your ear and vanishes"); | |
| 309 } | |
| 310 flush_type(); | |
| 311 return tr; | |
| 312 } | |
| 313 | |
| 314 /* | |
| 315 * rndmove: | |
| 316 * Move in a random direction if the monster/person is confused | |
| 317 */ | |
| 318 coord * | |
| 319 rndmove(who) | |
| 320 THING *who; | |
| 321 { | |
| 322 register int x, y; | |
| 323 register char ch; | |
| 324 register THING *obj; | |
| 325 static coord ret; /* what we will be returning */ | |
| 326 | |
| 327 y = ret.y = who->t_pos.y + rnd(3) - 1; | |
| 328 x = ret.x = who->t_pos.x + rnd(3) - 1; | |
| 329 /* | |
| 330 * Now check to see if that's a legal move. If not, don't move. | |
| 331 * (I.e., bump into the wall or whatever) | |
| 332 */ | |
| 333 if (y == who->t_pos.y && x == who->t_pos.x) | |
| 334 return &ret; | |
| 335 if ((y < 0 || y >= LINES - 1) || (x < 0 || x >= COLS)) | |
| 336 goto bad; | |
| 337 else if (!diag_ok(&who->t_pos, &ret)) | |
| 338 goto bad; | |
| 339 else | |
| 340 { | |
| 341 ch = winat(y, x); | |
| 342 if (!step_ok(ch)) | |
| 343 goto bad; | |
| 344 if (ch == SCROLL) | |
| 345 { | |
| 346 for (obj = lvl_obj; obj != NULL; obj = next(obj)) | |
| 347 if (y == obj->o_pos.y && x == obj->o_pos.x) | |
| 348 break; | |
| 349 if (obj != NULL && obj->o_which == S_SCARE) | |
| 350 goto bad; | |
| 351 } | |
| 352 } | |
| 353 return &ret; | |
| 354 | |
| 355 bad: | |
| 356 ret = who->t_pos; | |
| 357 return &ret; | |
| 358 } |
