Add the shopping list: name the gaps the board wants filled

JCA.build_gaps() splits the board's tags into unmet wants (some joker
wants it, no OTHER joker gives it) and untapped hooks (given, nothing
pays it off). Rendered at the top of the in-run Combos overlay via
TAG_LABEL; engine roles stay excluded because they hint nothing.
Board slots are compared by index, not db-entry identity, so two
copies of one cluster joker correctly feed each other.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-07-14 13:41:32 -07:00
parent ff71a8ef12
commit b81a6c6dcd
2 changed files with 103 additions and 9 deletions
+74 -9
View File
@@ -421,6 +421,46 @@ local function tag_labels(tag_set)
return labels
end
-- Build gaps: what the current board is shopping for. A tag is a gap when
-- some owned joker wants it and no OTHER owned joker gives it (same rule as
-- scoring and theme discovery: a joker cannot feed itself). The reverse -- a
-- give no other owned joker wants -- is an untapped hook a future purchase
-- could pay off. Engine roles (mult/chips/xmult) are skipped for the same
-- reason they have no TAG_LABEL: they hint nothing specific. Returns two
-- tag arrays in TAG_ORDER, so the display is stable across hovers.
function JCA.build_gaps()
local looking, untapped = {}, {}
if not (G.jokers and G.jokers.cards) then return looking, untapped end
local entries = {}
for _, c in ipairs(G.jokers.cards) do
if is_joker(c) then
local e = JCA.db[c.config.center.key]
if e then entries[#entries + 1] = e end
end
end
-- Compare by index, not table identity: two copies of the same joker
-- share one db entry, and they DO feed each other's cluster tags.
local function others_have(side, tag, self_idx)
for i, e in ipairs(entries) do
if i ~= self_idx and e[side][tag] then return true end
end
end
local want_gap, give_hook = {}, {}
for i, e in ipairs(entries) do
for t in pairs(e.wants) do
if TAG_LABEL[t] and not others_have('gives', t, i) then want_gap[t] = true end
end
for t in pairs(e.gives) do
if TAG_LABEL[t] and not others_have('wants', t, i) then give_hook[t] = true end
end
end
for _, t in ipairs(data.tag_order) do
if want_gap[t] then looking[#looking + 1] = t end
if give_hook[t] then untapped[#untapped + 1] = t end
end
return looking, untapped
end
local function tooltip_rows(card)
-- Touch mode enlarges every advice row for phone screens (see config.lua).
local S = JCA.config.touch_mode and 1.4 or 1
@@ -1250,18 +1290,43 @@ end
-- in an overlay. The overlay reuses catalog_tabs(); the page cyclers work
-- unchanged because vanilla create_tabs also names its body 'tab_contents'.
-- Shopping list shown at the top of the in-run overlay: the tags the board
-- wants but nothing else on it gives, and the hooks it gives that nothing
-- pays off yet. Teaching content, so learning mode keeps it.
local function build_gaps_rows()
local looking, untapped = JCA.build_gaps()
local nodes = {}
local function line(prefix, tags, colour)
if #tags == 0 then return end
local labels = {}
for _, t in ipairs(tags) do labels[#labels + 1] = {name = TAG_LABEL[t]} end
for i, l in ipairs(wrap_names(labels, 58, 2)) do
nodes[#nodes + 1] = {n = G.UIT.R, config = {align = 'cm', padding = 0.02}, nodes = {
{n = G.UIT.T, config = {text = (i == 1 and prefix or ' ') .. l,
colour = colour, scale = 0.3, shadow = true}},
}}
end
end
line('Your build is looking for: ', looking, G.C.GOLD)
line('Untapped on your board: ', untapped, G.C.UI.TEXT_LIGHT)
if #nodes == 0 then return nil end
return {n = G.UIT.R, config = {align = 'cm', padding = 0.04}, nodes = nodes}
end
G.FUNCS.jca_open_catalog = function()
local contents = {}
local ok, gaps = pcall(build_gaps_rows)
if ok and gaps then contents[#contents + 1] = gaps end
contents[#contents + 1] = {n = G.UIT.R, config = {align = 'tm', padding = 0}, nodes = {
create_tabs({
tabs = catalog_tabs(),
snap_to_nav = true,
colour = G.C.BOOSTER,
}),
}}
G.FUNCS.overlay_menu{definition = create_UIBox_generic_options({
back_func = 'exit_overlay_menu',
contents = {
{n = G.UIT.R, config = {align = 'tm', padding = 0}, nodes = {
create_tabs({
tabs = catalog_tabs(),
snap_to_nav = true,
colour = G.C.BOOSTER,
}),
}},
},
contents = contents,
})}
end