Mercurial > hg > early-roguelike
comparison urogue/magic.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 |
comparison
equal
deleted
inserted
replaced
| 253:d9badb9c0179 | 256:c495a4f288c6 |
|---|---|
| 1 /* | |
| 2 magic.c - This file contains functions for casting magic spells | |
| 3 | |
| 4 UltraRogue: The Ultimate Adventure in the Dungeons of Doom | |
| 5 Copyright (C) 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 <stdlib.h> | |
| 20 #include <string.h> | |
| 21 #include <ctype.h> | |
| 22 #include "rogue.h" | |
| 23 | |
| 24 /* | |
| 25 Cost for each level of spells level: | |
| 26 */ | |
| 27 | |
| 28 static const int spell_cost[] = {1, 5, 17, 29, 53, 91, 159, 247, 396}; | |
| 29 | |
| 30 static struct spells monst_spells[] = | |
| 31 { | |
| 32 {5, S_SELFTELEP, SCR_MAGIC}, | |
| 33 {4, P_HEALING, POT_MAGIC | _TWO_}, | |
| 34 {3, P_REGENERATE, POT_MAGIC}, | |
| 35 {2, P_HEALING, POT_MAGIC}, | |
| 36 {4, P_HASTE, POT_MAGIC}, | |
| 37 {2, P_SEEINVIS, POT_MAGIC}, | |
| 38 {3, P_SHERO, POT_MAGIC}, | |
| 39 {5, P_PHASE, POT_MAGIC}, | |
| 40 {4, P_INVIS, POT_MAGIC}, | |
| 41 {4, WS_CANCEL, ZAP_MAGIC}, | |
| 42 | |
| 43 /* In reverse order of damage ability */ | |
| 44 {6, WS_ELECT, ZAP_MAGIC | _TWO_}, | |
| 45 {6, WS_FIRE, ZAP_MAGIC | _TWO_}, | |
| 46 {6, WS_COLD, ZAP_MAGIC | _TWO_}, | |
| 47 {6, WS_MISSILE, ZAP_MAGIC | _TWO_}, | |
| 48 {5, WS_ELECT, ZAP_MAGIC}, | |
| 49 {5, WS_FIRE, ZAP_MAGIC}, | |
| 50 {5, WS_COLD, ZAP_MAGIC}, | |
| 51 {4, WS_ELECT, ZAP_MAGIC | ISCURSED}, | |
| 52 {4, WS_FIRE, ZAP_MAGIC | ISCURSED}, | |
| 53 {4, WS_COLD, ZAP_MAGIC | ISCURSED}, | |
| 54 {3, WS_MISSILE, ZAP_MAGIC}, | |
| 55 {1, WS_MISSILE, ZAP_MAGIC | ISCURSED}, | |
| 56 | |
| 57 {-1, -1, 0} | |
| 58 }; | |
| 59 | |
| 60 /* | |
| 61 Spells that a player can cast Non-mus only know ISKNOW spells until found | |
| 62 in the dungeon. Special classes know their spells one level lower, and | |
| 63 blessed one above. | |
| 64 */ | |
| 65 | |
| 66 static struct spells player_spells[] = | |
| 67 { | |
| 68 {1, WS_KNOCK, ZAP_MAGIC | ISKNOW}, | |
| 69 {1, S_SUMFAMILIAR, SCR_MAGIC | SP_DRUID | SP_MAGIC | SP_CLERIC, SP_ILLUSION }, | |
| 70 {1, S_GFIND, SCR_MAGIC | ISKNOW}, | |
| 71 {1, P_MONSTDET, POT_MAGIC | ISKNOW | SP_DRUID}, | |
| 72 {1, P_TREASDET, POT_MAGIC | ISKNOW | SP_MAGIC}, | |
| 73 {1, S_FOODDET, SCR_MAGIC | ISKNOW | SP_CLERIC}, | |
| 74 {1, S_LIGHT, SCR_MAGIC | ISKNOW | SP_ILLUSION}, | |
| 75 | |
| 76 {2, WS_CLOSE, ZAP_MAGIC | ISKNOW}, | |
| 77 {2, S_IDENTIFY, SCR_MAGIC | ISKNOW}, | |
| 78 {2, WS_HIT, ZAP_MAGIC | ISKNOW | SP_PRAYER}, | |
| 79 {2, P_SHIELD, POT_MAGIC | ISKNOW | SP_MAGIC}, | |
| 80 {2, P_COLDRESIST, POT_MAGIC | SP_WIZARD}, | |
| 81 {2, P_SEEINVIS, POT_MAGIC | SP_ILLUSION}, | |
| 82 {2, S_CONFUSE, SCR_MAGIC | SP_CLERIC}, | |
| 83 {2, P_SMELL, POT_MAGIC | SP_DRUID}, | |
| 84 {2, WS_MISSILE, ZAP_MAGIC | SP_MAGIC}, | |
| 85 {2, P_HEAR, POT_MAGIC}, | |
| 86 | |
| 87 {3, P_CLEAR, POT_MAGIC | ISKNOW}, | |
| 88 {3, P_HEALING, POT_MAGIC | ISKNOW | SP_PRAYER}, | |
| 89 {3, S_CURING, SCR_MAGIC | ISKNOW | SP_PRAYER}, | |
| 90 {3, WS_MONSTELEP, ZAP_MAGIC | SP_MAGIC}, | |
| 91 {3, WS_CANCEL, ZAP_MAGIC | SP_WIZARD}, | |
| 92 {3, S_SELFTELEP, SCR_MAGIC | SP_WIZARD}, | |
| 93 {3, P_FIRERESIST, POT_MAGIC | SP_WIZARD | SP_DRUID}, | |
| 94 {3, S_MAP, SCR_MAGIC | SP_ILLUSION | SP_DRUID}, | |
| 95 {3, S_REMOVECURSE, SCR_MAGIC | SP_PRAYER}, | |
| 96 {3, S_HOLD, SCR_MAGIC | SP_CLERIC}, | |
| 97 {3, S_SLEEP, SCR_MAGIC | SP_DRUID}, | |
| 98 {3, P_HASOXYGEN, POT_MAGIC | SP_DRUID}, | |
| 99 {3, WS_XENOHEALING, ZAP_MAGIC | SP_DRUID}, | |
| 100 {3, P_RESTORE, POT_MAGIC}, | |
| 101 | |
| 102 {4, S_MSHIELD, SCR_MAGIC | ISKNOW | SP_ILLUSION}, | |
| 103 {4, P_INVIS, POT_MAGIC | SP_ILLUSION}, | |
| 104 {4, S_REFLECT, SCR_MAGIC | SP_ILLUSION}, | |
| 105 {4, P_TRUESEE, POT_MAGIC | SP_ILLUSION}, | |
| 106 {4, P_REGENERATE, POT_MAGIC | SP_CLERIC}, | |
| 107 {4, WS_DRAIN, ZAP_MAGIC | SP_CLERIC}, | |
| 108 {4, P_HASTE, POT_MAGIC | SP_ILLUSION | SP_CLERIC}, | |
| 109 {4, P_LEVITATION, POT_MAGIC | SP_WIZARD | SP_DRUID}, | |
| 110 {4, WS_WEB, ZAP_MAGIC | SP_MAGIC}, | |
| 111 {4, P_PHASE, POT_MAGIC}, | |
| 112 | |
| 113 {5, P_SHERO, POT_MAGIC | ISKNOW}, | |
| 114 {5, S_PETRIFY, SCR_MAGIC | SP_MAGIC}, | |
| 115 {5, S_SCARE, SCR_MAGIC | _TWO_ | SP_PRAYER}, | |
| 116 {5, WS_COLD, ZAP_MAGIC | SP_DRUID}, | |
| 117 {5, WS_FIRE, ZAP_MAGIC | SP_CLERIC}, | |
| 118 {5, WS_ELECT, ZAP_MAGIC | SP_WIZARD}, | |
| 119 {5, WS_ANTIMATTER, ZAP_MAGIC | SP_ILLUSION}, | |
| 120 {5, S_ELECTRIFY, SCR_MAGIC | SP_ILLUSION}, | |
| 121 | |
| 122 {6, WS_DISINTEGRATE, ZAP_MAGIC | ISKNOW}, | |
| 123 {6, S_OWNERSHIP, SCR_MAGIC | SP_ALL}, | |
| 124 | |
| 125 {7, S_ENCHANT, SCR_MAGIC | SP_MAGIC}, | |
| 126 | |
| 127 {-1, -1, 0} | |
| 128 }; | |
| 129 | |
| 130 /* | |
| 131 incant() | |
| 132 Cast a spell | |
| 133 */ | |
| 134 | |
| 135 void | |
| 136 incant(struct thing *caster, coord dir) | |
| 137 { | |
| 138 int i; | |
| 139 struct stats *curp; | |
| 140 struct stats *maxp; | |
| 141 int is_player = (caster == &player); | |
| 142 int points_casters; | |
| 143 char *casters_name = (on(player, ISBLIND)) ? "it" : | |
| 144 monsters[caster->t_index].m_name; | |
| 145 struct spells *sp; | |
| 146 char *cast_name; /* = spell_name(sp) */ | |
| 147 char *spell_type; /* spell or prayer */ | |
| 148 int casting_cost; /* from spell_cost[] */ | |
| 149 int spell_roll; /* sucess/fail 1D100 die roll */ | |
| 150 int fumble_chance; /* Spell fumble chance */ | |
| 151 int num_fumbles = 0; /* for fumble_spell() */ | |
| 152 int bless_or_curse = ISNORMAL; /* blessed or cursed? */ | |
| 153 int message_flags = CAST_NORMAL; /* which message to print out */ | |
| 154 int class_casters; /* For determining ISKNOW */ | |
| 155 int stat_casters; /* s_intel or s_wisdom */ | |
| 156 int level_casters; /* spellcasting level */ | |
| 157 char buf[2 * LINELEN]; | |
| 158 struct spells sorted_spells[MAX_SPELLS]; | |
| 159 char spellbuf[2 * LINELEN]; | |
| 160 char spellbuf2[2 * LINELEN]; | |
| 161 | |
| 162 curp = &(caster->t_stats); | |
| 163 maxp = &(caster->maxstats); | |
| 164 points_casters = curp->s_power; | |
| 165 | |
| 166 if (points_casters <= 0) | |
| 167 { | |
| 168 if (is_player) | |
| 169 msg("You don't have any spell points."); | |
| 170 | |
| 171 return; | |
| 172 } | |
| 173 | |
| 174 /* | |
| 175 * Paladins, Rangers, ringwearers, and monsters cast at 4 levels | |
| 176 * below. Other non-specialists at 8 below | |
| 177 */ | |
| 178 | |
| 179 level_casters = curp->s_lvl; | |
| 180 | |
| 181 switch (caster->t_ctype) | |
| 182 { | |
| 183 case C_PALADIN: | |
| 184 level_casters -= 4; | |
| 185 /* fallthrough */ | |
| 186 case C_CLERIC: | |
| 187 class_casters = SP_CLERIC; | |
| 188 stat_casters = curp->s_wisdom; | |
| 189 break; | |
| 190 case C_RANGER: | |
| 191 level_casters -= 4; | |
| 192 /* fallthrough */ | |
| 193 case C_DRUID: | |
| 194 class_casters = SP_DRUID; | |
| 195 stat_casters = curp->s_wisdom; | |
| 196 break; | |
| 197 case C_MAGICIAN: | |
| 198 class_casters = SP_WIZARD; | |
| 199 stat_casters = curp->s_intel; | |
| 200 break; | |
| 201 case C_ILLUSION: | |
| 202 class_casters = SP_ILLUSION; | |
| 203 stat_casters = curp->s_intel; | |
| 204 break; | |
| 205 case C_MONSTER: | |
| 206 if (off(*caster, ISUNIQUE)) | |
| 207 level_casters -= 4; | |
| 208 class_casters = 0x0; | |
| 209 stat_casters = curp->s_intel; | |
| 210 break; | |
| 211 | |
| 212 default: | |
| 213 if (is_wearing(R_WIZARD)) | |
| 214 { | |
| 215 level_casters -= 4; | |
| 216 class_casters = (rnd(4) ? SP_WIZARD : SP_ILLUSION); | |
| 217 stat_casters = curp->s_intel; | |
| 218 } | |
| 219 else if (is_wearing(R_PIETY)) | |
| 220 { | |
| 221 level_casters -= 4; | |
| 222 class_casters = (rnd(4) ? SP_CLERIC : SP_DRUID); | |
| 223 stat_casters = curp->s_wisdom; | |
| 224 } | |
| 225 else | |
| 226 { | |
| 227 level_casters -= 8; | |
| 228 class_casters = 0x0; | |
| 229 stat_casters = (rnd(2) ? curp->s_wisdom : curp->s_intel); | |
| 230 } | |
| 231 } | |
| 232 | |
| 233 /* Bug - What about when WIS == INT? */ | |
| 234 | |
| 235 spell_type = (stat_casters == curp->s_intel) ? "spell" : "prayer"; | |
| 236 | |
| 237 if (!is_player && (sp = pick_monster_spell(caster)) == NULL) | |
| 238 return; | |
| 239 else if (is_player) | |
| 240 { | |
| 241 int num_spells = -1; /* num of spells cheap enough */ | |
| 242 | |
| 243 sorted_spells[0].sp_cost = -1; | |
| 244 | |
| 245 for (sp = player_spells; sp->sp_level != -1; sp++) | |
| 246 { | |
| 247 if (sp->sp_flags & class_casters) /* Does class know spell? */ | |
| 248 { | |
| 249 int rnd_number = rnd(2 * sp->sp_level) - sp->sp_level; | |
| 250 | |
| 251 /* Knows normal spell one level below others */ | |
| 252 | |
| 253 casting_cost = spell_cost[sp->sp_level - 1] + rnd_number; | |
| 254 | |
| 255 if (points_casters >= casting_cost) | |
| 256 { | |
| 257 sorted_spells[++num_spells] = *sp; | |
| 258 sorted_spells[num_spells].sp_cost = casting_cost; | |
| 259 sorted_spells[num_spells].sp_level = sp->sp_level - 1; | |
| 260 } | |
| 261 | |
| 262 /* Knows blessed spell one level above others */ | |
| 263 | |
| 264 casting_cost = spell_cost[sp->sp_level + 1] + rnd_number; | |
| 265 | |
| 266 if (points_casters >= casting_cost) | |
| 267 { | |
| 268 sorted_spells[++num_spells] = *sp; | |
| 269 sorted_spells[num_spells].sp_level = sp->sp_level + 1; | |
| 270 sorted_spells[num_spells].sp_cost = casting_cost; | |
| 271 sorted_spells[num_spells].sp_flags |= ISBLESSED; | |
| 272 } | |
| 273 } /* If class doesn't know spell, see if its a ISKNOW */ | |
| 274 else if (sp->sp_flags & ISKNOW) | |
| 275 { | |
| 276 int rnd_number = rnd(4 * sp->sp_level) - sp->sp_level; | |
| 277 | |
| 278 casting_cost = spell_cost[sp->sp_level] + rnd_number; | |
| 279 | |
| 280 if (points_casters >= casting_cost) | |
| 281 { | |
| 282 sorted_spells[++num_spells] = *sp; | |
| 283 sorted_spells[num_spells].sp_cost = casting_cost; | |
| 284 } | |
| 285 } | |
| 286 /* else this spell is unknown */ | |
| 287 } | |
| 288 | |
| 289 if (sorted_spells[0].sp_cost == -1) | |
| 290 { | |
| 291 msg("You don't have enough %s points.", spell_type); | |
| 292 after = FALSE; | |
| 293 return; | |
| 294 } | |
| 295 | |
| 296 qsort(sorted_spells,num_spells + 1,sizeof(struct spells),sort_spells); | |
| 297 | |
| 298 do /* Prompt for spells */ | |
| 299 { | |
| 300 struct spells *which_spell = NULL; | |
| 301 | |
| 302 buf[0] = '\0'; | |
| 303 msg("");/* Get rid of --More-- */ | |
| 304 msg("Which %s are you casting [%d points left] (* for list)? ", | |
| 305 spell_type, points_casters); | |
| 306 | |
| 307 switch(get_string(buf, cw)) | |
| 308 { | |
| 309 case NORM: break; | |
| 310 case QUIT: return; /* ESC - lose turn */ | |
| 311 default: continue; | |
| 312 } | |
| 313 | |
| 314 if (buf[0] == '*') /* print list */ | |
| 315 { | |
| 316 add_line("Cost Abbreviation Full Name"); | |
| 317 | |
| 318 for (i = 0; i <= num_spells; i++) | |
| 319 { | |
| 320 sp = &sorted_spells[i]; | |
| 321 sprintf(buf, "[%3d] %-12s\t%s", | |
| 322 sp->sp_cost, spell_abrev(sp,spellbuf2), | |
| 323 spell_name(sp,spellbuf)); | |
| 324 add_line(buf); | |
| 325 } | |
| 326 end_line(); | |
| 327 sp = NULL; | |
| 328 continue; | |
| 329 } | |
| 330 | |
| 331 if (isupper(buf[0])) /* Uppercase Abbreviation */ | |
| 332 { | |
| 333 for (i = 0; i <= num_spells; i++) | |
| 334 { | |
| 335 sp = &sorted_spells[i]; | |
| 336 | |
| 337 if ((strcmp(spell_abrev(sp,spellbuf2), buf) == 0)) | |
| 338 { | |
| 339 which_spell = sp; | |
| 340 break; | |
| 341 } | |
| 342 } | |
| 343 } | |
| 344 else /* Full Spell Name */ | |
| 345 { | |
| 346 for (i = 0; i <= num_spells; i++) | |
| 347 { | |
| 348 sp = &sorted_spells[i]; | |
| 349 | |
| 350 if ((strcmp(spell_name(sp,spellbuf), buf) == 0)) | |
| 351 { | |
| 352 which_spell = sp; | |
| 353 break; | |
| 354 } | |
| 355 } | |
| 356 } | |
| 357 | |
| 358 sp = which_spell; | |
| 359 } | |
| 360 while (sp == NULL); | |
