diff --git a/main.lua b/main.lua index 445ce82..75f0b45 100644 --- a/main.lua +++ b/main.lua @@ -844,8 +844,31 @@ end -- during the current run are also recorded in G.GAME.jca_run_combos (saved -- with the run) for end-of-run display. +-- Total pairwise synergy across the current board: every owned pair scored +-- once. The run's high-water mark is kept in G.GAME.jca_peak_synergy for the +-- recap; it can only rise when a joker arrives, so the emplace hook that +-- already drives discovery is the one place that needs to look. +function JCA.board_synergy() + if not (G.jokers and G.jokers.cards) then return 0 end + local keys = {} + for _, c in ipairs(G.jokers.cards) do + if is_joker(c) then keys[#keys + 1] = c.config.center.key end + end + local sum = 0 + for i = 1, #keys do + for j = i + 1, #keys do + sum = sum + JCA.score(keys[i], keys[j]) + end + end + return sum +end + function JCA.check_discoveries() if not (G.jokers and G.jokers.cards) then return end + if G.GAME then + local s = JCA.board_synergy() + if s > (G.GAME.jca_peak_synergy or 0) then G.GAME.jca_peak_synergy = s end + end local keys = {} for _, c in ipairs(G.jokers.cards) do if is_joker(c) then keys[#keys + 1] = c.config.center.key end @@ -943,28 +966,37 @@ end local function recap_row() local combos = G.GAME and G.GAME.jca_run_combos - if not combos or not next(combos) then return nil end + local peak = (G.GAME and G.GAME.jca_peak_synergy) or 0 local names = {} - for pk in pairs(combos) do + for pk in pairs(combos or {}) do local a, b = pk:match('^(.-)|(.+)$') if a then names[#names + 1] = name_of(a) .. ' + ' .. name_of(b) end end - if #names == 0 then return nil end + if #names == 0 and peak <= 0 then return nil end table.sort(names) - local rows = {{n = G.UIT.R, config = {align = 'cm', padding = 0.03}, nodes = { - {n = G.UIT.T, config = {text = 'Combos fielded this run', - colour = G.C.GOLD, scale = 0.35, shadow = true}}, - }}} - for i = 1, math.min(#names, 6) do - rows[#rows + 1] = {n = G.UIT.R, config = {align = 'cm', padding = 0.02}, nodes = { - {n = G.UIT.T, config = {text = names[i], - colour = G.C.WHITE, scale = 0.3, shadow = true}}, + local rows = {} + if #names > 0 then + rows[#rows + 1] = {n = G.UIT.R, config = {align = 'cm', padding = 0.03}, nodes = { + {n = G.UIT.T, config = {text = 'Combos fielded this run', + colour = G.C.GOLD, scale = 0.35, shadow = true}}, }} + for i = 1, math.min(#names, 6) do + rows[#rows + 1] = {n = G.UIT.R, config = {align = 'cm', padding = 0.02}, nodes = { + {n = G.UIT.T, config = {text = names[i], + colour = G.C.WHITE, scale = 0.3, shadow = true}}, + }} + end + if #names > 6 then + rows[#rows + 1] = {n = G.UIT.R, config = {align = 'cm', padding = 0.02}, nodes = { + {n = G.UIT.T, config = {text = '+' .. (#names - 6) .. ' more', + colour = G.C.UI.TEXT_LIGHT, scale = 0.3}}, + }} + end end - if #names > 6 then + if peak > 0 then rows[#rows + 1] = {n = G.UIT.R, config = {align = 'cm', padding = 0.02}, nodes = { - {n = G.UIT.T, config = {text = '+' .. (#names - 6) .. ' more', - colour = G.C.UI.TEXT_LIGHT, scale = 0.3}}, + {n = G.UIT.T, config = {text = 'Peak board synergy: ' .. peak, + colour = G.C.GOLD, scale = 0.3, shadow = true}}, }} end return {n = G.UIT.R, config = {align = 'cm', padding = 0.06}, nodes = rows} diff --git a/test.lua b/test.lua index 024034b..f86b730 100644 --- a/test.lua +++ b/test.lua @@ -415,6 +415,28 @@ per[2].ability = {perishable = true, perish_tally = 0} eq(JCA.weakest_link(), per[2], 'but a perished joker is the cut at any score - it will never work again') +-------------------------------------------------------------------------------- +section('Engine: board synergy total and its run peak') +-------------------------------------------------------------------------------- + +-- Every owned pair scored once: Baron+Mime is the famous 6, the plain Joker +-- adds only its generic +1 against Baron's xMult. +field('j_baron', 'j_mime', 'j_joker') +eq(JCA.board_synergy(), 7, 'board synergy sums every owned pair once') + +-- The peak rides the same emplace hook as discovery, and never goes down. +-- Discovery state is snapshotted so this cannot leak into the UI tests. +local saved_disc, saved_themes = JCA.config.discovered, JCA.config.themes_found +JCA.config.discovered, JCA.config.themes_found = {}, {} +G.GAME = {} +JCA.check_discoveries() +eq(G.GAME.jca_peak_synergy, 7, 'the emplace hook records the high-water mark') +field('j_joker') +JCA.check_discoveries() +eq(G.GAME.jca_peak_synergy, 7, 'selling down does not lower the recorded peak') +G.GAME = {} +JCA.config.discovered, JCA.config.themes_found = saved_disc, saved_themes + -------------------------------------------------------------------------------- section('Engine: deck context counts base suits') --------------------------------------------------------------------------------