Mercurial > hg > early-roguelike
comparison urogue/sticks.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 sticks.c - Functions to implement the various sticks one might find | |
| 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 <limits.h> | |
| 20 #include <string.h> | |
| 21 #include <ctype.h> | |
| 22 #include "rogue.h" | |
| 23 | |
| 24 /* for WS_HIT, WS_WEB, etc */ | |
| 25 | |
| 26 static struct object null_stick = | |
| 27 { | |
| 28 {0,0},NULL,NULL,"",0,"0d0",0,0,'X',0,0,0,0,0,0,0,0,0,{0} | |
| 29 }; | |
| 30 | |
| 31 /* | |
| 32 * Mask for cancelling special abilities The flags listed here will be the | |
| 33 * ones left on after the cancellation takes place | |
| 34 */ | |
| 35 | |
| 36 #define CANC0MASK ( ISBLIND | ISINWALL | ISRUN | \ | |
| 37 ISFLEE | ISMEAN | ISGREED | \ | |
| 38 CANSHOOT | ISHELD | ISHUH | \ | |
| 39 ISSLOW | ISHASTE | ISCLEAR | \ | |
| 40 ISUNIQUE) | |
| 41 | |
| 42 #define CANC1MASK ( HASDISEASE | DIDSUFFOCATE | CARRYGOLD | \ | |
| 43 HASITCH | CANSELL | CANBBURN | \ | |
| 44 CANSPEAK | CANFLY | ISFRIENDLY) | |
| 45 | |
| 46 #define CANC2MASK ( HASINFEST | NOMOVE | ISSCAVENGE | \ | |
| 47 DOROT | HASSTINK | DIDHOLD) | |
| 48 | |
| 49 #define CANC3MASK ( ISUNDEAD | CANBREATHE | CANCAST | \ | |
| 50 HASOXYGEN) | |
| 51 | |
| 52 #define CANC4MASK ( CANTRAMPLE | CANSWIM | CANWIELD | \ | |
| 53 ISFAST | CANBARGAIN | CANSPORE | \ | |
| 54 ISLARGE | ISSMALL | ISFLOCK | \ | |
| 55 ISSWARM | CANSTICK | CANTANGLE | \ | |
| 56 SHOOTNEEDLE | CANZAP | HASARMOR | \ | |
| 57 CANTELEPORT | ISBERSERK | ISFAMILIAR | \ | |
| 58 HASFAMILIAR | SUMMONING) | |
| 59 | |
| 60 #define CANC5MASK ( CANREFLECT | MAGICATTRACT | HASSHIELD | HASMSHIELD) | |
| 61 | |
| 62 #define CANC6MASK ( 0 ) | |
| 63 #define CANC7MASK ( 0 ) | |
| 64 #define CANC8MASK ( 0 ) | |
| 65 #define CANC9MASK ( 0 ) | |
| 66 #define CANCAMASK ( 0 ) | |
| 67 #define CANCBMASK ( 0 ) | |
| 68 #define CANCCMASK ( 0 ) | |
| 69 #define CANCDMASK ( 0 ) | |
| 70 #define CANCEMASK ( 0 ) | |
| 71 #define CANCFMASK ( 0 ) | |
| 72 | |
| 73 void | |
| 74 fix_stick(struct object *cur) | |
| 75 { | |
| 76 if (strcmp(ws_type[cur->o_which], "staff") == 0) | |
| 77 { | |
| 78 cur->o_weight = 100; | |
| 79 cur->o_charges = 5 + rnd(10); | |
| 80 cur->o_damage = "2d3"; | |
| 81 | |
| 82 switch (cur->o_which) | |
| 83 { | |
| 84 case WS_HIT: | |
| 85 cur->o_hplus = 3; | |
| 86 cur->o_dplus = 3; | |
| 87 cur->o_damage = "2d8"; | |
| 88 break; | |
| 89 | |
| 90 case WS_LIGHT: | |
| 91 cur->o_charges = 20 + rnd(10); | |
| 92 break; | |
| 93 } | |
| 94 } | |
| 95 else /* A wand */ | |
| 96 { | |
| 97 cur->o_damage = "1d3"; | |
| 98 cur->o_weight = 60; | |
| 99 cur->o_charges = 3 + rnd(5); | |
| 100 | |
| 101 switch (cur->o_which) | |
| 102 { | |
| 103 case WS_HIT: | |
| 104 cur->o_hplus = 3; | |
| 105 cur->o_dplus = 3; | |
| 106 cur->o_damage = "1d8"; | |
| 107 break; | |
| 108 | |
| 109 case WS_LIGHT: | |
| 110 cur->o_charges = 10 + rnd(10); | |
| 111 break; | |
| 112 } | |
| 113 } | |
| 114 | |
| 115 cur->o_hurldmg = "1d1"; | |
| 116 } | |
| 117 | |
| 118 /* | |
| 119 do_zap() | |
| 120 zap a stick (or effect a stick-like spell) | |
| 121 zapper: who does it | |
| 122 got_dir: need to ask for direction? | |
| 123 which: which WS_STICK (-1 means ask from pack) | |
| 124 flags: ISBLESSED, ISCURSED | |
| 125 */ | |
| 126 | |
| 127 void | |
| 128 do_zap(struct thing *zapper, int which, unsigned long flags) | |
| 129 { | |
| 130 struct linked_list *item = NULL, *nitem; | |
| 131 struct object *obj, *nobj; | |
| 132 struct room *rp; | |
| 133 struct thing *tp = NULL; | |
| 134 char *mname = NULL; | |
| 135 int y, x; | |
| 136 int blessed = flags & ISBLESSED; | |
| 137 int cursed = flags & ISCURSED; | |
| 138 int is_stick = (which < 0 ? TRUE : FALSE); | |
| 139 int got_one = TRUE; | |
| 140 | |
| 141 if (zapper != &player) | |
| 142 { | |
| 143 monster_do_zap(zapper, which, flags); | |
| 144 return; | |
| 145 } | |
| 146 | |
| 147 if (is_stick) | |
| 148 { | |
| 149 if ((obj = get_object(pack, "zap with", 0, bff_zappable)) == NULL) | |
| 150 return; | |
| 151 | |
| 152 if (obj->o_type != STICK && !(obj->o_flags & ISZAPPED)) | |
| 153 { | |
| 154 msg("You can't zap with that!"); | |
| 155 return; | |
| 156 } | |
| 157 | |
| 158 if (obj->o_type != STICK) /* an electrified weapon */ | |
| 159 which = WS_ELECT; | |
| 160 else | |
| 161 which = obj->o_which; | |
| 162 | |
| 163 if (obj->o_charges < 1) | |
| 164 { | |
| 165 nothing_message(flags); | |
| 166 return; | |
| 167 } | |
| 168 | |
| 169 obj->o_charges--; | |
| 170 | |
| 171 if (delta.y == 0 && delta.x == 0) | |
| 172 do | |
| 173 { | |
| 174 delta.y = rnd(3) - 1; | |
| 175 delta.x = rnd(3) - 1; | |
| 176 } | |
| 177 while (delta.y == 0 && delta.x == 0); | |
| 178 | |
| 179 flags = obj->o_flags; | |
| 180 cursed = obj->o_flags & ISCURSED; | |
| 181 blessed = obj->o_flags & ISBLESSED; | |
| 182 } | |
| 183 else | |
| 184 obj = &null_stick; | |
| 185 | |
| 186 /* Find out who the target is */ | |
| 187 | |
| 188 y = hero.y; | |
| 189 x = hero.x; | |
| 190 | |
| 191 while(shoot_ok(CCHAR(winat(y, x)))) | |
| 192 { | |
| 193 y += delta.y; | |
| 194 x += delta.x; | |
| 195 } | |
| 196 | |
| 197 if (x >= 0 && x < COLS && y >= 1 && y < LINES - 2 && | |
| 198 isalpha(mvwinch(mw, y, x))) | |
| 199 { | |
| 200 item = find_mons(y, x); | |
| 201 tp = THINGPTR(item); | |
| 202 mname = on(player, ISBLIND) ? "monster" : | |
| 203 monsters[tp->t_index].m_name; | |
| 204 | |
| 205 if (on(*tp, CANSELL)) | |
| 206 { | |
| 207 luck++; | |
| 208 aggravate(); | |
| 209 } | |
| 210 } | |
| 211 else | |
| 212 got_one = FALSE; | |
| 213 | |
| 214 debug("Zapping with %d", which); | |
| 215 | |
| 216 switch(which) | |
| 217 { | |
| 218 case WS_LIGHT: | |
| 219 /* Reddy Kilowat wand. Light up the room */ | |
| 220 if (blue_light(flags) && is_stick) | |
| 221 if (is_stick) | |
| 222 know_items[TYP_STICK][WS_LIGHT] = TRUE; | |
| 223 break; | |
| 224 | |
| 225 case WS_DRAIN: | |
| 226 | |
| 227 /* | |
| 228 * Take away 1/2 of hero's hit points, then take it away | |
| 229 * evenly from the monsters in the room or next to hero if he | |
| 230 * is in a passage. Leave the monsters alone if the stick is | |
| 231 * cursed. Drain 1/3rd of hero's hit points if blessed. | |
| 232 */ | |
| 233 | |
| 234 if (pstats.s_hpt < 2) | |
| 235 { | |
| 236 death(D_DRAINLIFE); | |
| 237 return; | |
| 238 } | |
| 239 | |
| 240 if (cursed) | |
| 241 pstats.s_hpt /= 2; | |
| 242 else if ((rp = roomin(hero)) == NULL) | |
| 243 drain(hero.y - 1, hero.y + 1, hero.x - 1, hero.x + 1); | |
| 244 else | |
| 245 drain(rp->r_pos.y, rp->r_pos.y + rp->r_max.y, | |
| 246 rp->r_pos.x, rp->r_pos.x + rp->r_max.x); | |
| 247 | |
| 248 if (blessed) | |
| 249 pstats.s_hpt = (int) (pstats.s_hpt * 2.0 / 3.0); | |
| 250 | |
| 251 break; | |
| 252 | |
| 253 case WS_POLYMORPH: | |
| 254 case WS_MONSTELEP: | |
| 255 case WS_CANCEL: | |
| 256 { | |
| 257 char oldch; | |
| 258 int rm; | |
| 259 int save_adj = 0; | |
| 260 | |
| 261 if (got_one) | |
| 262 { | |
| 263 /* if the monster gets the saving throw, leave the case */ | |
| 264 | |
| 265 if (blessed) | |
| 266 save_adj = -5; | |
| 267 | |
| 268 if (cursed) | |
| 269 if (which == WS_POLYMORPH) | |
| 270 save_adj = -5; /* not save vs becoming tougher */ | |
| 271 else | |
| 272 save_adj = 5; | |
| 273 | |
| 274 if (save_throw(VS_MAGIC - save_adj, tp)) | |
| 275 { | |
| 276 nothing_message(flags); | |
| 277 break; | |
| 278 } | |
| 279 else if (is_stick) | |
| 280 know_items[TYP_STICK][which] = TRUE; | |
| 281 | |
| 282 /* Unhold player */ | |
| 283 | |
| 284 if (on(*tp, DIDHOLD)) | |
| 285 { | |
| 286 turn_off(*tp, DIDHOLD); | |
| 287 | |
| 288 if (--hold_count == 0) | |
| 289 turn_off(player, ISHELD); | |
| 290 } | |
| 291 | |
| 292 /* unsuffocate player */ | |
| 293 | |
| 294 if (on(*tp, DIDSUFFOCATE)) | |
| 295 { | |
| 296 turn_off(*tp, DIDSUFFOCATE); | |
| 297 extinguish_fuse(FUSE_SUFFOCATE); | |
| 298 } | |
| 299 | |
| 300 if (which == WS_POLYMORPH) | |
| 301 { | |
| 302 int which_new; | |
| 303 int charmed; | |
| 304 | |
| 305 detach(mlist, item); | |
| 306 charmed = on(*tp, ISCHARMED); | |
| 307 oldch = tp->t_oldch; | |
| 308 delta.y = y; | |
| 309 delta.x = x; | |
| 310 | |
| 311 if (!blessed && !cursed) | |
| 312 which_new = randmonster(WANDER, GRAB); | |
| 313 else | |
| 314 { | |
| 315 /* duplicate randmonster() for now */ | |
| 316 /* Eventually fix to take level */ | |
| 317 | |
| 318 int cur_level = 0, range, i; | |
| 319 | |
| 320 if (blessed) | |
| 321 cur_level = level / 2; | |
| 322 | |
| 323 if (cursed) | |
| 324 cur_level = level * 2; | |
| 325 | |
| 326 range = 4 * NLEVMONS; | |
| 327 i = 0; | |
| 328 | |
| 329 do | |
| 330 { | |
| 331 if (i++ > range * 10) /* just in case all have */ | |
| 332 { /* been genocided */ | |
| 333 i = 0; | |
| 334 | |
| 335 if (--cur_level <= 0) | |
| 336 fatal("Rogue could not find a monster to make"); | |
| 337 } | |
| 338 | |
| 339 which_new = NLEVMONS * (cur_level - 1) + (rnd(range) - (range - 1 - NLEVMONS)); | |
| 340 | |
| 341 if (which_new < 1) | |
| 342 which_new = rnd(NLEVMONS) + 1; | |
| 343 | |
| 344 if (which_new > nummonst - NUMSUMMON - 1) | |
| 345 { | |
| 346 if (blessed) | |
| 347 which_new = rnd(range) + (nummonst - NUMSUMMON - 1) - (range - 1); | |
| 348 else if (which_new > nummonst - 1) | |
| 349 which_new = rnd(range + NUMSUMMON) + (nummonst - 1) - (range + NUMSUMMON - 1); | |
| 350 } | |
| 351 } | |
| 352 while (!monsters[which_new].m_normal); | |
| 353 } | |
| 354 | |
| 355 new_monster(item, which_new, &delta, NOMAXSTATS); | |
| 356 mname = on(player, ISBLIND) ? "monster" : monsters[tp->t_index].m_name; | |
| 357 | |
| 358 if (!cursed && charmed) | |
| 359 turn_on(*tp, ISCHARMED); | |
| 360 | |
| 361 if (off(*tp, ISRUN)) | |
| 362 chase_it(&delta, &player); | |
| 363 | |
| 364 if (isalpha(mvwinch(cw, y, x))) | |
| 365 mvwaddch(cw, y, x, tp->t_type); | |
| 366 | |
| 367 tp->t_oldch = oldch; | |
