buttonmen-dev / buttonmen

Buttonmen - an online dice game
Other
16 stars 24 forks source link

Time & Space and Turbo interaction #2253

Open dwvanstone opened 7 years ago

dwvanstone commented 7 years ago

http://buttonweavers.com/ui/game.html?game=27806

The SailorMur button features a ^(X)! die. When playing, we observed that the time & space rule (odd roll goes again) is applied to the value before the reroll instead of after the reroll.

Here is a case where irilyth got an extra turn but shouldn't have:

irilyth performed Power attack using [^(X=5)!:1] against [t(4):1]; Defender t(4) was captured; Attacker ^(X=5)! rerolled from 1, changed size due to turbo irilyth gets another turn because a Time and Space die rolled odd Turbo die ^(X=5)! remained the same size, rolled 4

Here is a case where irilyth did not got an extra turn but should have:

irilyth performed Power attack using [^(X=5)!:4] against [g(10):2]; Defender g(10) was captured; Attacker ^(X=5)! rerolled from 4, changed size due to turbo Turbo die ^(X=5)! remained the same size, rolled 3

blackshadowshade commented 7 years ago

Yeah, that looks like a real bug. It looks like I'll need to perform the TimeAndSpace check later in the turn sequence now.

blackshadowshade commented 7 years ago

@cgolubi1, when you've got a chance, would you be able to generate me a responder test case for this please? I figure it should be possible to test this with a pretty short test case.

cgolubi1 commented 7 years ago

Ack, will do.

blackshadowshade commented 6 years ago

Just noting that I'm still waiting on a responder test to replicate this bug, and I'd like to have that before attempting a fix, since I fear it's going to be a somewhat involved fix.

blackshadowshade commented 6 years ago

@cgolubi1, just bringing this to your attention again, so that you can generate me a responder test and I can fix this bug.

cgolubi1 commented 6 years ago

Ack. Putting this on my list for the week.

cgolubi1 commented 6 years ago

