buttonmen-dev / buttonmen

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

Pappy and Bruno (take 2) #2917

Closed blackshadowshade closed 1 month ago

blackshadowshade commented 7 months ago

Supersedes #2905, partly addresses #372.

I've taken the pull request from @craw-daddy and added action logging.

To do:

blackshadowshade commented 7 months ago

I've rebased this to be after the recent docker pull request.

cgolubi1 commented 7 months ago

I setup a dev site: https://pappy-and-bruno.blackshadowshade.dev.buttonweavers.com/

cgolubi1 commented 7 months ago

First smoke test, Pappy vs non-Bruno, failed: https://pappy-and-bruno.blackshadowshade.dev.buttonweavers.com/ui/game.html?game=258

(I got the internal error while accepting the game.)

pappy_vs_non_bruno_internal_error
cgolubi1 commented 7 months ago

The log message is:

Caught unexpected exception in ApiResponder: Infinite loop detected when advancing game state. Final game state: SPECIFY_RECIPES, referer: https://pappy-and-bruno.blackshadowshade.dev.buttonweavers.com/ui/game.html?game=258
blackshadowshade commented 7 months ago

Yay for a running test site!

I'll take a look and see what's triggering that infinite loop.

blackshadowshade commented 7 months ago

Oh wait, that's pretty obvious. The last two lines of code are not correctly in the if statement. That should be a doddle to fix.

blackshadowshade commented 7 months ago

Fix applied to the code. This should fix newly created games involving Bruno and Pappy, but not the already-broken game.

cgolubi1 commented 7 months ago

https://pappy-and-bruno.blackshadowshade.dev.buttonweavers.com/ui/ has been rebuild with the new code.

blackshadowshade commented 7 months ago

I've opened a Pappy vs Delia game at https://pappy-and-bruno.blackshadowshade.dev.buttonweavers.com/ui/game.html?game=258. It looks fine, I was able to choose swing values and play a turn.

Time to get testers looking at this.

dwvanstone commented 7 months ago
Screenshot

I've logged into pappy-and-bruno.blackshadowshade.dev.buttonweavers.com . When I try to create a game of Pappy vs. Bruno I get the message "Internal error when calling createGame",

dwvanstone commented 7 months ago

I was able to create a Bruno v. Pappy game but it won't load ("Internal error when calling loadGameData")

https://pappy-and-bruno.blackshadowshade.dev.buttonweavers.com/ui/game.html?game=260

blackshadowshade commented 7 months ago

I'm seeing the following error from the dev site when I try to create a Bruno vs Pappy game:


Notice: Undefined variable: message in /var/www/engine/BMGameAction.php on line 787

Notice: Undefined variable: message in /var/www/engine/BMGameAction.php on line 787
{"data":{"gameId":267},"message":"Game 267 created successfully.","status":"ok"}

That looks really odd, that shouldn't be failing.

blackshadowshade commented 7 months ago

Let me have a dig into the dev site, see if the correct code has been deployed.

cgolubi1 commented 7 months ago

Dev site has been rebuilt with rev3 --- try it out at https://pappy-and-bruno.blackshadowshade.dev.buttonweavers.com/ui/

dwvanstone commented 7 months ago

All my tests work fine. Nice!

I'd be curious if Bruno vs. Random Button works correctly if the random button turns out to be Pappy. (And same in reverse.) I couldn't test for that case.

cgolubi1 commented 7 months ago

I'd be curious if Bruno vs. Random Button works correctly if the random button turns out to be Pappy.

That'll be easy enough to test once i have RandomAI testing working under ECS (which i think i have to do for this PR anyway, since it has logic changes).

cgolubi1 commented 1 month ago

I'm going to tear down this dev site --- it has pretty stale ECS code, and i'll get a copy of the database backup, so if we want to stand up another one, we'll be able to.

cgolubi1 commented 1 month ago

Okay. Time for some replay testing.

cgolubi1 commented 1 month ago

