Commit 5ca698c3 authored by Vury Leo's avatar Vury Leo

Add has_same

parent ab62c789
--共命の翼ガルーラ
function c11765832.initial_effect(c)
local s,id,o=GetID()
function s.initial_effect(c)
c:EnableReviveLimit()
aux.AddFusionProcFunRep(c,c11765832.ffilter,2,true)
aux.AddFusionProcFunRep(c,s.ffilter,2,true)
Fusion.AddFusionProcedure(c,{
slots={
Fusion.Slot.Group({
min=2,
max=2,
unique_by=function(mc) return { mc:GetCode(),mc:GetFusionCode() } end,
has_same={
function(mc) return mc:GetFusionAttribute() end,
function(mc) return mc:GetRace() end,
}
})
}
})
--double damage
local e1=Effect.CreateEffect(c)
e1:SetType(EFFECT_TYPE_SINGLE)
......@@ -10,31 +24,31 @@ function c11765832.initial_effect(c)
c:RegisterEffect(e1)
--draw
local e2=Effect.CreateEffect(c)
e2:SetDescription(aux.Stringid(11765832,0))
e2:SetDescription(aux.Stringid(id,0))
e2:SetCategory(CATEGORY_DRAW)
e2:SetType(EFFECT_TYPE_SINGLE+EFFECT_TYPE_TRIGGER_O)
e2:SetProperty(EFFECT_FLAG_DELAY+EFFECT_FLAG_PLAYER_TARGET)
e2:SetCode(EVENT_TO_GRAVE)
e2:SetCountLimit(1,11765832)
e2:SetTarget(c11765832.target)
e2:SetOperation(c11765832.operation)
e2:SetCountLimit(1,id)
e2:SetTarget(s.target)
e2:SetOperation(s.operation)
c:RegisterEffect(e2)
end
function c11765832.matchfilter(c,attr,race)
function s.matchfilter(c,attr,race)
return c:IsFusionAttribute(attr) and c:IsRace(race)
end
function c11765832.ffilter(c,fc,sub,mg,sg)
function s.ffilter(c,fc,sub,mg,sg)
return not sg or sg:FilterCount(aux.TRUE,c)==0
or (sg:IsExists(c11765832.matchfilter,#sg-1,c,c:GetFusionAttribute(),c:GetRace())
or (sg:IsExists(s.matchfilter,#sg-1,c,c:GetFusionAttribute(),c:GetRace())
and not sg:IsExists(Card.IsFusionCode,1,c,c:GetFusionCode()))
end
function c11765832.target(e,tp,eg,ep,ev,re,r,rp,chk)
function s.target(e,tp,eg,ep,ev,re,r,rp,chk)
if chk==0 then return Duel.IsPlayerCanDraw(tp,1) end
Duel.SetTargetPlayer(tp)
Duel.SetTargetParam(1)
Duel.SetOperationInfo(0,CATEGORY_DRAW,nil,0,tp,1)
end
function c11765832.operation(e,tp,eg,ep,ev,re,r,rp)
function s.operation(e,tp,eg,ep,ev,re,r,rp)
local p,d=Duel.GetChainInfo(0,CHAININFO_TARGET_PLAYER,CHAININFO_TARGET_PARAM)
Duel.Draw(p,d,REASON_EFFECT)
end
......@@ -3465,7 +3465,7 @@ function Fusion.FusionCondition(slots,allow_extras)
return false
end
end
-- 3) unique‐key check
-- unique‐key check
if grp.unique_by then
if allow_extras then
-- in “search” mode we only require *some* subset of size grp.min
......@@ -3481,6 +3481,103 @@ function Fusion.FusionCondition(slots,allow_extras)
end
end
end
-- has_same: each fn must overlap
if grp.has_same then
if allow_extras then
-- search-mode: find SOME subset of size grp.min satisfying both unique_by & all has_same
local n,k=#matched,grp.min
local comb,found={},false
local function check_subset()
local S={}
for _,idx_sub in ipairs(comb) do
table.insert(S,matched[idx_sub])
end
-- unique_by on S
if grp.unique_by then
local m=Fusion.UniqueByMatching(grp.unique_by,k)
if not m(S) then return false end
end
-- all has_same on S
for _,fn in ipairs(grp.has_same) do
local v0=fn(S[1])
if type(v0)=="number" then
local mask=v0
for j=2,#S do
mask=mask&fn(S[j])
if mask==0 then return false end
end
else
local common={}
for _, key in ipairs(v0) do common[key] = true end
for j=2,#S do
local next_common = {}
for _,key in ipairs(fn(S[j])) do
if common[key] then
next_common[key]=true
end
end
common=next_common
if next(common)==nil then return false end
end
end
end
return true
end
local function dfs_comb(start)
if found then return end
if #comb==k then
if check_subset() then found = true end
return
end
for idx=start,n do
table.insert(comb,idx)
dfs_comb(idx + 1)
table.remove(comb)
if found then return end
end
end
dfs_comb(1)
if not found then return false end
else
for _,fn in ipairs(grp.has_same) do
local v0=fn(matched[1])
if type(v0)=="number" then
-- bitmask path
local common_mask=v0
for j=2,#matched do
common_mask=common_mask&fn(matched[j])
if common_mask==0 then
return false
end
end
elseif type(v0)=="table" then
-- list-of-keys path
local common={}
for _,k in ipairs(v0) do
common[k]=true
end
for j=2,#matched do
local next_common={}
for _, k in ipairs(fn(matched[j])) do
if common[k] then
next_common[k]=true
end
end
common=next_common
if next(common)==nil then
return false
end
end
else
error("unsupported return type of group.has_same")
return false
end
end
end
end
end
return true
end
......@@ -3815,15 +3912,80 @@ function Fusion.CanCompleteFromMappings(e,sel,eg,slots,handler,gc,chkf)
local used_keys=Fusion.ExtractUsedKeys(cards_sel,mapping,i,slot.group.unique_by)
new_filter=Fusion.MakeExcludeFilter(new_filter,slot.group.unique_by,used_keys)
end
-- preserve the full group slot
table.insert(rem_slots,{
group={
min=need,
max=slot.group.max-slot.group.min+need,
filter=new_filter,
unique_by=slot.unique_by,
}
})
-- if this slot has a has_same, wrap its filter to include only sames
if slot.group.has_same then
-- precompute, for each fn in has_same, the overlap of already-mapped cards
local used_overlap={} -- fn → (number mask) or (table of keys)
for _,fn in ipairs(slot.group.has_same) do
local bitmask,keytbl=nil,{}
-- fold each selected card’s fn(...) into either bitmask or keytbl
for idx,mapped_i in pairs(mapping) do
if mapped_i==i then
local v=fn(cards_sel[idx])
if type(v)=="number" then
bitmask=bitmask and (bitmask&v) or v
elseif type(v)=="table" then
for _,k in ipairs(v) do
keytbl[k]=true
end
end
end
end
-- store whichever collapsed structure is nonempty
if bitmask then
used_overlap[fn]=bitmask
elseif next(keytbl)~=nil then
used_overlap[fn]=keytbl
end
end
-- wrap the existing filter so it also enforces all has_same overlaps
local prev=new_filter
new_filter=function(tc)
-- original criteria
if prev and not prev(tc) then
return false
end
-- for each fn in has_same, check against the precomputed overlap
for fn,overlap in pairs(used_overlap) do
local v=fn(tc)
if type(overlap)=="number" then
-- bitmask path
if (overlap&v)==0 then
return false
end
else
-- list-of-keys path
local ok=false
for _,k in ipairs(v) do
if overlap[k] then
ok=true
break
end
end
if not ok then
return false
end
end
end
return true
end
end
if need>0 then
-- preserve the full group slot
table.insert(rem_slots,{
group={
min=need,
max=slot.group.max-slot.group.min+need,
filter=new_filter,
unique_by=slot.unique_by,
has_same=slot.has_same,
}
})
end
else
if not filled_single[i] then
-- single‐slot still unfilled
......
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