[BACK]Return to PowerTables.c CVS log [TXT][DIR] Up to [contributed] / brogue-ce / src / brogue

Annotation of brogue-ce/src/brogue/PowerTables.c, Revision 1.1

1.1     ! rubenllo    1: /*
        !             2:  *  PowerTables.c
        !             3:  *  Brogue
        !             4:  *
        !             5:  *  Created by Brian Walker on 4/9/17.
        !             6:  *  Copyright 2017. All rights reserved.
        !             7:  *
        !             8:  *  This file is part of Brogue.
        !             9:  *
        !            10:  *  This program is free software: you can redistribute it and/or modify
        !            11:  *  it under the terms of the GNU Affero General Public License as
        !            12:  *  published by the Free Software Foundation, either version 3 of the
        !            13:  *  License, or (at your option) any later version.
        !            14:  *
        !            15:  *  This program is distributed in the hope that it will be useful,
        !            16:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            17:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            18:  *  GNU Affero General Public License for more details.
        !            19:  *
        !            20:  *  You should have received a copy of the GNU Affero General Public License
        !            21:  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
        !            22:  */
        !            23:
        !            24: #include "Rogue.h"
        !            25:
        !            26: #define LAST_INDEX(a) (sizeof(a) / sizeof(fixpt) - 1)
        !            27:
        !            28: // As of v1.7.5, Brogue does not use floating-point math in any calculations
        !            29: // that have an effect on substantive gameplay. The two operations that were
        !            30: // annoying to convert were sqrt() (handled by an open source fixed point sqrt
        !            31: // implementation in Sqrt.c) and especially pow(). I could not find a fixed point
        !            32: // pow implementation that was good enough for the wide range of fractional bases
        !            33: // and exponents. Fortunately, all uses of pow() involved a fixed base and an exponent
        !            34: // that varied by increments of at least 0.25 (or really 0.1 for armor calculations but
        !            35: // I fudged that), or a fixed exponent and base that varied similarly. The one exception
        !            36: // were runic weapon activation chances, which modified the base by the damage of the weapon
        !            37: // and varied the exponent by the level, but I moved the damage modification into the exponent
        !            38: // without much affecting the results. So now pow() has been replaced by lookup tables.
        !            39: // Hopefully this will help with out of sync errors for saved games and recordings...
        !            40:
        !            41: // game data formulae:
        !            42:
        !            43: short wandDominate(creature *monst)                 {return (((monst)->currentHP * 5 < (monst)->info.maxHP) ? 100 : \
        !            44:                                                      max(0, 100 * ((monst)->info.maxHP - (monst)->currentHP) / (monst)->info.maxHP));}
        !            45:
        !            46: // All "enchant" parameters must already be multiplied by FP_FACTOR:
        !            47: short staffDamageLow(fixpt enchant)            {return ((int) ((2 + enchant / FP_FACTOR) * 3 / 4));}
        !            48: short staffDamageHigh(fixpt enchant)           {return ((int) (4 + (5 * enchant / FP_FACTOR / 2)));}
        !            49: short staffDamage(fixpt enchant)               {return ((int) randClumpedRange(staffDamageLow(enchant), staffDamageHigh(enchant), 1 + (enchant) / 3 / FP_FACTOR));}
        !            50: short staffBlinkDistance(fixpt enchant)        {return ((int) (2 + enchant * 2 / FP_FACTOR));}
        !            51: short staffHasteDuration(fixpt enchant)        {return ((int) (2 + enchant * 4 / FP_FACTOR));}
        !            52: short staffBladeCount(fixpt enchant)           {return ((int) (enchant * 3 / 2 / FP_FACTOR));}
        !            53: short staffDiscordDuration(fixpt enchant)      {return ((int) (enchant * 4 / FP_FACTOR));}
        !            54: short staffEntrancementDuration(fixpt enchant) {return ((int) (enchant * 3 / FP_FACTOR));}
        !            55: int staffProtection(fixpt enchant) {
        !            56:     return 130 * fp_pow(FP_FACTOR * 140 / 100, enchant / FP_FACTOR - 2) / FP_FACTOR;
        !            57: }
        !            58: int staffPoison(fixpt enchant) {
        !            59:     const fixpt POW_POISON[] = {
        !            60:         // 1.3^x fixed point, with x from 0 to 50 in increments of 1:
        !            61:         65536, 85196, 110755, 143982, 187177, 243330, 316329, 411228, 534597, 694976, 903469, 1174510, 1526863, 1984922, 2580398, 3354518, 4360874, 5669136, 7369877,
        !            62:         9580840, 12455093, 16191620, 21049107, 27363839, 35572991, 46244888, 60118355, 78153861, 101600020, 132080026, 171704034, 223215244, 290179818, 377233763,
        !            63:         490403892, 637525060, 828782579, 1077417352, 1400642558, 1820835326, 2367085924, 3077211701, 4000375211, 5200487775, 6760634107, 8788824340, 11425471642,
        !            64:         14853113134, 19309047075, 25101761197, 32632289557};
        !            65:
        !            66:     short idx = clamp(enchant / FP_FACTOR - 2, 0, LAST_INDEX(POW_POISON));
        !            67:     return 5 * POW_POISON[idx] / FP_FACTOR;
        !            68: }
        !            69:
        !            70: fixpt ringWisdomMultiplier(fixpt enchant) {
        !            71:     const fixpt POW_WISDOM[] = {
        !            72:         // 1.3^x fixed point, with x from -10 to 30 in increments of 1:
        !            73:         4753, 6180, 8034, 10444, 13577, 17650, 22945, 29829, 38778, 50412, 65536, 85196, 110755, 143982, 187177, 243330, 316329, 411228, 534597, 694976, 903469,
        !            74:         1174510, 1526863, 1984922, 2580398, 3354518, 4360874, 5669136, 7369877, 9580840, 12455093, 16191620, 21049107, 27363839, 35572991, 46244888, 60118355,
        !            75:         78153861, 101600020, 132080026, 171704034};
        !            76:
        !            77:     short idx = clamp(min(27, enchant / FP_FACTOR) + 10, 0, LAST_INDEX(POW_WISDOM));
        !            78:     return POW_WISDOM[idx];
        !            79: }
        !            80:
        !            81: short charmHealing(fixpt enchant)              {return ((int) clamp(20 * (enchant) / FP_FACTOR, 0, 100));}
        !            82: short charmShattering(fixpt enchant)           {return ((int) (4 + (enchant / FP_FACTOR)));}
        !            83: short charmGuardianLifespan(fixpt enchant)     {return ((int) (4 + 2 * (enchant / FP_FACTOR)));}
        !            84: short charmNegationRadius(fixpt enchant)       {return ((int) (1 + 3 * (enchant / FP_FACTOR)));}
        !            85: int charmProtection(fixpt enchant) {
        !            86:     const fixpt POW_CHARM_PROTECTION[] = {
        !            87:         // 1.35^x fixed point, with x from 0 to 50 in increments of 1:
        !            88:         65536, 88473, 119439, 161243, 217678, 293865, 396718, 535570, 723019, 976076, 1317703, 1778899, 2401514, 3242044, 4376759, 5908625, 7976644, 10768469,
        !            89:         14537434, 19625536, 26494473, 35767539, 48286178, 65186341, 88001560, 118802106, 160382844, 216516839, 292297733, 394601940, 532712620, 719162037, 970868750,
        !            90:         1310672812, 1769408297, 2388701201, 3224746621, 4353407939, 5877100717, 7934085969, 10711016058, 14459871678, 19520826766, 26353116134, 35576706781,
        !            91:         48028554155, 64838548109, 87532039948, 118168253930, 159527142806, 215361642788};
        !            92:
        !            93:     short idx = clamp(enchant / FP_FACTOR - 1, 0, LAST_INDEX(POW_CHARM_PROTECTION));
        !            94:     return 150 * POW_CHARM_PROTECTION[idx] / FP_FACTOR;
        !            95: }
        !            96:
        !            97: short weaponParalysisDuration(fixpt enchant)   {return (max(2, (int) (2 + ((enchant) / 2 / FP_FACTOR))));}
        !            98: short weaponConfusionDuration(fixpt enchant)   {return (max(3, (int) ((enchant) * 3/2 / FP_FACTOR)));}
        !            99: short weaponForceDistance(fixpt enchant)       {return (max(4, (int) (((enchant) * 2 / FP_FACTOR) + 2)));} // Depends on definition of staffBlinkDistance() above.
        !           100: short weaponSlowDuration(fixpt enchant)        {return (max(3, (int) ((((enchant) / FP_FACTOR) + 2) * ((enchant) + (2 * FP_FACTOR))) / 3 / FP_FACTOR));}
        !           101: short weaponImageCount(fixpt enchant)          {return (clamp((int) ((enchant) / 3 / FP_FACTOR), 1, 7));}
        !           102: short weaponImageDuration(fixpt enchant)       {return 3;}
        !           103:
        !           104: short armorReprisalPercent(fixpt enchant)      {return (max(5, (int) ((enchant) * 5 / FP_FACTOR)));}
        !           105: short armorAbsorptionMax(fixpt enchant)        {return (max(1, (int) ((enchant) / FP_FACTOR)));}
        !           106: short armorImageCount(fixpt enchant)           {return (clamp((int) ((enchant) / 3 / FP_FACTOR), 1, 5));}
        !           107: short reflectionChance(fixpt enchant) {
        !           108:     const fixpt POW_REFLECT[] = {
        !           109:         // 0.85^x fixed point, with x from 0.25 to 50 in increments of 0.25:
        !           110:         62926, 60421, 58015, 55705, 53487, 51358, 49313, 47349, 45464, 43654, 41916, 40247, 38644, 37106, 35628, 34210, 32848, 31540, 30284, 29078, 27920,
        !           111:         26809, 25741, 24716, 23732, 22787, 21880, 21009, 20172, 19369, 18598, 17857, 17146, 16464, 15808, 15179, 14574, 13994, 13437, 12902, 12388, 11895, 11421,
        !           112:         10967, 10530, 10111, 9708, 9321, 8950, 8594, 8252, 7923, 7608, 7305, 7014, 6735, 6466, 6209, 5962, 5724, 5496, 5278, 5067, 4866, 4672, 4486, 4307, 4136,
        !           113:         3971, 3813, 3661, 3515, 3375, 3241, 3112, 2988, 2869, 2755, 2645, 2540, 2439, 2341, 2248, 2159, 2073, 1990, 1911, 1835, 1762, 1692, 1624, 1559, 1497, 1438,
        !           114:         1380, 1325, 1273, 1222, 1173, 1127, 1082, 1039, 997, 958, 919, 883, 848, 814, 781, 750, 720, 692, 664, 638, 612, 588, 564, 542, 520, 500, 480, 461, 442,
        !           115:         425, 408, 391, 376, 361, 346, 333, 319, 307, 294, 283, 271, 261, 250, 240, 231, 221, 213, 204, 196, 188, 181, 173, 166, 160, 153, 147, 141, 136, 130, 125,
        !           116:         120, 115, 111, 106, 102, 98, 94, 90, 87, 83, 80, 77, 74, 71, 68, 65, 62, 60, 58, 55, 53, 51, 49, 47, 45, 43, 41, 40, 38, 37, 35, 34, 32, 31, 30, 29, 27,
        !           117:         26, 25, 24, 23, 22, 21, 21, 20, 19};
        !           118:
        !           119:     short idx = clamp(enchant * 4 / FP_FACTOR - 1, 0, LAST_INDEX(POW_REFLECT));
        !           120:     return clamp(100 - (100 * POW_REFLECT[idx] / FP_FACTOR), 1, 100);
        !           121: }
        !           122:
        !           123: long turnsForFullRegenInThousandths(fixpt bonus) {
        !           124:     const fixpt POW_REGEN[] = {
        !           125:         // 0.75^x fixed point, with x from -10 to 50 in increments of 1:
        !           126:         1163770, 872827, 654620, 490965, 368224, 276168, 207126, 155344, 116508, 87381, 65536, 49152, 36864, 27648, 20736, 15552, 11664, 8748, 6561, 4920, 3690,
        !           127:         2767, 2075, 1556, 1167, 875, 656, 492, 369, 277, 207, 155, 116, 87, 65, 49, 36, 27, 20, 15, 11, 8, 6, 4, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        !           128:
        !           129:     // This will max out at full regeneration in about two turns.
        !           130:     // This is the Syd nerf, after Syd broke the game over his knee with a +18 ring of regeneration.
        !           131:     short idx = clamp(bonus / FP_FACTOR + 10, 0, LAST_INDEX(POW_REGEN));
        !           132:     return (1000 * TURNS_FOR_FULL_REGEN * POW_REGEN[idx] / FP_FACTOR) + 2000;
        !           133: }
        !           134:
        !           135:
        !           136: fixpt damageFraction(fixpt netEnchant) {
        !           137:     const fixpt POW_DAMAGE_FRACTION[] = {
        !           138:         // 1.065^x fixed point, with x representing a change in 0.25 weapon enchantment points, ranging from -20 to 50.
        !           139:         18598, 18894, 19193, 19498, 19807, 20122, 20441, 20765, 21095, 21430, 21770, 22115, 22466, 22823, 23185, 23553, 23926, 24306, 24692, 25084, 25482, 25886,
        !           140:         26297, 26714, 27138, 27569, 28006, 28451, 28902, 29361, 29827, 30300, 30781, 31269, 31765, 32269, 32781, 33302, 33830, 34367, 34912, 35466, 36029, 36601,
        !           141:         37182, 37772, 38371, 38980, 39598, 40227, 40865, 41514, 42172, 42842, 43521, 44212, 44914, 45626, 46350, 47086, 47833, 48592, 49363, 50146, 50942, 51751,
        !           142:         52572, 53406, 54253, 55114, 55989, 56877, 57780, 58697, 59628, 60574, 61536, 62512, 63504, 64512, 65536, 66575, 67632, 68705, 69795, 70903, 72028, 73171,
        !           143:         74332, 75512, 76710, 77927, 79164, 80420, 81696, 82992, 84309, 85647, 87006, 88387, 89789, 91214, 92662, 94132, 95626, 97143, 98685, 100251, 101842, 103458,
        !           144:         105099, 106767, 108461, 110182, 111931, 113707, 115511, 117344, 119206, 121098, 123020, 124972, 126955, 128969, 131016, 133095, 135207, 137352, 139532,
        !           145:         141746, 143995, 146280, 148602, 150960, 153355, 155789, 158261, 160772, 163323, 165915, 168548, 171222, 173939, 176699, 179503, 182352, 185245, 188185,
        !           146:         191171, 194205, 197286, 200417, 203597, 206828, 210110, 213444, 216831, 220272, 223767, 227318, 230925, 234589, 238312, 242094, 245935, 249838, 253802,
        !           147:         257830, 261921, 266077, 270300, 274589, 278946, 283372, 287869, 292437, 297078, 301792, 306581, 311445, 316388, 321408, 326508, 331689, 336953, 342300,
        !           148:         347731, 353249, 358855, 364549, 370334, 376211, 382180, 388245, 394406, 400664, 407022, 413481, 420042, 426707, 433479, 440357, 447345, 454443, 461655,
        !           149:         468980, 476422, 483982, 491662, 499464, 507390, 515441, 523620, 531929, 540370, 548945, 557656, 566505, 575494, 584626, 593903, 603328, 612901, 622627,
        !           150:         632507, 642544, 652740, 663098, 673620, 684309, 695168, 706199, 717406, 728790, 740354, 752102, 764037, 776161, 788477, 800989, 813699, 826611, 839728,
        !           151:         853053, 866590, 880341, 894311, 908502, 922918, 937563, 952441, 967555, 982908, 998505, 1014350, 1030446, 1046797, 1063408, 1080282, 1097425, 1114839,
        !           152:         1132529, 1150501, 1168757, 1187303, 1206144, 1225283, 1244726, 1264478, 1284543, 1304927, 1325634, 1346669, 1368039, 1389747, 1411800, 1434203, 1456961,
        !           153:         1480081, 1503567, 1527426};
        !           154:
        !           155:     short idx = clamp(netEnchant * 4 / FP_FACTOR + 80, 0, LAST_INDEX(POW_DAMAGE_FRACTION));
        !           156:     return POW_DAMAGE_FRACTION[idx];
        !           157: }
        !           158:
        !           159: fixpt accuracyFraction(fixpt netEnchant) {
        !           160:     const fixpt POW_ACCURACY_FRACTION[] = {
        !           161:         // 1.065^x fixed point, with x representing a change in 0.25 weapon enchantment points (as displayed), ranging from -20 to 50.
        !           162:         18598, 18894, 19193, 19498, 19807, 20122, 20441, 20765, 21095, 21430, 21770, 22115, 22466, 22823, 23185, 23553, 23926, 24306, 24692, 25084, 25482, 25886,
        !           163:         26297, 26714, 27138, 27569, 28006, 28451, 28902, 29361, 29827, 30300, 30781, 31269, 31765, 32269, 32781, 33302, 33830, 34367, 34912, 35466, 36029, 36601,
        !           164:         37182, 37772, 38371, 38980, 39598, 40227, 40865, 41514, 42172, 42842, 43521, 44212, 44914, 45626, 46350, 47086, 47833, 48592, 49363, 50146, 50942, 51751,
        !           165:         52572, 53406, 54253, 55114, 55989, 56877, 57780, 58697, 59628, 60574, 61536, 62512, 63504, 64512, 65536, 66575, 67632, 68705, 69795, 70903, 72028, 73171,
        !           166:         74332, 75512, 76710, 77927, 79164, 80420, 81696, 82992, 84309, 85647, 87006, 88387, 89789, 91214, 92662, 94132, 95626, 97143, 98685, 100251, 101842, 103458,
        !           167:         105099, 106767, 108461, 110182, 111931, 113707, 115511, 117344, 119206, 121098, 123020, 124972, 126955, 128969, 131016, 133095, 135207, 137352, 139532,
        !           168:         141746, 143995, 146280, 148602, 150960, 153355, 155789, 158261, 160772, 163323, 165915, 168548, 171222, 173939, 176699, 179503, 182352, 185245, 188185,
        !           169:         191171, 194205, 197286, 200417, 203597, 206828, 210110, 213444, 216831, 220272, 223767, 227318, 230925, 234589, 238312, 242094, 245935, 249838, 253802,
        !           170:         257830, 261921, 266077, 270300, 274589, 278946, 283372, 287869, 292437, 297078, 301792, 306581, 311445, 316388, 321408, 326508, 331689, 336953, 342300,
        !           171:         347731, 353249, 358855, 364549, 370334, 376211, 382180, 388245, 394406, 400664, 407022, 413481, 420042, 426707, 433479, 440357, 447345, 454443, 461655,
        !           172:         468980, 476422, 483982, 491662, 499464, 507390, 515441, 523620, 531929, 540370, 548945, 557656, 566505, 575494, 584626, 593903, 603328, 612901, 622627,
        !           173:         632507, 642544, 652740, 663098, 673620, 684309, 695168, 706199, 717406, 728790, 740354, 752102, 764037, 776161, 788477, 800989, 813699, 826611, 839728,
        !           174:         853053, 866590, 880341, 894311, 908502, 922918, 937563, 952441, 967555, 982908, 998505, 1014350, 1030446, 1046797, 1063408, 1080282, 1097425, 1114839,
        !           175:         1132529, 1150501, 1168757, 1187303, 1206144, 1225283, 1244726, 1264478, 1284543, 1304927, 1325634, 1346669, 1368039, 1389747, 1411800, 1434203, 1456961,
        !           176:         1480081, 1503567, 1527426};
        !           177:
        !           178:     short idx = clamp(netEnchant * 4 / FP_FACTOR + 80, 0, LAST_INDEX(POW_ACCURACY_FRACTION));
        !           179:     return POW_ACCURACY_FRACTION[idx];
        !           180: }
        !           181:
        !           182: fixpt defenseFraction(fixpt netDefense) {
        !           183:     const fixpt POW_DEFENSE_FRACTION[] = {
        !           184:         // 0.877347265^x fixed point, with x representing a change in 0.25 armor points (as displayed), ranging from -20 to 50.
        !           185:         897530, 868644, 840688, 813632, 787446, 762103, 737575, 713837, 690863, 668629, 647110, 626283, 606127, 586619, 567740, 549468,
        !           186:         531784, 514669, 498105, 482074, 466559, 451543, 437011, 422946, 409334, 396160, 383410, 371071, 359128, 347570, 336384, 325558,
        !           187:         315080, 304940, 295125, 285627, 276435, 267538, 258927, 250594, 242529, 234724, 227169, 219858, 212782, 205934, 199306, 192892,
        !           188:         186684, 180676, 174861, 169233, 163786, 158515, 153414, 148476, 143698, 139073, 134597, 130265, 126073, 122015, 118088, 114288,
        !           189:         110609, 107050, 103604, 100270, 97043, 93920, 90897, 87971, 85140, 82400, 79748, 77181, 74697, 72293, 69967, 67715, 65536, 63426,
        !           190:         61385, 59409, 57497, 55647, 53856, 52123, 50445, 48822, 47250, 45730, 44258, 42833, 41455, 40121, 38829, 37580, 36370, 35200, 34067,
        !           191:         32970, 31909, 30882, 29888, 28926, 27995, 27094, 26222, 25378, 24562, 23771, 23006, 22266, 21549, 20855, 20184, 19535, 18906, 18297,
        !           192:         17709, 17139, 16587, 16053, 15536, 15036, 14552, 14084, 13631, 13192, 12768, 12357, 11959, 11574, 11201, 10841, 10492, 10154, 9828,
        !           193:         9511, 9205, 8909, 8622, 8345, 8076, 7816, 7565, 7321, 7085, 6857, 6637, 6423, 6216, 6016, 5823, 5635, 5454, 5278, 5108, 4944, 4785,
        !           194:         4631, 4482, 4337, 4198, 4063, 3932, 3805, 3683, 3564, 3450, 3339, 3231, 3127, 3026, 2929, 2835, 2744, 2655, 2570, 2487, 2407, 2329,
        !           195:         2255, 2182, 2112, 2044, 1978, 1914, 1853, 1793, 1735, 1679, 1625, 1573, 1522, 1473, 1426, 1380, 1336, 1293, 1251, 1211, 1172, 1134,
        !           196:         1097, 1062, 1028, 995, 963, 932, 902, 873, 845, 817, 791, 766, 741, 717, 694, 672, 650, 629, 609, 589, 570, 552, 534, 517, 500, 484,
        !           197:         469, 453, 439, 425, 411, 398, 385, 373, 361, 349, 338, 327, 316, 306, 296, 287, 277, 268, 260, 251, 243, 235, 228, 221, 213, 207,
        !           198:         200, 193, 187, 181, 175, 170, 164, 159, 154, 149, 144, 139, 135, 130, 126, 122, 118, 114, 111, 107, 104, 100, 97, 94};
        !           199:
        !           200:     short idx = clamp(netDefense * 4 / 10 / FP_FACTOR + 80, 0, LAST_INDEX(POW_DEFENSE_FRACTION));
        !           201:     return POW_DEFENSE_FRACTION[idx];
        !           202: }
        !           203:
        !           204: short charmEffectDuration(short charmKind, short enchant) {
        !           205:     const fixpt POW_0_CHARM_INCREMENT[] = { // 1.0
        !           206:         65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536,
        !           207:         65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536,
        !           208:         65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536};
        !           209:     const fixpt POW_120_CHARM_INCREMENT[] = { // 1.20^x fixed point, with x from 1 to 50 in increments of 1:
        !           210:         78643, 94371, 113246, 135895, 163074, 195689, 234827, 281792, 338151, 405781, 486937, 584325, 701190, 841428, 1009714, 1211657,
        !           211:         1453988, 1744786, 2093744, 2512492, 3014991, 3617989, 4341587, 5209905, 6251886, 7502263, 9002716, 10803259, 12963911, 15556694,
        !           212:         18668032, 22401639, 26881967, 32258360, 38710033, 46452039, 55742447, 66890937, 80269124, 96322949, 115587539, 138705047, 166446056,
        !           213:         199735268, 239682321, 287618785, 345142543, 414171051, 497005262, 596406314, 715687577};
        !           214:     const fixpt POW_125_CHARM_INCREMENT[] = { // 1.25^x fixed point, with x from 1 to 50 in increments of 1:
        !           215:         81920, 102400, 128000, 160000, 200000, 250000, 312500, 390625, 488281, 610351, 762939, 953674, 1192092, 1490116, 1862645, 2328306,
        !           216:         2910383, 3637978, 4547473, 5684341, 7105427, 8881784, 11102230, 13877787, 17347234, 21684043, 27105054, 33881317, 42351647, 52939559,
        !           217:         66174449, 82718061, 103397576, 129246970, 161558713, 201948391, 252435489, 315544362, 394430452, 493038065, 616297582, 770371977,
        !           218:         962964972, 1203706215, 1504632769, 1880790961, 2350988701, 2938735877, 3673419846, 4591774807, 5739718509};
        !           219:     const short duration[NUMBER_CHARM_KINDS] = {
        !           220:         3,  // Health
        !           221:         20, // Protection
        !           222:         7,  // Haste
        !           223:         10, // Fire immunity
        !           224:         5,  // Invisibility
        !           225:         25, // Telepathy
        !           226:         10, // Levitation
        !           227:         0,  // Shattering
        !           228:         18, // Guardian
        !           229:         0,  // Teleportation
        !           230:         0,  // Recharging
        !           231:         0,  // Negation
        !           232:     };
        !           233:     const fixpt *increment[NUMBER_CHARM_KINDS] = {
        !           234:         POW_0_CHARM_INCREMENT,      // Health
        !           235:         POW_0_CHARM_INCREMENT,      // Protection
        !           236:         POW_120_CHARM_INCREMENT,    // Haste
        !           237:         POW_125_CHARM_INCREMENT,    // Fire immunity
        !           238:         POW_120_CHARM_INCREMENT,    // Invisibility
        !           239:         POW_125_CHARM_INCREMENT,    // Telepathy
        !           240:         POW_125_CHARM_INCREMENT,    // Levitation
        !           241:         POW_0_CHARM_INCREMENT,      // Shattering
        !           242:         POW_0_CHARM_INCREMENT,      // Guardian
        !           243:         POW_0_CHARM_INCREMENT,      // Teleportation
        !           244:         POW_0_CHARM_INCREMENT,      // Recharging
        !           245:         POW_0_CHARM_INCREMENT,      // Negation
        !           246:     };
        !           247:
        !           248:     short idx = clamp(enchant - 1, 0, LAST_INDEX(POW_125_CHARM_INCREMENT));
        !           249:     return duration[charmKind] * increment[charmKind][idx] / FP_FACTOR;
        !           250: }
        !           251:
        !           252: short charmRechargeDelay(short charmKind, short enchant) {
        !           253:     const short duration[NUMBER_CHARM_KINDS] = {
        !           254:         2500,   // Health
        !           255:         1000,   // Protection
        !           256:         800,    // Haste
        !           257:         800,    // Fire immunity
        !           258:         800,    // Invisibility
        !           259:         800,    // Telepathy
        !           260:         800,    // Levitation
        !           261:         2500,   // Shattering
        !           262:         700,    // Guardian
        !           263:         920,    // Teleportation
        !           264:         10000,  // Recharging
        !           265:         2500,   // Negation
        !           266:     };
        !           267:     const fixpt base[NUMBER_CHARM_KINDS] = {
        !           268:         FP_FACTOR * 55 / 100, // Health
        !           269:         FP_FACTOR * 60 / 100, // Protection
        !           270:         FP_FACTOR * 65 / 100, // Haste
        !           271:         FP_FACTOR * 60 / 100, // Fire immunity
        !           272:         FP_FACTOR * 65 / 100, // Invisibility
        !           273:         FP_FACTOR * 65 / 100, // Telepathy
        !           274:         FP_FACTOR * 65 / 100, // Levitation
        !           275:         FP_FACTOR * 60 / 100, // Shattering
        !           276:         FP_FACTOR * 70 / 100, // Guardian
        !           277:         FP_FACTOR * 60 / 100, // Teleportation
        !           278:         FP_FACTOR * 55 / 100, // Recharging
        !           279:         FP_FACTOR * 60 / 100, // Negation
        !           280:     };
        !           281:
        !           282:     enchant = clamp(enchant, 1, 50);
        !           283:     short delay = charmEffectDuration(charmKind, enchant)
        !           284:         + (duration[charmKind] * fp_pow(base[charmKind], enchant) / FP_FACTOR);
        !           285:     return max(1, delay);
        !           286: }
        !           287:
        !           288: short runicWeaponChance(item *theItem, boolean customEnchantLevel, fixpt enchantLevel) {
        !           289:     const fixpt POW_16_RUNIC_DECREMENT[] = { // (1-0.16)^x fixed point, with x from 0 to 50 in increments of 0.25:
        !           290:         65536, 62740, 60064, 57502, 55050, 52702, 50454, 48302, 46242, 44269, 42381, 40574, 38843, 37186, 35600, 34082, 32628, 31236, 29904,
        !           291:         28629, 27407, 26238, 25119, 24048, 23022, 22040, 21100, 20200, 19339, 18514, 17724, 16968, 16244, 15551, 14888, 14253, 13645, 13063,
        !           292:         12506, 11972, 11462, 10973, 10505, 10057, 9628, 9217, 8824, 8448, 8087, 7742, 7412, 7096, 6793, 6503, 6226, 5961, 5706, 5463, 5230,
        !           293:         5007, 4793, 4589, 4393, 4206, 4026, 3854, 3690, 3533, 3382, 3238, 3100, 2967, 2841, 2720, 2604, 2492, 2386, 2284, 2187, 2094, 2004,
        !           294:         1919, 1837, 1759, 1684, 1612, 1543, 1477, 1414, 1354, 1296, 1241, 1188, 1137, 1089, 1042, 998, 955, 914, 875, 838, 802, 768, 735,
        !           295:         704, 674, 645, 617, 591, 566, 542, 519, 496, 475, 455, 436, 417, 399, 382, 366, 350, 335, 321, 307, 294, 281, 269, 258, 247, 236,
        !           296:         226, 217, 207, 198, 190, 182, 174, 167, 159, 153, 146, 140, 134, 128, 123, 117, 112, 108, 103, 99, 94, 90, 86, 83, 79, 76, 73, 69,
        !           297:         66, 64, 61, 58, 56, 53, 51, 49, 47, 45, 43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 18, 17, 16,
        !           298:         15, 15, 14, 13, 13, 12, 12, 11, 11, 10};
        !           299:     const fixpt POW_15_RUNIC_DECREMENT[] = { // (1-0.15)^x fixed point, with x from 0 to 50 in increments of 0.25:
        !           300:         65536, 62926, 60421, 58015, 55705, 53487, 51358, 49313, 47349, 45464, 43654, 41916, 40247, 38644, 37106, 35628, 34210, 32848, 31540,
        !           301:         30284, 29078, 27920, 26809, 25741, 24716, 23732, 22787, 21880, 21009, 20172, 19369, 18598, 17857, 17146, 16464, 15808, 15179, 14574,
        !           302:         13994, 13437, 12902, 12388, 11895, 11421, 10967, 10530, 10111, 9708, 9321, 8950, 8594, 8252, 7923, 7608, 7305, 7014, 6735, 6466, 6209,
        !           303:         5962, 5724, 5496, 5278, 5067, 4866, 4672, 4486, 4307, 4136, 3971, 3813, 3661, 3515, 3375, 3241, 3112, 2988, 2869, 2755, 2645, 2540,
        !           304:         2439, 2341, 2248, 2159, 2073, 1990, 1911, 1835, 1762, 1692, 1624, 1559, 1497, 1438, 1380, 1325, 1273, 1222, 1173, 1127, 1082, 1039,
        !           305:         997, 958, 919, 883, 848, 814, 781, 750, 720, 692, 664, 638, 612, 588, 564, 542, 520, 500, 480, 461, 442, 425, 408, 391, 376, 361, 346,
        !           306:         333, 319, 307, 294, 283, 271, 261, 250, 240, 231, 221, 213, 204, 196, 188, 181, 173, 166, 160, 153, 147, 141, 136, 130, 125, 120, 115,
        !           307:         111, 106, 102, 98, 94, 90, 87, 83, 80, 77, 74, 71, 68, 65, 62, 60, 58, 55, 53, 51, 49, 47, 45, 43, 41, 40, 38, 37, 35, 34, 32, 31, 30,
        !           308:         29, 27, 26, 25, 24, 23, 22, 21, 21, 20, 19};
        !           309:     const fixpt POW_14_RUNIC_DECREMENT[] = { // (1-0.14)^x fixed point, with x from 0 to 50 in increments of 0.25:
        !           310:         65536, 63110, 60775, 58526, 56360, 54275, 52267, 50332, 48470, 46676, 44949, 43286, 41684, 40142, 38656, 37226, 35848, 34522, 33244,
        !           311:         32014, 30829, 29689, 28590, 27532, 26513, 25532, 24587, 23677, 22801, 21958, 21145, 20363, 19609, 18883, 18185, 17512, 16864, 16240,
        !           312:         15639, 15060, 14503, 13966, 13449, 12952, 12472, 12011, 11566, 11138, 10726, 10329, 9947, 9579, 9224, 8883, 8554, 8238, 7933, 7639,
        !           313:         7357, 7084, 6822, 6570, 6327, 6092, 5867, 5650, 5441, 5239, 5046, 4859, 4679, 4506, 4339, 4179, 4024, 3875, 3732, 3593, 3460, 3332,
        !           314:         3209, 3090, 2976, 2866, 2760, 2658, 2559, 2465, 2373, 2285, 2201, 2119, 2041, 1965, 1893, 1823, 1755, 1690, 1628, 1567, 1509, 1454,
        !           315:         1400, 1348, 1298, 1250, 1204, 1159, 1116, 1075, 1035, 997, 960, 924, 890, 857, 825, 795, 765, 737, 710, 684, 658, 634, 610, 588, 566,
        !           316:         545, 525, 505, 487, 469, 451, 435, 418, 403, 388, 374, 360, 346, 334, 321, 309, 298, 287, 276, 266, 256, 247, 237, 229, 220, 212, 204,
        !           317:         197, 189, 182, 176, 169, 163, 157, 151, 145, 140, 135, 130, 125, 120, 116, 111, 107, 103, 99, 96, 92, 89, 85, 82, 79, 76, 73, 71, 68,
        !           318:         66, 63, 61, 58, 56, 54, 52, 50, 48, 47, 45, 43, 42, 40, 38, 37, 36, 34};
        !           319:     const fixpt POW_11_RUNIC_DECREMENT[] = { // (1-0.11)^x fixed point, with x from 0 to 50 in increments of 0.25:
        !           320:         65536, 63654, 61826, 60051, 58327, 56652, 55025, 53445, 51911, 50420, 48972, 47566, 46200, 44874, 43585, 42334, 41118, 39938, 38791,
        !           321:         37677, 36595, 35544, 34524, 33533, 32570, 31634, 30726, 29844, 28987, 28155, 27346, 26561, 25798, 25058, 24338, 23639, 22960, 22301,
        !           322:         21661, 21039, 20435, 19848, 19278, 18725, 18187, 17665, 17157, 16665, 16186, 15721, 15270, 14832, 14406, 13992, 13590, 13200, 12821,
        !           323:         12453, 12095, 11748, 11411, 11083, 10765, 10456, 10155, 9864, 9581, 9305, 9038, 8779, 8527, 8282, 8044, 7813, 7589, 7371, 7159, 6954,
        !           324:         6754, 6560, 6372, 6189, 6011, 5838, 5671, 5508, 5350, 5196, 5047, 4902, 4761, 4624, 4492, 4363, 4237, 4116, 3997, 3883, 3771, 3663,
        !           325:         3558, 3456, 3356, 3260, 3166, 3075, 2987, 2901, 2818, 2737, 2658, 2582, 2508, 2436, 2366, 2298, 2232, 2168, 2106, 2045, 1986, 1929,
        !           326:         1874, 1820, 1768, 1717, 1668, 1620, 1573, 1528, 1484, 1442, 1400, 1360, 1321, 1283, 1246, 1210, 1176, 1142, 1109, 1077, 1046, 1016,
        !           327:         987, 959, 931, 904, 878, 853, 829, 805, 782, 759, 737, 716, 696, 676, 656, 637, 619, 601, 584, 567, 551, 535, 520, 505, 490, 476, 462,
        !           328:         449, 436, 424, 412, 400, 388, 377, 366, 356, 345, 336, 326, 317, 307, 299, 290, 282, 274, 266, 258, 251, 243, 236, 230, 223, 217, 210,
        !           329:         204, 198, 193};
        !           330:     const fixpt POW_7_RUNIC_DECREMENT[] = { // (1-0.07)^x fixed point, with x from 0 to 50 in increments of 0.25:
        !           331:         65536, 64357, 63200, 62064, 60948, 59852, 58776, 57719, 56682, 55662, 54662, 53679, 52714, 51766, 50835, 49921, 49024, 48142, 47277,
        !           332:         46427, 45592, 44772, 43967, 43177, 42401, 41638, 40890, 40155, 39433, 38724, 38027, 37344, 36672, 36013, 35365, 34730, 34105, 33492,
        !           333:         32890, 32298, 31718, 31147, 30587, 30038, 29497, 28967, 28446, 27935, 27433, 26939, 26455, 25979, 25512, 25054, 24603, 24161, 23726,
        !           334:         23300, 22881, 22470, 22066, 21669, 21279, 20897, 20521, 20152, 19790, 19434, 19084, 18741, 18404, 18073, 17748, 17429, 17116, 16808,
        !           335:         16506, 16209, 15918, 15632, 15351, 15075, 14804, 14537, 14276, 14019, 13767, 13520, 13277, 13038, 12804, 12573, 12347, 12125, 11907,
        !           336:         11693, 11483, 11276, 11074, 10875, 10679, 10487, 10299, 10113, 9931, 9753, 9578, 9405, 9236, 9070, 8907, 8747, 8590, 8435, 8284, 8135,
        !           337:         7988, 7845, 7704, 7565, 7429, 7296, 7164, 7036, 6909, 6785, 6663, 6543, 6425, 6310, 6196, 6085, 5976, 5868, 5763, 5659, 5557, 5457,
        !           338:         5359, 5263, 5168, 5075, 4984, 4894, 4806, 4720, 4635, 4552, 4470, 4390, 4311, 4233, 4157, 4082, 4009, 3937, 3866, 3796, 3728, 3661,
        !           339:         3595, 3531, 3467, 3405, 3344, 3283, 3224, 3166, 3110, 3054, 2999, 2945, 2892, 2840, 2789, 2739, 2689, 2641, 2594, 2547, 2501, 2456,
        !           340:         2412, 2369, 2326, 2284, 2243, 2203, 2163, 2124, 2086, 2048, 2012, 1975, 1940, 1905, 1871, 1837, 1804, 1772, 1740};
        !           341:     const fixpt POW_6_RUNIC_DECREMENT[] = { // (1-0.06)^x fixed point, with x from 0 to 50 in increments of 0.25:
        !           342:         65536, 64530, 63539, 62564, 61603, 60658, 59727, 58810, 57907, 57018, 56143, 55281, 54433, 53597, 52774, 51964, 51167, 50381, 49608,
        !           343:         48846, 48097, 47358, 46631, 45916, 45211, 44517, 43833, 43161, 42498, 41846, 41203, 40571, 39948, 39335, 38731, 38137, 37551, 36975,
        !           344:         36407, 35848, 35298, 34756, 34223, 33698, 33180, 32671, 32169, 31676, 31189, 30711, 30239, 29775, 29318, 28868, 28425, 27989, 27559,
        !           345:         27136, 26719, 26309, 25905, 25508, 25116, 24731, 24351, 23977, 23609, 23247, 22890, 22539, 22193, 21852, 21516, 21186, 20861, 20541,
        !           346:         20225, 19915, 19609, 19308, 19012, 18720, 18433, 18150, 17871, 17597, 17327, 17061, 16799, 16541, 16287, 16037, 15791, 15549, 15310,
        !           347:         15075, 14843, 14616, 14391, 14170, 13953, 13739, 13528, 13320, 13116, 12914, 12716, 12521, 12329, 12139, 11953, 11770, 11589, 11411,
        !           348:         11236, 11063, 10894, 10726, 10562, 10400, 10240, 10083, 9928, 9776, 9625, 9478, 9332, 9189, 9048, 8909, 8772, 8638, 8505, 8374, 8246,
        !           349:         8119, 7995, 7872, 7751, 7632, 7515, 7400, 7286, 7174, 7064, 6956, 6849, 6744, 6640, 6538, 6438, 6339, 6242, 6146, 6052, 5959, 5867,
        !           350:         5777, 5688, 5601, 5515, 5430, 5347, 5265, 5184, 5105, 5026, 4949, 4873, 4798, 4725, 4652, 4581, 4510, 4441, 4373, 4306, 4240, 4175,
        !           351:         4111, 4047, 3985, 3924, 3864, 3805, 3746, 3689, 3632, 3576, 3521, 3467, 3414, 3362, 3310, 3259, 3209, 3160, 3111, 3064, 3017, 2970};
        !           352:     const fixpt *effectChances[NUMBER_WEAPON_RUNIC_KINDS] = {
        !           353:         POW_16_RUNIC_DECREMENT, // W_SPEED
        !           354:         POW_6_RUNIC_DECREMENT,  // W_QUIETUS
        !           355:         POW_7_RUNIC_DECREMENT,  // W_PARALYSIS
        !           356:         POW_15_RUNIC_DECREMENT, // W_MULTIPLICITY
        !           357:         POW_14_RUNIC_DECREMENT, // W_SLOWING
        !           358:         POW_11_RUNIC_DECREMENT, // W_CONFUSION
        !           359:         POW_15_RUNIC_DECREMENT, // W_FORCE
        !           360:         0,      // W_SLAYING
        !           361:         0,      // W_MERCY
        !           362:         0};     // W_PLENTY
        !           363:
        !           364:     fixpt modifier;
        !           365:     short runicType = theItem->enchant2;
        !           366:     short chance, adjustedBaseDamage, tableIndex;
        !           367:
        !           368:     if (runicType == W_SLAYING) {
        !           369:         return 0;
        !           370:     }
        !           371:     if (runicType >= NUMBER_GOOD_WEAPON_ENCHANT_KINDS) { // bad runic
        !           372:         return 15;
        !           373:     }
        !           374:     if (!customEnchantLevel) {
        !           375:         enchantLevel = netEnchant(theItem);
        !           376:     }
        !           377:
        !           378:     // Innately high-damage weapon types are less likely to trigger runic effects.
        !           379:     adjustedBaseDamage = (tableForItemCategory(theItem->category, NULL)[theItem->kind].range.lowerBound
        !           380:                           + tableForItemCategory(theItem->category, NULL)[theItem->kind].range.upperBound) / 2;
        !           381:
        !           382:     if (theItem->flags & ITEM_ATTACKS_STAGGER) {
        !           383:         adjustedBaseDamage /= 2; // Normalize as though they attacked once per turn instead of every other turn.
        !           384:     }
        !           385:     //    if (theItem->flags & ITEM_ATTACKS_QUICKLY) {
        !           386:     //      adjustedBaseDamage *= 2; // Normalize as though they attacked once per turn instead of twice per turn.
        !           387:     //  } // Testing disabling this for balance reasons...
        !           388:
        !           389:     modifier = FP_FACTOR - min((99 * FP_FACTOR)/100, (adjustedBaseDamage * FP_FACTOR) / 18);
        !           390:
        !           391:     if (enchantLevel < 0) {
        !           392:         chance = 0;
        !           393:     } else {
        !           394:         tableIndex = enchantLevel * modifier * 4 / FP_FACTOR / FP_FACTOR;
        !           395:         tableIndex = clamp(tableIndex, 0, LAST_INDEX(POW_16_RUNIC_DECREMENT));
        !           396:         chance = 100 - (short) (100LL * effectChances[runicType][tableIndex] / FP_FACTOR); // good runic
        !           397:     }
        !           398:
        !           399:     // Slow weapons get an adjusted chance of 1 - (1-p)^2 to reflect two bites at the apple instead of one.
        !           400:     if (theItem->flags & ITEM_ATTACKS_STAGGER) {
        !           401:         chance = 100 - (100 - chance) * (100 - chance) / 100;
        !           402:     }
        !           403:     // Fast weapons get an adjusted chance of 1 - sqrt(1-p) to reflect one bite at the apple instead of two.
        !           404:     if (theItem->flags & ITEM_ATTACKS_QUICKLY) {
        !           405:         chance = 100 * (FP_FACTOR - fp_sqrt(FP_FACTOR - (chance * FP_FACTOR)/100)) / FP_FACTOR;
        !           406:     }
        !           407:
        !           408:     // The lowest percent change that a weapon will ever have is its enchantment level (if greater than 0).
        !           409:     // That is so that even really heavy weapons will improve at least 1% per enchantment.
        !           410:     chance = clamp(chance, max(1, (short) (enchantLevel / FP_FACTOR)), 100);
        !           411:
        !           412:     return chance;
        !           413: }

CVSweb