Mercurial > hg > early-roguelike
comparison arogue7/sticks.c @ 125:adfa37e67084
Import Advanced Rogue 7.7 from the Roguelike Restoration Project (r1490)
| author | John "Elwin" Edwards |
|---|---|
| date | Fri, 08 May 2015 15:24:40 -0400 |
| parents | |
| children | b786053d2f37 |
comparison
equal
deleted
inserted
replaced
| 124:d10fc4a065ac | 125:adfa37e67084 |
|---|---|
| 1 /* | |
| 2 * sticks.c - Functions to implement the various sticks one might find | |
| 3 * | |
| 4 * Advanced Rogue | |
| 5 * Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T | |
| 6 * All rights reserved. | |
| 7 * | |
| 8 * Based on "Rogue: Exploring the Dungeons of Doom" | |
| 9 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman | |
| 10 * All rights reserved. | |
| 11 * | |
| 12 * See the file LICENSE.TXT for full copyright and licensing information. | |
| 13 */ | |
| 14 | |
| 15 /* | |
| 16 * Functions to implement the various sticks one might find | |
| 17 * while wandering around the dungeon. | |
| 18 */ | |
| 19 | |
| 20 #include "curses.h" | |
| 21 #include <ctype.h> | |
| 22 #include "rogue.h" | |
| 23 | |
| 24 | |
| 25 /* | |
| 26 * zap a stick and see what happens | |
| 27 */ | |
| 28 do_zap(zapper, obj, direction, which, flags) | |
| 29 struct thing *zapper; | |
| 30 struct object *obj; | |
| 31 coord *direction; | |
| 32 int which; | |
| 33 int flags; | |
| 34 { | |
| 35 register struct linked_list *item; | |
| 36 register struct thing *tp; | |
| 37 register int y, x, bonus; | |
| 38 struct linked_list *nitem; | |
| 39 struct object *nobj; | |
| 40 bool cursed, blessed, is_player; | |
| 41 char *mname; | |
| 42 | |
| 43 cursed = flags & ISCURSED; | |
| 44 blessed = flags & ISBLESSED; | |
| 45 | |
| 46 if (obj && obj->o_type != RELIC) { /* all relics are chargeless */ | |
| 47 if (obj->o_charges < 1) { | |
| 48 msg(nothing); | |
| 49 return; | |
| 50 } | |
| 51 obj->o_charges--; | |
| 52 } | |
| 53 if (which == WS_WONDER) { | |
| 54 switch (rnd(14)) { | |
| 55 case 0: which = WS_ELECT; | |
| 56 when 1: which = WS_FIRE; | |
| 57 when 2: which = WS_COLD; | |
| 58 when 3: which = WS_POLYMORPH; | |
| 59 when 4: which = WS_MISSILE; | |
| 60 when 5: which = WS_SLOW_M; | |
| 61 when 6: which = WS_TELMON; | |
| 62 when 7: which = WS_CANCEL; | |
| 63 when 8: which = WS_CONFMON; | |
| 64 when 9: which = WS_DISINTEGRATE; | |
| 65 when 10: which = WS_PETRIFY; | |
| 66 when 11: which = WS_PARALYZE; | |
| 67 when 12: which = WS_MDEG; | |
| 68 when 13: which = WS_FEAR; | |
| 69 } | |
| 70 if(ws_magic[which].mi_curse>0 && rnd(100)<=ws_magic[which].mi_curse){ | |
| 71 cursed = TRUE; | |
| 72 blessed = FALSE; | |
| 73 } | |
| 74 } | |
| 75 | |
| 76 tp = NULL; | |
| 77 switch (which) { | |
| 78 case WS_POLYMORPH: | |
| 79 case WS_SLOW_M: | |
| 80 case WS_TELMON: | |
| 81 case WS_CANCEL: | |
| 82 case WS_CONFMON: | |
| 83 case WS_DISINTEGRATE: | |
| 84 case WS_PETRIFY: | |
| 85 case WS_PARALYZE: | |
| 86 case WS_MDEG: | |
| 87 case WS_FEAR: | |
| 88 y = zapper->t_pos.y; | |
| 89 x = zapper->t_pos.x; | |
| 90 | |
| 91 do { | |
| 92 y += direction->y; | |
| 93 x += direction->x; | |
| 94 } | |
| 95 while (shoot_ok(winat(y, x)) && !(y == hero.y && x == hero.x)); | |
| 96 | |
| 97 if (y == hero.y && x == hero.x) | |
| 98 is_player = TRUE; | |
| 99 else if (isalpha(mvwinch(mw, y, x))) { | |
| 100 item = find_mons(y, x); | |
| 101 tp = THINGPTR(item); | |
| 102 runto(tp, &hero); | |
| 103 turn_off(*tp, CANSURPRISE); | |
| 104 mname = monster_name(tp); | |
| 105 is_player = FALSE; | |
| 106 | |
| 107 /* The monster may not like being shot at */ | |
| 108 if ((zapper == &player) && | |
| 109 on(*tp, ISCHARMED) && | |
| 110 save(VS_MAGIC, tp, 0)) { | |
| 111 msg("The eyes of %s turn clear.", prname(mname, FALSE)); | |
| 112 turn_off(*tp, ISCHARMED); | |
| 113 mname = monster_name(tp); | |
| 114 } | |
| 115 } | |
| 116 else { | |
| 117 /* | |
| 118 * if monster misses player because the player dodged then lessen | |
| 119 * the chances he will use the wand again since the player appears | |
| 120 * to be rather dextrous | |
| 121 */ | |
| 122 if (zapper != &player) | |
| 123 zapper->t_wand = zapper->t_wand * 3 / 4; | |
| 124 } | |
| 125 } | |
| 126 switch (which) { | |
| 127 case WS_LIGHT: | |
| 128 /* | |
| 129 * Reddy Kilowat wand. Light up the room | |
| 130 */ | |
| 131 blue_light(blessed, cursed); | |
| 132 when WS_DRAIN: | |
| 133 /* | |
| 134 * Take away 1/2 of hero's hit points, then take it away | |
| 135 * evenly from the monsters in the room or next to hero | |
| 136 * if he is in a passage (but leave the monsters alone | |
| 137 * if the stick is cursed) | |
| 138 */ | |
| 139 if (pstats.s_hpt < 2) { | |
| 140 msg("You are too weak to use it."); | |
| 141 } | |
| 142 else if (cursed) | |
| 143 pstats.s_hpt /= 2; | |
| 144 else | |
| 145 drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1); | |
| 146 | |
| 147 when WS_POLYMORPH: | |
| 148 { | |
| 149 register char oldch; | |
| 150 register struct room *rp; | |
| 151 register struct linked_list *pitem; | |
| 152 coord delta; | |
| 153 | |
| 154 if (tp == NULL) | |
| 155 break; | |
| 156 if (save(VS_MAGIC, tp, 0)) { | |
| 157 msg(nothing); | |
| 158 break; | |
| 159 } | |
| 160 rp = roomin(&tp->t_pos); | |
| 161 check_residue(tp); | |
| 162 delta.x = x; | |
| 163 delta.y = y; | |
| 164 detach(mlist, item); | |
| 165 oldch = tp->t_oldch; | |
| 166 pitem = tp->t_pack; /* save his pack */ | |
| 167 tp->t_pack = NULL; | |
| 168 new_monster(item,rnd(NUMMONST-NUMUNIQUE-1)+1,&delta,FALSE); | |
| 169 if (tp->t_pack != NULL) | |
| 170 o_free_list (tp->t_pack); | |
| 171 tp->t_pack = pitem; | |
| 172 if (isalpha(mvwinch(cw, y, x))) | |
| 173 mvwaddch(cw, y, x, tp->t_type); | |
| 174 tp->t_oldch = oldch; | |
| 175 /* | |
| 176 * should the room light up? | |
| 177 */ | |
| 178 if (on(*tp, HASFIRE)) { | |
| 179 if (rp) { | |
| 180 register struct linked_list *fire_item; | |
| 181 | |
| 182 fire_item = creat_item(); | |
| 183 ldata(fire_item) = (char *) tp; | |
| 184 attach(rp->r_fires, fire_item); | |
| 185 rp->r_flags |= HASFIRE; | |
| 186 if (cansee(tp->t_pos.y,tp->t_pos.x) && | |
| 187 next(rp->r_fires) == NULL) light(&hero); | |
| 188 } | |
| 189 } | |
| 190 runto(tp, &hero); | |
| 191 msg(terse ? "A new %s!" | |
| 192 : "You have created a new %s!", | |
| 193 monster_name(tp)); | |
| 194 } | |
| 195 | |
| 196 when WS_PETRIFY: | |
| 197 if (tp == NULL) | |
| 198 break; | |
| 199 if (save(VS_MAGIC, tp, 0)) { | |
| 200 msg(nothing); | |
| 201 break; | |
| 202 } | |
| 203 check_residue(tp); | |
| 204 turn_on(*tp, ISSTONE); | |
| 205 turn_on(*tp, NOSTONE); | |
| 206 turn_off(*tp, ISRUN); | |
| 207 turn_off(*tp, ISINVIS); | |
| 208 turn_off(*tp, CANSURPRISE); | |
| 209 turn_off(*tp, ISDISGUISE); | |
| 210 tp->t_action = A_NIL; | |
| 211 tp->t_no_move = 0; | |
| 212 msg("%s is turned to stone!",prname(mname, TRUE)); | |
| 213 | |
| 214 when WS_TELMON: | |
| 215 { | |
| 216 register int rm; | |
| 217 register struct room *rp; | |
| 218 | |
| 219 if (tp == NULL) | |
| 220 break; | |
| 221 if (save(VS_MAGIC, tp, 0)) { | |
| 222 msg(nothing); | |
| 223 break; | |
| 224 } | |
| 225 rp = NULL; | |
| 226 check_residue(tp); | |
| 227 tp->t_action = A_FREEZE; /* creature is disoriented */ | |
| 228 tp->t_no_move = 2; | |
| 229 if (cursed) { /* Teleport monster to player */ | |
| 230 if ((y == (hero.y + direction->y)) && | |
| 231 (x == (hero.x + direction->x))) | |
| 232 msg(nothing); | |
| 233 else { | |
| 234 tp->t_pos.y = hero.y + direction->y; | |
| 235 tp->t_pos.x = hero.x + direction->x; | |
| 236 } | |
| 237 } | |
| 238 else if (blessed) { /* Get rid of monster */ | |
| 239 killed(item, FALSE, TRUE, TRUE); | |
| 240 return; | |
| 241 } | |
| 242 else { | |
| 243 register int i=0; | |
| 244 | |
| 245 do { /* Move monster to another room */ | |
| 246 rm = rnd_room(); | |
| 247 rnd_pos(&rooms[rm], &tp->t_pos); | |
| 248 }until(winat(tp->t_pos.y,tp->t_pos.x)==FLOOR ||i++>500); | |
| 249 rp = &rooms[rm]; | |
| 250 } | |
| 251 | |
| 252 /* Now move the monster */ | |
| 253 if (isalpha(mvwinch(cw, y, x))) | |
| 254 mvwaddch(cw, y, x, tp->t_oldch); | |
| 255 mvwaddch(mw, y, x, ' '); | |
| 256 mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type); | |
| 257 if (tp->t_pos.y != y || tp->t_pos.x != x) | |
| 258 tp->t_oldch = CCHAR( mvwinch(cw, tp->t_pos.y, tp->t_pos.x) ); | |
| 259 /* | |
| 260 * check to see if room that creature appears in should | |
| 261 * light up | |
| 262 */ | |
| 263 if (on(*tp, HASFIRE)) { | |
| 264 if (rp) { | |
| 265 register struct linked_list *fire_item; | |
| 266 | |
| 267 fire_item = creat_item(); | |
| 268 ldata(fire_item) = (char *) tp; | |
| 269 attach(rp->r_fires, fire_item); | |
| 270 rp->r_flags |= HASFIRE; | |
| 271 if(cansee(tp->t_pos.y, tp->t_pos.x) && | |
| 272 next(rp->r_fires) == NULL) | |
| 273 light(&hero); | |
| 274 } | |
| 275 } | |
| 276 } | |
| 277 when WS_CANCEL: | |
| 278 if (tp == NULL) | |
| 279 break; | |
| 280 if (save(VS_MAGIC, tp, 0)) { | |
| 281 msg(nothing); | |
| 282 break; | |
| 283 } | |
| 284 check_residue(tp); | |
| 285 tp->t_flags[0] &= CANC0MASK; | |
| 286 tp->t_flags[1] &= CANC1MASK; | |
| 287 tp->t_flags[2] &= CANC2MASK; | |
| 288 tp->t_flags[3] &= CANC3MASK; | |
| 289 tp->t_flags[4] &= CANC4MASK; | |
| 290 tp->t_flags[5] &= CANC5MASK; | |
| 291 tp->t_flags[6] &= CANC6MASK; | |
| 292 tp->t_flags[7] &= CANC7MASK; | |
| 293 tp->t_flags[8] &= CANC8MASK; | |
| 294 tp->t_flags[9] &= CANC9MASK; | |
| 295 tp->t_flags[10] &= CANCAMASK; | |
| 296 tp->t_flags[11] &= CANCBMASK; | |
| 297 tp->t_flags[12] &= CANCCMASK; | |
| 298 tp->t_flags[13] &= CANCDMASK; | |
| 299 tp->t_flags[14] &= CANCEMASK; | |
| 300 tp->t_flags[15] &= CANCFMASK; | |
| 301 | |
| 302 when WS_MISSILE: | |
| 303 { | |
| 304 int dice; | |
| 305 static struct object bolt = | |
| 306 { | |
| 307 MISSILE , {0, 0}, "", 0, "", "1d4 " , NULL, 0, WS_MISSILE, 50, 1 | |
| 308 }; | |
| 309 | |
| 310 if (!obj) | |
| 311 dice = zapper->t_stats.s_lvl; | |
| 312 if (obj->o_type == RELIC) | |
| 313 dice = 15; | |
| 314 else if (EQUAL(ws_type[which], "staff")) | |
| 315 dice = 10; | |
| 316 else | |
| 317 dice = 6; | |
| 318 sprintf(bolt.o_hurldmg, "%dd4", dice); | |
| 319 do_motion(&bolt, direction->y, direction->x, zapper); | |
| 320 if (!hit_monster(unc(bolt.o_pos), &bolt, zapper)) | |
| 321 msg("The missile vanishes with a puff of smoke"); | |
| 322 } | |
| 323 when WS_HIT: | |
| 324 { | |
| 325 register char ch; | |
| 326 struct object strike; /* don't want to change sticks attributes */ | |
| 327 | |
| 328 direction->y += hero.y; | |
| 329 direction->x += hero.x; | |
| 330 ch = CCHAR( winat(direction->y, direction->x) ); | |
| 331 if (isalpha(ch)) | |
| 332 { | |
| 333 strike = *obj; | |
| 334 strike.o_hplus = 6; | |
| 335 if (EQUAL(ws_type[which], "staff")) | |
| 336 strncpy(strike.o_damage,"3d8",sizeof(strike.o_damage)); | |
| 337 else | |
| 338 strncpy(strike.o_damage,"2d8",sizeof(strike.o_damage)); | |
| 339 fight(direction, &strike, FALSE); | |
| 340 } | |
| 341 } | |
| 342 when WS_SLOW_M: | |
| 343 if (is_player) { | |
| 344 add_slow(); | |
| 345 break; | |
| 346 } | |
| 347 if (tp == NULL) | |
| 348 break; | |
| 349 if (cursed) { | |
| 350 if (on(*tp, ISSLOW)) | |
| 351 turn_off(*tp, ISSLOW); | |
| 352 else | |
| 353 turn_on(*tp, ISHASTE); | |
| 354 break; | |
| 355 } | |
| 356 if ((on(*tp,ISUNIQUE) && save(VS_MAGIC,tp,0)) || on(*tp,NOSLOW)) { | |
| 357 msg(nothing); | |
| 358 break; | |
| 359 } | |
| 360 else if (blessed) { | |
| 361 turn_off(*tp, ISRUN); | |
| 362 turn_on(*tp, ISHELD); | |
| 363 } | |
| 364 /* | |
| 365 * always slow in case he breaks free of HOLD | |
| 366 */ | |
| 367 if (on(*tp, ISHASTE)) | |
| 368 turn_off(*tp, ISHASTE); | |
| 369 else | |
| 370 turn_on(*tp, ISSLOW); | |
| 371 | |
| 372 when WS_CHARGE: | |
| 373 if (ws_know[WS_CHARGE] != TRUE && obj) | |
| 374 msg("This is a wand of charging."); | |
| 375 nitem = get_item(pack, "charge", STICK, FALSE, FALSE); |