Here you go, blackshadowshade. As noted by the comments, once the bug is fixed, we should actually check the response to make sure the code does the right thing, and i can help add that when we get to that point. But since the action log response is clearly wrong, i think this gives you enough to work with to fix the bug.

    /**
     * @depends test_request_savePlayerInfo
     * @group fulltest_deps
     *
     * Regression-testing Dead Guy skill attack behavior
     */
    public function test_interface_game_053() {

        // responder003 is the POV player, so if you need to fake
        // login as a different player e.g. to submit an attack, always
        // return to responder003 as soon as you've done so
        $this->game_number = 53;
        $_SESSION = $this->mock_test_user_login('responder003');

        $gameId = $this->verify_api_createGame(
            array(1, 1, 1, 1, 1, 1, 1, 1, 1),
            'responder003', 'responder004', 'SailorMur', 'Giant', 3
        );

        $expData = $this->generate_init_expected_data_array($gameId, 'responder003', 'responder004', 3, 'SPECIFY_DICE');
        $expData['gameSkillsInfo'] = $this->get_skill_info(array('Giant', 'Poison', 'Shadow', 'Stinger', 'TimeAndSpace', 'Trip', 'Turbo'));
        $expData['playerDataArray'][0]['button'] = array('name' => 'SailorMur', 'recipe' => 'g(10) sp(12) t(4) (10/20) ^(X)!', 'originalRecipe' => 'g(10) sp(12) t(4) (10/20) ^(X)!', 'artFilename' => 'BMdefaultRound.png');
        $expData['playerDataArray'][1]['button'] = array('name' => 'Giant', 'recipe' => '(20) (20) (20) (20) (20) (20)', 'originalRecipe' => '(20) (20) (20) (20) (20) (20)', 'artFilename' => 'giant.png');
        $expData['playerDataArray'][0]['swingRequestArray'] = array('X' => array(4, 20));
        $expData['playerDataArray'][0]['optRequestArray'] = array('3' => array(10, 20));
        $expData['playerDataArray'][1]['waitingOnAction'] = FALSE;
        $expData['playerDataArray'][0]['activeDieArray'] = array(
            array('value' => NULL, 'sides' => 10, 'skills' => array('Stinger'), 'properties' => array(), 'recipe' => 'g(10)', 'description' => 'Stinger 10-sided die'),
            array('value' => NULL, 'sides' => 12, 'skills' => array('Shadow', 'Poison'), 'properties' => array(), 'recipe' => 'sp(12)', 'description' => 'Shadow Poison 12-sided die'),
            array('value' => NULL, 'sides' => 4, 'skills' => array('Trip'), 'properties' => array(), 'recipe' => 't(4)', 'description' => 'Trip 4-sided die'),
            array('value' => NULL, 'sides' => NULL, 'skills' => array(), 'properties' => array(), 'recipe' => '(10/20)', 'description' => 'Option Die (with 10 or 20 sides)'),
            array('value' => NULL, 'sides' => NULL, 'skills' => array('TimeAndSpace', 'Turbo'), 'properties' => array(), 'recipe' => '^(X)!', 'description' => 'TimeAndSpace Turbo X Swing Die'),
        );
        $expData['playerDataArray'][1]['activeDieArray'] = array(
            array('value' => NULL, 'sides' => 20, 'skills' => array(), 'properties' => array(), 'recipe' => '(20)', 'description' => '20-sided die'),
            array('value' => NULL, 'sides' => 20, 'skills' => array(), 'properties' => array(), 'recipe' => '(20)', 'description' => '20-sided die'),
            array('value' => NULL, 'sides' => 20, 'skills' => array(), 'properties' => array(), 'recipe' => '(20)', 'description' => '20-sided die'),
            array('value' => NULL, 'sides' => 20, 'skills' => array(), 'properties' => array(), 'recipe' => '(20)', 'description' => '20-sided die'),
            array('value' => NULL, 'sides' => 20, 'skills' => array(), 'properties' => array(), 'recipe' => '(20)', 'description' => '20-sided die'),
            array('value' => NULL, 'sides' => 20, 'skills' => array(), 'properties' => array(), 'recipe' => '(20)', 'description' => '20-sided die'),
        );

        $retval = $this->verify_api_loadGameData($expData, $gameId, 10);

        ////////////////////
        // Move 01 - responder003 submits die values
        $this->verify_api_submitDieValues(
            array(1, 1),
            $gameId, 1, array('X' => 5), array(3 => 10));

        array_unshift($expData['gameActionLog'], array('timestamp' => 'TIMESTAMP', 'player' => 'responder003', 'message' => 'responder003 set swing values: X=5 and option dice: (10/20=10)'));
        array_unshift($expData['gameActionLog'], array('timestamp' => 'TIMESTAMP', 'player' => '', 'message' => 'responder003 won initiative for round 1. Initial die values: responder003 rolled [g(10):1, sp(12):1, t(4):1, (10/20=10):1, ^(X=5)!:1], responder004 rolled [(20):1, (20):1, (20):1, (20):1, (20):1, (20):1]. responder004\'s button has the "slow" button special, and cannot win initiative normally.'));
        $expData['gameActionLogCount'] = 3;
        $expData['gameState'] = 'START_TURN';
        $expData['activePlayerIdx'] = 0;
        $expData['playerWithInitiativeIdx'] = 0;
        $expData['validAttackTypeArray'] = array('Power', 'Skill', 'Shadow', 'Trip');
        $expData['playerDataArray'][0]['roundScore'] = 2.5;
        $expData['playerDataArray'][0]['sideScore'] = -38.3;
        $expData['playerDataArray'][1]['roundScore'] = 60;
        $expData['playerDataArray'][1]['sideScore'] = 38.3;
        $expData['playerDataArray'][0]['swingRequestArray'] = array();
        $expData['playerDataArray'][0]['turboSizeArray'] = array("4" => array(4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20));
        $expData['playerDataArray'][0]['activeDieArray'][0]['value'] = 1;
        $expData['playerDataArray'][0]['activeDieArray'][1]['value'] = 1;
        $expData['playerDataArray'][0]['activeDieArray'][2]['value'] = 1;
        $expData['playerDataArray'][0]['activeDieArray'][3]['value'] = 1;
        $expData['playerDataArray'][0]['activeDieArray'][3]['sides'] = 10;
        $expData['playerDataArray'][0]['activeDieArray'][3]['description'] = 'Option Die (with 10 sides)';
        $expData['playerDataArray'][0]['activeDieArray'][4]['value'] = 1;
        $expData['playerDataArray'][0]['activeDieArray'][4]['sides'] = 5;
        $expData['playerDataArray'][0]['activeDieArray'][4]['description'] = 'TimeAndSpace Turbo X Swing Die (with 5 sides)';
        $expData['playerDataArray'][1]['activeDieArray'][0]['value'] = 1;
        $expData['playerDataArray'][1]['activeDieArray'][1]['value'] = 1;
        $expData['playerDataArray'][1]['activeDieArray'][2]['value'] = 1;
        $expData['playerDataArray'][1]['activeDieArray'][3]['value'] = 1;
        $expData['playerDataArray'][1]['activeDieArray'][4]['value'] = 1;
        $expData['playerDataArray'][1]['activeDieArray'][5]['value'] = 1;

        $retval = $this->verify_api_loadGameData($expData, $gameId, 10);

        ////////////////////
        // Move 02 - responder003 Power attack using ^(X)!
        // BUG: responder003 should not get another turn
        $this->verify_api_submitTurn(
            array(2),
            'responder003 performed Power attack using [^(X=5)!:1] against [(20):1]; Defender (20) was captured; Attacker ^(X=5)! rerolled from 1. responder003 gets another turn because a Time and Space die rolled odd. Turbo die ^(X=5)! changed size from 5 to 10 sides, recipe changed from ^(X=5)! to ^(X=10)!, rolled 2. ',
            $retval, array(array(0, 4), array(1, 0)),
            $gameId, 1, 'Power', 0, 1, '', array(4 => 10));

        // FIXME: add a check of the response data to this once the bug is fixed and it's easy to get the data
    }