The button recipe for Bruno changed from B(8) B(8) B(20) B(20) B(X) to B(8) B(8) B(20) B(20) B(X) (X) because of Bruno's button special against Pappy

This message is hard to read. I think it's more usual for us to put square brackets around button recipes in log messages, so i would have expected this message to look like:

The button recipe for Bruno changed from [B(8) B(8) B(20) B(20) B(X)] to [B(8) B(8) B(20) B(20) B(X) (X)] because of Bruno's button special against Pappy

I think the latter is a little easier to parse.

cgolubi1 commented 1 month ago

I don't know if this is important, but it seems logically incorrect:

Maybe i've forgotten what originalRecipe does, but it seems to me that it should match the recipe as of the beginning of the action log. So if we have an action log entry talking about the recipe changing, then the recipe changed "during" the game, so originalRecipe should contain the recipe as it was before that change.

What do you think?

blackshadowshade commented 1 month ago

I'll have to take a deep dive into the code to have a look at what's going on with originalRecipe and original_recipe. I'll let you know once I've taken a better look.

cgolubi1 commented 1 month ago

Here's a responder test that locks in the behavior as it is right now by instantiating and playing a couple of turns of Pappy vs Bruno. It doesn't have the brackets you just added, but it should be trivial to insert them.

Note that the diff contains both the new test in responder04Test.php, and a little change you'll need to responderTestFramework.php in order for games with Pappy or Bruno to be replayable.

diff --git a/test/src/api/responder04Test.php b/test/src/api/responder04Test.php
index a5b6f44f..55ec5383 100644
--- a/test/src/api/responder04Test.php
+++ b/test/src/api/responder04Test.php
@@ -939,5 +939,204 @@ class responder04Test extends responderTestFramework {
         $retval = $this->verify_api_loadGameData($expData, $gameId, 10);

     }
