Mercurial > hg > early-roguelike
comparison arogue7/misc.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 * misc.c - routines dealing specifically with miscellaneous magic | |
| 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 #include "curses.h" | |
| 16 #include <ctype.h> | |
| 17 #include "rogue.h" | |
| 18 #ifdef PC7300 | |
| 19 #include "menu.h" | |
| 20 #endif | |
| 21 | |
| 22 /* | |
| 23 * routines dealing specifically with miscellaneous magic | |
| 24 */ | |
| 25 | |
| 26 /* | |
| 27 * changeclass: | |
| 28 * Change the player's class to the specified one. | |
| 29 */ | |
| 30 | |
| 31 changeclass(newclass) | |
| 32 int newclass; | |
| 33 { | |
| 34 if (newclass == player.t_ctype) { | |
| 35 msg("You feel more skillful."); | |
| 36 raise_level(); | |
| 37 } | |
| 38 else { | |
| 39 /* | |
| 40 * reset his class and then use check_level to reset hit | |
| 41 * points and the right level for his exp pts | |
| 42 * drop exp pts by 10% | |
| 43 */ | |
| 44 long save; | |
| 45 | |
| 46 msg("You feel like a whole new person!"); | |
| 47 | |
| 48 /* | |
| 49 * if he becomes a thief he has to have leather armor | |
| 50 */ | |
| 51 if ((newclass == C_THIEF || newclass == C_ASSASIN) && | |
| 52 cur_armor != NULL && | |
| 53 cur_armor->o_which != LEATHER && | |
| 54 cur_armor->o_which != STUDDED_LEATHER ) | |
| 55 cur_armor->o_which = STUDDED_LEATHER; | |
| 56 /* | |
| 57 * if he becomes a monk he can't wear armor | |
| 58 */ | |
| 59 if (newclass == C_MONK && cur_armor != NULL) { | |
| 60 cur_armor->o_ac = armors[cur_armor->o_which].a_class - | |
| 61 cur_armor->o_ac; | |
| 62 cur_armor->o_type = MM; | |
| 63 cur_armor->o_which = MM_PROTECT; | |
| 64 cur_armor->o_flags &= ~(ISPROT | ISKNOW | ISMETAL); | |
| 65 cur_misc[WEAR_CLOAK] = cur_armor; | |
| 66 cur_armor = NULL; | |
| 67 } | |
| 68 /* | |
| 69 * if he used to be a spell caster of some sort, kill the fuse | |
| 70 */ | |
| 71 if (player.t_ctype == C_MAGICIAN || player.t_ctype == C_RANGER) | |
| 72 extinguish(spell_recovery); | |
| 73 if (player.t_ctype == C_DRUID || player.t_ctype == C_RANGER) | |
| 74 extinguish(chant_recovery); | |
| 75 if ((player.t_ctype == C_CLERIC || player.t_ctype == C_PALADIN) && | |
| 76 !cur_relic[HEIL_ANKH]) | |
| 77 extinguish(prayer_recovery); | |
| 78 /* | |
| 79 * if he becomes a spell caster of some kind, give him a fuse | |
| 80 */ | |
| 81 if (newclass == C_MAGICIAN || newclass == C_RANGER) | |
| 82 fuse(spell_recovery, 0, SPELLTIME, AFTER); | |
| 83 if (newclass == C_DRUID || newclass == C_RANGER) | |
| 84 fuse(chant_recovery, 0, SPELLTIME, AFTER); | |
| 85 if ((newclass==C_CLERIC || newclass==C_PALADIN) && !cur_misc[HEIL_ANKH]) | |
| 86 fuse(prayer_recovery, 0, SPELLTIME, AFTER); | |
| 87 /* | |
| 88 * if he's changing from a fighter then may have to change | |
| 89 * his sword since only fighter can use two-handed | |
| 90 * and bastard swords | |
| 91 */ | |
| 92 if ((player.t_ctype == C_FIGHTER || | |
| 93 player.t_ctype == C_RANGER || | |
| 94 player.t_ctype == C_PALADIN) && | |
| 95 cur_weapon != NULL && | |
| 96 cur_weapon->o_type == WEAPON && | |
| 97 (cur_weapon->o_which== BASWORD || | |
| 98 cur_weapon->o_which== TWOSWORD ) && | |
| 99 !(newclass == C_FIGHTER || | |
| 100 newclass == C_RANGER || | |
| 101 newclass == C_PALADIN) && | |
| 102 !(newclass == C_ASSASIN && | |
| 103 cur_weapon->o_which == BASWORD)) | |
| 104 cur_weapon->o_which = SWORD; | |
| 105 | |
| 106 /* | |
| 107 * if he was a thief then take out the trap_look() daemon | |
| 108 */ | |
| 109 if (player.t_ctype == C_THIEF || | |
| 110 player.t_ctype == C_MONK || | |
| 111 player.t_ctype == C_ASSASIN) | |
| 112 kill_daemon(trap_look); | |
| 113 | |
| 114 /* | |
| 115 * if he becomes a thief then add the trap_look() daemon | |
| 116 */ | |
| 117 if (newclass == C_THIEF || newclass == C_ASSASIN || newclass == C_MONK) | |
| 118 daemon(trap_look, 0, AFTER); | |
| 119 char_type = player.t_ctype = newclass; | |
| 120 save = pstats.s_hpt; | |
| 121 max_stats.s_hpt = pstats.s_hpt = 0; | |
| 122 max_stats.s_lvl = pstats.s_lvl = 0; | |
| 123 max_stats.s_lvladj = pstats.s_lvladj = 0; | |
| 124 max_stats.s_exp = pstats.s_exp -= pstats.s_exp/10; | |
| 125 check_level(); | |
| 126 if (pstats.s_hpt > save) /* don't add to current hits */ | |
| 127 pstats.s_hpt = save; | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 /* | |
| 132 * Use the relic that our monster is wielding. | |
| 133 */ | |
| 134 m_use_relic(monster) | |
| 135 register struct thing *monster; | |
| 136 { | |
| 137 register struct object *obj; | |
| 138 | |
| 139 /* Make sure we really have it */ | |
| 140 if (monster->t_using) obj = OBJPTR(monster->t_using); | |
| 141 else { | |
| 142 debug("Relic not set!"); | |
| 143 monster->t_action = A_NIL; | |
| 144 return; | |
| 145 } | |
| 146 | |
| 147 /* Now let's see what we're using */ | |
| 148 if (obj->o_type == RELIC) switch (obj->o_which) { | |
| 149 case MING_STAFF: { | |
| 150 static struct object missile = { | |
| 151 MISSILE, {0,0}, "", 0, "", "0d4 " , NULL, 0, WS_MISSILE, 100, 1 | |
| 152 }; | |
| 153 | |
| 154 debug("Firing Ming's staff"); | |
| 155 sprintf(missile.o_hurldmg, "%dd4", monster->t_stats.s_lvl); | |
| 156 do_motion(&missile, | |
| 157 monster->t_newpos.y, monster->t_newpos.x, monster); | |
| 158 hit_monster(unc(missile.o_pos), &missile, monster); | |
| 159 monster->t_artifact = monster->t_artifact * 4 / 5; | |
| 160 } | |
| 161 when EMORI_CLOAK: | |
| 162 debug("stunning with Emori's cloak"); | |
| 163 do_zap(monster, obj, &monster->t_newpos, WS_PARALYZE, NULL); | |
| 164 obj->o_charges = 0; | |
| 165 | |
| 166 when ASMO_ROD: { | |
| 167 char *name; | |
| 168 | |
| 169 switch (rnd(3)) { /* Select a function */ | |
| 170 case 0: name = "lightning bolt"; | |
| 171 when 1: name = "flame"; | |
| 172 otherwise: name = "ice"; | |
| 173 } | |
| 174 shoot_bolt( monster, | |
| 175 monster->t_pos, | |
| 176 monster->t_newpos, | |
| 177 FALSE, | |
| 178 monster->t_index, | |
| 179 name, | |
| 180 roll(monster->t_stats.s_lvl,6)); | |
| 181 monster->t_artifact /= 2; | |
| 182 } | |
| 183 when BRIAN_MANDOLIN: | |
| 184 /* Make sure the defendant is still around */ | |
| 185 if (DISTANCE(monster->t_pos.y, monster->t_pos.x, | |
| 186 hero.y, hero.x) < 25) { | |
| 187 if (!save(VS_MAGIC, &player, -4) && | |
| 188 !ISWEARING(R_ALERT)) { | |
| 189 msg("Some beautiful music enthralls you."); | |
| 190 player.t_no_move += movement(&player) * FREEZETIME; | |
| 191 player.t_action = A_FREEZE; | |
| 192 monster->t_artifact = monster->t_artifact * 2 / 3; | |
| 193 } | |
| 194 else { | |
| 195 msg("You wince at a sour note."); | |
| 196 monster->t_artifact /= 3; | |
| 197 } | |
| 198 } | |
| 199 when GERYON_HORN: | |
| 200 /* Make sure the defendant is still around */ | |
| 201 if (DISTANCE(monster->t_pos.y, monster->t_pos.x, | |
| 202 hero.y, hero.x) < 25) { | |
| 203 if (!ISWEARING(R_HEROISM) && | |
| 204 !save(VS_MAGIC, &player, -4)) { | |
| 205 turn_on(player, ISFLEE); | |
| 206 player.t_dest = &monster->t_pos; | |
| 207 msg("A shrill blast terrifies you."); | |
| 208 monster->t_artifact = monster->t_artifact * 3 / 4; | |
| 209 } | |
| 210 else { | |
| 211 msg("A shrill blast sends chills up your spine."); | |
| 212 monster->t_artifact /= 3; | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 otherwise: | |
| 217 /* Unknown RELIC! */ | |
| 218 debug("Unknown wielded relic %d", obj->o_which); | |
| 219 } | |
| 220 else debug("Declared relic is %d", obj->o_type); | |
| 221 | |
| 222 turn_off(*monster, CANSURPRISE); | |
| 223 /* Reset the monsters actions */ | |
| 224 monster->t_action = A_NIL; | |
| 225 monster->t_using = NULL; | |
| 226 } | |
| 227 | |
| 228 /* | |
| 229 * add something to the contents of something else | |
| 230 */ | |
| 231 put_contents(bag, item) | |
| 232 register struct object *bag; /* the holder of the items */ | |
| 233 register struct linked_list *item; /* the item to put inside */ | |
| 234 { | |
| 235 register struct linked_list *titem; | |
| 236 register struct object *tobj; | |
| 237 | |
| 238 bag->o_ac++; | |
| 239 tobj = OBJPTR(item); | |
| 240 for (titem = bag->contents; titem != NULL; titem = next(titem)) { | |
| 241 if ((OBJPTR(titem))->o_which == tobj->o_which) | |
| 242 break; | |
| 243 } | |
| 244 if (titem == NULL) { /* if not a duplicate put at beginning */ | |
| 245 attach(bag->contents, item); | |
| 246 } | |
| 247 else { | |
| 248 item->l_prev = titem; | |
| 249 item->l_next = titem->l_next; | |
| 250 if (next(titem) != NULL) | |
| 251 (titem->l_next)->l_prev = item; | |
| 252 titem->l_next = item; | |
| 253 } | |
| 254 } | |
| 255 | |
| 256 /* | |
| 257 * remove something from something else | |
| 258 */ | |
| 259 take_contents(bag, item) | |
| 260 register struct object *bag; /* the holder of the items */ | |
| 261 register struct linked_list *item; | |
| 262 { | |
| 263 | |
| 264 if (bag->o_ac <= 0) { | |
| 265 msg("Nothing to take out"); | |
| 266 return; | |
| 267 } | |
| 268 bag->o_ac--; | |
| 269 detach(bag->contents, item); | |
| 270 if (!add_pack(item, FALSE, NULL)) | |
| 271 put_contents(bag, item); | |
| 272 } | |
| 273 | |
| 274 | |
| 275 do_bag(item) | |
| 276 register struct linked_list *item; | |
| 277 { | |
| 278 | |
| 279 register struct linked_list *titem; | |
| 280 register struct object *obj, *tobj; | |
| 281 bool doit = TRUE; | |
| 282 | |
| 283 obj = OBJPTR(item); | |
| 284 while (doit) { | |
| 285 msg("What do you want to do? (* for a list): "); | |
| 286 mpos = 0; | |
| 287 switch (readchar()) { | |
| 288 case EOF: | |
| 289 case ESCAPE: | |
| 290 msg (""); | |
| 291 doit = FALSE; | |
| 292 when '1': | |
| 293 inventory(obj->contents, ALL); | |
| 294 | |
| 295 when '2': | |
| 296 if (obj->o_ac >= MAXCONTENTS) { | |
| 297 msg("the %s is full", m_magic[obj->o_which].mi_name); | |
| 298 break; | |
| 299 } | |
| 300 switch (obj->o_which) { | |
| 301 case MM_BEAKER: | |
| 302 titem = get_item(pack, "put in", POTION, FALSE, FALSE); | |
| 303 when MM_BOOK: | |
| 304 titem = get_item(pack, "put in", SCROLL, FALSE, FALSE); | |
| 305 } | |
| 306 if (titem == NULL) | |
| 307 break; | |
| 308 detach(pack, titem); | |
| 309 inpack--; | |
| 310 put_contents(obj, titem); | |
| 311 | |
| 312 when '3': | |
| 313 titem = get_item(obj->contents,"take out",ALL,FALSE,FALSE); | |
| 314 if (titem == NULL) | |
| 315 break; | |
| 316 take_contents(obj, titem); | |
| 317 | |
| 318 when '4': | |
| 319 switch (obj->o_which) { | |
| 320 case MM_BEAKER: | |
| 321 titem = get_item(obj->contents,"quaff",ALL,FALSE,FALSE); | |
| 322 if (titem == NULL) | |
| 323 break; | |
| 324 tobj = OBJPTR(titem); | |
| 325 obj->o_ac--; | |
| 326 detach(obj->contents, titem); | |
| 327 quaff(tobj->o_which, | |
| 328 tobj->o_kind, | |
| 329 tobj->o_flags, | |
| 330 TRUE); | |
| 331 if (p_know[tobj->o_which] && p_guess[tobj->o_which]) | |
| 332 { | |
| 333 free(p_guess[tobj->o_which]); | |
| 334 p_guess[tobj->o_which] = NULL; | |
| 335 } | |
| 336 else if (!p_know[tobj->o_which] && | |
| 337 askme && | |
| 338 (tobj->o_flags & ISKNOW) == 0 && | |
| 339 (tobj->o_flags & ISPOST) == 0 && | |
| 340 p_guess[tobj->o_which] == NULL) { | |
| 341 nameitem(titem, FALSE); | |
| 342 } | |
| 343 o_discard(titem); | |
| 344 when MM_BOOK: | |
| 345 if (on(player, ISBLIND)) { | |
| 346 msg("You can't see to read anything"); | |
| 347 break; | |
| 348 } | |
| 349 titem = get_item(obj->contents,"read",ALL,FALSE,FALSE); | |
| 350 if (titem == NULL) | |
| 351 break; | |
| 352 tobj = OBJPTR(titem); | |
| 353 obj->o_ac--; | |
| 354 detach(obj->contents, titem); | |
| 355 read_scroll(tobj->o_which, | |
| 356 tobj->o_flags & (ISCURSED|ISBLESSED), | |
| 357 TRUE); | |
| 358 if (s_know[tobj->o_which] && s_guess[tobj->o_which]) | |
| 359 { | |
| 360 free(s_guess[tobj->o_which]); | |
| 361 s_guess[tobj->o_which] = NULL; | |
| 362 } | |
| 363 else if (!s_know[tobj->o_which] && | |
| 364 askme && | |
| 365 (tobj->o_flags & ISKNOW) == 0 && | |
| 366 (tobj->o_flags & ISPOST) == 0 && | |
| 367 s_guess[tobj->o_which] == NULL) { | |
| 368 nameitem(titem, FALSE); | |
| 369 } | |