blackshadowshade commented 6 years ago

@cgolubi1, I've created a branch called 2253_turbo_timespace_interaction. I haven't yet tested it manually, but all the responder tests (including a version of the one you provided above with an altered verify_api_submitTurn) now pass.

You should be able to give me some response data based on this branch.

jimmosk commented 4 years ago

The same thing appears to be true for Mighty Time&Space dice, or at least for Mighty Time&Space Stinger dice, as seen in http://www.buttonweavers.com/ui/game.html?game=55794

Screen Shot 2019-12-24 at 10 49 17 PM

blackshadowshade commented 4 years ago

I think it's likely that this TimeAndSpace bug is potentially caused by any skill that requires the attacking die to be replaced before being rolled. As well as Turbo (which has already been fixed), this includes Berserk, Mighty, Weak, Morphing, Mood, Mad.

Looks like I'll need to do some testing with CustomBMs to work out if this is true.

The actual fix should be pretty simple, since the major work was done for Turbo.

blackshadowshade commented 4 years ago

The only existing button (apart from RandomBM*) that combines TimeAndSpace with a skill that replaces the attacking die is

Coyote: f(1/4) (4/20) z(10,10) ^(U)? s(X)!

I tried a Coyote vs Coyote match, and after swing setting, I've hit the following error message:

"[22-Nov-2020 04:44:15 UTC] PHP Fatal error: Declaration of BMAttackShadow::validate_attack($game, array $attackers, array $defenders) must be compatible with BMAttackPower::validate_attack($game, array $attackers, array $defenders, array $args = Array) in /Volumes/Development/buttonmen/src/engine/BMAttackShadow.php on line 136"

Apparently, in PHP 7.2 and up (and I'm running either 7.2 or 7.3 at home), they've changed the warning to a fatal error. I'll open a new issue for that and put in a one line fix.

blackshadowshade commented 4 years ago

On the upside, though, testing with Coyote vs Coyote gives the expected behaviour for the TimeAndSpace Mood Swing die over 20 times in a row, so I'll exclude Mood/Mad from consideration.