+
+    /**
+     * @depends responder00Test::test_request_savePlayerInfo
+     */
+    public function test_interface_game_00063() {
+
+        // 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 = 63;
+        $_SESSION = $this->mock_test_user_login('responder003');
+
+
+        $gameId = $this->verify_api_createGame(
+            array('bm_rand' => array(3, 3, 7, 11, 1, 3, 7, 7), 'bm_skill_rand' => array()),
+            'responder003', 'responder004', 'Pappy', 'Bruno', 3,
+            '', NULL, 'gameId', array()
+        );
+
+        $expData = $this->generate_init_expected_data_array($gameId, 'responder003', 'responder004', 3, 'SPECIFY_DICE');
+        $expData['gameSkillsInfo'] = $this->get_skill_info(array('Berserk', 'Bruno', 'Pappy'));
+        $expData['playerDataArray'][0]['button'] = array('name' => 'Pappy', 'recipe' => '(4) (4) (10) B(20) (X) B(X)', 'originalRecipe' => '(4) (4) (10) B(20) (X) B(X)', 'artFilename' => 'pappy.png');
+        $expData['playerDataArray'][1]['button'] = array('name' => 'Bruno', 'recipe' => 'B(8) B(8) B(20) B(20) B(X) (X)', 'originalRecipe' => 'B(8) B(8) B(20) B(20) B(X) (X)', 'artFilename' => 'bruno.png');
+        $expData['playerDataArray'][0]['swingRequestArray'] = array('X' => array(4, 20));
+        $expData['playerDataArray'][1]['swingRequestArray'] = array('X' => array(4, 20));
+        $expData['playerDataArray'][0]['activeDieArray'] = array(
+            array('value' => NULL, 'sides' => 4, 'skills' => array(), 'properties' => array(), 'recipe' => '(4)', 'description' => '4-sided die'),
+            array('value' => NULL, 'sides' => 4, 'skills' => array(), 'properties' => array(), 'recipe' => '(4)', 'description' => '4-sided die'),
+            array('value' => NULL, 'sides' => 10, 'skills' => array(), 'properties' => array(), 'recipe' => '(10)', 'description' => '10-sided die'),
+            array('value' => NULL, 'sides' => 20, 'skills' => array('Berserk'), 'properties' => array(), 'recipe' => 'B(20)', 'description' => 'Berserk 20-sided die'),
+            array('value' => NULL, 'sides' => NULL, 'skills' => array(), 'properties' => array(), 'recipe' => '(X)', 'description' => 'X Swing Die'),
+            array('value' => NULL, 'sides' => NULL, 'skills' => array('Berserk'), 'properties' => array(), 'recipe' => 'B(X)', 'description' => 'Berserk X Swing Die'),
+        );
+        $expData['playerDataArray'][1]['activeDieArray'] = array(
+            array('value' => NULL, 'sides' => 8, 'skills' => array('Berserk'), 'properties' => array(), 'recipe' => 'B(8)', 'description' => 'Berserk 8-sided die'),
+            array('value' => NULL, 'sides' => 8, 'skills' => array('Berserk'), 'properties' => array(), 'recipe' => 'B(8)', 'description' => 'Berserk 8-sided die'),
+            array('value' => NULL, 'sides' => 20, 'skills' => array('Berserk'), 'properties' => array(), 'recipe' => 'B(20)', 'description' => 'Berserk 20-sided die'),
+            array('value' => NULL, 'sides' => 20, 'skills' => array('Berserk'), 'properties' => array(), 'recipe' => 'B(20)', 'description' => 'Berserk 20-sided die'),
+            array('value' => NULL, 'sides' => NULL, 'skills' => array('Berserk'), 'properties' => array(), 'recipe' => 'B(X)', 'description' => 'Berserk X Swing Die'),
+            array('value' => NULL, 'sides' => NULL, 'skills' => array(), 'properties' => array(), 'recipe' => '(X)', 'description' => 'X Swing Die'),
+        );
+        array_unshift($expData['gameActionLog'], array('timestamp' => 'TIMESTAMP', 'player' => '', 'message' => 'The button recipe for Pappy changed from (4) (4) (10) B(20) (X) to (4) (4) (10) B(20) (X) B(X) because of Pappy\'s button special against Bruno'));
+        array_unshift($expData['gameActionLog'], array('timestamp' => 'TIMESTAMP', 'player' => '', 'message' => 'The button recipe for Bruno changed from B(8) B(8) B(20) B(20) B(X) to B(8) B(8) B(20) B(20) B(X) (X) because of Bruno\'s button special against Pappy'));
+        $expData['gameActionLogCount'] = 3;
+
+        $expData['gameId'] = $gameId;
+        $expData['playerDataArray'][0]['playerId'] = $this->user_ids['responder003'];
+        $expData['playerDataArray'][1]['playerId'] = $this->user_ids['responder004'];
+
+        $retval = $this->verify_api_loadGameData($expData, $gameId, 10);
+
+        $this->verify_api_submitDieValues(
+            array(2, 1),
+            $gameId, 1, array('X' => 9), NULL);
+
+        array_unshift($expData['gameActionLog'], array('timestamp' => 'TIMESTAMP', 'player' => 'responder003', 'message' => 'responder003 set die sizes'));
+        $expData['gameActionLogCount'] = 4;
+        $expData['playerDataArray'][0]['activeDieArray'][4]['description'] = "X Swing Die (with 9 sides)";
+        $expData['playerDataArray'][0]['activeDieArray'][4]['sides'] = 9;
+        $expData['playerDataArray'][0]['activeDieArray'][5]['description'] = "Berserk X Swing Die (with 9 sides)";
+        $expData['playerDataArray'][0]['activeDieArray'][5]['sides'] = 9;
+        $expData['playerDataArray'][0]['waitingOnAction'] = false;
+
+        $retval = $this->verify_api_loadGameData($expData, $gameId, 10);
+
+        $_SESSION = $this->mock_test_user_login('responder004');
+        $this->verify_api_submitDieValues(
+            array(10, 8),
+            $gameId, 1, array('X' => 14), NULL);
+
+        $_SESSION = $this->mock_test_user_login('responder003');
+        $expData['activePlayerIdx'] = 0;
+        $expData['gameActionLog'] = array();
+        array_unshift($expData['gameActionLog'], array('timestamp' => 'TIMESTAMP', 'player' => '', 'message' => 'Game created by responder003'));
+        array_unshift($expData['gameActionLog'], array('timestamp' => 'TIMESTAMP', 'player' => '', 'message' => 'The button recipe for Pappy changed from (4) (4) (10) B(20) (X) to (4) (4) (10) B(20) (X) B(X) because of Pappy\'s button special against Bruno'));
+        array_unshift($expData['gameActionLog'], array('timestamp' => 'TIMESTAMP', 'player' => '', 'message' => 'The button recipe for Bruno changed from B(8) B(8) B(20) B(20) B(X) to B(8) B(8) B(20) B(20) B(X) (X) because of Bruno\'s button special against Pappy'));
+        array_unshift($expData['gameActionLog'], array('timestamp' => 'TIMESTAMP', 'player' => 'responder003', 'message' => 'responder003 set swing values: X=9'));
+        array_unshift($expData['gameActionLog'], array('timestamp' => 'TIMESTAMP', 'player' => 'responder004', 'message' => 'responder004 set swing values: X=14'));
+        array_unshift($expData['gameActionLog'], array('timestamp' => 'TIMESTAMP', 'player' => '', 'message' => 'responder003 won initiative for round 1. Initial die values: responder003 rolled [(4):3, (4):3, (10):7, B(20):11, (X=9):2, B(X=9):1], responder004 rolled [B(8):1, B(8):3, B(20):7, B(20):7, B(X=14):10, (X=14):8].'));
+        $expData['gameActionLogCount'] = 6;
+        $expData['gameState'] = "START_TURN";
+        $expData['playerDataArray'][0]['activeDieArray'][0]['value'] = 3;
+        $expData['playerDataArray'][0]['activeDieArray'][1]['value'] = 3;
+        $expData['playerDataArray'][0]['activeDieArray'][2]['value'] = 7;
+        $expData['playerDataArray'][0]['activeDieArray'][3]['value'] = 11;
+        $expData['playerDataArray'][0]['activeDieArray'][4]['value'] = 2;
+        $expData['playerDataArray'][0]['activeDieArray'][5]['value'] = 1;
+        $expData['playerDataArray'][0]['roundScore'] = 28;
+        $expData['playerDataArray'][0]['sideScore'] = -9.3;
+        $expData['playerDataArray'][0]['swingRequestArray'] = array();
+        $expData['playerDataArray'][0]['waitingOnAction'] = true;
+        $expData['playerDataArray'][1]['activeDieArray'][0]['value'] = 1;
+        $expData['playerDataArray'][1]['activeDieArray'][1]['value'] = 3;
+        $expData['playerDataArray'][1]['activeDieArray'][2]['value'] = 7;
+        $expData['playerDataArray'][1]['activeDieArray'][3]['value'] = 7;
+        $expData['playerDataArray'][1]['activeDieArray'][4]['description'] = "Berserk X Swing Die (with 14 sides)";
+        $expData['playerDataArray'][1]['activeDieArray'][4]['sides'] = 14;
+        $expData['playerDataArray'][1]['activeDieArray'][4]['value'] = 10;
+        $expData['playerDataArray'][1]['activeDieArray'][5]['description'] = "X Swing Die (with 14 sides)";
+        $expData['playerDataArray'][1]['activeDieArray'][5]['sides'] = 14;
+        $expData['playerDataArray'][1]['activeDieArray'][5]['value'] = 8;
+        $expData['playerDataArray'][1]['roundScore'] = 42;
+        $expData['playerDataArray'][1]['sideScore'] = 9.3;
+        $expData['playerDataArray'][1]['swingRequestArray'] = array();
+        $expData['playerDataArray'][1]['waitingOnAction'] = false;
+        $expData['playerWithInitiativeIdx'] = 0;
+        $expData['validAttackTypeArray'] = array("Power", "Skill", "Berserk");
+
+        $retval = $this->verify_api_loadGameData($expData, $gameId, 10);
+
+        $this->verify_api_submitTurn(
+            array(1),
+            'responder003 performed Power attack using [(X=9):2] against [B(8):1]; Defender B(8) was captured; Attacker (X=9) rerolled 2 => 1. ',
+            $retval, array(array(0, 4), array(1, 0)),
+            $gameId, 1, 'Power', 0, 1, '', array());
+
+        $expData['activePlayerIdx'] = 1;
+        array_unshift($expData['gameActionLog'], array('timestamp' => 'TIMESTAMP', 'player' => 'responder003', 'message' => 'responder003 performed Power attack using [(X=9):2] against [B(8):1]; Defender B(8) was captured; Attacker (X=9) rerolled 2 => 1'));
+        $expData['gameActionLogCount'] = 7;
+        $expData['playerDataArray'][0]['activeDieArray'][4]['value'] = 1;
+        $expData['playerDataArray'][0]['capturedDieArray'][0]['properties'] = array("WasJustCaptured");
+        $expData['playerDataArray'][0]['capturedDieArray'][0]['recipe'] = "B(8)";
+        $expData['playerDataArray'][0]['capturedDieArray'][0]['sides'] = 8;
+        $expData['playerDataArray'][0]['capturedDieArray'][0]['value'] = 1;
+        $expData['playerDataArray'][0]['roundScore'] = 36;
+        $expData['playerDataArray'][0]['sideScore'] = -1.3;
+        $expData['playerDataArray'][0]['waitingOnAction'] = false;
+        $expData['playerDataArray'][1]['activeDieArray'][0]['value'] = 3;
+        $expData['playerDataArray'][1]['activeDieArray'][1]['description'] = "Berserk 20-sided die";
+        $expData['playerDataArray'][1]['activeDieArray'][1]['recipe'] = "B(20)";
+        $expData['playerDataArray'][1]['activeDieArray'][1]['sides'] = 20;
+        $expData['playerDataArray'][1]['activeDieArray'][1]['value'] = 7;
+        $expData['playerDataArray'][1]['activeDieArray'][3]['description'] = "Berserk X Swing Die (with 14 sides)";
+        $expData['playerDataArray'][1]['activeDieArray'][3]['recipe'] = "B(X)";
+        $expData['playerDataArray'][1]['activeDieArray'][3]['sides'] = 14;
+        $expData['playerDataArray'][1]['activeDieArray'][3]['value'] = 10;
+        $expData['playerDataArray'][1]['activeDieArray'][4]['description'] = "X Swing Die (with 14 sides)";
+        $expData['playerDataArray'][1]['activeDieArray'][4]['recipe'] = "(X)";
+        $expData['playerDataArray'][1]['activeDieArray'][4]['skills'] = array();
+        $expData['playerDataArray'][1]['activeDieArray'][4]['value'] = 8;
+        array_pop($expData['playerDataArray'][1]['activeDieArray']);
+        $expData['playerDataArray'][1]['roundScore'] = 38;
+        $expData['playerDataArray'][1]['sideScore'] = 1.3;
+        $expData['playerDataArray'][1]['waitingOnAction'] = true;
+        $expData['validAttackTypeArray'] = array("Power", "Berserk");
+
+        $retval = $this->verify_api_loadGameData($expData, $gameId, 10);
+
+        $_SESSION = $this->mock_test_user_login('responder004');
+        $this->verify_api_submitTurn(
+            array(4),
+            'responder004 performed Berserk attack using [B(X=14):10] against [(4):3,(10):7]; Defender (4) was captured; Defender (10) was captured; Attacker B(X=14) changed size from 14 to 7 sides, recipe changed from B(X=14) to (X=7), rerolled 10 => 4. ',
+            $retval, array(array(1, 3), array(0, 0), array(0, 2)),
+            $gameId, 1, 'Berserk', 1, 0, '', array());
+
+        $_SESSION = $this->mock_test_user_login('responder003');
+        $expData['activePlayerIdx'] = 0;
+        array_unshift($expData['gameActionLog'], array('timestamp' => 'TIMESTAMP', 'player' => 'responder004', 'message' => 'responder004 performed Berserk attack using [B(X=14):10] against [(4):3,(10):7]; Defender (4) was captured; Defender (10) was captured; Attacker B(X=14) changed size from 14 to 7 sides, recipe changed from B(X=14) to (X=7), rerolled 10 => 4'));
+        $expData['gameActionLogCount'] = 8;
+        $expData['playerDataArray'][0]['activeDieArray'][1]['description'] = "Berserk 20-sided die";
+        $expData['playerDataArray'][0]['activeDieArray'][1]['recipe'] = "B(20)";
+        $expData['playerDataArray'][0]['activeDieArray'][1]['sides'] = 20;
+        $expData['playerDataArray'][0]['activeDieArray'][1]['skills'] = array("Berserk");
+        $expData['playerDataArray'][0]['activeDieArray'][1]['value'] = 11;
+        $expData['playerDataArray'][0]['activeDieArray'][2]['description'] = "X Swing Die (with 9 sides)";
+        $expData['playerDataArray'][0]['activeDieArray'][2]['recipe'] = "(X)";
+        $expData['playerDataArray'][0]['activeDieArray'][2]['sides'] = 9;
+        $expData['playerDataArray'][0]['activeDieArray'][2]['value'] = 1;
+        $expData['playerDataArray'][0]['activeDieArray'][3]['description'] = "Berserk X Swing Die (with 9 sides)";
+        $expData['playerDataArray'][0]['activeDieArray'][3]['recipe'] = "B(X)";
+        $expData['playerDataArray'][0]['activeDieArray'][3]['sides'] = 9;
+        $expData['playerDataArray'][0]['activeDieArray'][3]['value'] = 1;
+        array_pop($expData['playerDataArray'][0]['activeDieArray']);
+        array_pop($expData['playerDataArray'][0]['activeDieArray']);
+        $expData['playerDataArray'][0]['capturedDieArray'][0]['properties'] = array();
+        $expData['playerDataArray'][0]['roundScore'] = 29;
+        $expData['playerDataArray'][0]['sideScore'] = -13;
+        $expData['playerDataArray'][0]['waitingOnAction'] = true;
+        $expData['playerDataArray'][1]['activeDieArray'][3]['description'] = "X Swing Die (with 7 sides)";
+        $expData['playerDataArray'][1]['activeDieArray'][3]['properties'] = array("HasJustSplit", "JustPerformedBerserkAttack");
+        $expData['playerDataArray'][1]['activeDieArray'][3]['recipe'] = "(X)";
+        $expData['playerDataArray'][1]['activeDieArray'][3]['sides'] = 7;
+        $expData['playerDataArray'][1]['activeDieArray'][3]['skills'] = array();
+        $expData['playerDataArray'][1]['activeDieArray'][3]['value'] = 4;
+        $expData['playerDataArray'][1]['capturedDieArray'][0]['properties'] = array("WasJustCaptured");
+        $expData['playerDataArray'][1]['capturedDieArray'][0]['recipe'] = "(4)";
+        $expData['playerDataArray'][1]['capturedDieArray'][0]['sides'] = 4;
+        $expData['playerDataArray'][1]['capturedDieArray'][0]['value'] = 3;
+        $expData['playerDataArray'][1]['capturedDieArray'][1]['properties'] = array("WasJustCaptured");
+        $expData['playerDataArray'][1]['capturedDieArray'][1]['recipe'] = "(10)";
+        $expData['playerDataArray'][1]['capturedDieArray'][1]['sides'] = 10;
+        $expData['playerDataArray'][1]['capturedDieArray'][1]['value'] = 7;
+        $expData['playerDataArray'][1]['roundScore'] = 48.5;
+        $expData['playerDataArray'][1]['sideScore'] = 13;
+        $expData['playerDataArray'][1]['waitingOnAction'] = false;
+        $expData['validAttackTypeArray'] = array("Power", "Skill", "Berserk");
+
+        $retval = $this->verify_api_loadGameData($expData, $gameId, 10);
+    }
 }

