Commit 55b2a4bb authored by POLYMER's avatar POLYMER

fix

parent c3ae8a11
......@@ -35,17 +35,28 @@ end
function s.fselect(g,e,tp)
local sg=Duel.GetMatchingGroup(s.thfilter,tp,LOCATION_DECK,0,nil)
local lv=g:GetSum(Card.GetLevel)
return sg:CheckSubGroup(s.fselect2,1,#g-1,lv)
and Duel.IsExistingMatchingCard(s.spfilter,tp,LOCATION_HAND+LOCATION_DECK,0,1,g,e,tp)
if not Duel.IsExistingMatchingCard(s.spfilter,tp,LOCATION_HAND+LOCATION_DECK,0,1,g,e,tp) then return false end
local params=s.SubGroupParams
s.SubGroupParams={function(c,tc) return c:GetLevel()==tc:GetLevel() end,Card.GetLevel,nil,true,true}
local res=s.SelectSubGroup(sg,tp,s.fselect2,false,1,#g-1,lv)
s.SubGroupParams=params
return res
end
function s.fselect2(g,lv)
return g:GetSum(Card.GetLevel)==lv
end
function s.target(e,tp,eg,ep,ev,re,r,rp,chk)
local sg=Duel.GetMatchingGroup(s.costfilter1,tp,LOCATION_HAND,0,nil)
if chk==0 then return sg:CheckSubGroup(s.fselect,2,#sg,e,tp) end
if chk==0 then
s.SubGroupParams={function(c,tc) return c:GetLevel()==tc:GetLevel() end,Card.GetLevel,nil,false,true}
local res=s.SelectSubGroup(sg,tp,s.fselect,false,2,#sg,e,tp)
s.SubGroupParams={}
return res
end
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_CONFIRM)
local g=sg:SelectSubGroup(tp,s.fselect,false,2,#sg,e,tp)
s.SubGroupParams={function(c,tc) return c:GetLevel()==tc:GetLevel() end,Card.GetLevel,nil,false}
local g=s.SelectSubGroup(sg,tp,s.fselect,false,2,#sg,e,tp)
s.SubGroupParams={}
Duel.SetTargetCard(g)
local lv=g:GetSum(Card.GetLevel)
e:SetLabel(lv)
......@@ -65,7 +76,9 @@ function s.activate(e,tp,eg,ep,ev,re,r,rp)
if tg:GetCount()>0 then
local ct=Duel.SendtoDeck(tg,nil,SEQ_DECKSHUFFLE,REASON_EFFECT)
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_ATOHAND)
local tg=sg:SelectSubGroup(tp,s.fselect2,false,1,ct-1,lv)
s.SubGroupParams={function(c,tc) return c:GetLevel()==tc:GetLevel() end,Card.GetLevel,nil,true}
local tg=s.SelectSubGroup(sg,tp,s.fselect2,false,1,ct-1,lv)
s.SubGroupParams={}
Duel.SendtoHand(tg,nil,REASON_EFFECT)
Duel.ConfirmCards(1-tp,tg)
if #rg>0 then
......@@ -83,4 +96,187 @@ function s.activate(e,tp,eg,ep,ev,re,r,rp)
end
end
end
end
function s.SelectSubGroup(g,tp,f,cancelable,min,max,...)
--classif: function to classify cards, e.g. function(c,tc) return c:GetLevel()==tc:GetLevel() end
--sortif: function of subgroup search order, high to low. e.g. Card.GetLevel
--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(s.SubGroupParams)
goalstop=goalstop~=false
min=min or 1
max=max or #g
local sg=Group.CreateGroup()
local fg=Duel.GrabSelectedCard()
if #fg>max or min>max or #(g+fg)<min then return nil end
if not check then
for tc in aux.Next(fg) do
fg:SelectUnselect(sg,tp,false,false,min,max)
end
end
sg:Merge(fg)
local mg,iisg,tmp,stop,iter,ctab,rtab,gtab
--main check
local finish=(#sg>=min and #sg<=max and f(sg,...))
while #sg<max do
mg=g-sg
iisg=sg:Clone()
if passf then
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
if check then return false 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)
--Debug.Message(cm[0])
finish=(#sg>=min and #sg<=max and f(sg,...))
if #cg==0 then break end
local cancel=not finish and cancelable
local tc=cg:SelectUnselect(sg,tp,finish,cancel,min,max)
if not tc then break end
if not fg:IsContains(tc) then
if not sg:IsContains(tc) then
sg:AddCard(tc)
if #sg==max then finish=true end
else
sg:RemoveCard(tc)
end
elseif cancelable then
return nil
end
end
if finish then
return sg
else
return nil
end
end
\ No newline at end of file
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