Angband Forums

Angband Forums (http://angband.oook.cz/forum/index.php)
-   Vanilla (http://angband.oook.cz/forum/forumdisplay.php?f=3)
-   -   pStun on randarts? (http://angband.oook.cz/forum/showthread.php?t=6152)

AnonymousHero June 16, 2013 16:03

pStun on randarts?
 
Having done quite a lot of experiments, it seems to be the case that pStun cannot be generated on randarts that are not body armor. Is this intentional or a bug?

In any case, it seems rather strange considering that the only standart which has pStun is a crown.

EDIT: Oh, yeah, this is current 'master' if it matters.

Magnate June 17, 2013 08:57

Quote:

Originally Posted by AnonymousHero (Post 81604)
Having done quite a lot of experiments, it seems to be the case that pStun cannot be generated on randarts that are not body armor. Is this intentional or a bug?

In any case, it seems rather strange considering that the only standart which has pStun is a crown.

EDIT: Oh, yeah, this is current 'master' if it matters.

What sort of experiments? Do you just mean generating a lot of randart sets, or something else?

AFAIK there's no reason that pStun wouldn't occur on other types of item - it's rare, but not unheard of.

AnonymousHero June 17, 2013 15:10

Quote:

Originally Posted by Magnate (Post 81634)
What sort of experiments? Do you just mean generating a lot of randart sets, or something else?

AFAIK there's no reason that pStun wouldn't occur on other types of item - it's rare, but not unheard of.

Oh, I've generated several hundred sets of randarts. It never appears on non-body armor.

I've observed off-weapon extra blows and shots quite a few times and those are also very rare, so I don't think it's just a rarity issue.

Looking at the code, I think I can guess at the reason. AFAICT the only code which can potentially add pStun is:
Code:

                case ART_IDX_ARMOR_HRES:
                        add_high_resist(a_ptr);
                        break;

(This is the only call to add_high_resist.)

The only other place that ART_IDX_ARMOR_HRES is being referenced non-trivially is in the block

Code:

        if (a_ptr->tval == TV_SOFT_ARMOR ||
                        a_ptr->tval == TV_HARD_ARMOR || a_ptr->tval == TV_DRAG_ARMOR)
                {
                        temp = 0;
                        if (of_has(a_ptr->flags, OF_RES_POIS)) temp++;
                        if (of_has(a_ptr->flags, OF_RES_FEAR)) temp++;
                      (... snip a few almost identical lines...)
                        if (of_has(a_ptr->flags, OF_RES_DISEN)) temp++;
                        if (of_has(a_ptr->flags, OF_RES_STUN)) temp++;
                        file_putf(log_file, "Adding %d for high resists on body armor.\n", temp);

                        (artprobs[ART_IDX_ARMOR_HRES]) += temp;
                }

Am I on the right track?

scud June 17, 2013 15:16

Looking at the three winners I've posted, all 3.3.2, none of them wore pStun nor a source of pStun in their closets, though that's not to say I didn't find and discard a pStun randart. There was a ridiculous Bladeturner variant in one of them which had pStun (and p/r just about everything else, too) but I failed to find it.

I'll wear/carry a crown of Serenity for much of the time but eventually it gives way to a Helm of Badassness. It means I have to be 'watchful' around Grand Master Mystics – although that's probably advisable anyway – and I guess that if I were hugely unlucky I could get completely plasma-hounded on a teleport, but it hasn't happened to me yet. By the time I discard Serenity I've got speed/actions to spare.

pStun: there's not a lot of it about.

Magnate June 17, 2013 15:33

Quote:

Originally Posted by AnonymousHero (Post 81659)
Am I on the right track?

Turns out you were. There's nothing wrong with it being where it is - but what's missing is a stanza that says
Code:

case ART_IDX_GEN_PSTUN:
            add_flag(a_ptr, OF_RES_STUN);
            break;

at around line 2548 in the current master's randart.c

The absence of that code is why it's not getting added except as a high resist on body armour.

Well done.

AnonymousHero June 17, 2013 16:36

Thanks, I tried adding that, but it doesn't seem to be helping. (Btw, I've cranked pStun up to 5 in adjust_freqs() just to be able to reliably generate pStun while testing.)

One further little observation is that pStun is the last entry in both art_idx_gen and art_idx_high_resist, so it might be that there's an off-by-one somewhere that's still preventing it from working.

Out of interest, I added a printf() to the code you suggested, but it never triggers, so it appears that the "r" parameter never hits the required value to generate pStun. choose_ability() must be "avoiding" the value somehow.

Of note is also that ART_IDX_GEN_PSTUN = 86 which is the last ability (ART_IDX_TOTAL = 87).

Magnate June 17, 2013 18:00

Yes, I'm guessing it's an off-by-one as well then.

AnonymousHero June 17, 2013 21:02

Did a little further digging, and I think I've found the underlying reason, but I'm unsure how to fix it. Perhaps you have some ideas?

randart.log says:
Code:

...
Cumulative frequency of ability 84 is: 766
Cumulative frequency of ability 85 is: 766
Cumulative frequency of ability 86 is: 766

and the code in choose_ability() says
Code:

        r = randint1(freq_table[ART_IDX_TOTAL-1]);

        /* Find the entry in the table that this number represents. */
        ability = 0;
        while (r > freq_table[ability])
                ability++;

which, if I'm reading correctly, means that it will always choose the first of 84, 85, 86 if r hits the value 766. A little empirical testing with a printf for all ability >= 84 confirms this.

So, it'll always choose

#define ART_IDX_NONWEAPON_SHOTS 84

over

#define ART_IDX_GEN_AC_SUPER 85
#define ART_IDX_GEN_PSTUN 86

AnonymousHero June 17, 2013 21:11

Just to confirm: Added the following code to choose_ability():

Code:

        if ((freq_table[ART_IDX_NONWEAPON_SHOTS] != freq_table[ART_IDX_GEN_AC_SUPER]) ||
            (freq_table[ART_IDX_GEN_AC_SUPER] != freq_table[ART_IDX_GEN_PSTUN]) ||
            (freq_table[ART_IDX_NONWEAPON_SHOTS] != freq_table[ART_IDX_GEN_PSTUN])) {
                printf("GOT DIFFERENT VALUES!\n!");
        }

It never triggers the printf() so the cumulative frequency seems to always be identical for all the mentioned abilities. (Which surely can't be right if the code indeed forces a per-ability minimum frequency so that randarts can choose abilities that aren't in the set of abilities in the standart set.)

Magnate June 18, 2013 18:10

Well I notice that ART_IDX_GEN_COUNT is 31 when it should be 32, but I'm not sure that alone will solve the problem. This is proof that there are way too many constants in the randart code, and not nearly enough use of N_ELEMENTS and other macros.


All times are GMT +1. The time now is 18:46.

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