diff --git a/test/src/api/responderTestFramework.php b/test/src/api/responderTestFramework.php
index 616f2de6..e15817b0 100644
--- a/test/src/api/responderTestFramework.php
+++ b/test/src/api/responderTestFramework.php
@@ -132,6 +132,11 @@ class responderTestFramework extends PHPUnit_Framework_TestCase {
                     'Stealth' => 'Stealth dice may be targeted by boom attacks',
                 ),
             ),
+            'Bruno' => array(
+                'code' => '',
+                'description' => 'Bruno gets an extra die, an (X), if his opponent is Pappy.',
+                'interacts' => array(),
+            ),
             'Chance' => array(
                 'code' => 'c',
                 'description' => 'If you do not have the initiative at the start of a round you may re-roll one of your Chance Dice. If this results in you gaining the initiative, your opponent may re-roll one of their Chance Dice. This can continue with each player re-rolling Chance Dice, even re-rolling the same die, until one person fails to gain the initiative or lets their opponent go first. Re-rolling Chance Dice is not only a way to gain the initiative; it can also be useful in protecting your larger dice, or otherwise improving your starting roll. Unlike Focus Dice, Chance Dice can be immediately re-used in an attack even if you do gain the initiative with them.',
@@ -281,6 +286,11 @@ class responderTestFramework extends PHPUnit_Framework_TestCase {
                     'Mood' => 'Dice with both Ornery and Mood Swing have their sizes randomized during ornery rerolls',
                 ),
             ),
