Commit 7c961424 authored by Vury Leo's avatar Vury Leo

init new synchro

parent 47840bc7
--A・O・J カタストル --A・O・J カタストル
function c26593852.initial_effect(c) function c26593852.initial_effect(c)
--synchro summon --synchro summon
aux.AddSynchroProcedure(c,nil,aux.NonTuner(nil),1) Synchro.AddSynchroProcedure(c)
-- aux.AddSynchroProcedure(c,nil,aux.NonTuner(nil),1)
c:EnableReviveLimit() c:EnableReviveLimit()
--destroy --destroy
local e1=Effect.CreateEffect(c) local e1=Effect.CreateEffect(c)
......
...@@ -3439,3 +3439,212 @@ function FusionSpell.GetCheckFieldPlayer(tp,skip_location_count_check) ...@@ -3439,3 +3439,212 @@ function FusionSpell.GetCheckFieldPlayer(tp,skip_location_count_check)
end end
return tp return tp
end end
--- Synchro
Synchro = {}
-- Use this as the "infinite" maximum count
Synchro.Infinite={}
--- Add Synchro procedure effect to a card using a single params table
--- @param c Card -- the Synchro monster card
--- @param params? table -- parameters table with keys: f1,f2,minc,maxc
function Synchro.AddSynchroProcedure(c,params)
params=params or {}
local tunerFilter=params.tunerFilter or function(mc,tc) return mc:IsType(TYPE_TUNER) end
local nonTunerFilter=params.nonTunerFilter or function(mc,tc) return not mc:IsType(TYPE_TUNER) end
local tunerMin=params.tunerMin or 1
local tunerMax=params.tunerMax or 1
local nonTunerMin=params.nonTunerMin or 1
local nonTunerMax=params.nonTunerMax or Synchro.Infinite
local e1=Effect.CreateEffect(c)
e1:SetDescription(1164)
e1:SetType(EFFECT_TYPE_FIELD)
e1:SetCode(EFFECT_SPSUMMON_PROC)
e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE)
e1:SetRange(LOCATION_EXTRA)
e1:SetCondition(Synchro.SynCondition(tunerFilter,nonTunerFilter,tunerMin,tunerMax,nonTunerMin,nonTunerMax))
e1:SetTarget(Synchro.SynTarget(tunerFilter,nonTunerFilter,tunerMin,tunerMax,nonTunerMin,nonTunerMax))
e1:SetOperation(Synchro.SynOperation())
e1:SetValue(SUMMON_TYPE_SYNCHRO)
c:RegisterEffect(e1)
end
--- DFS helper: check if partial selection + candidates can form valid Synchro material group
--- @param candidates table -- array of candidate cards
--- @param targetLevel integer -- required total level
--- @param tunerFilter fun(card:Card,targetCard:Card):boolean
--- @param nonTunerFilter fun(card:Card,targetCard:Card):boolean
--- @param targetCard Card -- the Synchro monster being summoned
--- @param tunerMin integer
--- @param tunerMax integer|table
--- @param nonTunerMin integer
--- @param nonTunerMax integer|table
--- @param selected table -- array of currently selected cards
--- @param index integer -- current index in candidates array for DFS, default 1
--- @param currentSum integer -- current sum of levels, default 0
--- @return boolean
function Synchro.CanCompleteSelection(candidates,targetLevel,tunerFilter,nonTunerFilter,targetCard,tunerMin,tunerMax,nonTunerMin,nonTunerMax,selected,index,currentSum)
index=index or 1
currentSum=currentSum or 0
selected=selected or {}
if currentSum>targetLevel then return false end
if index>#candidates then
return Synchro.IsSelectionValid(selected,targetLevel,tunerFilter,nonTunerFilter,targetCard,tunerMin,tunerMax,nonTunerMin,nonTunerMax)
end
local card=candidates[index]
table.insert(selected,card)
if Synchro.CanCompleteSelection(candidates,targetLevel,tunerFilter,nonTunerFilter,targetCard,tunerMin,tunerMax,nonTunerMin,nonTunerMax,selected,index+1,currentSum+card:GetLevel()) then
table.remove(selected)
return true
end
table.remove(selected)
if Synchro.CanCompleteSelection(candidates,targetLevel,tunerFilter,nonTunerFilter,targetCard,tunerMin,tunerMax,nonTunerMin,nonTunerMax,selected,index+1,currentSum) then
return true
end
return false
end
--- Synchro condition generator using tuner/non-tuner min/max counts and filters
function Synchro.SynCondition(tunerFilter,nonTunerFilter,tunerMin,tunerMax,nonTunerMin,nonTunerMax)
return function(e,c,smat,mg,min,max)
if c==nil then return true end
if c:IsType(TYPE_PENDULUM) and c:IsFaceup() then return false end
local targetLevel=c:GetLevel()
mg=mg or Duel.GetMatchingGroup(Card.IsCanBeSynchroMaterial,c:GetControler(),LOCATION_MZONE+LOCATION_HAND,0,nil)
local candidates={}
for card in aux.Next(mg) do
table.insert(candidates,card)
end
return Synchro.CanCompleteSelection(candidates,targetLevel,tunerFilter,nonTunerFilter,c,tunerMin,tunerMax,nonTunerMin,nonTunerMax,{},1,0)
end
end
function Synchro.SynTarget(tunerFilter,nonTunerFilter,tunerMin,tunerMax,nonTunerMin,nonTunerMax)
return function(e,tp,eg,ep,ev,re,r,rp,chk,c,smat,mg,min,max)
local tc=c
local mg=Duel.GetMatchingGroup(function(mc) return mc:IsCanBeSynchroMaterial(mc,tc) end,tc:GetOwner(),LOCATION_MZONE+LOCATION_HAND,0,nil)
local sg=Group.CreateGroup()
local function GroupToArray(group)
local arr={}
for card in aux.Next(group) do table.insert(arr,card) end
return arr
end
while true do
local addable=Group.CreateGroup()
local sg_arr=GroupToArray(sg)
local cg_arr=GroupToArray(mg-sg)
local targetLevel=tc:GetLevel()
for _, candidate in ipairs(cg_arr) do
-- simulate adding candidate to sg_arr
local testSelection = {}
for _, card in ipairs(sg_arr) do table.insert(testSelection, card) end
table.insert(testSelection, candidate)
-- build testCandidates without candidate
local testCandidates = {}
for _, other in ipairs(cg_arr) do
if other ~= candidate then
table.insert(testCandidates, other)
end
end
if Synchro.CanCompleteSelection(
testCandidates,
targetLevel,
tunerFilter,
nonTunerFilter,
tc,
tunerMin,
tunerMax,
nonTunerMin,
nonTunerMax,
testSelection,
1,
0
) then
addable:AddCard(candidate)
end
end
if #addable==0 then
break
end
local finishable=Synchro.IsSelectionValid(sg_arr,targetLevel,tunerFilter,nonTunerFilter,tc,tunerMin,tunerMax,nonTunerMin,nonTunerMax)
local picked=Group.SelectUnselect(addable,sg,tp,finishable,true,tunerMin+nonTunerMin,Synchro.GetDisplayMax(tunerMax,nonTunerMax))
if not picked then
-- user clicked Complete
if finishable then
break
else
-- user clicked Cancel
return false
end
else
if sg:IsContains(picked) then
sg:RemoveCard(picked)
else
sg:AddCard(picked)
end
end
end
sg:KeepAlive()
e:SetLabelObject(sg)
return true
end
end
--- Synchro operation function that applies selected materials
function Synchro.SynOperation()
return function(e,tp,eg,ep,ev,re,r,rp,c)
local g=e:GetLabelObject()
c:SetMaterial(g)
Duel.SendtoGrave(g,REASON_MATERIAL+REASON_SYNCHRO)
g:DeleteGroup()
end
end
function Synchro.ExceedsMax(count,max)
if max==Synchro.Infinite then return false end
return count>max
end
function Synchro.GetDisplayMax(tunerMax,nonTunerMax)
if tunerMax==Synchro.Infinite or nonTunerMax==Synchro.Infinite then
return 99
end
return tunerMax+nonTunerMax
end
function Synchro.IsSelectionValid(selection,targetLevel,tunerFilter,nonTunerFilter,targetCard,tunerMin,tunerMax,nonTunerMin,nonTunerMax)
local tunerCount,nonTunerCount,levelSum=0,0,0
for _,card in ipairs(selection) do
if tunerFilter(card,targetCard) then tunerCount=tunerCount+1
elseif nonTunerFilter(card,targetCard) then nonTunerCount=nonTunerCount+1
else return false end
levelSum=levelSum+card:GetLevel()
end
if tunerCount<tunerMin or (tunerMax~=Synchro.Infinite and tunerCount>tunerMax) then return false end
if nonTunerCount<nonTunerMin or (nonTunerMax~=Synchro.Infinite and nonTunerCount>nonTunerMax) then return false end
return levelSum==targetLevel
end
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