{"abstract":"The 90th pull may fail to award a top-rarity item.","category":"Game economy crafting balance","checks":8,"contract":"Each roll is 0..999. Pull number n = pity+1. Top-rarity rate is 6 per mille, plus 50*(n-73) from n >= 74 (soft pity); n >= 90 always hits. On a hit pity resets to 0; the item is featured (\"F\") if guarantee is set or the roll is even, otherwise lost (\"L\") and the guarantee is set; a featured hit clears the guarantee. Misses (\"-\") set pity = n.","evaluation_group":"w2-game-economy-crafting-balance-banner-pity","failed_approach":"Testing the stored pity instead of the pull number moves hard pity to pull 91.","family":"w2-game-economy-crafting-balance-banner-pity-hard-pity-guarantee","id":"FA-85921","implementations":{"attempt":{"sha256":"ecc60c2d0d8ed07a0a19a8983090a7d6745b15e2af520b19d9625c49b2df1d25","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(rolls, state):\n    pity = state['pity']\n    guarantee = state['guarantee']\n    out = []\n    for r in rolls:\n        n = pity + 1\n        rate = 6\n        if n >= 74:\n            rate += 50 * (n - 73)\n        if pity >= 90 or r < rate:\n            pity = 0\n            if guarantee or r % 2 == 0:\n                out.append('F')\n                guarantee = False\n            else:\n                out.append('L')\n                guarantee = True\n        else:\n            pity = n\n            out.append('-')\n    return {'results': ''.join(out), 'pity': pity, 'guarantee': guarantee}\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = [[('hard pity pull #1',\n   [[999, 999], {'pity': 89, 'guarantee': False}],\n   {'results': 'L-', 'pity': 1, 'guarantee': True}),\n  ('regression hard pity guarantee #1',\n   [[935, 90, 29, 166, 937, 997, 903, 315, 848, 1, 893, 36, 218, 730, 858, 726, 972, 10],\n    {'pity': 89, 'guarantee': True}],\n   {'results': 'F--------L--------', 'pity': 8, 'guarantee': True}),\n  ('regression hard pity guarantee #2',\n   [[986], {'pity': 89, 'guarantee': True}],\n   {'results': 'F', 'pity': 0, 'guarantee': False}),\n  ('regression hard pity guarantee #3',\n   [[879, 933, 335, 968, 23, 554, 957, 37, 960, 47, 35, 24, 892, 11, 52, 851, 334, 43, 807, 808],\n    {'pity': 88, 'guarantee': False}],\n   {'results': '-L------------------', 'pity': 18, 'guarantee': True}),\n  ('regression hard pity guarantee #4',\n   [[812, 997, 899, 10], {'pity': 88, 'guarantee': False}],\n   {'results': '-L--', 'pity': 2, 'guarantee': True}),\n  ('first soft pity pull #1',\n   [[100, 3], {'pity': 73, 'guarantee': True}],\n   {'results': '-F', 'pity': 0, 'guarantee': False}),\n  ('lost fifty fifty then featured #1',\n   [[1, 999, 0], {'pity': 10, 'guarantee': False}],\n   {'results': 'L-F', 'pity': 0, 'guarantee': False}),\n  ('control #1',\n   [[15, 31, 302, 259, 332, 886, 12, 851, 55, 45, 6, 903, 946, 869, 725], {'pity': 88, 'guarantee': True}],\n   {'results': 'F--------------', 'pity': 14, 'guarantee': False})],\n [('hard pity pull #1',\n   [[999, 999], {'pity': 89, 'guarantee': False}],\n   {'results': 'L-', 'pity': 1, 'guarantee': True}),\n  ('regression hard pity guarantee #1',\n   [[986], {'pity': 89, 'guarantee': True}],\n   {'results': 'F', 'pity': 0, 'guarantee': False}),\n  ('regression hard pity guarantee #2',\n   [[879, 933, 335, 968, 23, 554, 957, 37, 960, 47, 35, 24, 892, 11, 52, 851, 334, 43, 807, 808],\n    {'pity': 88, 'guarantee': False}],\n   {'results': '-L------------------', 'pity': 18, 'guarantee': True}),\n  ('regression hard pity guarantee #3',\n   [[812, 997, 899, 10], {'pity': 88, 'guarantee': False}],\n   {'results': '-L--', 'pity': 2, 'guarantee': True}),\n  ('regression hard pity guarantee #4',\n   [[941, 855, 955], {'pity': 89, 'guarantee': False}],\n   {'results': 'L--', 'pity': 2, 'guarantee': True}),\n  ('first soft pity pull #1',\n   [[100, 3], {'pity': 73, 'guarantee': True}],\n   {'results': '-F', 'pity': 0, 'guarantee': False}),\n  ('lost fifty fifty then featured #1',\n   [[1, 999, 0], {'pity': 10, 'guarantee': False}],\n   {'results': 'L-F', 'pity': 0, 'guarantee': False}),\n  ('control #1',\n   [[15, 31, 302, 259, 332, 886, 12, 851, 55, 45, 6, 903, 946, 869, 725], {'pity': 88, 'guarantee': True}],\n   {'results': 'F--------------', 'pity': 14, 'guarantee': False})],\n [('hard pity pull #1',\n   [[999, 999], {'pity': 89, 'guarantee': False}],\n   {'results': 'L-', 'pity': 1, 'guarantee': True}),\n  ('regression hard pity guarantee #1',\n   [[812, 997, 899, 10], {'pity': 88, 'guarantee': False}],\n   {'results': '-L--', 'pity': 2, 'guarantee': True}),\n  ('regression hard pity guarantee #2',\n   [[941, 855, 955], {'pity': 89, 'guarantee': False}],\n   {'results': 'L--', 'pity': 2, 'guarantee': True}),\n  ('regression hard pity guarantee #3',\n   [[866, 716, 336, 806, 719, 971, 56, 858, 215, 881, 854, 21, 997, 459, 240],\n    {'pity': 89, 'guarantee': False}],\n   {'results': 'F--------------', 'pity': 14, 'guarantee': False}),\n  ('regression hard pity guarantee #4',\n   [[835, 921, 31, 855, 841, 35, 966, 806, 957, 858, 42, 57, 921], {'pity': 88, 'guarantee': False}],\n   {'results': '-L-----------', 'pity': 11, 'guarantee': True}),\n  ('first soft pity pull #1',\n   [[100, 3], {'pity': 73, 'guarantee': True}],\n   {'results': '-F', 'pity': 0, 'guarantee': False}),\n  ('lost fifty fifty then featured #1',\n   [[1, 999, 0], {'pity': 10, 'guarantee': False}],\n   {'results': 'L-F', 'pity': 0, 'guarantee': False}),\n  ('control #1',\n   [[15, 31, 302, 259, 332, 886, 12, 851, 55, 45, 6, 903, 946, 869, 725], {'pity': 88, 'guarantee': True}],\n   {'results': 'F--------------', 'pity': 14, 'guarantee': False})],\n [('hard pity pull #1',\n   [[999, 999], {'pity': 89, 'guarantee': False}],\n   {'results': 'L-', 'pity': 1, 'guarantee': True}),\n  ('regression hard pity guarantee #1',\n   [[866, 716, 336, 806, 719, 971, 56, 858, 215, 881, 854, 21, 997, 459, 240],\n    {'pity': 89, 'guarantee': False}],\n   {'results': 'F--------------', 'pity': 14, 'guarantee': False}),\n  ('regression hard pity guarantee #2',\n   [[835, 921, 31, 855, 841, 35, 966, 806, 957, 858, 42, 57, 921], {'pity': 88, 'guarantee': False}],\n   {'results': '-L-----------', 'pity': 11, 'guarantee': True}),\n  ('regression hard pity guarantee #3',\n   [[890, 52, 19, 184, 980], {'pity': 89, 'guarantee': False}],\n   {'results': 'F----', 'pity': 4, 'guarantee': False}),\n  ('regression hard pity guarantee #4',\n   [[929, 229, 908, 987, 916, 982, 868, 899, 703, 873, 474, 54, 48, 190, 47, 959, 85],\n    {'pity': 89, 'guarantee': False}],\n   {'results': 'L----------------', 'pity': 16, 'guarantee': True}),\n  ('first soft pity pull #1',\n   [[100, 3], {'pity': 73, 'guarantee': True}],\n   {'results': '-F', 'pity': 0, 'guarantee': False}),\n  ('lost fifty fifty then featured #1',\n   [[1, 999, 0], {'pity': 10, 'guarantee': False}],\n   {'results': 'L-F', 'pity': 0, 'guarantee': False}),\n  ('control #1',\n   [[507, 965, 27, 525, 851], {'pity': 73, 'guarantee': True}],\n   {'results': '--F--', 'pity': 2, 'guarantee': False})],\n [('hard pity pull #1',\n   [[999, 999], {'pity': 89, 'guarantee': False}],\n   {'results': 'L-', 'pity': 1, 'guarantee': True}),\n  ('regression hard pity guarantee #1',\n   [[890, 52, 19, 184, 980], {'pity': 89, 'guarantee': False}],\n   {'results': 'F----', 'pity': 4, 'guarantee': False}),\n  ('regression hard pity guarantee #2',\n   [[929, 229, 908, 987, 916, 982, 868, 899, 703, 873, 474, 54, 48, 190, 47, 959, 85],\n    {'pity': 89, 'guarantee': False}],\n   {'results': 'L----------------', 'pity': 16, 'guarantee': True}),\n  ('regression hard pity guarantee #3',\n   [[860, 578, 19, 809, 175, 896, 995, 51, 817, 955, 882, 623, 519, 962, 886, 900, 785, 824, 15],\n    {'pity': 89, 'guarantee': False}],\n   {'results': 'F------------------', 'pity': 18, 'guarantee': False}),\n  ('regression hard pity guarantee #4',\n   [[999, 955, 867, 824, 299, 243, 930, 89, 25, 397, 757, 7, 112, 301, 716, 703, 998, 888, 950, 816],\n    {'pity': 88, 'guarantee': True}],\n   {'results': '-F------------------', 'pity': 18, 'guarantee': False}),\n  ('first soft pity pull #1',\n   [[100, 3], {'pity': 73, 'guarantee': True}],\n   {'results': '-F', 'pity': 0, 'guarantee': False}),\n  ('lost fifty fifty then featured #1',\n   [[1, 999, 0], {'pity': 10, 'guarantee': False}],\n   {'results': 'L-F', 'pity': 0, 'guarantee': False}),\n  ('control #1',\n   [[480, 489, 823, 13, 936, 776, 44, 409, 26, 974, 9, 54, 911, 804, 433, 47, 942, 847],\n    {'pity': 89, 'guarantee': True}],\n   {'results': 'F-----------------', 'pity': 17, 'guarantee': False})]]\nfor label, args, expected in cases[N-1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"a0e24a984b1ad7a66fdd83e673f5a2de6ad33e4935e704aaa962d90af2f9f57a","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(rolls, state):\n    pity = state['pity']\n    guarantee = state['guarantee']\n    out = []\n    for r in rolls:\n        n = pity + 1\n        rate = 6\n        if n >= 74:\n            rate += 50 * (n - 73)\n        if n > 90 or r < rate:\n            pity = 0\n            if guarantee or r % 2 == 0:\n                out.append('F')\n                guarantee = False\n            else:\n                out.append('L')\n                guarantee = True\n        else:\n            pity = n\n            out.append('-')\n    return {'results': ''.join(out), 'pity': pity, 'guarantee': guarantee}\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = [[('hard pity pull #1',\n   [[999, 999], {'pity': 89, 'guarantee': False}],\n   {'results': 'L-', 'pity': 1, 'guarantee': True}),\n  ('regression hard pity guarantee #1',\n   [[935, 90, 29, 166, 937, 997, 903, 315, 848, 1, 893, 36, 218, 730, 858, 726, 972, 10],\n    {'pity': 89, 'guarantee': True}],\n   {'results': 'F--------L--------', 'pity': 8, 'guarantee': True}),\n  ('regression hard pity guarantee #2',\n   [[986], {'pity': 89, 'guarantee': True}],\n   {'results': 'F', 'pity': 0, 'guarantee': False}),\n  ('regression hard pity guarantee #3',\n   [[879, 933, 335, 968, 23, 554, 957, 37, 960, 47, 35, 24, 892, 11, 52, 851, 334, 43, 807, 808],\n    {'pity': 88, 'guarantee': False}],\n   {'results': '-L------------------', 'pity': 18, 'guarantee': True}),\n  ('regression hard pity guarantee #4',\n   [[812, 997, 899, 10], {'pity': 88, 'guarantee': False}],\n   {'results': '-L--', 'pity': 2, 'guarantee': True}),\n  ('first soft pity pull #1',\n   [[100, 3], {'pity': 73, 'guarantee': True}],\n   {'results': '-F', 'pity': 0, 'guarantee': False}),\n  ('lost fifty fifty then featured #1',\n   [[1, 999, 0], {'pity': 10, 'guarantee': False}],\n   {'results': 'L-F', 'pity': 0, 'guarantee': False}),\n  ('control #1',\n   [[15, 31, 302, 259, 332, 886, 12, 851, 55, 45, 6, 903, 946, 869, 725], {'pity': 88, 'guarantee': True}],\n   {'results': 'F--------------', 'pity': 14, 'guarantee': False})],\n [('hard pity pull #1',\n   [[999, 999], {'pity': 89, 'guarantee': False}],\n   {'results': 'L-', 'pity': 1, 'guarantee': True}),\n  ('regression hard pity guarantee #1',\n   [[986], {'pity': 89, 'guarantee': True}],\n   {'results': 'F', 'pity': 0, 'guarantee': False}),\n  ('regression hard pity guarantee #2',\n   [[879, 933, 335, 968, 23, 554, 957, 37, 960, 47, 35, 24, 892, 11, 52, 851, 334, 43, 807, 808],\n    {'pity': 88, 'guarantee': False}],\n   {'results': '-L------------------', 'pity': 18, 'guarantee': True}),\n  ('regression hard pity guarantee #3',\n   [[812, 997, 899, 10], {'pity': 88, 'guarantee': False}],\n   {'results': '-L--', 'pity': 2, 'guarantee': True}),\n  ('regression hard pity guarantee #4',\n   [[941, 855, 955], {'pity': 89, 'guarantee': False}],\n   {'results': 'L--', 'pity': 2, 'guarantee': True}),\n  ('first soft pity pull #1',\n   [[100, 3], {'pity': 73, 'guarantee': True}],\n   {'results': '-F', 'pity': 0, 'guarantee': False}),\n  ('lost fifty fifty then featured #1',\n   [[1, 999, 0], {'pity': 10, 'guarantee': False}],\n   {'results': 'L-F', 'pity': 0, 'guarantee': False}),\n  ('control #1',\n   [[15, 31, 302, 259, 332, 886, 12, 851, 55, 45, 6, 903, 946, 869, 725], {'pity': 88, 'guarantee': True}],\n   {'results': 'F--------------', 'pity': 14, 'guarantee': False})],\n [('hard pity pull #1',\n   [[999, 999], {'pity': 89, 'guarantee': False}],\n   {'results': 'L-', 'pity': 1, 'guarantee': True}),\n  ('regression hard pity guarantee #1',\n   [[812, 997, 899, 10], {'pity': 88, 'guarantee': False}],\n   {'results': '-L--', 'pity': 2, 'guarantee': True}),\n  ('regression hard pity guarantee #2',\n   [[941, 855, 955], {'pity': 89, 'guarantee': False}],\n   {'results': 'L--', 'pity': 2, 'guarantee': True}),\n  ('regression hard pity guarantee #3',\n   [[866, 716, 336, 806, 719, 971, 56, 858, 215, 881, 854, 21, 997, 459, 240],\n    {'pity': 89, 'guarantee': False}],\n   {'results': 'F--------------', 'pity': 14, 'guarantee': False}),\n  ('regression hard pity guarantee #4',\n   [[835, 921, 31, 855, 841, 35, 966, 806, 957, 858, 42, 57, 921], {'pity': 88, 'guarantee': False}],\n   {'results': '-L-----------', 'pity': 11, 'guarantee': True}),\n  ('first soft pity pull #1',\n   [[100, 3], {'pity': 73, 'guarantee': True}],\n   {'results': '-F', 'pity': 0, 'guarantee': False}),\n  ('lost fifty fifty then featured #1',\n   [[1, 999, 0], {'pity': 10, 'guarantee': False}],\n   {'results': 'L-F', 'pity': 0, 'guarantee': False}),\n  ('control #1',\n   [[15, 31, 302, 259, 332, 886, 12, 851, 55, 45, 6, 903, 946, 869, 725], {'pity': 88, 'guarantee': True}],\n   {'results': 'F--------------', 'pity': 14, 'guarantee': False})],\n [('hard pity pull #1',\n   [[999, 999], {'pity': 89, 'guarantee': False}],\n   {'results': 'L-', 'pity': 1, 'guarantee': True}),\n  ('regression hard pity guarantee #1',\n   [[866, 716, 336, 806, 719, 971, 56, 858, 215, 881, 854, 21, 997, 459, 240],\n    {'pity': 89, 'guarantee': False}],\n   {'results': 'F--------------', 'pity': 14, 'guarantee': False}),\n  ('regression hard pity guarantee #2',\n   [[835, 921, 31, 855, 841, 35, 966, 806, 957, 858, 42, 57, 921], {'pity': 88, 'guarantee': False}],\n   {'results': '-L-----------', 'pity': 11, 'guarantee': True}),\n  ('regression hard pity guarantee #3',\n   [[890, 52, 19, 184, 980], {'pity': 89, 'guarantee': False}],\n   {'results': 'F----', 'pity': 4, 'guarantee': False}),\n  ('regression hard pity guarantee #4',\n   [[929, 229, 908, 987, 916, 982, 868, 899, 703, 873, 474, 54, 48, 190, 47, 959, 85],\n    {'pity': 89, 'guarantee': False}],\n   {'results': 'L----------------', 'pity': 16, 'guarantee': True}),\n  ('first soft pity pull #1',\n   [[100, 3], {'pity': 73, 'guarantee': True}],\n   {'results': '-F', 'pity': 0, 'guarantee': False}),\n  ('lost fifty fifty then featured #1',\n   [[1, 999, 0], {'pity': 10, 'guarantee': False}],\n   {'results': 'L-F', 'pity': 0, 'guarantee': False}),\n  ('control #1',\n   [[507, 965, 27, 525, 851], {'pity': 73, 'guarantee': True}],\n   {'results': '--F--', 'pity': 2, 'guarantee': False})],\n [('hard pity pull #1',\n   [[999, 999], {'pity': 89, 'guarantee': False}],\n   {'results': 'L-', 'pity': 1, 'guarantee': True}),\n  ('regression hard pity guarantee #1',\n   [[890, 52, 19, 184, 980], {'pity': 89, 'guarantee': False}],\n   {'results': 'F----', 'pity': 4, 'guarantee': False}),\n  ('regression hard pity guarantee #2',\n   [[929, 229, 908, 987, 916, 982, 868, 899, 703, 873, 474, 54, 48, 190, 47, 959, 85],\n    {'pity': 89, 'guarantee': False}],\n   {'results': 'L----------------', 'pity': 16, 'guarantee': True}),\n  ('regression hard pity guarantee #3',\n   [[860, 578, 19, 809, 175, 896, 995, 51, 817, 955, 882, 623, 519, 962, 886, 900, 785, 824, 15],\n    {'pity': 89, 'guarantee': False}],\n   {'results': 'F------------------', 'pity': 18, 'guarantee': False}),\n  ('regression hard pity guarantee #4',\n   [[999, 955, 867, 824, 299, 243, 930, 89, 25, 397, 757, 7, 112, 301, 716, 703, 998, 888, 950, 816],\n    {'pity': 88, 'guarantee': True}],\n   {'results': '-F------------------', 'pity': 18, 'guarantee': False}),\n  ('first soft pity pull #1',\n   [[100, 3], {'pity': 73, 'guarantee': True}],\n   {'results': '-F', 'pity': 0, 'guarantee': False}),\n  ('lost fifty fifty then featured #1',\n   [[1, 999, 0], {'pity': 10, 'guarantee': False}],\n   {'results': 'L-F', 'pity': 0, 'guarantee': False}),\n  ('control #1',\n   [[480, 489, 823, 13, 936, 776, 44, 409, 26, 974, 9, 54, 911, 804, 433, 47, 942, 847],\n    {'pity': 89, 'guarantee': True}],\n   {'results': 'F-----------------', 'pity': 17, 'guarantee': False})]]\nfor label, args, expected in cases[N-1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"fixed":{"sha256":"b11ab144bd7ec78de822e2145292a33125a6e797dbfb93dd138f362919fb3a26","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(rolls, state):\n    pity = state['pity']\n    guarantee = state['guarantee']\n    out = []\n    for r in rolls:\n        n = pity + 1\n        rate = 6\n        if n >= 74:\n            rate += 50 * (n - 73)\n        if n >= 90 or r < rate:\n            pity = 0\n            if guarantee or r % 2 == 0:\n                out.append('F')\n                guarantee = False\n            else:\n                out.append('L')\n                guarantee = True\n        else:\n            pity = n\n            out.append('-')\n    return {'results': ''.join(out), 'pity': pity, 'guarantee': guarantee}\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = [[('hard pity pull #1',\n   [[999, 999], {'pity': 89, 'guarantee': False}],\n   {'results': 'L-', 'pity': 1, 'guarantee': True}),\n  ('regression hard pity guarantee #1',\n   [[935, 90, 29, 166, 937, 997, 903, 315, 848, 1, 893, 36, 218, 730, 858, 726, 972, 10],\n    {'pity': 89, 'guarantee': True}],\n   {'results': 'F--------L--------', 'pity': 8, 'guarantee': True}),\n  ('regression hard pity guarantee #2',\n   [[986], {'pity': 89, 'guarantee': True}],\n   {'results': 'F', 'pity': 0, 'guarantee': False}),\n  ('regression hard pity guarantee #3',\n   [[879, 933, 335, 968, 23, 554, 957, 37, 960, 47, 35, 24, 892, 11, 52, 851, 334, 43, 807, 808],\n    {'pity': 88, 'guarantee': False}],\n   {'results': '-L------------------', 'pity': 18, 'guarantee': True}),\n  ('regression hard pity guarantee #4',\n   [[812, 997, 899, 10], {'pity': 88, 'guarantee': False}],\n   {'results': '-L--', 'pity': 2, 'guarantee': True}),\n  ('first soft pity pull #1',\n   [[100, 3], {'pity': 73, 'guarantee': True}],\n   {'results': '-F', 'pity': 0, 'guarantee': False}),\n  ('lost fifty fifty then featured #1',\n   [[1, 999, 0], {'pity': 10, 'guarantee': False}],\n   {'results': 'L-F', 'pity': 0, 'guarantee': False}),\n  ('control #1',\n   [[15, 31, 302, 259, 332, 886, 12, 851, 55, 45, 6, 903, 946, 869, 725], {'pity': 88, 'guarantee': True}],\n   {'results': 'F--------------', 'pity': 14, 'guarantee': False})],\n [('hard pity pull #1',\n   [[999, 999], {'pity': 89, 'guarantee': False}],\n   {'results': 'L-', 'pity': 1, 'guarantee': True}),\n  ('regression hard pity guarantee #1',\n   [[986], {'pity': 89, 'guarantee': True}],\n   {'results': 'F', 'pity': 0, 'guarantee': False}),\n  ('regression hard pity guarantee #2',\n   [[879, 933, 335, 968, 23, 554, 957, 37, 960, 47, 35, 24, 892, 11, 52, 851, 334, 43, 807, 808],\n    {'pity': 88, 'guarantee': False}],\n   {'results': '-L------------------', 'pity': 18, 'guarantee': True}),\n  ('regression hard pity guarantee #3',\n   [[812, 997, 899, 10], {'pity': 88, 'guarantee': False}],\n   {'results': '-L--', 'pity': 2, 'guarantee': True}),\n  ('regression hard pity guarantee #4',\n   [[941, 855, 955], {'pity': 89, 'guarantee': False}],\n   {'results': 'L--', 'pity': 2, 'guarantee': True}),\n  ('first soft pity pull #1',\n   [[100, 3], {'pity': 73, 'guarantee': True}],\n   {'results': '-F', 'pity': 0, 'guarantee': False}),\n  ('lost fifty fifty then featured #1',\n   [[1, 999, 0], {'pity': 10, 'guarantee': False}],\n   {'results': 'L-F', 'pity': 0, 'guarantee': False}),\n  ('control #1',\n   [[15, 31, 302, 259, 332, 886, 12, 851, 55, 45, 6, 903, 946, 869, 725], {'pity': 88, 'guarantee': True}],\n   {'results': 'F--------------', 'pity': 14, 'guarantee': False})],\n [('hard pity pull #1',\n   [[999, 999], {'pity': 89, 'guarantee': False}],\n   {'results': 'L-', 'pity': 1, 'guarantee': True}),\n  ('regression hard pity guarantee #1',\n   [[812, 997, 899, 10], {'pity': 88, 'guarantee': False}],\n   {'results': '-L--', 'pity': 2, 'guarantee': True}),\n  ('regression hard pity guarantee #2',\n   [[941, 855, 955], {'pity': 89, 'guarantee': False}],\n   {'results': 'L--', 'pity': 2, 'guarantee': True}),\n  ('regression hard pity guarantee #3',\n   [[866, 716, 336, 806, 719, 971, 56, 858, 215, 881, 854, 21, 997, 459, 240],\n    {'pity': 89, 'guarantee': False}],\n   {'results': 'F--------------', 'pity': 14, 'guarantee': False}),\n  ('regression hard pity guarantee #4',\n   [[835, 921, 31, 855, 841, 35, 966, 806, 957, 858, 42, 57, 921], {'pity': 88, 'guarantee': False}],\n   {'results': '-L-----------', 'pity': 11, 'guarantee': True}),\n  ('first soft pity pull #1',\n   [[100, 3], {'pity': 73, 'guarantee': True}],\n   {'results': '-F', 'pity': 0, 'guarantee': False}),\n  ('lost fifty fifty then featured #1',\n   [[1, 999, 0], {'pity': 10, 'guarantee': False}],\n   {'results': 'L-F', 'pity': 0, 'guarantee': False}),\n  ('control #1',\n   [[15, 31, 302, 259, 332, 886, 12, 851, 55, 45, 6, 903, 946, 869, 725], {'pity': 88, 'guarantee': True}],\n   {'results': 'F--------------', 'pity': 14, 'guarantee': False})],\n [('hard pity pull #1',\n   [[999, 999], {'pity': 89, 'guarantee': False}],\n   {'results': 'L-', 'pity': 1, 'guarantee': True}),\n  ('regression hard pity guarantee #1',\n   [[866, 716, 336, 806, 719, 971, 56, 858, 215, 881, 854, 21, 997, 459, 240],\n    {'pity': 89, 'guarantee': False}],\n   {'results': 'F--------------', 'pity': 14, 'guarantee': False}),\n  ('regression hard pity guarantee #2',\n   [[835, 921, 31, 855, 841, 35, 966, 806, 957, 858, 42, 57, 921], {'pity': 88, 'guarantee': False}],\n   {'results': '-L-----------', 'pity': 11, 'guarantee': True}),\n  ('regression hard pity guarantee #3',\n   [[890, 52, 19, 184, 980], {'pity': 89, 'guarantee': False}],\n   {'results': 'F----', 'pity': 4, 'guarantee': False}),\n  ('regression hard pity guarantee #4',\n   [[929, 229, 908, 987, 916, 982, 868, 899, 703, 873, 474, 54, 48, 190, 47, 959, 85],\n    {'pity': 89, 'guarantee': False}],\n   {'results': 'L----------------', 'pity': 16, 'guarantee': True}),\n  ('first soft pity pull #1',\n   [[100, 3], {'pity': 73, 'guarantee': True}],\n   {'results': '-F', 'pity': 0, 'guarantee': False}),\n  ('lost fifty fifty then featured #1',\n   [[1, 999, 0], {'pity': 10, 'guarantee': False}],\n   {'results': 'L-F', 'pity': 0, 'guarantee': False}),\n  ('control #1',\n   [[507, 965, 27, 525, 851], {'pity': 73, 'guarantee': True}],\n   {'results': '--F--', 'pity': 2, 'guarantee': False})],\n [('hard pity pull #1',\n   [[999, 999], {'pity': 89, 'guarantee': False}],\n   {'results': 'L-', 'pity': 1, 'guarantee': True}),\n  ('regression hard pity guarantee #1',\n   [[890, 52, 19, 184, 980], {'pity': 89, 'guarantee': False}],\n   {'results': 'F----', 'pity': 4, 'guarantee': False}),\n  ('regression hard pity guarantee #2',\n   [[929, 229, 908, 987, 916, 982, 868, 899, 703, 873, 474, 54, 48, 190, 47, 959, 85],\n    {'pity': 89, 'guarantee': False}],\n   {'results': 'L----------------', 'pity': 16, 'guarantee': True}),\n  ('regression hard pity guarantee #3',\n   [[860, 578, 19, 809, 175, 896, 995, 51, 817, 955, 882, 623, 519, 962, 886, 900, 785, 824, 15],\n    {'pity': 89, 'guarantee': False}],\n   {'results': 'F------------------', 'pity': 18, 'guarantee': False}),\n  ('regression hard pity guarantee #4',\n   [[999, 955, 867, 824, 299, 243, 930, 89, 25, 397, 757, 7, 112, 301, 716, 703, 998, 888, 950, 816],\n    {'pity': 88, 'guarantee': True}],\n   {'results': '-F------------------', 'pity': 18, 'guarantee': False}),\n  ('first soft pity pull #1',\n   [[100, 3], {'pity': 73, 'guarantee': True}],\n   {'results': '-F', 'pity': 0, 'guarantee': False}),\n  ('lost fifty fifty then featured #1',\n   [[1, 999, 0], {'pity': 10, 'guarantee': False}],\n   {'results': 'L-F', 'pity': 0, 'guarantee': False}),\n  ('control #1',\n   [[480, 489, 823, 13, 936, 776, 44, 409, 26, 974, 9, 54, 911, 804, 433, 47, 942, 847],\n    {'pity': 89, 'guarantee': True}],\n   {'results': 'F-----------------', 'pity': 17, 'guarantee': False})]]\nfor label, args, expected in cases[N-1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"Deterministic toy contract stipulated for this model; integer or exact arithmetic only, not a reproduction of any specific game engine. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-game-economy-crafting-balance-banner-pity-hard-pity-guarantee","generated_at":"2026-09-29T14:50:44.858338+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Game economies leak or destroy currency when one crafting or pricing rule is off by one boundary, rounding stage or state update; the defect is observable in exact integer outcomes.","repair":"Restore `n >= 90 or r < rate` at the hard pity guarantee step.","root_cause":"The hard-pity comparison is strict, so pull 90 only hits by rate.","sha256":"23b4e45d4a733f9a930cdc6380a99d35a2c84f182b613f2d48d01c2c7b64d71f","title":"Banner pity counter: Hard pity pull can miss · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":38.24,"exit_code":1,"observations":[{"actual":{"guarantee":true,"pity":0,"results":"-L"},"check":"hard pity pull #1","expected":{"guarantee":true,"pity":1,"results":"L-"},"passed":false},{"actual":{"guarantee":true,"pity":8,"results":"-F-------L--------"},"check":"regression hard pity guarantee #1","expected":{"guarantee":true,"pity":8,"results":"F--------L--------"},"passed":false},{"actual":{"guarantee":true,"pity":90,"results":"-"},"check":"regression hard pity guarantee #2","expected":{"guarantee":false,"pity":0,"results":"F"},"passed":false},{"actual":{"guarantee":true,"pity":17,"results":"--L-----------------"},"check":"regression hard pity guarantee #3","expected":{"guarantee":true,"pity":18,"results":"-L------------------"},"passed":false},{"actual":{"guarantee":true,"pity":1,"results":"--L-"},"check":"regression hard pity guarantee #4","expected":{"guarantee":true,"pity":2,"results":"-L--"},"passed":false},{"actual":{"guarantee":false,"pity":0,"results":"-F"},"check":"first soft pity pull #1","expected":{"guarantee":false,"pity":0,"results":"-F"},"passed":true},{"actual":{"guarantee":false,"pity":0,"results":"L-F"},"check":"lost fifty fifty then featured #1","expected":{"guarantee":false,"pity":0,"results":"L-F"},"passed":true},{"actual":{"guarantee":false,"pity":14,"results":"F--------------"},"check":"control #1","expected":{"guarantee":false,"pity":14,"results":"F--------------"},"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"hard pity pull #1\", \"actual\": {\"results\": \"-L\", \"pity\": 0, \"guarantee\": true}, \"expected\": {\"results\": \"L-\", \"pity\": 1, \"guarantee\": true}, \"passed\": false}, {\"check\": \"regression hard pity guarantee #1\", \"actual\": {\"results\": \"-F-------L--------\", \"pity\": 8, \"guarantee\": true}, \"expected\": {\"results\": \"F--------L--------\", \"pity\": 8, \"guarantee\": true}, \"passed\": false}, {\"check\": \"regression hard pity guarantee #2\", \"actual\": {\"results\": \"-\", \"pity\": 90, \"guarantee\": true}, \"expected\": {\"results\": \"F\", \"pity\": 0, \"guarantee\": false}, \"passed\": false}, {\"check\": \"regression hard pity guarantee #3\", \"actual\": {\"results\": \"--L-----------------\", \"pity\": 17, \"guarantee\": true}, \"expected\": {\"results\": \"-L------------------\", \"pity\": 18, \"guarantee\": true}, \"passed\": false}, {\"check\": \"regression hard pity guarantee #4\", \"actual\": {\"results\": \"--L-\", \"pity\": 1, \"guarantee\": true}, \"expected\": {\"results\": \"-L--\", \"pity\": 2, \"guarantee\": true}, \"passed\": false}, {\"check\": \"first soft pity pull #1\", \"actual\": {\"results\": \"-F\", \"pity\": 0, \"guarantee\": false}, \"expected\": {\"results\": \"-F\", \"pity\": 0, \"guarantee\": false}, \"passed\": true}, {\"check\": \"lost fifty fifty then featured #1\", \"actual\": {\"results\": \"L-F\", \"pity\": 0, \"guarantee\": false}, \"expected\": {\"results\": \"L-F\", \"pity\": 0, \"guarantee\": false}, \"passed\": true}, {\"check\": \"control #1\", \"actual\": {\"results\": \"F--------------\", \"pity\": 14, \"guarantee\": false}, \"expected\": {\"results\": \"F--------------\", \"pity\": 14, \"guarantee\": false}, \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":39.685,"exit_code":1,"observations":[{"actual":{"guarantee":true,"pity":0,"results":"-L"},"check":"hard pity pull #1","expected":{"guarantee":true,"pity":1,"results":"L-"},"passed":false},{"actual":{"guarantee":true,"pity":8,"results":"-F-------L--------"},"check":"regression hard pity guarantee #1","expected":{"guarantee":true,"pity":8,"results":"F--------L--------"},"passed":false},{"actual":{"guarantee":true,"pity":90,"results":"-"},"check":"regression hard pity guarantee #2","expected":{"guarantee":false,"pity":0,"results":"F"},"passed":false},{"actual":{"guarantee":true,"pity":17,"results":"--L-----------------"},"check":"regression hard pity guarantee #3","expected":{"guarantee":true,"pity":18,"results":"-L------------------"},"passed":false},{"actual":{"guarantee":true,"pity":1,"results":"--L-"},"check":"regression hard pity guarantee #4","expected":{"guarantee":true,"pity":2,"results":"-L--"},"passed":false},{"actual":{"guarantee":false,"pity":0,"results":"-F"},"check":"first soft pity pull #1","expected":{"guarantee":false,"pity":0,"results":"-F"},"passed":true},{"actual":{"guarantee":false,"pity":0,"results":"L-F"},"check":"lost fifty fifty then featured #1","expected":{"guarantee":false,"pity":0,"results":"L-F"},"passed":true},{"actual":{"guarantee":false,"pity":14,"results":"F--------------"},"check":"control #1","expected":{"guarantee":false,"pity":14,"results":"F--------------"},"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"hard pity pull #1\", \"actual\": {\"results\": \"-L\", \"pity\": 0, \"guarantee\": true}, \"expected\": {\"results\": \"L-\", \"pity\": 1, \"guarantee\": true}, \"passed\": false}, {\"check\": \"regression hard pity guarantee #1\", \"actual\": {\"results\": \"-F-------L--------\", \"pity\": 8, \"guarantee\": true}, \"expected\": {\"results\": \"F--------L--------\", \"pity\": 8, \"guarantee\": true}, \"passed\": false}, {\"check\": \"regression hard pity guarantee #2\", \"actual\": {\"results\": \"-\", \"pity\": 90, \"guarantee\": true}, \"expected\": {\"results\": \"F\", \"pity\": 0, \"guarantee\": false}, \"passed\": false}, {\"check\": \"regression hard pity guarantee #3\", \"actual\": {\"results\": \"--L-----------------\", \"pity\": 17, \"guarantee\": true}, \"expected\": {\"results\": \"-L------------------\", \"pity\": 18, \"guarantee\": true}, \"passed\": false}, {\"check\": \"regression hard pity guarantee #4\", \"actual\": {\"results\": \"--L-\", \"pity\": 1, \"guarantee\": true}, \"expected\": {\"results\": \"-L--\", \"pity\": 2, \"guarantee\": true}, \"passed\": false}, {\"check\": \"first soft pity pull #1\", \"actual\": {\"results\": \"-F\", \"pity\": 0, \"guarantee\": false}, \"expected\": {\"results\": \"-F\", \"pity\": 0, \"guarantee\": false}, \"passed\": true}, {\"check\": \"lost fifty fifty then featured #1\", \"actual\": {\"results\": \"L-F\", \"pity\": 0, \"guarantee\": false}, \"expected\": {\"results\": \"L-F\", \"pity\": 0, \"guarantee\": false}, \"passed\": true}, {\"check\": \"control #1\", \"actual\": {\"results\": \"F--------------\", \"pity\": 14, \"guarantee\": false}, \"expected\": {\"results\": \"F--------------\", \"pity\": 14, \"guarantee\": false}, \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":41.526,"exit_code":0,"observations":[{"actual":{"guarantee":true,"pity":1,"results":"L-"},"check":"hard pity pull #1","expected":{"guarantee":true,"pity":1,"results":"L-"},"passed":true},{"actual":{"guarantee":true,"pity":8,"results":"F--------L--------"},"check":"regression hard pity guarantee #1","expected":{"guarantee":true,"pity":8,"results":"F--------L--------"},"passed":true},{"actual":{"guarantee":false,"pity":0,"results":"F"},"check":"regression hard pity guarantee #2","expected":{"guarantee":false,"pity":0,"results":"F"},"passed":true},{"actual":{"guarantee":true,"pity":18,"results":"-L------------------"},"check":"regression hard pity guarantee #3","expected":{"guarantee":true,"pity":18,"results":"-L------------------"},"passed":true},{"actual":{"guarantee":true,"pity":2,"results":"-L--"},"check":"regression hard pity guarantee #4","expected":{"guarantee":true,"pity":2,"results":"-L--"},"passed":true},{"actual":{"guarantee":false,"pity":0,"results":"-F"},"check":"first soft pity pull #1","expected":{"guarantee":false,"pity":0,"results":"-F"},"passed":true},{"actual":{"guarantee":false,"pity":0,"results":"L-F"},"check":"lost fifty fifty then featured #1","expected":{"guarantee":false,"pity":0,"results":"L-F"},"passed":true},{"actual":{"guarantee":false,"pity":14,"results":"F--------------"},"check":"control #1","expected":{"guarantee":false,"pity":14,"results":"F--------------"},"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"hard pity pull #1\", \"actual\": {\"results\": \"L-\", \"pity\": 1, \"guarantee\": true}, \"expected\": {\"results\": \"L-\", \"pity\": 1, \"guarantee\": true}, \"passed\": true}, {\"check\": \"regression hard pity guarantee #1\", \"actual\": {\"results\": \"F--------L--------\", \"pity\": 8, \"guarantee\": true}, \"expected\": {\"results\": \"F--------L--------\", \"pity\": 8, \"guarantee\": true}, \"passed\": true}, {\"check\": \"regression hard pity guarantee #2\", \"actual\": {\"results\": \"F\", \"pity\": 0, \"guarantee\": false}, \"expected\": {\"results\": \"F\", \"pity\": 0, \"guarantee\": false}, \"passed\": true}, {\"check\": \"regression hard pity guarantee #3\", \"actual\": {\"results\": \"-L------------------\", \"pity\": 18, \"guarantee\": true}, \"expected\": {\"results\": \"-L------------------\", \"pity\": 18, \"guarantee\": true}, \"passed\": true}, {\"check\": \"regression hard pity guarantee #4\", \"actual\": {\"results\": \"-L--\", \"pity\": 2, \"guarantee\": true}, \"expected\": {\"results\": \"-L--\", \"pity\": 2, \"guarantee\": true}, \"passed\": true}, {\"check\": \"first soft pity pull #1\", \"actual\": {\"results\": \"-F\", \"pity\": 0, \"guarantee\": false}, \"expected\": {\"results\": \"-F\", \"pity\": 0, \"guarantee\": false}, \"passed\": true}, {\"check\": \"lost fifty fifty then featured #1\", \"actual\": {\"results\": \"L-F\", \"pity\": 0, \"guarantee\": false}, \"expected\": {\"results\": \"L-F\", \"pity\": 0, \"guarantee\": false}, \"passed\": true}, {\"check\": \"control #1\", \"actual\": {\"results\": \"F--------------\", \"pity\": 14, \"guarantee\": false}, \"expected\": {\"results\": \"F--------------\", \"pity\": 14, \"guarantee\": false}, \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}