+            'Pappy' => array(
+                'code' => '',
+                'description' => 'Pappy gets an extra die, a B(X), if his opponent is Bruno.',
+                'interacts' => array(),
+            ),
             'Poison' => array(
                 'code' => 'p',
                 'description' => 'These dice are worth negative points. If you keep a Poison Die of your own at the end of a round, subtract its full value from your score. If you capture a Poison Die from someone else, subtract half its value from your score.',
cgolubi1 commented 1 month ago

Sounds good. I think this is on your plate now to decide what you think is right about originalRecipe, and install the replay test. I'm going to tear the replay site down for now --- i didn't see any other issues except the missing responderTestFramework skill info stubs.

blackshadowshade commented 1 month ago

I've taken a look, and I believe that you're correct, the original recipe needs to be cached before the button skill takes effect. Let's see if I can work out how to do that!

blackshadowshade commented 1 month ago

Okay, I've shifted the logic of the recipe change to being slightly later so that the cache occurs first. I've also added the responder test and rebased.

I think this is ready to be redeployed to a test site so that testers can take one more quick look.

cgolubi1 commented 1 month ago

I kicked off replay testing, and started launching a dev site. It should be up in about 15 minutes at https://pappy-and-bruno.blackshadowshade.dev.buttonweavers.com/ (if it doesn't come up, i'll take a look tomorrow).

blackshadowshade commented 1 month ago

I've taken a look at the test site and a Pappy vs Bruno game appears to work okay into round 2.

blackshadowshade commented 1 month ago

@craw-daddy, @dwvanstone, if one of you (or another tester) could take a quick look at this test site, that would be lovely.

dwvanstone commented 1 month ago

I've explored the test site, looked at the button sets, created a few games, and everything looks good to me.

cgolubi1 commented 1 month ago

Thanks, all! I'll let the replay tests run for a few more hours, and assuming there are no surprises when i check this evening or so, i'll merge this.

cgolubi1 commented 1 month ago

I think everything checks out here. (The test site played 1600 new and replayed games without incident.)