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 } |
