Commit 4b8db707 authored by POLYMER's avatar POLYMER

fix

parent 93ecc3e4
...@@ -157,7 +157,7 @@ function cm.thop(e,tp,eg,ep,ev,re,r,rp) ...@@ -157,7 +157,7 @@ function cm.thop(e,tp,eg,ep,ev,re,r,rp)
e3:SetCode(EVENT_CHAIN_SOLVED) e3:SetCode(EVENT_CHAIN_SOLVED)
e3:SetCountLimit(1) e3:SetCountLimit(1)
e3:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE) e3:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
e3:SetLabelObject(tc) e3:SetLabelObject(e2)
e3:SetCondition(cm.descon) e3:SetCondition(cm.descon)
e3:SetOperation(cm.desop) e3:SetOperation(cm.desop)
Duel.RegisterEffect(e3,tp) Duel.RegisterEffect(e3,tp)
...@@ -165,8 +165,8 @@ function cm.thop(e,tp,eg,ep,ev,re,r,rp) ...@@ -165,8 +165,8 @@ function cm.thop(e,tp,eg,ep,ev,re,r,rp)
end end
end end
function cm.descon(e,tp,eg,ep,ev,re,r,rp) function cm.descon(e,tp,eg,ep,ev,re,r,rp)
local tc=e:GetLabelObject() local te=e:GetLabelObject()
if tc:GetFlagEffect(m)~=0 then if te and te:GetHandler() and te:GetHandler():GetFlagEffect(m)~=0 then
return true return true
else else
e:Reset() e:Reset()
...@@ -174,6 +174,8 @@ function cm.descon(e,tp,eg,ep,ev,re,r,rp) ...@@ -174,6 +174,8 @@ function cm.descon(e,tp,eg,ep,ev,re,r,rp)
end end
end end
function cm.desop(e,tp,eg,ep,ev,re,r,rp) function cm.desop(e,tp,eg,ep,ev,re,r,rp)
local tc=e:GetLabelObject() local te=e:GetLabelObject()
local tc=te:GetHandler()
te:Reset()
if tc:GetFlagEffect(m)~=0 and tc:GetFlagEffect(11451905)==0 then Duel.SendtoDeck(tc,nil,2,REASON_EFFECT) end if tc:GetFlagEffect(m)~=0 and tc:GetFlagEffect(11451905)==0 then Duel.SendtoDeck(tc,nil,2,REASON_EFFECT) end
end end
\ No newline at end of file
...@@ -90,18 +90,29 @@ function cm.smfilter11(c) ...@@ -90,18 +90,29 @@ function cm.smfilter11(c)
end end
function cm.smfilter(c,e,tp,fg) function cm.smfilter(c,e,tp,fg)
local eset1={c:IsHasEffect(EFFECT_LIMIT_SUMMON_PROC)} local eset1={c:IsHasEffect(EFFECT_LIMIT_SUMMON_PROC)}
local eset2={c:IsHasEffect(EFFECT_SUMMON_PROC)} local eset2={c:IsHasEffect(EFFECT_LIMIT_SET_PROC)}
local eset3={c:IsHasEffect(EFFECT_SET_PROC)} local eset3={c:IsHasEffect(EFFECT_SUMMON_PROC)}
local eset4={c:IsHasEffect(EFFECT_SET_PROC)}
local e1,e2=Effect.CreateEffect(c),Effect.CreateEffect(c) local e1,e2=Effect.CreateEffect(c),Effect.CreateEffect(c)
local _CheckTribute=Duel.CheckTribute local _CheckTribute=Duel.CheckTribute
local _GetLocationCount=Duel.GetLocationCount
local _GetMZoneCount=Duel.GetMZoneCount
if aux.GetValueType(fg)=="Group" then if aux.GetValueType(fg)=="Group" then
function Duel.CheckTribute(c,mi,ma,mg,top,...) function Duel.CheckTribute(c,mi,ma,mg,top,...)
local g=mg or Duel.GetTributeGroup(c) local g=mg or Duel.GetTributeGroup(c)
return _CheckTribute(c,mi,ma,g-fg,top,...) return _CheckTribute(c,mi,ma,g-fg,top,...)
end end
function Duel.GetLocationCount(p,loc,...)
if loc~=LOCATION_MZONE then return _GetLocationCount(p,loc,...) end
return _GetMZoneCount(p,fg,...)
end
function Duel.GetMZoneCount(p,lg,...)
if lg then return _GetMZoneCount(p,fg+lg,...) end
return _GetMZoneCount(p,fg,...)
end
end end
if #eset1==0 and #eset2==0 and #eset3==0 then local mi,ma=c:GetTributeRequirement()
local mi,ma=c:GetTributeRequirement() if #eset1==0 then
--summon --summon
e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE) e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE)
e1:SetType(EFFECT_TYPE_SINGLE) e1:SetType(EFFECT_TYPE_SINGLE)
...@@ -110,6 +121,8 @@ function cm.smfilter(c,e,tp,fg) ...@@ -110,6 +121,8 @@ function cm.smfilter(c,e,tp,fg)
e1:SetCondition(cm.ttcon) e1:SetCondition(cm.ttcon)
if mi>0 then e1:SetValue(SUMMON_TYPE_ADVANCE) end if mi>0 then e1:SetValue(SUMMON_TYPE_ADVANCE) end
c:RegisterEffect(e1,true) c:RegisterEffect(e1,true)
end
if #eset2==0 then
e2:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE) e2:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE)
e2:SetType(EFFECT_TYPE_SINGLE) e2:SetType(EFFECT_TYPE_SINGLE)
e2:SetCode(EFFECT_LIMIT_SET_PROC) e2:SetCode(EFFECT_LIMIT_SET_PROC)
...@@ -118,9 +131,38 @@ function cm.smfilter(c,e,tp,fg) ...@@ -118,9 +131,38 @@ function cm.smfilter(c,e,tp,fg)
c:RegisterEffect(e2,true) c:RegisterEffect(e2,true)
end end
local res=c:IsSummonable(true,nil) or c:IsMSetable(true,nil) local res=c:IsSummonable(true,nil) or c:IsMSetable(true,nil)
Duel.CheckTribute=_CheckTribute
e1:Reset() e1:Reset()
e2:Reset() e2:Reset()
if not res then
if #eset1==0 and #eset3>0 then
for _,te in pairs(eset3) do
local te1=te:Clone()
te1:SetType(EFFECT_TYPE_SINGLE)
te1:SetCode(EFFECT_LIMIT_SUMMON_PROC)
te1:SetRange(nil)
c:RegisterEffect(te1,true)
res=res or c:IsSummonable(true,nil)
te1:Reset()
if res then break end
end
end
if #eset2==0 and #eset4>0 then
for _,te in pairs(eset4) do
local te1=te:Clone()
te1:SetType(EFFECT_TYPE_SINGLE)
te1:SetCode(EFFECT_LIMIT_SET_PROC)
te1:SetRange(nil)
c:RegisterEffect(te1,true)
res=res or c:IsMSetable(true,nil)
te1:Reset()
if res then break end
end
end
end
Duel.CheckTribute=_CheckTribute
Duel.GetLocationCount=_GetLocationCount
Duel.GetMZoneCount=_GetMZoneCount
--Debug.Message(res)
return res return res
end end
function cm.ttcon(e,c,minc) function cm.ttcon(e,c,minc)
......
...@@ -72,30 +72,19 @@ function cm.hspgcheck(lv,tp) ...@@ -72,30 +72,19 @@ function cm.hspgcheck(lv,tp)
return cm.fselect(g,lv,tp) --g:CheckSubGroup(cm.fselect,1,#g,lv,tp) return cm.fselect(g,lv,tp) --g:CheckSubGroup(cm.fselect,1,#g,lv,tp)
end end
end end
function cm.CheckGroupRecursiveCapture(bool,sg,g,f,min,max,ext_params)
local eg=g:Clone()
if bool then cm.esg=sg:Clone() end
for c in aux.Next(g-sg) do
sg:AddCard(c)
if not Auxiliary.GCheckAdditional or Auxiliary.GCheckAdditional(sg,c,eg,f,min,max,ext_params) then
if (#sg>=min and #sg<=max and f(sg,table.unpack(ext_params))) then
for sc in aux.Next(sg-cm.esg) do
Auxiliary.SubGroupCaptured:Merge(eg:Filter(cm.slfilter,nil,sc))
end
end
if #sg<max then cm.CheckGroupRecursiveCapture(false,sg,eg,f,min,max,ext_params) end
end
sg:RemoveCard(c)
eg:Sub(eg:Filter(cm.slfilter,nil,c))
end
end
function cm.slfilter(c,sc) function cm.slfilter(c,sc)
return cm.lvplus(c)==cm.lvplus(sc) return cm.lvplus(c)==cm.lvplus(sc) and cm.filter4(c)==cm.filter4(sc)
end end
--subgroup optimization
function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...) function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...)
local min=min or 1 --classif: function to classify cards, e.g. function(c,tc) return c:GetLevel()==tc:GetLevel() end
local max=max or #g --sortif: function of subgroup search order, high to low. e.g. Card.GetLevel
local ext_params={...} --passf: cards that do not require check, e.g. function(c) return c:IsLevel(1) end
--goalstop: do you want to backtrack after reaching the goal? true/false
--check: do you want to return true after reaching the goal firstly? true/false
local classif,sortf,passf,goalstop,check=table.unpack(cm.SubGroupParams)
min=min or 1
max=max or #g
local sg=Group.CreateGroup() local sg=Group.CreateGroup()
local fg=Duel.GrabSelectedCard() local fg=Duel.GrabSelectedCard()
if #fg>max or min>max or #(g+fg)<min then return nil end if #fg>max or min>max or #(g+fg)<min then return nil end
...@@ -103,13 +92,146 @@ function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...) ...@@ -103,13 +92,146 @@ function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...)
fg:SelectUnselect(sg,tp,false,false,min,max) fg:SelectUnselect(sg,tp,false,false,min,max)
end end
sg:Merge(fg) sg:Merge(fg)
local mg,iisg,tmp,stop,iter,ctab,rtab,gtab
--main check
local finish=(#sg>=min and #sg<=max and f(sg,...)) local finish=(#sg>=min and #sg<=max and f(sg,...))
while #sg<max do while #sg<max do
Auxiliary.SubGroupCaptured=Group.CreateGroup() mg=g-sg
cm.CheckGroupRecursiveCapture(true,sg,g,f,min,max,ext_params) iisg=sg:Clone()
local cg=Auxiliary.SubGroupCaptured:Clone() if passf then
Auxiliary.SubGroupCaptured:Clear() aux.SubGroupCaptured=mg:Filter(passf,nil,sg,g)
else
aux.SubGroupCaptured=Group.CreateGroup()
end
ctab,rtab,gtab={},{},{1}
for tc in aux.Next(mg) do
ctab[#ctab+1]=tc
end
--high to low
if sortf then
for i=1,#ctab-1 do
for j=1,#ctab-1-i do
if sortf(ctab[j])<sortf(ctab[j+1]) then
tmp=ctab[j]
ctab[j]=ctab[j+1]
ctab[j+1]=tmp
end
end
end
end
--classify
if classif then
--make similar cards adjacent
for i=1,#ctab-2 do
for j=i+2,#ctab do
if classif(ctab[i],ctab[j]) then
tmp=ctab[j]
ctab[j]=ctab[i+1]
ctab[i+1]=tmp
end
end
end
--rtab[i]: what category does the i-th card belong to
--gtab[i]: What is the first card's number in the i-th category
for i=1,#ctab-1 do
rtab[i]=#gtab
if not classif(ctab[i],ctab[i+1]) then
gtab[#gtab+1]=i+1
end
end
rtab[#ctab]=#gtab
--iter record all cards' number in sg
iter={1}
sg:AddCard(ctab[1])
while #sg>#iisg and #aux.SubGroupCaptured<#mg do
stop=#sg>=max
--prune if too much cards
if (aux.GCheckAdditional and not aux.GCheckAdditional(sg,c,g,f,min,max,...)) then
stop=true
--skip check if no new cards
elseif #(sg-iisg-aux.SubGroupCaptured)>0 and #sg>=min and #sg<=max and f(sg,...) then
for sc in aux.Next(sg-iisg) do
if check then return true end
aux.SubGroupCaptured:Merge(mg:Filter(classif,nil,sc))
end
stop=goalstop
end
local code=iter[#iter]
--last card isn't in the last category
if code and code<gtab[#gtab] then
if stop then
--backtrack and add 1 card from next category
iter[#iter]=gtab[rtab[code]+1]
sg:RemoveCard(ctab[code])
sg:AddCard(ctab[(iter[#iter])])
else
--continue searching forward
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
end
--last card is in the last category
elseif code then
if stop or code>=#ctab then
--clear all cards in the last category
while #iter>0 and iter[#iter]>=gtab[#gtab] do
sg:RemoveCard(ctab[(iter[#iter])])
iter[#iter]=nil
end
--backtrack and add 1 card from next category
local code2=iter[#iter]
if code2 then
iter[#iter]=gtab[rtab[code2]+1]
sg:RemoveCard(ctab[code2])
sg:AddCard(ctab[(iter[#iter])])
end
else
--continue searching forward
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
end
end
end
--classification is essential for efficiency, and this part is only for backup
else
iter={1}
sg:AddCard(ctab[1])
while #sg>#iisg and #aux.SubGroupCaptured<#mg do
stop=#sg>=max
if (aux.GCheckAdditional and not aux.GCheckAdditional(sg,c,g,f,min,max,...)) then
stop=true
elseif #(sg-iisg-aux.SubGroupCaptured)>0 and #sg>=min and #sg<=max and f(sg,...) then
for sc in aux.Next(sg-iisg) do
if check then return true end
aux.SubGroupCaptured:AddCard(sc) --Merge(mg:Filter(class,nil,sc))
end
stop=goalstop
end
local code=iter[#iter]
if code<#ctab then
if stop then
iter[#iter]=nil
sg:RemoveCard(ctab[code])
end
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
else
local code2=iter[#iter-1]
iter[#iter]=nil
sg:RemoveCard(ctab[code])
if code2 and code2>0 then
iter[#iter]=code2+1
sg:RemoveCard(ctab[code2])
sg:AddCard(ctab[code2+1])
end
end
end
end
--finish searching
sg=iisg
local cg=aux.SubGroupCaptured:Clone()
aux.SubGroupCaptured:Clear()
cg:Sub(sg) cg:Sub(sg)
--Debug.Message(cm[0])
finish=(#sg>=min and #sg<=max and f(sg,...)) finish=(#sg>=min and #sg<=max and f(sg,...))
if #cg==0 then break end if #cg==0 then break end
local cancel=not finish and cancelable local cancel=not finish and cancelable
...@@ -175,9 +297,11 @@ function cm.sptg(e,tp,eg,ep,ev,re,r,rp,chk) ...@@ -175,9 +297,11 @@ function cm.sptg(e,tp,eg,ep,ev,re,r,rp,chk)
local sg=Duel.GetMatchingGroup(cm.filter3,tp,LOCATION_DECK,0,nil,e,tp) local sg=Duel.GetMatchingGroup(cm.filter3,tp,LOCATION_DECK,0,nil,e,tp)
local tg=Group.CreateGroup() local tg=Group.CreateGroup()
for sc in aux.Next(sg) do for sc in aux.Next(sg) do
cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,true,true}
aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(sc),tp) aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(sc),tp)
local tc=mg:CheckSubGroup(cm.hspcheck,1,#mg,cm.lvplus(sc),tp) local tc=cm.SelectSubGroup(mg,tp,cm.fselect,false,1,#mg,cm.lvplus(sc),tp)
aux.GCheckAdditional=nil aux.GCheckAdditional=nil
cm.SubGroupParams={}
if tc then return true end if tc then return true end
end end
return false return false
...@@ -191,9 +315,11 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp) ...@@ -191,9 +315,11 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp)
local sg=Duel.GetMatchingGroup(cm.filter3,tp,LOCATION_DECK,0,nil,e,tp) local sg=Duel.GetMatchingGroup(cm.filter3,tp,LOCATION_DECK,0,nil,e,tp)
local tg=Group.CreateGroup() local tg=Group.CreateGroup()
for sc in aux.Next(sg) do for sc in aux.Next(sg) do
cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,true,true}
aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(sc),tp) aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(sc),tp)
local tc=mg:CheckSubGroup(cm.hspcheck,1,#mg,cm.lvplus(sc),tp) local tc=cm.SelectSubGroup(mg,tp,cm.fselect,false,1,#mg,cm.lvplus(sc),tp)
aux.GCheckAdditional=nil aux.GCheckAdditional=nil
cm.SubGroupParams={}
if tc then tg:AddCard(sc) end if tc then tg:AddCard(sc) end
end end
if not tg or #tg==0 then return end if not tg or #tg==0 then return end
...@@ -203,11 +329,14 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp) ...@@ -203,11 +329,14 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp)
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SPSUMMON) Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SPSUMMON)
tc=tg:Select(tp,1,1,nil):GetFirst() tc=tg:Select(tp,1,1,nil):GetFirst()
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_REMOVE) Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_REMOVE)
cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,true}
aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(tc),tp) aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(tc),tp)
rg=cm.SelectSubGroup(mg,tp,cm.hspcheck,true,1,#mg,cm.lvplus(tc),tp) rg=cm.SelectSubGroup(mg,tp,cm.fselect,true,1,#mg,cm.lvplus(tc),tp)
aux.GCheckAdditional=nil aux.GCheckAdditional=nil
cm.SubGroupParams={}
end end
Duel.ConfirmCards(1-tp,rg:Filter(Card.IsFacedown,nil)) Duel.ConfirmCards(1-tp,rg:Filter(Card.IsFacedown,nil))
tc:SetMaterial(rg)
local tg=rg:Filter(cm.filter5,nil) local tg=rg:Filter(cm.filter5,nil)
if not tg or #tg==0 then if not tg or #tg==0 then
if Duel.Remove(rg,POS_FACEUP,REASON_EFFECT)>0 then Duel.SpecialSummon(tc,0,tp,tp,false,false,POS_FACEUP) end if Duel.Remove(rg,POS_FACEUP,REASON_EFFECT)>0 then Duel.SpecialSummon(tc,0,tp,tp,false,false,POS_FACEUP) end
......
...@@ -68,30 +68,19 @@ function cm.hspgcheck(lv,tp) ...@@ -68,30 +68,19 @@ function cm.hspgcheck(lv,tp)
return cm.fselect(g,lv,tp) return cm.fselect(g,lv,tp)
end end
end end
function cm.CheckGroupRecursiveCapture(bool,sg,g,f,min,max,ext_params)
local eg=g:Clone()
if bool then cm.esg=sg:Clone() end
for c in aux.Next(g-sg) do
sg:AddCard(c)
if not Auxiliary.GCheckAdditional or Auxiliary.GCheckAdditional(sg,c,eg,f,min,max,ext_params) then
if (#sg>=min and #sg<=max and f(sg,table.unpack(ext_params))) then
for sc in aux.Next(sg-cm.esg) do
Auxiliary.SubGroupCaptured:Merge(eg:Filter(cm.slfilter,nil,sc))
end
end
if #sg<max then cm.CheckGroupRecursiveCapture(false,sg,eg,f,min,max,ext_params) end
end
sg:RemoveCard(c)
eg:Sub(eg:Filter(cm.slfilter,nil,c))
end
end
function cm.slfilter(c,sc) function cm.slfilter(c,sc)
return cm.lvplus(c)==cm.lvplus(sc) return cm.lvplus(c)==cm.lvplus(sc) and cm.filter4(c)==cm.filter4(sc)
end end
--subgroup optimization
function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...) function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...)
local min=min or 1 --classif: function to classify cards, e.g. function(c,tc) return c:GetLevel()==tc:GetLevel() end
local max=max or #g --sortif: function of subgroup search order, high to low. e.g. Card.GetLevel
local ext_params={...} --passf: cards that do not require check, e.g. function(c) return c:IsLevel(1) end
--goalstop: do you want to backtrack after reaching the goal? true/false
--check: do you want to return true after reaching the goal firstly? true/false
local classif,sortf,passf,goalstop,check=table.unpack(cm.SubGroupParams)
min=min or 1
max=max or #g
local sg=Group.CreateGroup() local sg=Group.CreateGroup()
local fg=Duel.GrabSelectedCard() local fg=Duel.GrabSelectedCard()
if #fg>max or min>max or #(g+fg)<min then return nil end if #fg>max or min>max or #(g+fg)<min then return nil end
...@@ -99,13 +88,146 @@ function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...) ...@@ -99,13 +88,146 @@ function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...)
fg:SelectUnselect(sg,tp,false,false,min,max) fg:SelectUnselect(sg,tp,false,false,min,max)
end end
sg:Merge(fg) sg:Merge(fg)
local mg,iisg,tmp,stop,iter,ctab,rtab,gtab
--main check
local finish=(#sg>=min and #sg<=max and f(sg,...)) local finish=(#sg>=min and #sg<=max and f(sg,...))
while #sg<max do while #sg<max do
Auxiliary.SubGroupCaptured=Group.CreateGroup() mg=g-sg
cm.CheckGroupRecursiveCapture(true,sg,g,f,min,max,ext_params) iisg=sg:Clone()
local cg=Auxiliary.SubGroupCaptured:Clone() if passf then
Auxiliary.SubGroupCaptured:Clear() aux.SubGroupCaptured=mg:Filter(passf,nil,sg,g)
else
aux.SubGroupCaptured=Group.CreateGroup()
end
ctab,rtab,gtab={},{},{1}
for tc in aux.Next(mg) do
ctab[#ctab+1]=tc
end
--high to low
if sortf then
for i=1,#ctab-1 do
for j=1,#ctab-1-i do
if sortf(ctab[j])<sortf(ctab[j+1]) then
tmp=ctab[j]
ctab[j]=ctab[j+1]
ctab[j+1]=tmp
end
end
end
end
--classify
if classif then
--make similar cards adjacent
for i=1,#ctab-2 do
for j=i+2,#ctab do
if classif(ctab[i],ctab[j]) then
tmp=ctab[j]
ctab[j]=ctab[i+1]
ctab[i+1]=tmp
end
end
end
--rtab[i]: what category does the i-th card belong to
--gtab[i]: What is the first card's number in the i-th category
for i=1,#ctab-1 do
rtab[i]=#gtab
if not classif(ctab[i],ctab[i+1]) then
gtab[#gtab+1]=i+1
end
end
rtab[#ctab]=#gtab
--iter record all cards' number in sg
iter={1}
sg:AddCard(ctab[1])
while #sg>#iisg and #aux.SubGroupCaptured<#mg do
stop=#sg>=max
--prune if too much cards
if (aux.GCheckAdditional and not aux.GCheckAdditional(sg,c,g,f,min,max,...)) then
stop=true
--skip check if no new cards
elseif #(sg-iisg-aux.SubGroupCaptured)>0 and #sg>=min and #sg<=max and f(sg,...) then
for sc in aux.Next(sg-iisg) do
if check then return true end
aux.SubGroupCaptured:Merge(mg:Filter(classif,nil,sc))
end
stop=goalstop
end
local code=iter[#iter]
--last card isn't in the last category
if code and code<gtab[#gtab] then
if stop then
--backtrack and add 1 card from next category
iter[#iter]=gtab[rtab[code]+1]
sg:RemoveCard(ctab[code])
sg:AddCard(ctab[(iter[#iter])])
else
--continue searching forward
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
end
--last card is in the last category
elseif code then
if stop or code>=#ctab then
--clear all cards in the last category
while #iter>0 and iter[#iter]>=gtab[#gtab] do
sg:RemoveCard(ctab[(iter[#iter])])
iter[#iter]=nil
end
--backtrack and add 1 card from next category
local code2=iter[#iter]
if code2 then
iter[#iter]=gtab[rtab[code2]+1]
sg:RemoveCard(ctab[code2])
sg:AddCard(ctab[(iter[#iter])])
end
else
--continue searching forward
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
end
end
end
--classification is essential for efficiency, and this part is only for backup
else
iter={1}
sg:AddCard(ctab[1])
while #sg>#iisg and #aux.SubGroupCaptured<#mg do
stop=#sg>=max
if (aux.GCheckAdditional and not aux.GCheckAdditional(sg,c,g,f,min,max,...)) then
stop=true
elseif #(sg-iisg-aux.SubGroupCaptured)>0 and #sg>=min and #sg<=max and f(sg,...) then
for sc in aux.Next(sg-iisg) do
if check then return true end
aux.SubGroupCaptured:AddCard(sc) --Merge(mg:Filter(class,nil,sc))
end
stop=goalstop
end
local code=iter[#iter]
if code<#ctab then
if stop then
iter[#iter]=nil
sg:RemoveCard(ctab[code])
end
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
else
local code2=iter[#iter-1]
iter[#iter]=nil
sg:RemoveCard(ctab[code])
if code2 and code2>0 then
iter[#iter]=code2+1
sg:RemoveCard(ctab[code2])
sg:AddCard(ctab[code2+1])
end
end
end
end
--finish searching
sg=iisg
local cg=aux.SubGroupCaptured:Clone()
aux.SubGroupCaptured:Clear()
cg:Sub(sg) cg:Sub(sg)
--Debug.Message(cm[0])
finish=(#sg>=min and #sg<=max and f(sg,...)) finish=(#sg>=min and #sg<=max and f(sg,...))
if #cg==0 then break end if #cg==0 then break end
local cancel=not finish and cancelable local cancel=not finish and cancelable
...@@ -156,9 +278,11 @@ function cm.sptg(e,tp,eg,ep,ev,re,r,rp,chk) ...@@ -156,9 +278,11 @@ function cm.sptg(e,tp,eg,ep,ev,re,r,rp,chk)
local sg=Duel.GetMatchingGroup(cm.filter3,tp,LOCATION_DECK,0,nil,e,tp) local sg=Duel.GetMatchingGroup(cm.filter3,tp,LOCATION_DECK,0,nil,e,tp)
local tg=Group.CreateGroup() local tg=Group.CreateGroup()
for sc in aux.Next(sg) do for sc in aux.Next(sg) do
cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,true,true}
aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(sc),tp) aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(sc),tp)
local tc=mg:CheckSubGroup(cm.hspcheck,1,#mg,cm.lvplus(sc),tp) local tc=cm.SelectSubGroup(mg,tp,cm.fselect,false,1,#mg,cm.lvplus(sc),tp)
aux.GCheckAdditional=nil aux.GCheckAdditional=nil
cm.SubGroupParams={}
if tc then return true end if tc then return true end
end end
return false return false
...@@ -172,9 +296,11 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp) ...@@ -172,9 +296,11 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp)
local sg=Duel.GetMatchingGroup(cm.filter3,tp,LOCATION_DECK,0,nil,e,tp) local sg=Duel.GetMatchingGroup(cm.filter3,tp,LOCATION_DECK,0,nil,e,tp)
local tg=Group.CreateGroup() local tg=Group.CreateGroup()
for sc in aux.Next(sg) do for sc in aux.Next(sg) do
cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,true,true}
aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(sc),tp) aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(sc),tp)
local tc=mg:CheckSubGroup(cm.hspcheck,1,#mg,cm.lvplus(sc),tp) local tc=cm.SelectSubGroup(mg,tp,cm.fselect,false,1,#mg,cm.lvplus(sc),tp)
aux.GCheckAdditional=nil aux.GCheckAdditional=nil
cm.SubGroupParams={}
if tc then tg:AddCard(sc) end if tc then tg:AddCard(sc) end
end end
if not tg or #tg==0 then return end if not tg or #tg==0 then return end
...@@ -184,11 +310,14 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp) ...@@ -184,11 +310,14 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp)
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SPSUMMON) Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SPSUMMON)
tc=tg:Select(tp,1,1,nil):GetFirst() tc=tg:Select(tp,1,1,nil):GetFirst()
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_REMOVE) Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_REMOVE)
cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,true}
aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(tc),tp) aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(tc),tp)
rg=cm.SelectSubGroup(mg,tp,cm.hspcheck,true,1,#mg,cm.lvplus(tc),tp) rg=cm.SelectSubGroup(mg,tp,cm.fselect,true,1,#mg,cm.lvplus(tc),tp)
aux.GCheckAdditional=nil aux.GCheckAdditional=nil
cm.SubGroupParams={}
end end
Duel.ConfirmCards(1-tp,rg:Filter(Card.IsFacedown,nil)) Duel.ConfirmCards(1-tp,rg:Filter(Card.IsFacedown,nil))
tc:SetMaterial(rg)
local tg=rg:Filter(cm.filter5,nil) local tg=rg:Filter(cm.filter5,nil)
if not tg or #tg==0 then if not tg or #tg==0 then
if Duel.Remove(rg,POS_FACEUP,REASON_EFFECT)>0 then Duel.SpecialSummon(tc,0,tp,tp,false,false,POS_FACEUP) end if Duel.Remove(rg,POS_FACEUP,REASON_EFFECT)>0 then Duel.SpecialSummon(tc,0,tp,tp,false,false,POS_FACEUP) end
......
...@@ -101,30 +101,19 @@ function cm.hspgcheck(lv,tp) ...@@ -101,30 +101,19 @@ function cm.hspgcheck(lv,tp)
return cm.fselect(g,lv,tp) return cm.fselect(g,lv,tp)
end end
end end
function cm.CheckGroupRecursiveCapture(bool,sg,g,f,min,max,ext_params)
local eg=g:Clone()
if bool then cm.esg=sg:Clone() end
for c in aux.Next(g-sg) do
sg:AddCard(c)
if not Auxiliary.GCheckAdditional or Auxiliary.GCheckAdditional(sg,c,eg,f,min,max,ext_params) then
if (#sg>=min and #sg<=max and f(sg,table.unpack(ext_params))) then
for sc in aux.Next(sg-cm.esg) do
Auxiliary.SubGroupCaptured:Merge(eg:Filter(cm.slfilter,nil,sc))
end
end
if #sg<max then cm.CheckGroupRecursiveCapture(false,sg,eg,f,min,max,ext_params) end
end
sg:RemoveCard(c)
eg:Sub(eg:Filter(cm.slfilter,nil,c))
end
end
function cm.slfilter(c,sc) function cm.slfilter(c,sc)
return cm.lvplus(c)==cm.lvplus(sc) return cm.lvplus(c)==cm.lvplus(sc) and cm.filter4(c)==cm.filter4(sc)
end end
--subgroup optimization
function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...) function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...)
local min=min or 1 --classif: function to classify cards, e.g. function(c,tc) return c:GetLevel()==tc:GetLevel() end
local max=max or #g --sortif: function of subgroup search order, high to low. e.g. Card.GetLevel
local ext_params={...} --passf: cards that do not require check, e.g. function(c) return c:IsLevel(1) end
--goalstop: do you want to backtrack after reaching the goal? true/false
--check: do you want to return true after reaching the goal firstly? true/false
local classif,sortf,passf,goalstop,check=table.unpack(cm.SubGroupParams)
min=min or 1
max=max or #g
local sg=Group.CreateGroup() local sg=Group.CreateGroup()
local fg=Duel.GrabSelectedCard() local fg=Duel.GrabSelectedCard()
if #fg>max or min>max or #(g+fg)<min then return nil end if #fg>max or min>max or #(g+fg)<min then return nil end
...@@ -132,13 +121,146 @@ function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...) ...@@ -132,13 +121,146 @@ function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...)
fg:SelectUnselect(sg,tp,false,false,min,max) fg:SelectUnselect(sg,tp,false,false,min,max)
end end
sg:Merge(fg) sg:Merge(fg)
local mg,iisg,tmp,stop,iter,ctab,rtab,gtab
--main check
local finish=(#sg>=min and #sg<=max and f(sg,...)) local finish=(#sg>=min and #sg<=max and f(sg,...))
while #sg<max do while #sg<max do
Auxiliary.SubGroupCaptured=Group.CreateGroup() mg=g-sg
cm.CheckGroupRecursiveCapture(true,sg,g,f,min,max,ext_params) iisg=sg:Clone()
local cg=Auxiliary.SubGroupCaptured:Clone() if passf then
Auxiliary.SubGroupCaptured:Clear() aux.SubGroupCaptured=mg:Filter(passf,nil,sg,g)
else
aux.SubGroupCaptured=Group.CreateGroup()
end
ctab,rtab,gtab={},{},{1}
for tc in aux.Next(mg) do
ctab[#ctab+1]=tc
end
--high to low
if sortf then
for i=1,#ctab-1 do
for j=1,#ctab-1-i do
if sortf(ctab[j])<sortf(ctab[j+1]) then
tmp=ctab[j]
ctab[j]=ctab[j+1]
ctab[j+1]=tmp
end
end
end
end
--classify
if classif then
--make similar cards adjacent
for i=1,#ctab-2 do
for j=i+2,#ctab do
if classif(ctab[i],ctab[j]) then
tmp=ctab[j]
ctab[j]=ctab[i+1]
ctab[i+1]=tmp
end
end
end
--rtab[i]: what category does the i-th card belong to
--gtab[i]: What is the first card's number in the i-th category
for i=1,#ctab-1 do
rtab[i]=#gtab
if not classif(ctab[i],ctab[i+1]) then
gtab[#gtab+1]=i+1
end
end
rtab[#ctab]=#gtab
--iter record all cards' number in sg
iter={1}
sg:AddCard(ctab[1])
while #sg>#iisg and #aux.SubGroupCaptured<#mg do
stop=#sg>=max
--prune if too much cards
if (aux.GCheckAdditional and not aux.GCheckAdditional(sg,c,g,f,min,max,...)) then
stop=true
--skip check if no new cards
elseif #(sg-iisg-aux.SubGroupCaptured)>0 and #sg>=min and #sg<=max and f(sg,...) then
for sc in aux.Next(sg-iisg) do
if check then return true end
aux.SubGroupCaptured:Merge(mg:Filter(classif,nil,sc))
end
stop=goalstop
end
local code=iter[#iter]
--last card isn't in the last category
if code and code<gtab[#gtab] then
if stop then
--backtrack and add 1 card from next category
iter[#iter]=gtab[rtab[code]+1]
sg:RemoveCard(ctab[code])
sg:AddCard(ctab[(iter[#iter])])
else
--continue searching forward
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
end
--last card is in the last category
elseif code then
if stop or code>=#ctab then
--clear all cards in the last category
while #iter>0 and iter[#iter]>=gtab[#gtab] do
sg:RemoveCard(ctab[(iter[#iter])])
iter[#iter]=nil
end
--backtrack and add 1 card from next category
local code2=iter[#iter]
if code2 then
iter[#iter]=gtab[rtab[code2]+1]
sg:RemoveCard(ctab[code2])
sg:AddCard(ctab[(iter[#iter])])
end
else
--continue searching forward
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
end
end
end
--classification is essential for efficiency, and this part is only for backup
else
iter={1}
sg:AddCard(ctab[1])
while #sg>#iisg and #aux.SubGroupCaptured<#mg do
stop=#sg>=max
if (aux.GCheckAdditional and not aux.GCheckAdditional(sg,c,g,f,min,max,...)) then
stop=true
elseif #(sg-iisg-aux.SubGroupCaptured)>0 and #sg>=min and #sg<=max and f(sg,...) then
for sc in aux.Next(sg-iisg) do
if check then return true end
aux.SubGroupCaptured:AddCard(sc) --Merge(mg:Filter(class,nil,sc))
end
stop=goalstop
end
local code=iter[#iter]
if code<#ctab then
if stop then
iter[#iter]=nil
sg:RemoveCard(ctab[code])
end
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
else
local code2=iter[#iter-1]
iter[#iter]=nil
sg:RemoveCard(ctab[code])
if code2 and code2>0 then
iter[#iter]=code2+1
sg:RemoveCard(ctab[code2])
sg:AddCard(ctab[code2+1])
end
end
end
end
--finish searching
sg=iisg
local cg=aux.SubGroupCaptured:Clone()
aux.SubGroupCaptured:Clear()
cg:Sub(sg) cg:Sub(sg)
--Debug.Message(cm[0])
finish=(#sg>=min and #sg<=max and f(sg,...)) finish=(#sg>=min and #sg<=max and f(sg,...))
if #cg==0 then break end if #cg==0 then break end
local cancel=not finish and cancelable local cancel=not finish and cancelable
...@@ -211,9 +333,11 @@ function cm.sptg(e,tp,eg,ep,ev,re,r,rp,chk) ...@@ -211,9 +333,11 @@ function cm.sptg(e,tp,eg,ep,ev,re,r,rp,chk)
local sg=Duel.GetMatchingGroup(cm.filter3,tp,LOCATION_DECK,0,nil,e,tp) local sg=Duel.GetMatchingGroup(cm.filter3,tp,LOCATION_DECK,0,nil,e,tp)
local tg=Group.CreateGroup() local tg=Group.CreateGroup()
for sc in aux.Next(sg) do for sc in aux.Next(sg) do
cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,true,true}
aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(sc),tp) aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(sc),tp)
local tc=mg:CheckSubGroup(cm.hspcheck,1,#mg,cm.lvplus(sc),tp) local tc=cm.SelectSubGroup(mg,tp,cm.fselect,false,1,#mg,cm.lvplus(sc),tp)
aux.GCheckAdditional=nil aux.GCheckAdditional=nil
cm.SubGroupParams={}
if tc then return true end if tc then return true end
end end
return false return false
...@@ -227,9 +351,11 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp) ...@@ -227,9 +351,11 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp)
local sg=Duel.GetMatchingGroup(cm.filter3,tp,LOCATION_DECK,0,nil,e,tp) local sg=Duel.GetMatchingGroup(cm.filter3,tp,LOCATION_DECK,0,nil,e,tp)
local tg=Group.CreateGroup() local tg=Group.CreateGroup()
for sc in aux.Next(sg) do for sc in aux.Next(sg) do
cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,true,true}
aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(sc),tp) aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(sc),tp)
local tc=mg:CheckSubGroup(cm.hspcheck,1,#mg,cm.lvplus(sc),tp) local tc=cm.SelectSubGroup(mg,tp,cm.fselect,false,1,#mg,cm.lvplus(sc),tp)
aux.GCheckAdditional=nil aux.GCheckAdditional=nil
cm.SubGroupParams={}
if tc then tg:AddCard(sc) end if tc then tg:AddCard(sc) end
end end
if not tg or #tg==0 then return end if not tg or #tg==0 then return end
...@@ -239,11 +365,14 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp) ...@@ -239,11 +365,14 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp)
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SPSUMMON) Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SPSUMMON)
tc=tg:Select(tp,1,1,nil):GetFirst() tc=tg:Select(tp,1,1,nil):GetFirst()
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_REMOVE) Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_REMOVE)
cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,true}
aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(tc),tp) aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(tc),tp)
rg=cm.SelectSubGroup(mg,tp,cm.hspcheck,true,1,#mg,cm.lvplus(tc),tp) rg=cm.SelectSubGroup(mg,tp,cm.fselect,true,1,#mg,cm.lvplus(tc),tp)
aux.GCheckAdditional=nil aux.GCheckAdditional=nil
cm.SubGroupParams={}
end end
Duel.ConfirmCards(1-tp,rg:Filter(Card.IsFacedown,nil)) Duel.ConfirmCards(1-tp,rg:Filter(Card.IsFacedown,nil))
tc:SetMaterial(rg)
local tg=rg:Filter(cm.filter5,nil) local tg=rg:Filter(cm.filter5,nil)
if not tg or #tg==0 then if not tg or #tg==0 then
if Duel.Remove(rg,POS_FACEUP,REASON_EFFECT)>0 then Duel.SpecialSummon(tc,0,tp,tp,false,false,POS_FACEUP) end if Duel.Remove(rg,POS_FACEUP,REASON_EFFECT)>0 then Duel.SpecialSummon(tc,0,tp,tp,false,false,POS_FACEUP) end
......
...@@ -85,30 +85,19 @@ function cm.hspgcheck(lv,tp) ...@@ -85,30 +85,19 @@ function cm.hspgcheck(lv,tp)
return cm.fselect(g,lv,tp) return cm.fselect(g,lv,tp)
end end
end end
function cm.CheckGroupRecursiveCapture(bool,sg,g,f,min,max,ext_params)
local eg=g:Clone()
if bool then cm.esg=sg:Clone() end
for c in aux.Next(g-sg) do
sg:AddCard(c)
if not Auxiliary.GCheckAdditional or Auxiliary.GCheckAdditional(sg,c,eg,f,min,max,ext_params) then
if (#sg>=min and #sg<=max and f(sg,table.unpack(ext_params))) then
for sc in aux.Next(sg-cm.esg) do
Auxiliary.SubGroupCaptured:Merge(eg:Filter(cm.slfilter,nil,sc))
end
end
if #sg<max then cm.CheckGroupRecursiveCapture(false,sg,eg,f,min,max,ext_params) end
end
sg:RemoveCard(c)
eg:Sub(eg:Filter(cm.slfilter,nil,c))
end
end
function cm.slfilter(c,sc) function cm.slfilter(c,sc)
return cm.lvplus(c)==cm.lvplus(sc) return cm.lvplus(c)==cm.lvplus(sc) and cm.filter4(c)==cm.filter4(sc)
end end
--subgroup optimization
function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...) function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...)
local min=min or 1 --classif: function to classify cards, e.g. function(c,tc) return c:GetLevel()==tc:GetLevel() end
local max=max or #g --sortif: function of subgroup search order, high to low. e.g. Card.GetLevel
local ext_params={...} --passf: cards that do not require check, e.g. function(c) return c:IsLevel(1) end
--goalstop: do you want to backtrack after reaching the goal? true/false
--check: do you want to return true after reaching the goal firstly? true/false
local classif,sortf,passf,goalstop,check=table.unpack(cm.SubGroupParams)
min=min or 1
max=max or #g
local sg=Group.CreateGroup() local sg=Group.CreateGroup()
local fg=Duel.GrabSelectedCard() local fg=Duel.GrabSelectedCard()
if #fg>max or min>max or #(g+fg)<min then return nil end if #fg>max or min>max or #(g+fg)<min then return nil end
...@@ -116,13 +105,146 @@ function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...) ...@@ -116,13 +105,146 @@ function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...)
fg:SelectUnselect(sg,tp,false,false,min,max) fg:SelectUnselect(sg,tp,false,false,min,max)
end end
sg:Merge(fg) sg:Merge(fg)
local mg,iisg,tmp,stop,iter,ctab,rtab,gtab
--main check
local finish=(#sg>=min and #sg<=max and f(sg,...)) local finish=(#sg>=min and #sg<=max and f(sg,...))
while #sg<max do while #sg<max do
Auxiliary.SubGroupCaptured=Group.CreateGroup() mg=g-sg
cm.CheckGroupRecursiveCapture(true,sg,g,f,min,max,ext_params) iisg=sg:Clone()
local cg=Auxiliary.SubGroupCaptured:Clone() if passf then
Auxiliary.SubGroupCaptured:Clear() aux.SubGroupCaptured=mg:Filter(passf,nil,sg,g)
else
aux.SubGroupCaptured=Group.CreateGroup()
end
ctab,rtab,gtab={},{},{1}
for tc in aux.Next(mg) do
ctab[#ctab+1]=tc
end
--high to low
if sortf then
for i=1,#ctab-1 do
for j=1,#ctab-1-i do
if sortf(ctab[j])<sortf(ctab[j+1]) then
tmp=ctab[j]
ctab[j]=ctab[j+1]
ctab[j+1]=tmp
end
end
end
end
--classify
if classif then
--make similar cards adjacent
for i=1,#ctab-2 do
for j=i+2,#ctab do
if classif(ctab[i],ctab[j]) then
tmp=ctab[j]
ctab[j]=ctab[i+1]
ctab[i+1]=tmp
end
end
end
--rtab[i]: what category does the i-th card belong to
--gtab[i]: What is the first card's number in the i-th category
for i=1,#ctab-1 do
rtab[i]=#gtab
if not classif(ctab[i],ctab[i+1]) then
gtab[#gtab+1]=i+1
end
end
rtab[#ctab]=#gtab
--iter record all cards' number in sg
iter={1}
sg:AddCard(ctab[1])
while #sg>#iisg and #aux.SubGroupCaptured<#mg do
stop=#sg>=max
--prune if too much cards
if (aux.GCheckAdditional and not aux.GCheckAdditional(sg,c,g,f,min,max,...)) then
stop=true
--skip check if no new cards
elseif #(sg-iisg-aux.SubGroupCaptured)>0 and #sg>=min and #sg<=max and f(sg,...) then
for sc in aux.Next(sg-iisg) do
if check then return true end
aux.SubGroupCaptured:Merge(mg:Filter(classif,nil,sc))
end
stop=goalstop
end
local code=iter[#iter]
--last card isn't in the last category
if code and code<gtab[#gtab] then
if stop then
--backtrack and add 1 card from next category
iter[#iter]=gtab[rtab[code]+1]
sg:RemoveCard(ctab[code])
sg:AddCard(ctab[(iter[#iter])])
else
--continue searching forward
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
end
--last card is in the last category
elseif code then
if stop or code>=#ctab then
--clear all cards in the last category
while #iter>0 and iter[#iter]>=gtab[#gtab] do
sg:RemoveCard(ctab[(iter[#iter])])
iter[#iter]=nil
end
--backtrack and add 1 card from next category
local code2=iter[#iter]
if code2 then
iter[#iter]=gtab[rtab[code2]+1]
sg:RemoveCard(ctab[code2])
sg:AddCard(ctab[(iter[#iter])])
end
else
--continue searching forward
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
end
end
end
--classification is essential for efficiency, and this part is only for backup
else
iter={1}
sg:AddCard(ctab[1])
while #sg>#iisg and #aux.SubGroupCaptured<#mg do
stop=#sg>=max
if (aux.GCheckAdditional and not aux.GCheckAdditional(sg,c,g,f,min,max,...)) then
stop=true
elseif #(sg-iisg-aux.SubGroupCaptured)>0 and #sg>=min and #sg<=max and f(sg,...) then
for sc in aux.Next(sg-iisg) do
if check then return true end
aux.SubGroupCaptured:AddCard(sc) --Merge(mg:Filter(class,nil,sc))
end
stop=goalstop
end
local code=iter[#iter]
if code<#ctab then
if stop then
iter[#iter]=nil
sg:RemoveCard(ctab[code])
end
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
else
local code2=iter[#iter-1]
iter[#iter]=nil
sg:RemoveCard(ctab[code])
if code2 and code2>0 then
iter[#iter]=code2+1
sg:RemoveCard(ctab[code2])
sg:AddCard(ctab[code2+1])
end
end
end
end
--finish searching
sg=iisg
local cg=aux.SubGroupCaptured:Clone()
aux.SubGroupCaptured:Clear()
cg:Sub(sg) cg:Sub(sg)
--Debug.Message(cm[0])
finish=(#sg>=min and #sg<=max and f(sg,...)) finish=(#sg>=min and #sg<=max and f(sg,...))
if #cg==0 then break end if #cg==0 then break end
local cancel=not finish and cancelable local cancel=not finish and cancelable
...@@ -189,9 +311,11 @@ function cm.sptg(e,tp,eg,ep,ev,re,r,rp,chk) ...@@ -189,9 +311,11 @@ function cm.sptg(e,tp,eg,ep,ev,re,r,rp,chk)
local sg=Duel.GetMatchingGroup(cm.filter3,tp,LOCATION_DECK,0,nil,e,tp) local sg=Duel.GetMatchingGroup(cm.filter3,tp,LOCATION_DECK,0,nil,e,tp)
local tg=Group.CreateGroup() local tg=Group.CreateGroup()
for sc in aux.Next(sg) do for sc in aux.Next(sg) do
cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,true,true}
aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(sc),tp) aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(sc),tp)
local tc=mg:CheckSubGroup(cm.hspcheck,1,#mg,cm.lvplus(sc),tp) local tc=cm.SelectSubGroup(mg,tp,cm.fselect,false,1,#mg,cm.lvplus(sc),tp)
aux.GCheckAdditional=nil aux.GCheckAdditional=nil
cm.SubGroupParams={}
if tc then return true end if tc then return true end
end end
return false return false
...@@ -205,9 +329,11 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp) ...@@ -205,9 +329,11 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp)
local sg=Duel.GetMatchingGroup(cm.filter3,tp,LOCATION_DECK,0,nil,e,tp) local sg=Duel.GetMatchingGroup(cm.filter3,tp,LOCATION_DECK,0,nil,e,tp)
local tg=Group.CreateGroup() local tg=Group.CreateGroup()
for sc in aux.Next(sg) do for sc in aux.Next(sg) do
cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,true,true}
aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(sc),tp) aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(sc),tp)
local tc=mg:CheckSubGroup(cm.hspcheck,1,#mg,cm.lvplus(sc),tp) local tc=cm.SelectSubGroup(mg,tp,cm.fselect,false,1,#mg,cm.lvplus(sc),tp)
aux.GCheckAdditional=nil aux.GCheckAdditional=nil
cm.SubGroupParams={}
if tc then tg:AddCard(sc) end if tc then tg:AddCard(sc) end
end end
if not tg or #tg==0 then return end if not tg or #tg==0 then return end
...@@ -217,11 +343,14 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp) ...@@ -217,11 +343,14 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp)
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SPSUMMON) Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SPSUMMON)
tc=tg:Select(tp,1,1,nil):GetFirst() tc=tg:Select(tp,1,1,nil):GetFirst()
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_REMOVE) Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_REMOVE)
cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,true}
aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(tc),tp) aux.GCheckAdditional=cm.hspgcheck(cm.lvplus(tc),tp)
rg=cm.SelectSubGroup(mg,tp,cm.hspcheck,true,1,#mg,cm.lvplus(tc),tp) rg=cm.SelectSubGroup(mg,tp,cm.fselect,true,1,#mg,cm.lvplus(tc),tp)
aux.GCheckAdditional=nil aux.GCheckAdditional=nil
cm.SubGroupParams={}
end end
Duel.ConfirmCards(1-tp,rg:Filter(Card.IsFacedown,nil)) Duel.ConfirmCards(1-tp,rg:Filter(Card.IsFacedown,nil))
tc:SetMaterial(rg)
local tg=rg:Filter(cm.filter5,nil) local tg=rg:Filter(cm.filter5,nil)
if not tg or #tg==0 then if not tg or #tg==0 then
if Duel.Remove(rg,POS_FACEUP,REASON_EFFECT)>0 then Duel.SpecialSummon(tc,0,tp,tp,false,false,POS_FACEUP) end if Duel.Remove(rg,POS_FACEUP,REASON_EFFECT)>0 then Duel.SpecialSummon(tc,0,tp,tp,false,false,POS_FACEUP) end
......
...@@ -83,9 +83,13 @@ function cm.fselect(g,ng,goal,tp) ...@@ -83,9 +83,13 @@ function cm.fselect(g,ng,goal,tp)
elseif g:GetSum(cm.lvplus)==goal and Duel.GetMZoneCount(tp,g)>0 then elseif g:GetSum(cm.lvplus)==goal and Duel.GetMZoneCount(tp,g)>0 then
return true return true
end end
local _SubGroupParams=cm.SubGroupParams
cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,true,true}
aux.GCheckAdditional=cm.hspgcheck2(g,g:GetSum(cm.lvplus)-goal,tp) aux.GCheckAdditional=cm.hspgcheck2(g,g:GetSum(cm.lvplus)-goal,tp)
local tc=cm.CheckSubGroup(ng,cm.fselect3,1,#ng,g,g:GetSum(cm.lvplus)-goal,tp) local tc=cm.SelectSubGroup(ng,tp,cm.fselect3,false,1,#ng,g,g:GetSum(cm.lvplus)-goal,tp)
--local tc=ng:CheckSubGroup(cm.fselect3,1,#ng,g,g:GetSum(cm.lvplus)-goal,tp)
aux.GCheckAdditional=nil aux.GCheckAdditional=nil
cm.SubGroupParams=_SubGroupParams
return tc return tc
end end
function cm.fselect3(g,g1,lv,tp) function cm.fselect3(g,g1,lv,tp)
...@@ -103,53 +107,19 @@ function cm.hspgcheck2(ng,goal,tp) ...@@ -103,53 +107,19 @@ function cm.hspgcheck2(ng,goal,tp)
return cm.fselect3(g,ng,goal,tp) return cm.fselect3(g,ng,goal,tp)
end end
end end
function cm.CheckSubGroup(g,f,min,max,...)
local min=min or 1
local max=max or #g
if min>max then return false end
local ext_params={...}
local sg=Duel.GrabSelectedCard()
if #sg>max or #(g+sg)<min then return false end
if #sg==max and (not f(sg,...) or Auxiliary.GCheckAdditional and not Auxiliary.GCheckAdditional(sg,nil,g,f,min,max,ext_params)) then return false end
if #sg>=min and #sg<=max and f(sg,...) and (not Auxiliary.GCheckAdditional or Auxiliary.GCheckAdditional(sg,nil,g,f,min,max,ext_params)) then return true end
return cm.CheckGroupRecursive(sg,g,f,min,max,ext_params)
end
function cm.CheckGroupRecursive(sg,g,f,min,max,ext_params)
local eg=g:Clone()
for c in aux.Next(g-sg) do
sg:AddCard(c)
if not Auxiliary.GCheckAdditional or Auxiliary.GCheckAdditional(sg,c,eg,f,min,max,ext_params) then
if (#sg>=min and #sg<=max and f(sg,table.unpack(ext_params))) or (#sg<max and cm.CheckGroupRecursive(sg,eg,f,min,max,ext_params)) then return true end
end
sg:RemoveCard(c)
eg:RemoveCard(c)
end
return false
end
function cm.CheckGroupRecursiveCapture(bool,sg,g,f,min,max,ext_params)
local eg=g:Clone()
if bool then cm.esg=sg:Clone() end
for c in aux.Next(g-sg) do
sg:AddCard(c)
if not Auxiliary.GCheckAdditional or Auxiliary.GCheckAdditional(sg,c,eg,f,min,max,ext_params) then
if (#sg>=min and #sg<=max and f(sg,table.unpack(ext_params))) then
for sc in aux.Next(sg-cm.esg) do
Auxiliary.SubGroupCaptured:Merge(eg:Filter(cm.slfilter,nil,sc))
end
end
if #sg<max then cm.CheckGroupRecursiveCapture(false,sg,eg,f,min,max,ext_params) end
end
sg:RemoveCard(c)
eg:Sub(eg:Filter(cm.slfilter,nil,c))
end
end
function cm.slfilter(c,sc) function cm.slfilter(c,sc)
return cm.lvplus(c)==cm.lvplus(sc) return cm.lvplus(c)==cm.lvplus(sc) and cm.filter4(c)==cm.filter4(sc)
end end
--subgroup optimization
function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...) function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...)
local min=min or 1 --classif: function to classify cards, e.g. function(c,tc) return c:GetLevel()==tc:GetLevel() end
local max=max or #g --sortif: function of subgroup search order, high to low. e.g. Card.GetLevel
local ext_params={...} --passf: cards that do not require check, e.g. function(c) return c:IsLevel(1) end
--goalstop: do you want to backtrack after reaching the goal? true/false
--check: do you want to return true after reaching the goal firstly? true/false
local classif,sortf,passf,goalstop,check=table.unpack(cm.SubGroupParams)
min=min or 1
max=max or #g
local sg=Group.CreateGroup() local sg=Group.CreateGroup()
local fg=Duel.GrabSelectedCard() local fg=Duel.GrabSelectedCard()
if #fg>max or min>max or #(g+fg)<min then return nil end if #fg>max or min>max or #(g+fg)<min then return nil end
...@@ -157,13 +127,146 @@ function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...) ...@@ -157,13 +127,146 @@ function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...)
fg:SelectUnselect(sg,tp,false,false,min,max) fg:SelectUnselect(sg,tp,false,false,min,max)
end end
sg:Merge(fg) sg:Merge(fg)
local mg,iisg,tmp,stop,iter,ctab,rtab,gtab
--main check
local finish=(#sg>=min and #sg<=max and f(sg,...)) local finish=(#sg>=min and #sg<=max and f(sg,...))
while #sg<max do while #sg<max do
Auxiliary.SubGroupCaptured=Group.CreateGroup() mg=g-sg
cm.CheckGroupRecursiveCapture(true,sg,g,f,min,max,ext_params) iisg=sg:Clone()
local cg=Auxiliary.SubGroupCaptured:Clone() if passf then
Auxiliary.SubGroupCaptured:Clear() aux.SubGroupCaptured=mg:Filter(passf,nil,sg,g)
else
aux.SubGroupCaptured=Group.CreateGroup()
end
ctab,rtab,gtab={},{},{1}
for tc in aux.Next(mg) do
ctab[#ctab+1]=tc
end
--high to low
if sortf then
for i=1,#ctab-1 do
for j=1,#ctab-1-i do
if sortf(ctab[j])<sortf(ctab[j+1]) then
tmp=ctab[j]
ctab[j]=ctab[j+1]
ctab[j+1]=tmp
end
end
end
end
--classify
if classif then
--make similar cards adjacent
for i=1,#ctab-2 do
for j=i+2,#ctab do
if classif(ctab[i],ctab[j]) then
tmp=ctab[j]
ctab[j]=ctab[i+1]
ctab[i+1]=tmp
end
end
end
--rtab[i]: what category does the i-th card belong to
--gtab[i]: What is the first card's number in the i-th category
for i=1,#ctab-1 do
rtab[i]=#gtab
if not classif(ctab[i],ctab[i+1]) then
gtab[#gtab+1]=i+1
end
end
rtab[#ctab]=#gtab
--iter record all cards' number in sg
iter={1}
sg:AddCard(ctab[1])
while #sg>#iisg and #aux.SubGroupCaptured<#mg do
stop=#sg>=max
--prune if too much cards
if (aux.GCheckAdditional and not aux.GCheckAdditional(sg,c,g,f,min,max,...)) then
stop=true
--skip check if no new cards
elseif #(sg-iisg-aux.SubGroupCaptured)>0 and #sg>=min and #sg<=max and f(sg,...) then
for sc in aux.Next(sg-iisg) do
if check then return true end
aux.SubGroupCaptured:Merge(mg:Filter(classif,nil,sc))
end
stop=goalstop
end
local code=iter[#iter]
--last card isn't in the last category
if code and code<gtab[#gtab] then
if stop then
--backtrack and add 1 card from next category
iter[#iter]=gtab[rtab[code]+1]
sg:RemoveCard(ctab[code])
sg:AddCard(ctab[(iter[#iter])])
else
--continue searching forward
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
end
--last card is in the last category
elseif code then
if stop or code>=#ctab then
--clear all cards in the last category
while #iter>0 and iter[#iter]>=gtab[#gtab] do
sg:RemoveCard(ctab[(iter[#iter])])
iter[#iter]=nil
end
--backtrack and add 1 card from next category
local code2=iter[#iter]
if code2 then
iter[#iter]=gtab[rtab[code2]+1]
sg:RemoveCard(ctab[code2])
sg:AddCard(ctab[(iter[#iter])])
end
else
--continue searching forward
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
end
end
end
--classification is essential for efficiency, and this part is only for backup
else
iter={1}
sg:AddCard(ctab[1])
while #sg>#iisg and #aux.SubGroupCaptured<#mg do
stop=#sg>=max
if (aux.GCheckAdditional and not aux.GCheckAdditional(sg,c,g,f,min,max,...)) then
stop=true
elseif #(sg-iisg-aux.SubGroupCaptured)>0 and #sg>=min and #sg<=max and f(sg,...) then
for sc in aux.Next(sg-iisg) do
if check then return true end
aux.SubGroupCaptured:AddCard(sc) --Merge(mg:Filter(class,nil,sc))
end
stop=goalstop
end
local code=iter[#iter]
if code<#ctab then
if stop then
iter[#iter]=nil
sg:RemoveCard(ctab[code])
end
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
else
local code2=iter[#iter-1]
iter[#iter]=nil
sg:RemoveCard(ctab[code])
if code2 and code2>0 then
iter[#iter]=code2+1
sg:RemoveCard(ctab[code2])
sg:AddCard(ctab[code2+1])
end
end
end
end
--finish searching
sg=iisg
local cg=aux.SubGroupCaptured:Clone()
aux.SubGroupCaptured:Clear()
cg:Sub(sg) cg:Sub(sg)
--Debug.Message(cm[0])
finish=(#sg>=min and #sg<=max and f(sg,...)) finish=(#sg>=min and #sg<=max and f(sg,...))
if #cg==0 then break end if #cg==0 then break end
local cancel=not finish and cancelable local cancel=not finish and cancelable
...@@ -217,9 +320,9 @@ function cm.sptg(e,tp,eg,ep,ev,re,r,rp,chk) ...@@ -217,9 +320,9 @@ function cm.sptg(e,tp,eg,ep,ev,re,r,rp,chk)
local ng=mg-trg local ng=mg-trg
local tg=Group.CreateGroup() local tg=Group.CreateGroup()
for sc in aux.Next(sg) do for sc in aux.Next(sg) do
--aux.GCheckAdditional=cm.hspgcheck cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,false,true}
local tc=cm.CheckSubGroup(trg,cm.fselect,1,#trg,ng,cm.lvplus(sc),tp) local tc=cm.SelectSubGroup(trg,tp,cm.fselect,false,1,#trg,ng,cm.lvplus(sc),tp)
--aux.GCheckAdditional=nil cm.SubGroupParams={}
if tc then return true end if tc then return true end
end end
return false return false
...@@ -235,9 +338,9 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp) ...@@ -235,9 +338,9 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp)
local ng=mg-trg local ng=mg-trg
local tg=Group.CreateGroup() local tg=Group.CreateGroup()
for sc in aux.Next(sg) do for sc in aux.Next(sg) do
--aux.GCheckAdditional=cm.hspgcheck cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,false,true}
local tc=cm.CheckSubGroup(trg,cm.fselect,1,#trg,ng,cm.lvplus(sc),tp) local tc=cm.SelectSubGroup(trg,tp,cm.fselect,false,1,#trg,ng,cm.lvplus(sc),tp)
--aux.GCheckAdditional=nil cm.SubGroupParams={}
if tc then tg:AddCard(sc) end if tc then tg:AddCard(sc) end
end end
if not tg or #tg==0 then return end if not tg or #tg==0 then return end
...@@ -248,13 +351,16 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp) ...@@ -248,13 +351,16 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp)
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SPSUMMON) Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SPSUMMON)
tc=tg:Select(tp,1,1,nil):GetFirst() tc=tg:Select(tp,1,1,nil):GetFirst()
Duel.Hint(HINT_SELECTMSG,tp,aux.Stringid(m,6)) Duel.Hint(HINT_SELECTMSG,tp,aux.Stringid(m,6))
--aux.GCheckAdditional=cm.hspgcheck cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,false}
rg=trg:SelectSubGroup(tp,cm.fselect,true,1,#trg,ng,cm.lvplus(tc),tp) rg=cm.SelectSubGroup(trg,tp,cm.fselect,true,1,#trg,ng,cm.lvplus(tc),tp)
cm.SubGroupParams={}
if rg and #rg>0 and rg:GetSum(cm.lvplus)>cm.lvplus(tc) then if rg and #rg>0 and rg:GetSum(cm.lvplus)>cm.lvplus(tc) then
Duel.Hint(HINT_SELECTMSG,tp,aux.Stringid(m,7)) Duel.Hint(HINT_SELECTMSG,tp,aux.Stringid(m,7))
cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,true}
aux.GCheckAdditional=cm.hspgcheck2(rg,rg:GetSum(cm.lvplus)-cm.lvplus(tc),tp) aux.GCheckAdditional=cm.hspgcheck2(rg,rg:GetSum(cm.lvplus)-cm.lvplus(tc),tp)
rg2=cm.SelectSubGroup(ng,tp,cm.fselect3,true,1,#ng,rg,rg:GetSum(cm.lvplus)-cm.lvplus(tc),tp) rg2=cm.SelectSubGroup(ng,tp,cm.fselect3,true,1,#ng,rg,rg:GetSum(cm.lvplus)-cm.lvplus(tc),tp)
aux.GCheckAdditional=nil aux.GCheckAdditional=nil
cm.SubGroupParams={}
if rg2 and #rg2>0 then if rg2 and #rg2>0 then
res=true res=true
rg:Merge(rg2) rg:Merge(rg2)
...@@ -264,6 +370,7 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp) ...@@ -264,6 +370,7 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp)
end end
end end
Duel.ConfirmCards(1-tp,rg:Filter(Card.IsFacedown,nil)) Duel.ConfirmCards(1-tp,rg:Filter(Card.IsFacedown,nil))
tc:SetMaterial(rg)
local tg=rg:Filter(cm.filter5,nil) local tg=rg:Filter(cm.filter5,nil)
if not tg or #tg==0 then if not tg or #tg==0 then
if Duel.Remove(rg,POS_FACEUP,REASON_EFFECT)>0 then Duel.SpecialSummon(tc,0,tp,tp,false,false,POS_FACEUP) end if Duel.Remove(rg,POS_FACEUP,REASON_EFFECT)>0 then Duel.SpecialSummon(tc,0,tp,tp,false,false,POS_FACEUP) end
......
...@@ -86,9 +86,13 @@ function cm.fselect(g,ng,goal,tp) ...@@ -86,9 +86,13 @@ function cm.fselect(g,ng,goal,tp)
elseif g:GetSum(cm.lvplus)==goal and Duel.GetMZoneCount(tp,g)>0 then elseif g:GetSum(cm.lvplus)==goal and Duel.GetMZoneCount(tp,g)>0 then
return true return true
end end
local _SubGroupParams=cm.SubGroupParams
cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,true,true}
aux.GCheckAdditional=cm.hspgcheck2(g,g:GetSum(cm.lvplus)-goal,tp) aux.GCheckAdditional=cm.hspgcheck2(g,g:GetSum(cm.lvplus)-goal,tp)
local tc=cm.CheckSubGroup(ng,cm.fselect3,1,#ng,g,g:GetSum(cm.lvplus)-goal,tp) local tc=cm.SelectSubGroup(ng,tp,cm.fselect3,false,1,#ng,g,g:GetSum(cm.lvplus)-goal,tp)
--local tc=ng:CheckSubGroup(cm.fselect3,1,#ng,g,g:GetSum(cm.lvplus)-goal,tp)
aux.GCheckAdditional=nil aux.GCheckAdditional=nil
cm.SubGroupParams=_SubGroupParams
return tc return tc
end end
function cm.fselect3(g,g1,lv,tp) function cm.fselect3(g,g1,lv,tp)
...@@ -106,53 +110,19 @@ function cm.hspgcheck2(ng,goal,tp) ...@@ -106,53 +110,19 @@ function cm.hspgcheck2(ng,goal,tp)
return cm.fselect3(g,ng,goal,tp) return cm.fselect3(g,ng,goal,tp)
end end
end end
function cm.CheckSubGroup(g,f,min,max,...)
local min=min or 1
local max=max or #g
if min>max then return false end
local ext_params={...}
local sg=Duel.GrabSelectedCard()
if #sg>max or #(g+sg)<min then return false end
if #sg==max and (not f(sg,...) or Auxiliary.GCheckAdditional and not Auxiliary.GCheckAdditional(sg,nil,g,f,min,max,ext_params)) then return false end
if #sg>=min and #sg<=max and f(sg,...) and (not Auxiliary.GCheckAdditional or Auxiliary.GCheckAdditional(sg,nil,g,f,min,max,ext_params)) then return true end
return cm.CheckGroupRecursive(sg,g,f,min,max,ext_params)
end
function cm.CheckGroupRecursive(sg,g,f,min,max,ext_params)
local eg=g:Clone()
for c in aux.Next(g-sg) do
sg:AddCard(c)
if not Auxiliary.GCheckAdditional or Auxiliary.GCheckAdditional(sg,c,eg,f,min,max,ext_params) then
if (#sg>=min and #sg<=max and f(sg,table.unpack(ext_params))) or (#sg<max and cm.CheckGroupRecursive(sg,eg,f,min,max,ext_params)) then return true end
end
sg:RemoveCard(c)
eg:RemoveCard(c)
end
return false
end
function cm.CheckGroupRecursiveCapture(bool,sg,g,f,min,max,ext_params)
local eg=g:Clone()
if bool then cm.esg=sg:Clone() end
for c in aux.Next(g-sg) do
sg:AddCard(c)
if not Auxiliary.GCheckAdditional or Auxiliary.GCheckAdditional(sg,c,eg,f,min,max,ext_params) then
if (#sg>=min and #sg<=max and f(sg,table.unpack(ext_params))) then
for sc in aux.Next(sg-cm.esg) do
Auxiliary.SubGroupCaptured:Merge(eg:Filter(cm.slfilter,nil,sc))
end
end
if #sg<max then cm.CheckGroupRecursiveCapture(false,sg,eg,f,min,max,ext_params) end
end
sg:RemoveCard(c)
eg:Sub(eg:Filter(cm.slfilter,nil,c))
end
end
function cm.slfilter(c,sc) function cm.slfilter(c,sc)
return cm.lvplus(c)==cm.lvplus(sc) return cm.lvplus(c)==cm.lvplus(sc) and cm.filter4(c)==cm.filter4(sc)
end end
--subgroup optimization
function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...) function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...)
local min=min or 1 --classif: function to classify cards, e.g. function(c,tc) return c:GetLevel()==tc:GetLevel() end
local max=max or #g --sortif: function of subgroup search order, high to low. e.g. Card.GetLevel
local ext_params={...} --passf: cards that do not require check, e.g. function(c) return c:IsLevel(1) end
--goalstop: do you want to backtrack after reaching the goal? true/false
--check: do you want to return true after reaching the goal firstly? true/false
local classif,sortf,passf,goalstop,check=table.unpack(cm.SubGroupParams)
min=min or 1
max=max or #g
local sg=Group.CreateGroup() local sg=Group.CreateGroup()
local fg=Duel.GrabSelectedCard() local fg=Duel.GrabSelectedCard()
if #fg>max or min>max or #(g+fg)<min then return nil end if #fg>max or min>max or #(g+fg)<min then return nil end
...@@ -160,13 +130,146 @@ function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...) ...@@ -160,13 +130,146 @@ function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...)
fg:SelectUnselect(sg,tp,false,false,min,max) fg:SelectUnselect(sg,tp,false,false,min,max)
end end
sg:Merge(fg) sg:Merge(fg)
local mg,iisg,tmp,stop,iter,ctab,rtab,gtab
--main check
local finish=(#sg>=min and #sg<=max and f(sg,...)) local finish=(#sg>=min and #sg<=max and f(sg,...))
while #sg<max do while #sg<max do
Auxiliary.SubGroupCaptured=Group.CreateGroup() mg=g-sg
cm.CheckGroupRecursiveCapture(true,sg,g,f,min,max,ext_params) iisg=sg:Clone()
local cg=Auxiliary.SubGroupCaptured:Clone() if passf then
Auxiliary.SubGroupCaptured:Clear() aux.SubGroupCaptured=mg:Filter(passf,nil,sg,g)
else
aux.SubGroupCaptured=Group.CreateGroup()
end
ctab,rtab,gtab={},{},{1}
for tc in aux.Next(mg) do
ctab[#ctab+1]=tc
end
--high to low
if sortf then
for i=1,#ctab-1 do
for j=1,#ctab-1-i do
if sortf(ctab[j])<sortf(ctab[j+1]) then
tmp=ctab[j]
ctab[j]=ctab[j+1]
ctab[j+1]=tmp
end
end
end
end
--classify
if classif then
--make similar cards adjacent
for i=1,#ctab-2 do
for j=i+2,#ctab do
if classif(ctab[i],ctab[j]) then
tmp=ctab[j]
ctab[j]=ctab[i+1]
ctab[i+1]=tmp
end
end
end
--rtab[i]: what category does the i-th card belong to
--gtab[i]: What is the first card's number in the i-th category
for i=1,#ctab-1 do
rtab[i]=#gtab
if not classif(ctab[i],ctab[i+1]) then
gtab[#gtab+1]=i+1
end
end
rtab[#ctab]=#gtab
--iter record all cards' number in sg
iter={1}
sg:AddCard(ctab[1])
while #sg>#iisg and #aux.SubGroupCaptured<#mg do
stop=#sg>=max
--prune if too much cards
if (aux.GCheckAdditional and not aux.GCheckAdditional(sg,c,g,f,min,max,...)) then
stop=true
--skip check if no new cards
elseif #(sg-iisg-aux.SubGroupCaptured)>0 and #sg>=min and #sg<=max and f(sg,...) then
for sc in aux.Next(sg-iisg) do
if check then return true end
aux.SubGroupCaptured:Merge(mg:Filter(classif,nil,sc))
end
stop=goalstop
end
local code=iter[#iter]
--last card isn't in the last category
if code and code<gtab[#gtab] then
if stop then
--backtrack and add 1 card from next category
iter[#iter]=gtab[rtab[code]+1]
sg:RemoveCard(ctab[code])
sg:AddCard(ctab[(iter[#iter])])
else
--continue searching forward
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
end
--last card is in the last category
elseif code then
if stop or code>=#ctab then
--clear all cards in the last category
while #iter>0 and iter[#iter]>=gtab[#gtab] do
sg:RemoveCard(ctab[(iter[#iter])])
iter[#iter]=nil
end
--backtrack and add 1 card from next category
local code2=iter[#iter]
if code2 then
iter[#iter]=gtab[rtab[code2]+1]
sg:RemoveCard(ctab[code2])
sg:AddCard(ctab[(iter[#iter])])
end
else
--continue searching forward
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
end
end
end
--classification is essential for efficiency, and this part is only for backup
else
iter={1}
sg:AddCard(ctab[1])
while #sg>#iisg and #aux.SubGroupCaptured<#mg do
stop=#sg>=max
if (aux.GCheckAdditional and not aux.GCheckAdditional(sg,c,g,f,min,max,...)) then
stop=true
elseif #(sg-iisg-aux.SubGroupCaptured)>0 and #sg>=min and #sg<=max and f(sg,...) then
for sc in aux.Next(sg-iisg) do
if check then return true end
aux.SubGroupCaptured:AddCard(sc) --Merge(mg:Filter(class,nil,sc))
end
stop=goalstop
end
local code=iter[#iter]
if code<#ctab then
if stop then
iter[#iter]=nil
sg:RemoveCard(ctab[code])
end
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
else
local code2=iter[#iter-1]
iter[#iter]=nil
sg:RemoveCard(ctab[code])
if code2 and code2>0 then
iter[#iter]=code2+1
sg:RemoveCard(ctab[code2])
sg:AddCard(ctab[code2+1])
end
end
end
end
--finish searching
sg=iisg
local cg=aux.SubGroupCaptured:Clone()
aux.SubGroupCaptured:Clear()
cg:Sub(sg) cg:Sub(sg)
--Debug.Message(cm[0])
finish=(#sg>=min and #sg<=max and f(sg,...)) finish=(#sg>=min and #sg<=max and f(sg,...))
if #cg==0 then break end if #cg==0 then break end
local cancel=not finish and cancelable local cancel=not finish and cancelable
...@@ -257,9 +360,9 @@ function cm.sptg(e,tp,eg,ep,ev,re,r,rp,chk) ...@@ -257,9 +360,9 @@ function cm.sptg(e,tp,eg,ep,ev,re,r,rp,chk)
local ng=mg-trg local ng=mg-trg
local tg=Group.CreateGroup() local tg=Group.CreateGroup()
for sc in aux.Next(sg) do for sc in aux.Next(sg) do
--aux.GCheckAdditional=cm.hspgcheck cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,false,true}
local tc=cm.CheckSubGroup(trg,cm.fselect,1,#trg,ng,cm.lvplus(sc),tp) local tc=cm.SelectSubGroup(trg,tp,cm.fselect,false,1,#trg,ng,cm.lvplus(sc),tp)
--aux.GCheckAdditional=nil cm.SubGroupParams={}
if tc then return true end if tc then return true end
end end
return false return false
...@@ -275,9 +378,9 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp) ...@@ -275,9 +378,9 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp)
local ng=mg-trg local ng=mg-trg
local tg=Group.CreateGroup() local tg=Group.CreateGroup()
for sc in aux.Next(sg) do for sc in aux.Next(sg) do
--aux.GCheckAdditional=cm.hspgcheck cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,false,true}
local tc=cm.CheckSubGroup(trg,cm.fselect,1,#trg,ng,cm.lvplus(sc),tp) local tc=cm.SelectSubGroup(trg,tp,cm.fselect,false,1,#trg,ng,cm.lvplus(sc),tp)
--aux.GCheckAdditional=nil cm.SubGroupParams={}
if tc then tg:AddCard(sc) end if tc then tg:AddCard(sc) end
end end
if not tg or #tg==0 then return end if not tg or #tg==0 then return end
...@@ -288,13 +391,16 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp) ...@@ -288,13 +391,16 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp)
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SPSUMMON) Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SPSUMMON)
tc=tg:Select(tp,1,1,nil):GetFirst() tc=tg:Select(tp,1,1,nil):GetFirst()
Duel.Hint(HINT_SELECTMSG,tp,aux.Stringid(m,6)) Duel.Hint(HINT_SELECTMSG,tp,aux.Stringid(m,6))
--aux.GCheckAdditional=cm.hspgcheck cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,false}
rg=trg:SelectSubGroup(tp,cm.fselect,true,1,#trg,ng,cm.lvplus(tc),tp) rg=cm.SelectSubGroup(trg,tp,cm.fselect,true,1,#trg,ng,cm.lvplus(tc),tp)
cm.SubGroupParams={}
if rg and #rg>0 and rg:GetSum(cm.lvplus)>cm.lvplus(tc) then if rg and #rg>0 and rg:GetSum(cm.lvplus)>cm.lvplus(tc) then
Duel.Hint(HINT_SELECTMSG,tp,aux.Stringid(m,7)) Duel.Hint(HINT_SELECTMSG,tp,aux.Stringid(m,7))
cm.SubGroupParams={cm.slfilter,Card.GetLevel,nil,true}
aux.GCheckAdditional=cm.hspgcheck2(rg,rg:GetSum(cm.lvplus)-cm.lvplus(tc),tp) aux.GCheckAdditional=cm.hspgcheck2(rg,rg:GetSum(cm.lvplus)-cm.lvplus(tc),tp)
rg2=cm.SelectSubGroup(ng,tp,cm.fselect3,true,1,#ng,rg,rg:GetSum(cm.lvplus)-cm.lvplus(tc),tp) rg2=cm.SelectSubGroup(ng,tp,cm.fselect3,true,1,#ng,rg,rg:GetSum(cm.lvplus)-cm.lvplus(tc),tp)
aux.GCheckAdditional=nil aux.GCheckAdditional=nil
cm.SubGroupParams={}
if rg2 and #rg2>0 then if rg2 and #rg2>0 then
res=true res=true
rg:Merge(rg2) rg:Merge(rg2)
...@@ -304,6 +410,7 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp) ...@@ -304,6 +410,7 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp)
end end
end end
Duel.ConfirmCards(1-tp,rg:Filter(Card.IsFacedown,nil)) Duel.ConfirmCards(1-tp,rg:Filter(Card.IsFacedown,nil))
tc:SetMaterial(rg)
local tg=rg:Filter(cm.filter5,nil) local tg=rg:Filter(cm.filter5,nil)
if not tg or #tg==0 then if not tg or #tg==0 then
if Duel.Remove(rg,POS_FACEUP,REASON_EFFECT)>0 then Duel.SpecialSummon(tc,0,tp,tp,false,false,POS_FACEUP) end if Duel.Remove(rg,POS_FACEUP,REASON_EFFECT)>0 then Duel.SpecialSummon(tc,0,tp,tp,false,false,POS_FACEUP) end
......
...@@ -36,66 +36,22 @@ end ...@@ -36,66 +36,22 @@ end
function cm.mzfilter(c) function cm.mzfilter(c)
return c:IsAbleToDeckOrExtraAsCost() and c:GetLevel()>=1 and c:IsRace(RACE_PSYCHO) and (c:IsLocation(LOCATION_GRAVE) or c:IsFacedown()) return c:IsAbleToDeckOrExtraAsCost() and c:GetLevel()>=1 and c:IsRace(RACE_PSYCHO) and (c:IsLocation(LOCATION_GRAVE) or c:IsFacedown())
end end
function cm.CheckSubGroup(g,f,min,max,...)
local min=min or 1
local max=max or #g
if min>max then return false end
local ext_params={...}
local sg=Duel.GrabSelectedCard()
if #sg>max or #(g+sg)<min then return false end
if #sg==max and (not f(sg,...) or Auxiliary.GCheckAdditional and not Auxiliary.GCheckAdditional(sg,nil,g,f,min,max,ext_params)) then return false end
if #sg>=min and #sg<=max and f(sg,...) and (not Auxiliary.GCheckAdditional or Auxiliary.GCheckAdditional(sg,nil,g,f,min,max,ext_params)) then return true end
return cm.CheckGroupRecursive(sg,g,f,min,max,ext_params)
end
function cm.CheckGroupRecursive(sg,g,f,min,max,ext_params)
local eg=g:Clone()
for c in aux.Next(g-sg) do
sg:AddCard(c)
if not Auxiliary.GCheckAdditional or Auxiliary.GCheckAdditional(sg,c,eg,f,min,max,ext_params) then
if (#sg>=min and #sg<=max and f(sg,table.unpack(ext_params))) or (#sg<max and cm.CheckGroupRecursive(sg,eg,f,min,max,ext_params)) then return true end
end
sg:RemoveCard(c)
eg:Sub(eg:Filter(cm.slfilter,nil,c))
end
return false
end
function cm.CheckGroupRecursiveCapture(bool,sg,g,f,min,max,ext_params)
local eg=g:Clone()
if bool then cm.esg=sg:Clone() cm.eeg=g:Clone() end
local tempg=g-sg
local c=tempg:GetFirst()
while c do
if not bool or not Auxiliary.SubGroupCaptured:IsContains(c) then
sg:AddCard(c)
if not Auxiliary.GCheckAdditional or Auxiliary.GCheckAdditional(sg,c,eg,f,min,max,ext_params) then
if (#sg>=min and #sg<=max and f(sg,table.unpack(ext_params))) then -- or (#sg<max and cm.CheckGroupRecursiveCapture(false,sg,eg,f,min,max,ext_params)) then
--Debug.Message(cm[0])
for sc in aux.Next(sg-cm.esg) do
Auxiliary.SubGroupCaptured:Merge(cm.eeg:Filter(cm.slfilter,nil,sc))
end
end
if #sg<max then cm.CheckGroupRecursiveCapture(false,sg,eg,f,min,max,ext_params) end
end
sg:RemoveCard(c)
--eg:RemoveCard(c)
eg:Sub(eg:Filter(cm.slfilter,nil,c))
tempg:Sub(eg:Filter(cm.slfilter,nil,c))
end
tempg:RemoveCard(c)
c=tempg:GetFirst()
end
end
function cm.slfilter(c,sc) function cm.slfilter(c,sc)
return c:IsLocation(sc:GetLocation()) and (c:GetLevel()-sc:GetLevel())%5==0 return c:IsLocation(sc:GetLocation()) and (c:GetLevel()-sc:GetLevel())%5==0
end end
function cm.srfilter(c) function cm.srfilter(c)
return c:GetLevel()%5==0 return c:GetLevel()%5==0
end end
--subgroup optimization
function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...) function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...)
Auxiliary.SubGroupCaptured=g:Filter(cm.srfilter,nil) --classif: function to classify cards, e.g. function(c,tc) return c:GetLevel()==tc:GetLevel() end
local min=min or 1 --sortif: function of subgroup search order, high to low. e.g. Card.GetLevel
local max=max or #g --passf: cards that do not require check, e.g. function(c) return c:IsLevel(1) end
local ext_params={...} --goalstop: do you want to backtrack after reaching the goal? true/false
--check: do you want to return true after reaching the goal firstly? true/false
local classif,sortf,passf,goalstop,check=table.unpack(cm.SubGroupParams)
min=min or 1
max=max or #g
local sg=Group.CreateGroup() local sg=Group.CreateGroup()
local fg=Duel.GrabSelectedCard() local fg=Duel.GrabSelectedCard()
if #fg>max or min>max or #(g+fg)<min then return nil end if #fg>max or min>max or #(g+fg)<min then return nil end
...@@ -103,14 +59,146 @@ function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...) ...@@ -103,14 +59,146 @@ function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...)
fg:SelectUnselect(sg,tp,false,false,min,max) fg:SelectUnselect(sg,tp,false,false,min,max)
end end
sg:Merge(fg) sg:Merge(fg)
local mg,iisg,tmp,stop,iter,ctab,rtab,gtab
--main check
local finish=(#sg>=min and #sg<=max and f(sg,...)) local finish=(#sg>=min and #sg<=max and f(sg,...))
while #sg<max do while #sg<max do
Auxiliary.SubGroupCaptured=(g-sg):Filter(cm.srfilter,nil) mg=g-sg
cm.CheckGroupRecursiveCapture(true,sg,g,f,min,max,ext_params) iisg=sg:Clone()
local cg=Auxiliary.SubGroupCaptured:Clone() if passf then
Auxiliary.SubGroupCaptured:Clear() aux.SubGroupCaptured=mg:Filter(passf,nil,sg,g)
--Debug.Message(cm[0]) else
aux.SubGroupCaptured=Group.CreateGroup()
end
ctab,rtab,gtab={},{},{1}
for tc in aux.Next(mg) do
ctab[#ctab+1]=tc
end
--high to low
if sortf then
for i=1,#ctab-1 do
for j=1,#ctab-1-i do
if sortf(ctab[j])<sortf(ctab[j+1]) then
tmp=ctab[j]
ctab[j]=ctab[j+1]
ctab[j+1]=tmp
end
end
end
end
--classify
if classif then
--make similar cards adjacent
for i=1,#ctab-2 do
for j=i+2,#ctab do
if classif(ctab[i],ctab[j]) then
tmp=ctab[j]
ctab[j]=ctab[i+1]
ctab[i+1]=tmp
end
end
end
--rtab[i]: what category does the i-th card belong to
--gtab[i]: What is the first card's number in the i-th category
for i=1,#ctab-1 do
rtab[i]=#gtab
if not classif(ctab[i],ctab[i+1]) then
gtab[#gtab+1]=i+1
end
end
rtab[#ctab]=#gtab
--iter record all cards' number in sg
iter={1}
sg:AddCard(ctab[1])
while #sg>#iisg and #aux.SubGroupCaptured<#mg do
stop=#sg>=max
--prune if too much cards
if (aux.GCheckAdditional and not aux.GCheckAdditional(sg,c,g,f,min,max,...)) then
stop=true
--skip check if no new cards
elseif #(sg-iisg-aux.SubGroupCaptured)>0 and #sg>=min and #sg<=max and f(sg,...) then
for sc in aux.Next(sg-iisg) do
if check then return true end
aux.SubGroupCaptured:Merge(mg:Filter(classif,nil,sc))
end
stop=goalstop
end
local code=iter[#iter]
--last card isn't in the last category
if code and code<gtab[#gtab] then
if stop then
--backtrack and add 1 card from next category
iter[#iter]=gtab[rtab[code]+1]
sg:RemoveCard(ctab[code])
sg:AddCard(ctab[(iter[#iter])])
else
--continue searching forward
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
end
--last card is in the last category
elseif code then
if stop or code>=#ctab then
--clear all cards in the last category
while #iter>0 and iter[#iter]>=gtab[#gtab] do
sg:RemoveCard(ctab[(iter[#iter])])
iter[#iter]=nil
end
--backtrack and add 1 card from next category
local code2=iter[#iter]
if code2 then
iter[#iter]=gtab[rtab[code2]+1]
sg:RemoveCard(ctab[code2])
sg:AddCard(ctab[(iter[#iter])])
end
else
--continue searching forward
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
end
end
end
--classification is essential for efficiency, and this part is only for backup
else
iter={1}
sg:AddCard(ctab[1])
while #sg>#iisg and #aux.SubGroupCaptured<#mg do
stop=#sg>=max
if (aux.GCheckAdditional and not aux.GCheckAdditional(sg,c,g,f,min,max,...)) then
stop=true
elseif #(sg-iisg-aux.SubGroupCaptured)>0 and #sg>=min and #sg<=max and f(sg,...) then
for sc in aux.Next(sg-iisg) do
if check then return true end
aux.SubGroupCaptured:AddCard(sc) --Merge(mg:Filter(class,nil,sc))
end
stop=goalstop
end
local code=iter[#iter]
if code<#ctab then
if stop then
iter[#iter]=nil
sg:RemoveCard(ctab[code])
end
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
else
local code2=iter[#iter-1]
iter[#iter]=nil
sg:RemoveCard(ctab[code])
if code2 and code2>0 then
iter[#iter]=code2+1
sg:RemoveCard(ctab[code2])
sg:AddCard(ctab[code2+1])
end
end
end
end
--finish searching
sg=iisg
local cg=aux.SubGroupCaptured:Clone()
aux.SubGroupCaptured:Clear()
cg:Sub(sg) cg:Sub(sg)
--Debug.Message(cm[0])
finish=(#sg>=min and #sg<=max and f(sg,...)) finish=(#sg>=min and #sg<=max and f(sg,...))
if #cg==0 then break end if #cg==0 then break end
local cancel=not finish and cancelable local cancel=not finish and cancelable
...@@ -137,11 +225,11 @@ function cm.sprcon(e,c) ...@@ -137,11 +225,11 @@ function cm.sprcon(e,c)
if c==nil then return true end if c==nil then return true end
local tp=c:GetControler() local tp=c:GetControler()
local mg=Duel.GetMatchingGroup(cm.mzfilter,tp,LOCATION_GRAVE+LOCATION_REMOVED,0,nil) local mg=Duel.GetMatchingGroup(cm.mzfilter,tp,LOCATION_GRAVE+LOCATION_REMOVED,0,nil)
--[[Auxiliary.SubGroupCaptured=Group.CreateGroup() cm.SubGroupParams={cm.slfilter,Card.GetLevel,cm.srfilter,false,true}
local sg=Group.CreateGroup() local res=cm.SelectSubGroup(mg,tp,cm.syngoal,Duel.IsSummonCancelable(),2,#mg)
cm.CheckGroupRecursiveCapture(true,sg,mg,cm.syngoal,4,#mg,{1}) cm.SubGroupParams={}
Debug.Message(cm[0])--]] --Debug.Message(cm[0])
return mg:IsExists(Card.IsLocation,2,nil,LOCATION_GRAVE) and mg:IsExists(Card.IsLocation,2,nil,LOCATION_REMOVED) and Duel.GetLocationCountFromEx(tp,tp,nil,c)>0 and cm.CheckSubGroup(mg,cm.syngoal) return mg:IsExists(Card.IsLocation,2,nil,LOCATION_GRAVE) and mg:IsExists(Card.IsLocation,2,nil,LOCATION_REMOVED) and Duel.GetLocationCountFromEx(tp,tp,nil,c)>0 and res
end end
--cm[0]=0 --cm[0]=0
function cm.syngoal(g) function cm.syngoal(g)
...@@ -150,40 +238,18 @@ function cm.syngoal(g) ...@@ -150,40 +238,18 @@ function cm.syngoal(g)
end end
function cm.sprtg(e,tp,eg,ep,ev,re,r,rp,chk,c) function cm.sprtg(e,tp,eg,ep,ev,re,r,rp,chk,c)
local mg=Duel.GetMatchingGroup(cm.mzfilter,tp,LOCATION_GRAVE+LOCATION_REMOVED,0,nil) local mg=Duel.GetMatchingGroup(cm.mzfilter,tp,LOCATION_GRAVE+LOCATION_REMOVED,0,nil)
local sg=cm.SelectSubGroup(mg,tp,cm.syngoal,Duel.IsSummonCancelable(),4,#mg) cm.SubGroupParams={cm.slfilter,Card.GetLevel,cm.srfilter,false}
local sg=cm.SelectSubGroup(mg,tp,cm.syngoal,Duel.IsSummonCancelable(),2,#mg)
cm.SubGroupParams={}
if sg then if sg then
sg:KeepAlive() sg:KeepAlive()
e:SetLabelObject(sg) e:SetLabelObject(sg)
return true return true
else return false end else return false end
--[[local sg=Group.CreateGroup()
local cg=mg:Filter(cm.syncheck,sg,sg,mg)
local cg0=cg
local finish=cm.syngoal(sg)
while 1==1 do
cg=cg0:Filter(cm.syncheck,sg,sg,cg0)
cg:Sub(sg)
finish=cm.syngoal(sg)
local cancel=not finish and Duel.IsSummonCancelable()
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_TODECK)
local tc=cg:SelectUnselect(sg,tp,finish,cancel,4,#mg)
if not tc then break end
if not sg:IsContains(tc) then
sg:AddCard(tc)
if #sg==#cg then finish=true end
else
sg:RemoveCard(tc)
end
end
if finish then
sg:KeepAlive()
e:SetLabelObject(sg)
return true
else return false end--]]
end end
function cm.sprop(e,tp,eg,ep,ev,re,r,rp,c) function cm.sprop(e,tp,eg,ep,ev,re,r,rp,c)
local sg=e:GetLabelObject() local sg=e:GetLabelObject()
Card.SetMaterial(c,sg) c:SetMaterial(sg)
local cg=sg:Filter(Card.IsFacedown,nil) local cg=sg:Filter(Card.IsFacedown,nil)
Duel.SendtoDeck(sg,nil,2,REASON_COST+REASON_MATERIAL) Duel.SendtoDeck(sg,nil,2,REASON_COST+REASON_MATERIAL)
if #cg>0 then Duel.ConfirmCards(1-tp,cg) end if #cg>0 then Duel.ConfirmCards(1-tp,cg) end
......
...@@ -136,10 +136,10 @@ function cm.sptg(e,tp,eg,ep,ev,re,r,rp,chk) ...@@ -136,10 +136,10 @@ function cm.sptg(e,tp,eg,ep,ev,re,r,rp,chk)
local mg2=Duel.GetOverlayGroup(tp,1,1):Filter(cm.matfilter,nil) local mg2=Duel.GetOverlayGroup(tp,1,1):Filter(cm.matfilter,nil)
mg:Merge(mg2) mg:Merge(mg2)
if chk==0 then if chk==0 then
aux.GCheckAdditional=cm.fselect --aux.GCheckAdditional=cm.fselect
local res=Duel.IsExistingMatchingCard(Card.IsLinkSummonable,tp,LOCATION_EXTRA,0,1,nil,mg) --local res=Duel.IsExistingMatchingCard(Card.IsLinkSummonable,tp,LOCATION_EXTRA,0,1,nil,mg)
aux.GCheckAdditional=nil --aux.GCheckAdditional=nil
return res return Duel.IsExistingMatchingCard(cm.scfilter,tp,LOCATION_EXTRA,0,1,nil,mg)
end end
Duel.SetOperationInfo(0,CATEGORY_SPECIAL_SUMMON,nil,1,0,0) Duel.SetOperationInfo(0,CATEGORY_SPECIAL_SUMMON,nil,1,0,0)
end end
......
...@@ -183,7 +183,7 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp) ...@@ -183,7 +183,7 @@ function cm.spop(e,tp,eg,ep,ev,re,r,rp)
end end
local _GetReason=Card.GetReason local _GetReason=Card.GetReason
local _GetReasonCard=Card.GetReasonCard local _GetReasonCard=Card.GetReasonCard
Card.GetReason=function(c) if c:GetFlagEffect(m)>0 then return 0x40008 else return _GetReason(c) end end Card.GetReason=function(c) if c:GetFlagEffect(m)>0 then return _GetReason(c)|0x40008 else return _GetReason(c) end end
Card.GetReasonCard=function(c) if c:GetFlagEffect(m)>0 then return tc else return _GetReasonCard(c) end end Card.GetReasonCard=function(c) if c:GetFlagEffect(m)>0 then return tc else return _GetReasonCard(c) end end
--[[if c:GetFlagEffect(m)>0 then --[[if c:GetFlagEffect(m)>0 then
local _,fusc=_GetReasonCard(c) local _,fusc=_GetReasonCard(c)
......
...@@ -48,20 +48,31 @@ function cm.fselect2(g) ...@@ -48,20 +48,31 @@ function cm.fselect2(g)
end end
function cm.fselect3(g) function cm.fselect3(g)
local ct2=g:FilterCount(cm.sfilter,nil) local ct2=g:FilterCount(cm.sfilter,nil)
return #g<=2*ct2 return #g<=2*ct2 and #g%2==0
end end
function cm.fselect4(g) function cm.fselect4(g)
return #g%2==0 return #g%2==0
end end
function cm.fselect5(g) function cm.fselect5(g)
local ct4=g:FilterCount(cm.mfilter,nil) local ct4=g:FilterCount(cm.mfilter,nil)
return #g<=2*ct4 return #g<=2*ct4 and #g%2==0
end end
function cm.slfilter(c,sc)
return (c:IsOnField() and sc:IsOnField() and cm.sfilter(c,e)==cm.sfilter(sc,e)) or (not c:IsOnField() and not sc:IsOnField() and cm.mfilter(c,e)==cm.mfilter(sc,e))
end
function cm.srfilter(c,sg,g)
return (cm.sfilter(c) or cm.mfilter(c)) and #(g-sg)>1
end
--subgroup optimization
function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...) function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...)
Auxiliary.SubGroupCaptured=Group.CreateGroup() --classif: function to classify cards, e.g. function(c,tc) return c:GetLevel()==tc:GetLevel() end
local min=min or 1 --sortif: function of subgroup search order, high to low. e.g. Card.GetLevel
local max=max or #g --passf: cards that do not require check, e.g. function(c) return c:IsLevel(1) end
local ext_params={...} --goalstop: do you want to backtrack after reaching the goal? true/false
--check: do you want to return true after reaching the goal firstly? true/false
local classif,sortf,passf,goalstop,check=table.unpack(cm.SubGroupParams)
min=min or 1
max=max or #g
local sg=Group.CreateGroup() local sg=Group.CreateGroup()
local fg=Duel.GrabSelectedCard() local fg=Duel.GrabSelectedCard()
if #fg>max or min>max or #(g+fg)<min then return nil end if #fg>max or min>max or #(g+fg)<min then return nil end
...@@ -69,18 +80,146 @@ function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...) ...@@ -69,18 +80,146 @@ function cm.SelectSubGroup(g,tp,f,cancelable,min,max,...)
fg:SelectUnselect(sg,tp,false,false,min,max) fg:SelectUnselect(sg,tp,false,false,min,max)
end end
sg:Merge(fg) sg:Merge(fg)
local mg,iisg,tmp,stop,iter,ctab,rtab,gtab
--main check
local finish=(#sg>=min and #sg<=max and f(sg,...)) local finish=(#sg>=min and #sg<=max and f(sg,...))
while #sg<max do while #sg<max do
local cg=Group.CreateGroup() mg=g-sg
local eg=g:Clone() iisg=sg:Clone()
for c in aux.Next(g-sg) do if passf then
if not cg:IsContains(c) then aux.SubGroupCaptured=mg:Filter(passf,nil,sg,g)
if Auxiliary.CheckGroupRecursiveCapture(c,sg,eg,f,min,max,ext_params) then else
cg:Merge(Auxiliary.SubGroupCaptured) aux.SubGroupCaptured=Group.CreateGroup()
end
ctab,rtab,gtab={},{},{1}
for tc in aux.Next(mg) do
ctab[#ctab+1]=tc
end
--high to low
if sortf then
for i=1,#ctab-1 do
for j=1,#ctab-1-i do
if sortf(ctab[j])<sortf(ctab[j+1]) then
tmp=ctab[j]
ctab[j]=ctab[j+1]
ctab[j+1]=tmp
end
end end
end end
end end
--classify
if classif then
--make similar cards adjacent
for i=1,#ctab-2 do
for j=i+2,#ctab do
if classif(ctab[i],ctab[j]) then
tmp=ctab[j]
ctab[j]=ctab[i+1]
ctab[i+1]=tmp
end
end
end
--rtab[i]: what category does the i-th card belong to
--gtab[i]: What is the first card's number in the i-th category
for i=1,#ctab-1 do
rtab[i]=#gtab
if not classif(ctab[i],ctab[i+1]) then
gtab[#gtab+1]=i+1
end
end
rtab[#ctab]=#gtab
--iter record all cards' number in sg
iter={1}
sg:AddCard(ctab[1])
while #sg>#iisg and #aux.SubGroupCaptured<#mg do
stop=#sg>=max
--prune if too much cards
if (aux.GCheckAdditional and not aux.GCheckAdditional(sg,c,g,f,min,max,...)) then
stop=true
--skip check if no new cards
elseif #(sg-iisg-aux.SubGroupCaptured)>0 and #sg>=min and #sg<=max and f(sg,...) then
for sc in aux.Next(sg-iisg) do
if check then return true end
aux.SubGroupCaptured:Merge(mg:Filter(classif,nil,sc))
end
stop=goalstop
end
local code=iter[#iter]
--last card isn't in the last category
if code and code<gtab[#gtab] then
if stop then
--backtrack and add 1 card from next category
iter[#iter]=gtab[rtab[code]+1]
sg:RemoveCard(ctab[code])
sg:AddCard(ctab[(iter[#iter])])
else
--continue searching forward
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
end
--last card is in the last category
elseif code then
if stop or code>=#ctab then
--clear all cards in the last category
while #iter>0 and iter[#iter]>=gtab[#gtab] do
sg:RemoveCard(ctab[(iter[#iter])])
iter[#iter]=nil
end
--backtrack and add 1 card from next category
local code2=iter[#iter]
if code2 then
iter[#iter]=gtab[rtab[code2]+1]
sg:RemoveCard(ctab[code2])
sg:AddCard(ctab[(iter[#iter])])
end
else
--continue searching forward
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
end
end
end
--classification is essential for efficiency, and this part is only for backup
else
iter={1}
sg:AddCard(ctab[1])
while #sg>#iisg and #aux.SubGroupCaptured<#mg do
stop=#sg>=max
if (aux.GCheckAdditional and not aux.GCheckAdditional(sg,c,g,f,min,max,...)) then
stop=true
elseif #(sg-iisg-aux.SubGroupCaptured)>0 and #sg>=min and #sg<=max and f(sg,...) then
for sc in aux.Next(sg-iisg) do
if check then return true end
aux.SubGroupCaptured:AddCard(sc) --Merge(mg:Filter(class,nil,sc))
end
stop=goalstop
end
local code=iter[#iter]
if code<#ctab then
if stop then
iter[#iter]=nil
sg:RemoveCard(ctab[code])
end
iter[#iter+1]=code+1
sg:AddCard(ctab[code+1])
else
local code2=iter[#iter-1]
iter[#iter]=nil
sg:RemoveCard(ctab[code])
if code2 and code2>0 then
iter[#iter]=code2+1
sg:RemoveCard(ctab[code2])
sg:AddCard(ctab[code2+1])
end
end
end
end
--finish searching
sg=iisg
local cg=aux.SubGroupCaptured:Clone()
aux.SubGroupCaptured:Clear()
cg:Sub(sg) cg:Sub(sg)
--Debug.Message(cm[0])
finish=(#sg>=min and #sg<=max and f(sg,...)) finish=(#sg>=min and #sg<=max and f(sg,...))
if #cg==0 then break end if #cg==0 then break end
local cancel=not finish and cancelable local cancel=not finish and cancelable
...@@ -114,12 +253,14 @@ function cm.thtg(e,tp,eg,ep,ev,re,r,rp,chk,chkc) ...@@ -114,12 +253,14 @@ function cm.thtg(e,tp,eg,ep,ev,re,r,rp,chk,chkc)
--Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_TARGET) --Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_TARGET)
local min=2 local min=2
if Duel.IsExistingTarget(cm.mfilter,tp,LOCATION_GRAVE,LOCATION_GRAVE,1,nil,e) then min=0 end if Duel.IsExistingTarget(cm.mfilter,tp,LOCATION_GRAVE,LOCATION_GRAVE,1,nil,e) then min=0 end
aux.GCheckAdditional=cm.fselect3 cm.SubGroupParams={cm.slfilter,nil,cm.srfilter,false}
local tg=cm.SelectSubGroup(g1,tp,cm.fselect4,false,min,#g1) --aux.GCheckAdditional=cm.fselect3
local tg=cm.SelectSubGroup(g1,tp,cm.fselect3,false,min,#g1)
Duel.Hint(HINT_SELECTMSG,tp,aux.Stringid(m,14)) Duel.Hint(HINT_SELECTMSG,tp,aux.Stringid(m,14))
aux.GCheckAdditional=cm.fselect5 --aux.GCheckAdditional=cm.fselect5
local tg2=cm.SelectSubGroup(g2,tp,cm.fselect4,false,math.max(0,2-#tg),#g2) local tg2=cm.SelectSubGroup(g2,tp,cm.fselect5,false,math.max(0,2-#tg),#g2)
aux.GCheckAdditional=nil --aux.GCheckAdditional=nil
cm.SubGroupParams={}
tg:Merge(tg2) tg:Merge(tg2)
Duel.SetTargetCard(tg) Duel.SetTargetCard(tg)
end end
...@@ -176,12 +317,12 @@ function cm.filter1(c,fid) ...@@ -176,12 +317,12 @@ function cm.filter1(c,fid)
return c:GetFlagEffect(m)>0 and c:GetFlagEffectLabel(m)==fid return c:GetFlagEffect(m)>0 and c:GetFlagEffectLabel(m)==fid
end end
function Group.ForEach(group,func,...) function Group.ForEach(group,func,...)
if aux.GetValueType(group)=="Group" and group:GetCount()>0 then if aux.GetValueType(group)=="Group" and group:GetCount()>0 then
local d_group=group:Clone() local d_group=group:Clone()
for tc in aux.Next(d_group) do for tc in aux.Next(d_group) do
func(tc,...) func(tc,...)
end end
end end
end end
function cm.acop(e,tp,eg,ep,ev,re,r,rp) function cm.acop(e,tp,eg,ep,ev,re,r,rp)
if pnfl_adjusting then return end if pnfl_adjusting then return end
......
...@@ -106,7 +106,7 @@ function c28318027.rsop(e,tp,eg,ep,ev,re,r,rp) ...@@ -106,7 +106,7 @@ function c28318027.rsop(e,tp,eg,ep,ev,re,r,rp)
local xlv=c:GetFlagEffectLabel(28318027) local xlv=c:GetFlagEffectLabel(28318027)
local e1=Effect.CreateEffect(c) local e1=Effect.CreateEffect(c)
e1:SetType(EFFECT_TYPE_SINGLE) e1:SetType(EFFECT_TYPE_SINGLE)
e1:SetCode(EFFECT_CHANGE_RANK) e1:SetCode(EFFECT_CHANGE_RANK_FINAL)
e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE) e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE)
e1:SetReset(RESET_EVENT+RESETS_STANDARD) e1:SetReset(RESET_EVENT+RESETS_STANDARD)
e1:SetValue(xlv) e1:SetValue(xlv)
......
...@@ -109,7 +109,7 @@ function c28318749.rsop(e,tp,eg,ep,ev,re,r,rp) ...@@ -109,7 +109,7 @@ function c28318749.rsop(e,tp,eg,ep,ev,re,r,rp)
local xlv=c:GetFlagEffectLabel(28318749) local xlv=c:GetFlagEffectLabel(28318749)
local e1=Effect.CreateEffect(c) local e1=Effect.CreateEffect(c)
e1:SetType(EFFECT_TYPE_SINGLE) e1:SetType(EFFECT_TYPE_SINGLE)
e1:SetCode(EFFECT_CHANGE_RANK) e1:SetCode(EFFECT_CHANGE_RANK_FINAL)
e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE) e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE)
e1:SetReset(RESET_EVENT+RESETS_STANDARD) e1:SetReset(RESET_EVENT+RESETS_STANDARD)
e1:SetValue(xlv) e1:SetValue(xlv)
......
...@@ -127,7 +127,7 @@ function c28322413.rsop(e,tp,eg,ep,ev,re,r,rp) ...@@ -127,7 +127,7 @@ function c28322413.rsop(e,tp,eg,ep,ev,re,r,rp)
local xlv=c:GetFlagEffectLabel(28322413) local xlv=c:GetFlagEffectLabel(28322413)
local e1=Effect.CreateEffect(c) local e1=Effect.CreateEffect(c)
e1:SetType(EFFECT_TYPE_SINGLE) e1:SetType(EFFECT_TYPE_SINGLE)
e1:SetCode(EFFECT_CHANGE_RANK) e1:SetCode(EFFECT_CHANGE_RANK_FINAL)
e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE) e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_UNCOPYABLE)
e1:SetReset(RESET_EVENT+RESETS_STANDARD) e1:SetReset(RESET_EVENT+RESETS_STANDARD)
e1:SetValue(xlv) e1:SetValue(xlv)
...@@ -178,19 +178,58 @@ function c28322413.ruop(e,tp,eg,ep,ev,re,r,rp) ...@@ -178,19 +178,58 @@ function c28322413.ruop(e,tp,eg,ep,ev,re,r,rp)
local og=Duel.GetOperatedGroup() local og=Duel.GetOperatedGroup()
local ct=og:FilterCount(Card.IsLocation,nil,LOCATION_DECK+LOCATION_EXTRA) local ct=og:FilterCount(Card.IsLocation,nil,LOCATION_DECK+LOCATION_EXTRA)
if ct>0 then if ct>0 then
local e1=Effect.CreateEffect(e:GetHandler()) local e1=Effect.CreateEffect(c)
e1:SetType(EFFECT_TYPE_FIELD) e1:SetType(EFFECT_TYPE_FIELD+EFFECT_TYPE_CONTINUOUS)
e1:SetCode(EFFECT_UPDATE_LEVEL) e1:SetCode(EVENT_ADJUST)
e1:SetTargetRange(LOCATION_MZONE,0) e1:SetCondition(c28322413.adcon)
e1:SetValue(ct)
e1:SetReset(RESET_PHASE+PHASE_END+RESET_OPPO_TURN) e1:SetReset(RESET_PHASE+PHASE_END+RESET_OPPO_TURN)
e1:SetTarget(aux.TargetBoolFunction(Card.IsSetCard,0x284)) e1:SetOperation(c28322413.adop)
e1:SetLabel(ct)
e1:SetLabelObject(c)
Duel.RegisterEffect(e1,tp) Duel.RegisterEffect(e1,tp)
local e2=e1:Clone() table.insert(c28322413.et,{e1})
e2:SetCode(EFFECT_UPDATE_RANK) end
Duel.RegisterEffect(e2,tp) end
function c28322413.adcon(e,tp,eg,ep,ev,re,r,rp)
return Duel.IsExistingMatchingCard(c28322413.adf,tp,LOCATION_MZONE,0,1,nil,e)
end
function c28322413.adop(e,tp,eg,ep,ev,re,r,rp)
local ct=e:GetLabel()
local c,g= e:GetLabelObject(),Duel.GetMatchingGroup(c28322413.adf,tp,LOCATION_MZONE,0,nil,e)
for xc in aux.Next(g) do
local x
if xc:GetLevel()>0 then x=EFFECT_UPDATE_LEVEL
elseif xc:GetRank()>0 then x=EFFECT_UPDATE_RANK end
local e1=Effect.CreateEffect(c)
e1:SetType(EFFECT_TYPE_SINGLE)
e1:SetCode(x)
e1:SetReset(RESET_EVENT+RESETS_STANDARD+RESET_PHASE+PHASE_END+RESET_OPPO_TURN)
e1:SetValue(ct)
e1:SetCondition(c28322413.efcon)
e1:SetOwnerPlayer(tp)
xc:RegisterEffect(e1)
table.insert(c28322413.get(e),xc)
end end
end end
function c28322413.efcon(e,tp,eg,ep,ev,re,r,rp)
return e:GetHandler():GetControler()==e:GetOwnerPlayer()
end
c28322413.et = { }
function c28322413.get(v)
for _,i in ipairs(c28322413.et) do
if i[1]==v then return i end
end
end
function c28322413.ck(e,c)
local t = c28322413.get(e)
for _,v in ipairs(t) do
if v == c then return false end
end
return true
end
function c28322413.adf(c,e)
return c:IsSetCard(0x284) and (c:GetLevel()>0 or c:GetRank()>0) and c28322413.ck(e,c)
end
function c28322413.immunefilter(e,te) function c28322413.immunefilter(e,te)
return te:IsActiveType(TYPE_MONSTER) and not te:GetHandler():IsType(TYPE_XYZ) return te:IsActiveType(TYPE_MONSTER) and not te:GetHandler():IsType(TYPE_XYZ)
end 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