Split rank-limited retriggers so Hack stops courting face payoffs
Business Card claimed a synergy with Hack, but Hack only retriggers 2s-5s and Business Card only pays on faces. The single retrig_scoring tag lumped every retriggerer with every retrigger payoff. retrig_scoring now means rank-agnostic (Dusk, Seltzer, Hanging Chad, Splash). Hack gives retrig_low; Sock and Buskin gives retrig_faces. Payoffs want only the scopes their ranks can reach: low-rank payoffs (Even Steven, Odd Todd, Walkie Talkie, Fibonacci, Wee) add retrig_low, face payoffs (Scary Face, Business, Photograph, Triboulet) add retrig_faces, rank-agnostic ones (Hiker, the suit gems, The Idol) add both. Scholar keeps only retrig_scoring - no retriggerer targets Aces. This also kills Hack+Scholar, Hack+Scary Face, Hack+Photograph, Hack+Triboulet, and Sock and Buskin vs every low-rank payoff. Both new tags are full themes (catalog page, label, teaching line) so Hack and Sock and Buskin stay visible in the Engine tab. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,7 +14,7 @@ does not get redone from scratch every session.
|
||||
| Famous pairs | 36 |
|
||||
| Clashes | 25 |
|
||||
| Cautions | 15 |
|
||||
| Themes | 29 |
|
||||
| Themes | 31 |
|
||||
| Jokers in no famous pair | 102 |
|
||||
|
||||
## Jokers the advisor is silent about
|
||||
@@ -88,8 +88,10 @@ A tag with two is fragile: drop either joker and the theme dies.
|
||||
| `pair` | 4 | 3 | 4 | yes |
|
||||
| `planet` | 3 | 3 | 3 | yes |
|
||||
| `probability` | 1 | 7 | 8 | yes |
|
||||
| `retrig_faces` | 1 | 10 | 11 | yes |
|
||||
| `retrig_held` | 1 | 4 | 5 | yes |
|
||||
| `retrig_scoring` | 6 | 16 | 22 | yes |
|
||||
| `retrig_low` | 1 | 11 | 12 | yes |
|
||||
| `retrig_scoring` | 4 | 16 | 20 | yes |
|
||||
| `sell_value` | 2 | 2 | 4 | yes |
|
||||
| `spades` | 2 | 3 | 3 | yes |
|
||||
| `spectral_gen` | 2 | 2 | **2** | yes |
|
||||
@@ -107,9 +109,7 @@ mis-tagged, the error is spread across the whole database.
|
||||
|
||||
| joker | partners scoring >= 2 |
|
||||
|---|---|
|
||||
| `j_sock_and_buskin` | 18 |
|
||||
| `j_dusk` | 16 |
|
||||
| `j_hack` | 16 |
|
||||
| `j_hanging_chad` | 16 |
|
||||
| `j_selzer` | 16 |
|
||||
| `j_smeared` | 16 |
|
||||
@@ -119,6 +119,8 @@ mis-tagged, the error is spread across the whole database.
|
||||
| `j_bull` | 15 |
|
||||
| `j_four_fingers` | 12 |
|
||||
| `j_seance` | 12 |
|
||||
| `j_sock_and_buskin` | 12 |
|
||||
| `j_blueprint` | 11 |
|
||||
|
||||
Jokers with **no** partner scoring >= 2 anywhere in the game: 25
|
||||
|
||||
|
||||
@@ -393,6 +393,7 @@ end
|
||||
-- mult/chips/xmult are deliberately absent — they hint nothing specific).
|
||||
local TAG_LABEL = {
|
||||
faces = 'face cards', retrig_scoring = 'played-card retriggers',
|
||||
retrig_low = 'low-card (2-5) retriggers', retrig_faces = 'face-card retriggers',
|
||||
retrig_held = 'held-card retriggers', hand_size = 'hand size',
|
||||
hands_up = 'extra hands', discards_up = 'discards',
|
||||
probability = 'listed odds', money = 'money',
|
||||
@@ -819,6 +820,8 @@ local THEME_TABS = {
|
||||
{ label = 'Engine', themes = {
|
||||
{tag = 'faces', name = 'Face cards'},
|
||||
{tag = 'retrig_scoring', name = 'Retrigger played cards'},
|
||||
{tag = 'retrig_low', name = 'Retrigger low cards'},
|
||||
{tag = 'retrig_faces', name = 'Retrigger face cards'},
|
||||
{tag = 'retrig_held', name = 'Retrigger held cards'},
|
||||
{tag = 'copy_target', name = 'Copy targets (Blueprint/Brainstorm)'},
|
||||
{tag = 'probability', name = 'Probability'},
|
||||
|
||||
+28
-19
@@ -8,7 +8,12 @@
|
||||
--- "scaler + multiplier" complement rule)
|
||||
--- money earns money; money = wants money (econ payoffs)
|
||||
--- faces makes cards count as face cards / wants face cards
|
||||
--- retrig_scoring retriggers (or multiplies triggers of) played cards
|
||||
--- retrig_scoring retriggers (or multiplies triggers of) ANY played
|
||||
--- card -- reserve it for rank-agnostic retriggerers
|
||||
--- retrig_low / retrig_faces rank-limited retriggers (Hack's 2s-5s, Sock
|
||||
--- and Buskin's faces); wanted only by payoffs those
|
||||
--- ranks can reach, so Hack never claims to feed a
|
||||
--- face payoff like Business Card
|
||||
--- retrig_held retriggers cards held in hand
|
||||
--- hand_size / hands_up / discards_up resource increases
|
||||
--- probability improves listed probabilities / cares about them
|
||||
@@ -53,16 +58,16 @@ j('j_8_ball', {'tarot_gen'}, {'probability'})
|
||||
j('j_misprint', {'mult'})
|
||||
j('j_raised_fist', {'mult'}, {'retrig_held','hand_size'})
|
||||
j('j_chaos', {})
|
||||
j('j_scary_face', {'chips'}, {'faces','retrig_scoring'})
|
||||
j('j_scary_face', {'chips'}, {'faces','retrig_scoring','retrig_faces'})
|
||||
-- Abstract Joker's Mult is the joker count (`#G.jokers.cards`, card.lua:4119), so
|
||||
-- anything that hands you spare Jokers feeds it. Riff-Raff is +6 Mult on its own.
|
||||
j('j_abstract', {'mult'}, {'joker_gen'})
|
||||
j('j_delayed_grat', {'money'})
|
||||
j('j_gros_michel', {'mult'})
|
||||
j('j_even_steven', {'mult'}, {'retrig_scoring'})
|
||||
j('j_odd_todd', {'chips'}, {'retrig_scoring'})
|
||||
j('j_even_steven', {'mult'}, {'retrig_scoring','retrig_low'})
|
||||
j('j_odd_todd', {'chips'}, {'retrig_scoring','retrig_low'})
|
||||
j('j_scholar', {'chips','mult'}, {'retrig_scoring'})
|
||||
j('j_business', {'money'}, {'faces','probability','retrig_scoring'})
|
||||
j('j_business', {'money'}, {'faces','probability','retrig_scoring','retrig_faces'})
|
||||
j('j_supernova', {'mult'})
|
||||
j('j_ride_the_bus', {'mult'})
|
||||
j('j_egg', {'sell_value'})
|
||||
@@ -97,7 +102,7 @@ j('j_juggler', {'hand_size'})
|
||||
j('j_drunkard', {'discards_up'})
|
||||
j('j_golden', {'money'})
|
||||
j('j_popcorn', {'mult'})
|
||||
j('j_walkie_talkie', {'chips','mult'}, {'retrig_scoring'})
|
||||
j('j_walkie_talkie', {'chips','mult'}, {'retrig_scoring','retrig_low'})
|
||||
j('j_smiley', {'mult'}, {'faces'})
|
||||
j('j_ticket', {'money'}, {'gold_gen'})
|
||||
j('j_swashbuckler', {'mult'}, {'sell_value','joker_gen'})
|
||||
@@ -114,16 +119,16 @@ j('j_ceremonial', {'mult'})
|
||||
j('j_marble', {'stone_gen','card_gen','enhance_gen'})
|
||||
j('j_loyalty_card', {'xmult'})
|
||||
j('j_dusk', {'retrig_scoring'})
|
||||
j('j_fibonacci', {'mult'}, {'retrig_scoring'})
|
||||
j('j_fibonacci', {'mult'}, {'retrig_scoring','retrig_low'})
|
||||
j('j_steel_joker', {'xmult'})
|
||||
j('j_hack', {'retrig_scoring'})
|
||||
j('j_hack', {'retrig_low'}) -- retriggers 2-5 ONLY, never faces/aces
|
||||
j('j_pareidolia', {'faces'})
|
||||
j('j_space', {}, {'probability'})
|
||||
j('j_burglar', {'hands_up'})
|
||||
j('j_blackboard', {'xmult'}, {'spades','clubs'})
|
||||
j('j_sixth_sense', {'spectral_gen'}, {'spectral_gen'})
|
||||
j('j_constellation', {'xmult','planet'}, {'planet'})
|
||||
j('j_hiker', {'chips'}, {'retrig_scoring'})
|
||||
j('j_hiker', {'chips'}, {'retrig_scoring','retrig_low','retrig_faces'})
|
||||
j('j_card_sharp', {'xmult'})
|
||||
j('j_madness', {'xmult','copy_target'})
|
||||
j('j_seance', {'spectral_gen'}, {'straight','flush','spectral_gen'})
|
||||
@@ -138,7 +143,7 @@ j('j_bootstraps', {'mult'}, {'money'})
|
||||
-- it gives the matching-hand tags without wanting them.
|
||||
j('j_dna', {'card_gen','pair','three_kind','four_kind'})
|
||||
j('j_midas_mask', {'gold_gen','enhance_gen'}, {'faces'})
|
||||
j('j_photograph', {'xmult','copy_target'}, {'faces','retrig_scoring'})
|
||||
j('j_photograph', {'xmult','copy_target'}, {'faces','retrig_scoring','retrig_faces'})
|
||||
j('j_stone', {'chips'}, {'stone_gen'})
|
||||
j('j_lucky_cat', {'xmult'}, {'probability'})
|
||||
j('j_baseball', {'xmult'})
|
||||
@@ -152,21 +157,21 @@ j('j_selzer', {'retrig_scoring'})
|
||||
j('j_castle', {'chips'}, {'discards_up'})
|
||||
j('j_mr_bones', {})
|
||||
j('j_acrobat', {'xmult'}, {'hands_up'})
|
||||
j('j_sock_and_buskin', {'retrig_scoring'}, {'faces'})
|
||||
j('j_sock_and_buskin', {'retrig_faces'}, {'faces'}) -- retriggers faces ONLY
|
||||
j('j_troubadour', {'hand_size'})
|
||||
j('j_certificate', {'card_gen'})
|
||||
j('j_smeared', {'flush','suit_flex'})
|
||||
j('j_throwback', {'xmult'})
|
||||
j('j_rough_gem', {'money','diamonds'}, {'retrig_scoring','diamonds','suit_flex'})
|
||||
j('j_bloodstone', {'xmult','hearts'}, {'retrig_scoring','hearts','suit_flex','probability'})
|
||||
j('j_arrowhead', {'chips','spades'}, {'retrig_scoring','spades','suit_flex'})
|
||||
j('j_onyx_agate', {'mult','clubs'}, {'retrig_scoring','clubs','suit_flex'})
|
||||
j('j_rough_gem', {'money','diamonds'}, {'retrig_scoring','retrig_low','retrig_faces','diamonds','suit_flex'})
|
||||
j('j_bloodstone', {'xmult','hearts'}, {'retrig_scoring','retrig_low','retrig_faces','hearts','suit_flex','probability'})
|
||||
j('j_arrowhead', {'chips','spades'}, {'retrig_scoring','retrig_low','retrig_faces','spades','suit_flex'})
|
||||
j('j_onyx_agate', {'mult','clubs'}, {'retrig_scoring','retrig_low','retrig_faces','clubs','suit_flex'})
|
||||
j('j_glass', {'xmult'})
|
||||
j('j_ring_master', {})
|
||||
j('j_flower_pot', {'xmult'}, {'suit_flex'})
|
||||
j('j_merry_andy', {'discards_up'})
|
||||
j('j_oops', {'probability'})
|
||||
j('j_idol', {'xmult','copy_target'}, {'retrig_scoring'})
|
||||
j('j_idol', {'xmult','copy_target'}, {'retrig_scoring','retrig_low','retrig_faces'})
|
||||
j('j_seeing_double', {'xmult','clubs'}, {'clubs','suit_flex'})
|
||||
j('j_matador', {'money'})
|
||||
j('j_hit_the_road', {'xmult'}, {'discards_up'})
|
||||
@@ -189,11 +194,11 @@ j('j_invisible', {}, {'copy_target'})
|
||||
j('j_blueprint', {}, {'copy_target'})
|
||||
j('j_brainstorm', {}, {'copy_target'})
|
||||
j('j_drivers_license', {'xmult'}, {'enhance_gen'})
|
||||
j('j_wee', {'chips'}, {'retrig_scoring'})
|
||||
j('j_wee', {'chips'}, {'retrig_scoring','retrig_low'})
|
||||
|
||||
-- Legendary jokers ----------------------------------------------------------
|
||||
j('j_caino', {'xmult','copy_target'}, {'faces'})
|
||||
j('j_triboulet', {'xmult','copy_target'}, {'retrig_scoring'})
|
||||
j('j_triboulet', {'xmult','copy_target'}, {'retrig_scoring','retrig_faces'})
|
||||
j('j_yorick', {'xmult','copy_target'}, {'discards_up'})
|
||||
j('j_chicot', {})
|
||||
j('j_perkeo', {'tarot_gen'}, {'tarot_gen'})
|
||||
@@ -345,6 +350,8 @@ local CAUTIONS = {
|
||||
local TAG_TEXT = {
|
||||
faces = {give = 'turns cards into faces', want = 'pays off face cards'},
|
||||
retrig_scoring = {give = 'retriggers scored cards', want = 'pays per extra trigger'},
|
||||
retrig_low = {give = 'retriggers 2s through 5s', want = 'pays per extra trigger'},
|
||||
retrig_faces = {give = 'retriggers face cards', want = 'pays per extra trigger'},
|
||||
retrig_held = {give = 'retriggers cards in hand', want = 'pays off held-card triggers'},
|
||||
hand_size = {give = 'adds hand size', want = 'wants a big hand'},
|
||||
hands_up = {give = 'grants extra hands', want = 'uses the extra hands'},
|
||||
@@ -395,7 +402,7 @@ local TAG_TEXT = {
|
||||
-- Order in which tags are considered when picking the one reason to show;
|
||||
-- most specific mechanics first, broad engine roles last.
|
||||
local TAG_ORDER = {
|
||||
'retrig_held', 'retrig_scoring', 'faces',
|
||||
'retrig_held', 'retrig_low', 'retrig_faces', 'retrig_scoring', 'faces',
|
||||
'gold_gen', 'stone_gen', 'enhance_gen', 'card_gen',
|
||||
'tarot_gen', 'spectral_gen', 'planet',
|
||||
'probability', 'discards_up', 'hands_up', 'hand_size',
|
||||
@@ -411,6 +418,8 @@ local TAG_ORDER = {
|
||||
local THEME_INFO = {
|
||||
faces = 'Face cards trigger these effects; makers like Pareidolia turn every card into one.',
|
||||
retrig_scoring = 'Retriggers make each scored card count again, so per-card payoffs double up.',
|
||||
retrig_low = 'Hack replays each scored 2-5; low-rank payoffs like Fibonacci collect twice.',
|
||||
retrig_faces = 'Sock and Buskin replays scored face cards, so face payoffs trigger again.',
|
||||
retrig_held = 'Some jokers pay for cards sitting in hand; retriggering the hand pays them again.',
|
||||
copy_target = 'Blueprint and Brainstorm mirror a joker - the stronger the target, the better.',
|
||||
probability = 'Listed "1 in X" odds are dice rolls; odds boosters make gambling jokers hit more.',
|
||||
|
||||
@@ -140,10 +140,17 @@ section('Engine: scoring tiers')
|
||||
eq(JCA.score('j_baron', 'j_mime'), 6, 'famous pair + shared tags = 6')
|
||||
eq(JCA.score('j_blueprint', 'j_brainstorm'), 4, 'famous pair alone = 4')
|
||||
eq(JCA.score('j_jolly', 'j_sly'), 4, 'hand-type cluster (2 + 2) = 4')
|
||||
-- Hack gives retrig_scoring, which The Idol wants; neither side triggers the
|
||||
-- generic complement (Hack adds no Mult or Chips), so this is a clean 2.
|
||||
-- Hack gives retrig_low, which The Idol wants (the Idol card can roll any
|
||||
-- rank); neither side triggers the generic complement (Hack adds no Mult or
|
||||
-- Chips), so this is a clean 2.
|
||||
eq(JCA.score('j_hack', 'j_idol'), 2, 'single tag match = 2')
|
||||
eq(JCA.score('j_8_ball', 'j_scary_face'), 0, 'unrelated jokers = 0')
|
||||
-- Rank-limited retriggers must not claim payoffs their ranks cannot reach:
|
||||
-- Hack replays only 2s-5s, so it never feeds a face or Ace payoff; Sock and
|
||||
-- Buskin replays only faces, so Wee's 2s mean nothing to it.
|
||||
eq(JCA.score('j_hack', 'j_business'), 0, 'Hack cannot retrigger Business Card faces')
|
||||
eq(JCA.score('j_hack', 'j_scholar'), 0, 'Hack cannot retrigger Scholar Aces')
|
||||
eq(JCA.score('j_sock_and_buskin', 'j_wee'), 0, 'Sock and Buskin cannot retrigger 2s')
|
||||
-- The generic complement stacks on top of a tag match: Gluttonous gives clubs
|
||||
-- (Blackboard wants them) AND feeds Blackboard's xMult, so 2 + 1.
|
||||
eq(JCA.score('j_gluttenous_joker', 'j_blackboard'), 3, 'tag match + generic complement = 3')
|
||||
@@ -505,7 +512,7 @@ JCA.register('j_mod_test', {'mult', 'bogus_tag'}, {'retrig_scoring'})
|
||||
ok(JCA.db.j_mod_test, 'JCA.register adds a joker')
|
||||
ok(JCA.db.j_mod_test.gives.mult, 'known tags survive registration')
|
||||
ok(not JCA.db.j_mod_test.gives.bogus_tag, 'unknown tags are dropped, not fatal')
|
||||
ok(JCA.score('j_mod_test', 'j_hack') >= 2, 'a registered joker scores against vanilla')
|
||||
ok(JCA.score('j_mod_test', 'j_dusk') >= 2, 'a registered joker scores against vanilla')
|
||||
local before = JCA.score('j_mod_test', 'j_baron')
|
||||
JCA.register_pair('j_mod_test', 'j_baron', 'test blurb')
|
||||
eq(JCA.score('j_mod_test', 'j_baron') - before, 4, 'JCA.register_pair adds the +4 pair bonus')
|
||||
|
||||
Reference in New Issue
Block a user