smogon / pokemon-showdown

Pokémon battle simulator.
https://pokemonshowdown.com
MIT License
4.77k stars 2.79k forks source link

Stone edge is not 80 acc #8491

Closed ghost closed 3 years ago

ghost commented 3 years ago

100's of times clicking stone edge and I miss more than half. take another look at how you implement this fucking move.

mia-pi-git commented 3 years ago

https://pokemonshowdown.com/pages/rng

ghost commented 3 years ago

100's of trials and I miss more than half. take a stats course plz

mia-pi-git commented 3 years ago

100's of trials and I miss more than half. take a stats course plz

Please read the FAQ I linked above.

Zarel commented 3 years ago

https://github.com/smogon/pokemon-showdown/blob/d3a2911c2759f8e0a21028cbddcecb6e71931b90/data/moves.ts#L16901-L16915

Here's the code for Stone Edge, in case you wanted to check for yourself.

HoeenCoder commented 3 years ago

Hi, I'm sorry to hear you are frustrated about the RNG on showdown, I know having moves miss at critical moments can be a frustration, it happens to all of us. I was curious about this issue due to this (as well as focus blast and such) being a common complaint so heres my review and proof as to why theres no issue with the code.

First off, while your claim of using Stone Edge 100 times and missing >50 may be true (its possible), its a statistical outlier. Think of the probability of hitting stone edge like this:

You have a bag with 100 slips of paper in it. 80 say HIT 20 say MISS. Each time you use the move, you mix up the slips and grab one without looking. Once you get your answer you put the slip back. Meaning each time you use the move you have a 80% chance to hit. If the slips were not replaced except when the bag was empty you would be guaranteed to hit 80/100 stone edges, but thats not how accuracy works in Pokemon.

Now, I went ahead and wrote a test for Stone Edge to check its accuracy to prove its working correctly. I won't commit this test to the simulator because its written in such a way to ensure its random each time its run (which could randomly break tests in the event we get unlucky) and it also takes a while to run.

I've added lots of comments (grey text starting with //) to explain how the code works if you are unfamiliar with programming in general. Please give those a read.

Heres my code:

'use strict';

const {PRNG} = require('../../../sim');
const assert = require('./../../assert');
const common = require('./../../common');

let battle;

describe('Stone Edge', function () {
    afterEach(function () {
        battle.destroy();
    });

    it('should hit 80% of the time', function () {
        battle = common.createBattle({
            // Override the default seed used for tests
            // Normally using the same seed for tests is fine, as we want tests to always
            // give the same result for a given seed. However, for this we want to test the hit %
            // so we need to give a different seed each time like an actual battle
            seed: PRNG.generateSeed(),
        });
        // Weak stone edge user to not KO the target
        battle.setPlayer('p1', {team: [{species: "Gible", level: 5, ability: 'sandveil', item: '', moves: ['stoneedge']}]});
        // Strong target that wont do anything but soak hits
        battle.setPlayer('p2', {team: [{species: "Chansey", ability: 'naturalcure', item: 'eviolite', moves: ['splash']}]});

        // Number of times stone edge has hit
        let hits = 0;
        // Number of turns to play, 1000 goes over the 1000 turn limit hence 999
        const rolls = 999;

        // Repeat this 999 times
        for (let i = 1; i <= rolls; i++) {
            // Auto will choose the only options avaliable: stone edge for gible and splash for chansey
            battle.makeChoices('auto', 'auto');
            // After the turn completes, check if stone edge hit (chansey lost HP)
            if (battle.p2.active[0].hp < battle.p2.active[0].maxhp) {
                // If so increase the hit counter
                hits++;
                // And restore chansey's HP so its not eventually KOed
                battle.p2.active[0].hp = battle.p2.active[0].maxhp;
            }

            // Restore PP for both mon's moves so neither end up struggling
            battle.p2.active[0].moveSlots[0].pp = battle.p2.active[0].moveSlots[0].maxpp;
            battle.p1.active[0].moveSlots[0].pp = battle.p1.active[0].moveSlots[0].maxpp;
        }

        // Number of hits as a percentage
        const hitRatio = hits / rolls;
        // multiply by 100 for proper display
        console.log("Stone Edge hit " + (hitRatio * 100) + "% of the time.");
        // Actual test assertion, test fails if stone edge hits less than 75% of the time or more than 85% of the time
        // The reason for the buffer is simple: 100 uses wont always mean 80 hits and 20 misses, thats not how probability
        // works when the odds do not change each time you perform the check.
        assert.equal(hitRatio >= 0.75 && hitRatio <= 0.85, true);
    });
});

The ides here is simple: Use stone edge alot and see how often it hit. We use it the maximum amount of times we can in a single battle, and calculate the result by dividing hits by number of times used. See the comments in the code for details. Here are the results of me running this multiple times:

image

As you can see, Stone Edge is hitting right around 80% of the time. This will vary slightly of course because as mentioned above its not always going to hit 80 times of every 100 uses. Of these 6 runs of the test, the best luck was a 81.88% hit rate and the worst was a 79.48% hit rate.

I hope this clarifies your issue, and I hope you have better luck in the future.

KamilaBorowska commented 3 years ago

First off, while your claim of using Stone Edge 100 times and missing >50 may be true (its possible), its a statistical outlier.

Out of curiosity, I did some calculations, the odds of Stone Missing more than 50 times are 1 in 1.9×1011. It's... possible I guess, but rather unlikely that it ever happened to anyone on Pokemon Showdown (assuming there were 1432330739 battles on Showdown, and Stone Edge was used thrice in each one the probability of that happening at least once is 2.2%).

That said, I find it probable that issue author didn't count some attempts that did succeed. Not missing Stone Edge is normal, missing Stone Edge is unusual and way more likely to be counted by a human. There is no evidence at all such as replays which suggests the value in question wasn't carefully calculated.

Alternatively they put Stone Edge on Pokemon with Hustle, reducing accuracy to 64%.