Mercurial > hg > early-roguelike
comparison rogue5/sticks.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 | 1e1c81fbb533 |
comparison
equal
deleted
inserted
replaced
| 32:2dcd75e6a736 | 33:f502bf60e6e4 |
|---|---|
| 1 /* | |
| 2 * Functions to implement the various sticks one might find | |
| 3 * while wandering around the dungeon. | |
| 4 * | |
| 5 * @(#)sticks.c 4.39 (Berkeley) 02/05/99 | |
| 6 * | |
| 7 * Rogue: Exploring the Dungeons of Doom | |
| 8 * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman | |
| 9 * All rights reserved. | |
| 10 * | |
| 11 * See the file LICENSE.TXT for full copyright and licensing information. | |
| 12 */ | |
| 13 | |
| 14 #include <curses.h> | |
| 15 #include <string.h> | |
| 16 #include <ctype.h> | |
| 17 #include "rogue.h" | |
| 18 | |
| 19 /* | |
| 20 * fix_stick: | |
| 21 * Set up a new stick | |
| 22 */ | |
| 23 | |
| 24 void | |
| 25 fix_stick(THING *cur) | |
| 26 { | |
| 27 if (strcmp(ws_type[cur->o_which], "staff") == 0) | |
| 28 strncpy(cur->o_damage,"2x3",sizeof(cur->o_damage)); | |
| 29 else | |
| 30 strncpy(cur->o_damage,"1x1",sizeof(cur->o_damage)); | |
| 31 strncpy(cur->o_hurldmg,"1x1",sizeof(cur->o_hurldmg)); | |
| 32 | |
| 33 switch (cur->o_which) | |
| 34 { | |
| 35 case WS_LIGHT: | |
| 36 cur->o_charges = rnd(10) + 10; | |
| 37 otherwise: | |
| 38 cur->o_charges = rnd(5) + 3; | |
| 39 } | |
| 40 } | |
| 41 | |
| 42 /* | |
| 43 * do_zap: | |
| 44 * Perform a zap with a wand | |
| 45 */ | |
| 46 | |
| 47 void | |
| 48 do_zap(void) | |
| 49 { | |
| 50 THING *obj, *tp; | |
| 51 int y, x; | |
| 52 char *name; | |
| 53 int monster, oldch; | |
| 54 THING bolt; | |
| 55 | |
| 56 if ((obj = get_item("zap with", STICK)) == NULL) | |
| 57 return; | |
| 58 if (obj->o_type != STICK) | |
| 59 { | |
| 60 after = FALSE; | |
| 61 msg("you can't zap with that!"); | |
| 62 return; | |
| 63 } | |
| 64 if (obj->o_charges == 0) | |
| 65 { | |
| 66 msg("nothing happens"); | |
| 67 return; | |
| 68 } | |
| 69 switch (obj->o_which) | |
| 70 { | |
| 71 case WS_LIGHT: | |
| 72 /* | |
| 73 * Reddy Kilowat wand. Light up the room | |
| 74 */ | |
| 75 ws_info[WS_LIGHT].oi_know = TRUE; | |
| 76 if (proom->r_flags & ISGONE) | |
| 77 msg("the corridor glows and then fades"); | |
| 78 else | |
| 79 { | |
| 80 proom->r_flags &= ~ISDARK; | |
| 81 /* | |
| 82 * Light the room and put the player back up | |
| 83 */ | |
| 84 enter_room(&hero); | |
| 85 addmsg("the room is lit"); | |
| 86 if (!terse) | |
| 87 addmsg(" by a shimmering %s light", pick_color("blue")); | |
| 88 endmsg(); | |
| 89 } | |
| 90 when WS_DRAIN: | |
| 91 /* | |
| 92 * take away 1/2 of hero's hit points, then take it away | |
| 93 * evenly from the monsters in the room (or next to hero | |
| 94 * if he is in a passage) | |
| 95 */ | |
| 96 if (pstats.s_hpt < 2) | |
| 97 { | |
| 98 msg("you are too weak to use it"); | |
| 99 return; | |
| 100 } | |
| 101 else | |
| 102 drain(); | |
| 103 when WS_INVIS: | |
| 104 case WS_POLYMORPH: | |
| 105 case WS_TELAWAY: | |
| 106 case WS_TELTO: | |
| 107 case WS_CANCEL: | |
| 108 y = hero.y; | |
| 109 x = hero.x; | |
| 110 while (step_ok(winat(y, x))) | |
| 111 { | |
| 112 y += delta.y; | |
| 113 x += delta.x; | |
| 114 } | |
| 115 if ((tp = moat(y, x)) != NULL) | |
| 116 { | |
| 117 monster = tp->t_type; | |
| 118 if (monster == 'F') | |
| 119 player.t_flags &= ~ISHELD; | |
| 120 switch (obj->o_which) { | |
| 121 case WS_INVIS: | |
| 122 tp->t_flags |= ISINVIS; | |
| 123 if (cansee(y, x)) | |
| 124 mvaddch(y, x, tp->t_oldch); | |
| 125 break; | |
| 126 case WS_POLYMORPH: | |
| 127 { | |
| 128 THING *pp; | |
| 129 | |
| 130 pp = tp->t_pack; | |
| 131 detach(mlist, tp); | |
| 132 if (see_monst(tp)) | |
| 133 mvaddch(y, x, chat(y, x)); | |
| 134 oldch = tp->t_oldch; | |
| 135 delta.y = y; | |
| 136 delta.x = x; | |
| 137 new_monster(tp, monster = rnd(26) + 'A', &delta); | |
| 138 if (see_monst(tp)) | |
| 139 mvaddch(y, x, monster); | |
| 140 tp->t_oldch = oldch; | |
| 141 tp->t_pack = pp; | |
| 142 ws_info[WS_POLYMORPH].oi_know |= see_monst(tp); | |
| 143 break; | |
| 144 } | |
| 145 case WS_CANCEL: | |
| 146 tp->t_flags |= ISCANC; | |
| 147 tp->t_flags &= ~(ISINVIS|CANHUH); | |
| 148 tp->t_disguise = tp->t_type; | |
| 149 if (see_monst(tp)) | |
| 150 mvaddch(y, x, tp->t_disguise); | |
| 151 break; | |
| 152 case WS_TELAWAY: | |
| 153 case WS_TELTO: | |
| 154 { | |
| 155 coord new_pos; | |
| 156 | |
| 157 if (obj->o_which == WS_TELAWAY) | |
| 158 { | |
| 159 do | |
| 160 { | |
| 161 find_floor(NULL, &new_pos, FALSE, TRUE); | |
| 162 } while (ce(new_pos, hero)); | |
| 163 } | |
| 164 else | |
| 165 { | |
| 166 new_pos.y = hero.y + delta.y; | |
| 167 new_pos.x = hero.x + delta.x; | |
| 168 } | |
| 169 tp->t_dest = &hero; | |
| 170 tp->t_flags |= ISRUN; | |
| 171 relocate(tp, &new_pos); | |
| 172 } | |
| 173 } | |
| 174 } | |
| 175 when WS_MISSILE: | |
| 176 ws_info[WS_MISSILE].oi_know = TRUE; | |
| 177 bolt.o_type = '*'; | |
| 178 strncpy(bolt.o_hurldmg,"1x4",sizeof(bolt.o_hurldmg)); | |
| 179 bolt.o_hplus = 100; | |
| 180 bolt.o_dplus = 1; | |
| 181 bolt.o_flags = ISMISL; | |
| 182 if (cur_weapon != NULL) | |
| 183 bolt.o_launch = cur_weapon->o_which; | |
| 184 do_motion(&bolt, delta.y, delta.x); | |
| 185 if ((tp = moat(bolt.o_pos.y, bolt.o_pos.x)) != NULL | |
| 186 && !save_throw(VS_MAGIC, tp)) | |
| 187 hit_monster(unc(bolt.o_pos), &bolt); | |
| 188 else if (terse) | |
| 189 msg("missle vanishes"); | |
| 190 else | |
| 191 msg("the missle vanishes with a puff of smoke"); | |
| 192 when WS_HASTE_M: | |
| 193 case WS_SLOW_M: | |
| 194 y = hero.y; | |
| 195 x = hero.x; | |
| 196 while (step_ok(winat(y, x))) | |
| 197 { | |
| 198 y += delta.y; | |
| 199 x += delta.x; | |
| 200 } | |
| 201 if ((tp = moat(y, x)) != NULL) | |
| 202 { | |
| 203 if (obj->o_which == WS_HASTE_M) | |
| 204 { | |
| 205 if (on(*tp, ISSLOW)) | |
| 206 tp->t_flags &= ~ISSLOW; | |
| 207 else | |
| 208 tp->t_flags |= ISHASTE; | |
| 209 } | |
| 210 else | |
| 211 { | |
| 212 if (on(*tp, ISHASTE)) | |
| 213 tp->t_flags &= ~ISHASTE; | |
| 214 else | |
| 215 tp->t_flags |= ISSLOW; | |
| 216 tp->t_turn = TRUE; | |
| 217 } | |
| 218 delta.y = y; | |
| 219 delta.x = x; | |
| 220 runto(&delta); | |
| 221 } | |
| 222 when WS_ELECT: | |
| 223 case WS_FIRE: | |
| 224 case WS_COLD: | |
| 225 if (obj->o_which == WS_ELECT) | |
| 226 name = "bolt"; | |
| 227 else if (obj->o_which == WS_FIRE) | |
| 228 name = "flame"; | |
| 229 else | |
| 230 name = "ice"; | |
| 231 fire_bolt(&hero, &delta, name); | |
| 232 ws_info[obj->o_which].oi_know = TRUE; | |
| 233 when WS_NOP: | |
| 234 break; | |
| 235 #ifdef MASTER | |
| 236 otherwise: | |
| 237 msg("what a bizarre schtick!"); | |
| 238 #endif | |
| 239 } | |
| 240 obj->o_charges--; | |
| 241 } | |
| 242 | |
| 243 /* | |
| 244 * drain: | |
| 245 * Do drain hit points from player shtick | |
| 246 */ | |
| 247 | |
| 248 void | |
| 249 drain(void) | |
| 250 { | |
| 251 THING *mp; | |
| 252 struct room *corp; | |
| 253 THING **dp; | |
| 254 int cnt; | |
| 255 int inpass; | |
| 256 THING *drainee[40]; | |
| 257 | |
| 258 /* | |
| 259 * First cnt how many things we need to spread the hit points among | |
| 260 */ | |
| 261 cnt = 0; | |
| 262 if (chat(hero.y, hero.x) == DOOR) | |
| 263 corp = &passages[flat(hero.y, hero.x) & F_PNUM]; | |
| 264 else | |
| 265 corp = NULL; | |
| 266 inpass = (proom->r_flags & ISGONE); | |
| 267 dp = drainee; | |
| 268 for (mp = mlist; mp != NULL; mp = next(mp)) | |
| 269 if (mp->t_room == proom || mp->t_room == corp || | |
| 270 (inpass && chat(mp->t_pos.y, mp->t_pos.x) == DOOR && | |
| 271 &passages[flat(mp->t_pos.y, mp->t_pos.x) & F_PNUM] == proom)) | |
| 272 *dp++ = mp; | |
| 273 if ((cnt = (int)(dp - drainee)) == 0) | |
| 274 { | |
| 275 msg("you have a tingling feeling"); | |
| 276 return; | |
| 277 } | |
| 278 *dp = NULL; | |
| 279 pstats.s_hpt /= 2; | |
| 280 cnt = pstats.s_hpt / cnt; | |
| 281 /* | |
| 282 * Now zot all of the monsters | |
| 283 */ | |
| 284 for (dp = drainee; *dp; dp++) | |
| 285 { | |
| 286 mp = *dp; | |
| 287 if ((mp->t_stats.s_hpt -= cnt) <= 0) | |
| 288 killed(mp, see_monst(mp)); | |
| 289 else | |
| 290 runto(&mp->t_pos); | |
| 291 } | |
| 292 } | |
| 293 | |
| 294 /* | |
| 295 * fire_bolt: | |
| 296 * Fire a bolt in a given direction from a specific starting place | |
| 297 */ | |
| 298 | |
| 299 void | |
| 300 fire_bolt(const coord *start, coord *dir, const char *name) | |
| 301 { | |
| 302 coord *c1, *c2; | |
| 303 THING *tp; | |
| 304 int dirch = 0, ch; | |
| 305 int hit_hero, used, changed; | |
| 306 coord pos; | |
| 307 coord spotpos[BOLT_LENGTH]; | |
| 308 THING bolt; | |
| 309 | |
| 310 bolt.o_type = WEAPON; | |
| 311 bolt.o_which = FLAME; | |
| 312 strncpy(bolt.o_hurldmg,"6x6",sizeof(bolt.o_hurldmg)); | |
| 313 bolt.o_hplus = 100; | |
| 314 bolt.o_dplus = 0; | |
| 315 weap_info[FLAME].oi_name = name; | |
| 316 switch (dir->y + dir->x) | |
| 317 { | |
| 318 case 0: dirch = '/'; | |
| 319 when 1: case -1: dirch = (dir->y == 0 ? '-' : '|'); | |
| 320 when 2: case -2: dirch = '\\'; | |
| 321 } | |
| 322 pos = *start; | |
| 323 hit_hero = (start != &hero); | |
| 324 used = FALSE; | |
| 325 changed = FALSE; | |
| 326 for (c1 = spotpos; c1 <= &spotpos[BOLT_LENGTH-1] && !used; c1++) | |
| 327 { | |
| 328 pos.y += dir->y; | |
| 329 pos.x += dir->x; | |
| 330 *c1 = pos; | |
| 331 ch = winat(pos.y, pos.x); | |
| 332 switch (ch) | |
| 333 { | |
| 334 case DOOR: | |
| 335 /* | |
| 336 * this code is necessary if the hero is on a door | |
| 337 * and he fires at the wall the door is in, it would | |
| 338 * otherwise loop infinitely | |
| 339 */ | |
| 340 if (ce(hero, pos)) | |
| 341 goto def; | |
| 342 /* FALLTHROUGH */ | |
| 343 case '|': | |
| 344 case '-': | |
| 345 case ' ': | |
| 346 if (!changed) | |
| 347 hit_hero = !hit_hero; | |
| 348 changed = FALSE; | |
| 349 dir->y = -dir->y; | |
| 350 dir->x = -dir->x; | |
| 351 c1--; | |
| 352 msg("the %s bounces", name); | |
| 353 break; | |
| 354 default: | |
| 355 def: | |
| 356 if (!hit_hero && (tp = moat(pos.y, pos.x)) != NULL) | |
| 357 { | |
| 358 hit_hero = TRUE; | |
| 359 changed = !changed; | |
| 360 tp->t_oldch = chat(pos.y, pos.x); | |
| 361 if (!save_throw(VS_MAGIC, tp)) | |
| 362 { | |
| 363 bolt.o_pos = pos; | |
| 364 used = TRUE; | |
| 365 if (tp->t_type == 'D' && strcmp(name, "flame") == 0) | |
| 366 { | |
| 367 addmsg("the flame bounces"); | |
| 368 if (!terse) | |
| 369 addmsg(" off the dragon"); | |
| 370 endmsg(); | |
| 371 } | |
| 372 else | |
| 373 hit_monster(unc(pos), &bolt); | |
| 374 } | |
| 375 else if (ch != 'M' || tp->t_disguise == 'M') | |
| 376 { | |
| 377 if (start == &hero) | |
| 378 runto(&pos); | |
| 379 if (terse) | |
| 380 msg("%s misses", name); | |
| 381 else | |
| 382 msg("the %s whizzes past %s", name, set_mname(tp)); | |
| 383 } | |
