Angband Forums

Angband Forums (http://angband.oook.cz/forum/index.php)
-   Vanilla (http://angband.oook.cz/forum/forumdisplay.php?f=3)
-   -   Blows tables (http://angband.oook.cz/forum/showthread.php?t=9077)

wobbly September 20, 2018 19:26

Blows tables
 
Someone asked, so here they are. These are all from player-calcs.c, the multipliers & minimum weight are in class.txt

As you can see there are instructions to read it, though how easy they are to follow...

Code:

/**
 * This table is used to help calculate the number of blows the player can
 * make in a single round of attacks (one player turn) with a normal weapon.
 *
 * This number ranges from a single blow/round for weak players to up to six
 * blows/round for powerful warriors.
 *
 * Note that certain artifacts and ego-items give "bonus" blows/round.
 *
 * First, from the player class, we extract some values:
 *
 *    Warrior --> num = 6; mul = 5; div = MAX(30, weapon_weight);
 *    Mage    --> num = 4; mul = 2; div = MAX(40, weapon_weight);
 *    Priest  --> num = 4; mul = 3; div = MAX(35, weapon_weight);
 *    Rogue  --> num = 5; mul = 4; div = MAX(30, weapon_weight);
 *    Ranger  --> num = 5; mul = 4; div = MAX(35, weapon_weight);
 *    Paladin --> num = 5; mul = 5; div = MAX(30, weapon_weight);
 * (all specified in class.txt now)
 *
 * To get "P", we look up the relevant "adj_str_blow[]" (see above),
 * multiply it by "mul", and then divide it by "div", rounding down.
 *
 * To get "D", we look up the relevant "adj_dex_blow[]" (see above).
 *
 * Then we look up the energy cost of each blow using "blows_table[P][D]".
 * The player gets blows/round equal to 100/this number, up to a maximum of
 * "num" blows/round, plus any "bonus" blows/round.
 */
static const int blows_table[12][12] =
{
        /* P */
  /* D:  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10,  11+ */
  /* DEX: 3,  10,  17,  /20, /40, /60, /80, /100,/120,/150,/180,/200 */

        /* 0  */
        {  100, 100, 95,  85,  75,  60,  50,  42,  35,  30,  25,  23 },

        /* 1  */
        {  100, 95,  85,  75,  60,  50,  42,  35,  30,  25,  23,  21 },

        /* 2  */
        {  95,  85,  75,  60,  50,  42,  35,  30,  26,  23,  21,  20 },

        /* 3  */
        {  85,  75,  60,  50,  42,  36,  32,  28,  25,  22,  20,  19 },

        /* 4  */
        {  75,  60,  50,  42,  36,  33,  28,  25,  23,  21,  19,  18 },

        /* 5  */
        {  60,  50,  42,  36,  33,  30,  27,  24,  22,  21,  19,  17 },

        /* 6  */
        {  50,  42,  36,  33,  30,  27,  25,  23,  21,  20,  18,  17 },

        /* 7  */
        {  42,  36,  33,  30,  28,  26,  24,  22,  20,  19,  18,  17 },

        /* 8  */
        {  36,  33,  30,  28,  26,  24,  22,  21,  20,  19,  17,  16 },

        /* 9  */
        {  35,  32,  29,  26,  24,  22,  21,  20,  19,  18,  17,  16 },

        /* 10 */
        {  34,  30,  27,  25,  23,  22,  21,  20,  19,  18,  17,  16 },

        /* 11+ */
        {  33,  29,  26,  24,  22,  21,  20,  19,  18,  17,  16,  15 },
  /* DEX: 3,  10,  17,  /20, /40, /60, /80, /100,/120,/150,/180,/200 */

Code:

/**
 * Stat Table (STR) -- help index into the "blow" table
 */
const int adj_str_blow[STAT_RANGE] =
{
        3        /* 3 */,
        4        /* 4 */,
        5        /* 5 */,
        6        /* 6 */,
        7        /* 7 */,
        8        /* 8 */,
        9        /* 9 */,
        10        /* 10 */,
        11        /* 11 */,
        12        /* 12 */,
        13        /* 13 */,
        14        /* 14 */,
        15        /* 15 */,
        16        /* 16 */,
        17        /* 17 */,
        20 /* 18/00-18/09 */,
        30 /* 18/10-18/19 */,
        40 /* 18/20-18/29 */,
        50 /* 18/30-18/39 */,
        60 /* 18/40-18/49 */,
        70 /* 18/50-18/59 */,
        80 /* 18/60-18/69 */,
        90 /* 18/70-18/79 */,
        100 /* 18/80-18/89 */,
        110 /* 18/90-18/99 */,
        120 /* 18/100-18/109 */,
        130 /* 18/110-18/119 */,
        140 /* 18/120-18/129 */,
        150 /* 18/130-18/139 */,
        160 /* 18/140-18/149 */,
        170 /* 18/150-18/159 */,
        180 /* 18/160-18/169 */,
        190 /* 18/170-18/179 */,
        200 /* 18/180-18/189 */,
        210 /* 18/190-18/199 */,
        220 /* 18/200-18/209 */,
        230 /* 18/210-18/219 */,
        240 /* 18/220+ */
};

Code:

/**
 * Stat Table (DEX) -- index into the "blow" table
 */
static const int adj_dex_blow[STAT_RANGE] =
{
        0        /* 3 */,
        0        /* 4 */,
        0        /* 5 */,
        0        /* 6 */,
        0        /* 7 */,
        0        /* 8 */,
        0        /* 9 */,
        1        /* 10 */,
        1        /* 11 */,
        1        /* 12 */,
        1        /* 13 */,
        1        /* 14 */,
        1        /* 15 */,
        1        /* 16 */,
        2        /* 17 */,
        2        /* 18/00-18/09 */,
        2        /* 18/10-18/19 */,
        3        /* 18/20-18/29 */,
        3        /* 18/30-18/39 */,
        4        /* 18/40-18/49 */,
        4        /* 18/50-18/59 */,
        5        /* 18/60-18/69 */,
        5        /* 18/70-18/79 */,
        6        /* 18/80-18/89 */,
        6        /* 18/90-18/99 */,
        7        /* 18/100-18/109 */,
        7        /* 18/110-18/119 */,
        8        /* 18/120-18/129 */,
        8        /* 18/130-18/139 */,
        8        /* 18/140-18/149 */,
        9        /* 18/150-18/159 */,
        9        /* 18/160-18/169 */,
        9        /* 18/170-18/179 */,
        10        /* 18/180-18/189 */,
        10        /* 18/190-18/199 */,
        11        /* 18/200-18/209 */,
        11        /* 18/210-18/219 */,
        11        /* 18/220+ */
};


gglibertine September 23, 2018 15:22

Thanks for posting. I'm going to enlist my husband (who does code) to help me decipher this.

AnonymousHero September 23, 2018 20:19

Quote:

Originally Posted by gglibertine (Post 133404)
Thanks for posting. I'm going to enlist my husband (who does code) to help me decipher this.

I hope he has the patience of a saint because it's infuriatingly indirect. Yes, it's "only" two levels at first sight, but then you realize that there are the two dimensions of STR/DEX... The quickest way (for me) was honestly just putting DEX+STR + the tables into a spreadsheet and doing the weird "indexing dance" from there. (That doesn't help you optimize, directly, but at least you can do hypotheticals pretty easily.)

This mess could really stand to be simplified, especially given that these numbers seem quite arbitrary. (Of course, it might have been originally derived from a function, but saved as concrete numbers. Even if it happened in the 1980s I'm not sure if there's any excuse for not just having that in the code and pre-computing the tables on startup, so this parenthetical hypothesis seems kind of dubious...)

Werbaer September 27, 2018 11:37

Quote:

Originally Posted by AnonymousHero (Post 133407)
This mess could really stand to be simplified, especially given that these numbers seem quite arbitrary. (Of course, it might have been originally derived from a function, but saved as concrete numbers.

Edit: Disregard this comment. As wobbly pointed out, i looked at the wrong table.

Comment from an old version:
Code:

* This table allows quick conversion from "speed" to "energy"
 * The basic function WAS ((S>=110) ? (S-110) : (100 / (120-S)))
 * Note that table access is *much* quicker than computation.
 *
 * Note that the table has been changed at high speeds.  From
 * "Slow (-40)" to "Fast (+30)" is pretty much unchanged, but
 * at speeds above "Fast (+30)", one approaches an asymptotic
 * effective limit of 50 energy per turn.


wobbly September 27, 2018 11:46

That's the speed tables isn't it? A different table for showing how much energy you gain/turn at various speeds.

Derakon September 27, 2018 15:31

Ahh, the days when the performance implications of table lookup vs. doing division was an issue that deserved serious consideration.

wobbly September 27, 2018 19:28

Perhaps an example is helpful? A human warrior with recommended stats:
18/20 str
18/20 dex
dagger weight is 12 deci-pounds, however Min warrior weight for calculations is 30.
warrior class multiplier = 5

Looking up 18/20 dex in the 3rd table (dex index) we get 3. That is the column number. Looking at table 1, column 3 you will see it's actually got 18/20 dex written on it.

Looking up 18/20 str in the 2nd table we get 40.
40 x 5 = 200 ( adj_str x class multiplier)
200 / 30 = 6.66 (adj_str x class multiplier / weapon weight)
we round down - row 6

reading column 3, row 6 we get 33. This is energy/blow. 3 blows would take 99 energy.

You get your turn when energy reaches 100 (You & all monsters gain energy every "game tick" depending on speed, this is the table Werbaer mentioned). So our warrior gets 3 blows spending 99 energy then waits for his/her energy to reach 100 again. If he/she kills something with 2 blows he/she spends 66 energy instead (I believe you don't get the final blow till you reach 100 again but would have to check)

Note 1.5 blows (66 energy/turn) technically means 1 blow costing 66 energy. If you were dead on 100 energy, you'd hit once and spend 66 leaving 34 energy. You would then reach 100 energy (your next turn) sooner.

Pete Mack September 27, 2018 23:13

I am not convinced that floating point would be better here: integer arithmetic has no pesky round-off issues, and working by percentages is certainly no real problem conceptually.


Quote:

Originally Posted by Derakon (Post 133489)
Ahh, the days when the performance implications of table lookup vs. doing division was an issue that deserved serious consideration.



All times are GMT +1. The time now is 15:21.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2020, vBulletin Solutions Inc.