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