Commit 81a1b411 authored by Vury Leo's avatar Vury Leo

Add has_same

parent 5ca698c3
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
local s,id,o=GetID() local s,id,o=GetID()
function s.initial_effect(c) function s.initial_effect(c)
c:EnableReviveLimit() c:EnableReviveLimit()
aux.AddFusionProcFunRep(c,s.ffilter,2,true) -- aux.AddFusionProcFunRep(c,s.ffilter,2,true)
Fusion.AddFusionProcedure(c,{ Fusion.AddFusionProcedure(c,{
slots={ slots={
Fusion.Slot.Group({ Fusion.Slot.Group({
...@@ -10,7 +10,7 @@ function s.initial_effect(c) ...@@ -10,7 +10,7 @@ function s.initial_effect(c)
max=2, max=2,
unique_by=function(mc) return { mc:GetCode(),mc:GetFusionCode() } end, unique_by=function(mc) return { mc:GetCode(),mc:GetFusionCode() } end,
has_same={ has_same={
function(mc) return mc:GetFusionAttribute() end, function(mc,tc) return mc:GetFusionAttribute(tc:GetOwner()) end,
function(mc) return mc:GetRace() end, function(mc) return mc:GetRace() end,
} }
}) })
......
...@@ -3500,11 +3500,11 @@ function Fusion.FusionCondition(slots,allow_extras) ...@@ -3500,11 +3500,11 @@ function Fusion.FusionCondition(slots,allow_extras)
end end
-- all has_same on S -- all has_same on S
for _,fn in ipairs(grp.has_same) do for _,fn in ipairs(grp.has_same) do
local v0=fn(S[1]) local v0=fn(S[1],e:GetHandler())
if type(v0)=="number" then if type(v0)=="number" then
local mask=v0 local mask=v0
for j=2,#S do for j=2,#S do
mask=mask&fn(S[j]) mask=mask&fn(S[j],e:GetHandler())
if mask==0 then return false end if mask==0 then return false end
end end
else else
...@@ -3512,7 +3512,7 @@ function Fusion.FusionCondition(slots,allow_extras) ...@@ -3512,7 +3512,7 @@ function Fusion.FusionCondition(slots,allow_extras)
for _, key in ipairs(v0) do common[key] = true end for _, key in ipairs(v0) do common[key] = true end
for j=2,#S do for j=2,#S do
local next_common = {} local next_common = {}
for _,key in ipairs(fn(S[j])) do for _,key in ipairs(fn(S[j],e:GetHandler())) do
if common[key] then if common[key] then
next_common[key]=true next_common[key]=true
end end
...@@ -3533,7 +3533,7 @@ function Fusion.FusionCondition(slots,allow_extras) ...@@ -3533,7 +3533,7 @@ function Fusion.FusionCondition(slots,allow_extras)
end end
for idx=start,n do for idx=start,n do
table.insert(comb,idx) table.insert(comb,idx)
dfs_comb(idx + 1) dfs_comb(idx+1)
table.remove(comb) table.remove(comb)
if found then return end if found then return end
end end
...@@ -3543,12 +3543,12 @@ function Fusion.FusionCondition(slots,allow_extras) ...@@ -3543,12 +3543,12 @@ function Fusion.FusionCondition(slots,allow_extras)
if not found then return false end if not found then return false end
else else
for _,fn in ipairs(grp.has_same) do for _,fn in ipairs(grp.has_same) do
local v0=fn(matched[1]) local v0=fn(matched[1],e:GetHandler())
if type(v0)=="number" then if type(v0)=="number" then
-- bitmask path -- bitmask path
local common_mask=v0 local common_mask=v0
for j=2,#matched do for j=2,#matched do
common_mask=common_mask&fn(matched[j]) common_mask=common_mask&fn(matched[j],e:GetHandler())
if common_mask==0 then if common_mask==0 then
return false return false
end end
...@@ -3561,7 +3561,7 @@ function Fusion.FusionCondition(slots,allow_extras) ...@@ -3561,7 +3561,7 @@ function Fusion.FusionCondition(slots,allow_extras)
end end
for j=2,#matched do for j=2,#matched do
local next_common={} local next_common={}
for _, k in ipairs(fn(matched[j])) do for _, k in ipairs(fn(matched[j],e:GetHandler())) do
if common[k] then if common[k] then
next_common[k]=true next_common[k]=true
end end
...@@ -3663,7 +3663,7 @@ function Fusion.FusionOperation(slots) ...@@ -3663,7 +3663,7 @@ function Fusion.FusionOperation(slots)
max_req=max_req+1 max_req=max_req+1
end end
end end
local max_req=math.min(max_req,eg:GetCount()) max_req=math.min(max_req,eg:GetCount())
-- prompt player -- prompt player
Duel.Hint(HINT_SELECTMSG, tp, HINTMSG_FMATERIAL) Duel.Hint(HINT_SELECTMSG, tp, HINTMSG_FMATERIAL)
...@@ -3812,17 +3812,19 @@ function Fusion.FindAllMappings(cards_sel,slots,handler) ...@@ -3812,17 +3812,19 @@ function Fusion.FindAllMappings(cards_sel,slots,handler)
-- passes all uniqueness checks → record it -- passes all uniqueness checks → record it
local copy={} local copy={}
for k,v in pairs(mapping) do for k,v in pairs(mapping) do
copy[k] = v copy[k]=v
end end
table.insert(all_maps, copy) table.insert(all_maps,copy)
return return
end end
local tc=cards_sel[idx] local tc=cards_sel[idx]
local any_match=false -- track if we managed to assign tc
-- try single slots -- try single slots
for i,slot in ipairs(slots) do for i,slot in ipairs(slots) do
if not slot.group and not filled[i] and Fusion.MatchSlot(tc, slot, handler) then if not slot.group and not filled[i] and Fusion.MatchSlot(tc,slot,handler) then
any_match=true
filled[i]=true filled[i]=true
mapping[idx]=i mapping[idx]=i
dfs(idx+1) dfs(idx+1)
...@@ -3835,9 +3837,50 @@ function Fusion.FindAllMappings(cards_sel,slots,handler) ...@@ -3835,9 +3837,50 @@ function Fusion.FindAllMappings(cards_sel,slots,handler)
for i,slot in ipairs(slots) do for i,slot in ipairs(slots) do
if slot.group then if slot.group then
local assigned=group_assigned[i] local assigned=group_assigned[i]
local max_ok=assigned<slot.group.max if assigned<slot.group.max then
if max_ok and (not slot.group.filter or slot.group.filter(tc)) then -- base filter
group_assigned[i]=assigned+1 if not slot.group.filter or slot.group.filter(tc) then
-- has_same check: only if there's already ≥1 in this slot
local ok=true
if slot.group.has_same and assigned>0 then
for _,fn in ipairs(slot.group.has_same) do
-- start intersection with this candidate
local v0=fn(tc,handler)
if type(v0)=="number" then
-- bitmask path
local mask=v0
-- AND with each already‐assigned card
for j=1,idx-1 do
if mapping[j]==i then
mask=mask&fn(cards_sel[j],handler)
if mask==0 then break end
end
end
if mask==0 then ok=false end
else
-- list-of-keys path
local common={}
for _,k in ipairs(v0) do common[k]=true end
-- intersect with each already-assigned card
for j=1,idx-1 do
if mapping[j]==i then
local next_c={}
for _,k in ipairs(fn(cards_sel[j],handler)) do
if common[k] then next_c[k]=true end
end
common=next_c
if not next(common) then break end
end
end
if not next(common) then ok=false end
end
if not ok then break end
end
end
if ok then
any_match=true
group_assigned[i]=assigned + 1
mapping[idx]=i mapping[idx]=i
dfs(idx+1) dfs(idx+1)
group_assigned[i]=assigned group_assigned[i]=assigned
...@@ -3846,6 +3889,13 @@ function Fusion.FindAllMappings(cards_sel,slots,handler) ...@@ -3846,6 +3889,13 @@ function Fusion.FindAllMappings(cards_sel,slots,handler)
end end
end end
end end
end
-- If we couldn’t assign tc to any slot, prune this branch
if not any_match then
return
end
end
dfs(1) dfs(1)
return all_maps return all_maps
...@@ -3914,16 +3964,23 @@ function Fusion.CanCompleteFromMappings(e,sel,eg,slots,handler,gc,chkf) ...@@ -3914,16 +3964,23 @@ function Fusion.CanCompleteFromMappings(e,sel,eg,slots,handler,gc,chkf)
end end
-- if this slot has a has_same, wrap its filter to include only sames -- if this slot has a has_same, wrap its filter to include only sames
if slot.group.has_same then if slot.group.has_same then
-- only if there is at least one already‐selected card for this slot…
local has_sel = false
for _,mapped_i in pairs(mapping) do
if mapped_i==i then
has_sel=true
break
end
end
if has_sel then
-- precompute, for each fn in has_same, the overlap of already-mapped cards -- precompute, for each fn in has_same, the overlap of already-mapped cards
local used_overlap={} -- fn → (number mask) or (table of keys) local used_overlap={} -- fn → (number mask) or (table of keys)
for _,fn in ipairs(slot.group.has_same) do for _,fn in ipairs(slot.group.has_same) do
local bitmask,keytbl=nil,{} local bitmask,keytbl=nil,{}
-- fold each selected card’s fn(...) into either bitmask or keytbl -- fold each selected card’s fn(...) into either bitmask or keytbl
for idx,mapped_i in pairs(mapping) do for idx,mapped_i in pairs(mapping) do
if mapped_i==i then if mapped_i==i then
local v=fn(cards_sel[idx]) local v=fn(cards_sel[idx],handler)
if type(v)=="number" then if type(v)=="number" then
bitmask=bitmask and (bitmask&v) or v bitmask=bitmask and (bitmask&v) or v
elseif type(v)=="table" then elseif type(v)=="table" then
...@@ -3933,7 +3990,6 @@ function Fusion.CanCompleteFromMappings(e,sel,eg,slots,handler,gc,chkf) ...@@ -3933,7 +3990,6 @@ function Fusion.CanCompleteFromMappings(e,sel,eg,slots,handler,gc,chkf)
end end
end end
end end
-- store whichever collapsed structure is nonempty -- store whichever collapsed structure is nonempty
if bitmask then if bitmask then
used_overlap[fn]=bitmask used_overlap[fn]=bitmask
...@@ -3941,17 +3997,16 @@ function Fusion.CanCompleteFromMappings(e,sel,eg,slots,handler,gc,chkf) ...@@ -3941,17 +3997,16 @@ function Fusion.CanCompleteFromMappings(e,sel,eg,slots,handler,gc,chkf)
used_overlap[fn]=keytbl used_overlap[fn]=keytbl
end end
end end
-- wrap the existing filter so it also enforces all has_same overlaps -- wrap the existing filter so it also enforces all has_same overlaps
local prev=new_filter local prev=new_filter
new_filter=function(tc) new_filter=function(mc)
-- original criteria -- original criteria
if prev and not prev(tc) then if prev and not prev(mc) then
return false return false
end end
-- for each fn in has_same, check against the precomputed overlap -- for each fn in has_same, check against the precomputed overlap
for fn,overlap in pairs(used_overlap) do for fn,overlap in pairs(used_overlap) do
local v=fn(tc) local v=fn(mc,handler)
if type(overlap)=="number" then if type(overlap)=="number" then
-- bitmask path -- bitmask path
if (overlap&v)==0 then if (overlap&v)==0 then
...@@ -3974,6 +4029,7 @@ function Fusion.CanCompleteFromMappings(e,sel,eg,slots,handler,gc,chkf) ...@@ -3974,6 +4029,7 @@ function Fusion.CanCompleteFromMappings(e,sel,eg,slots,handler,gc,chkf)
return true return true
end end
end end
end
if need>0 then if need>0 then
-- preserve the full group slot -- preserve the full group slot
table.insert(rem_slots,{ table.insert(rem_slots,{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment