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