Commit 2c59c8b6 authored by Vury Leo's avatar Vury Leo

fix mono

parent 0b1e497d
...@@ -3475,6 +3475,62 @@ function Synchro.AddSynchroProcedure(c,params) ...@@ -3475,6 +3475,62 @@ function Synchro.AddSynchroProcedure(c,params)
c:RegisterEffect(e1) c:RegisterEffect(e1)
end end
-- Entry point: prepares and invokes the DFS
function Synchro.FindValidSelection(candidates,target_level,
tuner_filter,non_tuner_filter,tc,
tuner_min,tuner_max,
non_tuner_min,non_tuner_max,
base_mapper,pre_select,state)
-- 1) Sort candidates: Mono first, then Flower, then normals
local function is_mono(c)
return c:IsCode(56897896)
end
local function is_flower(c)
return c:IsCode(57261568, 33541430, 89818984)
end
table.sort(candidates,function(a,b)
if is_mono(a)~=is_mono(b) then
return is_mono(a) -- monos first
end
if is_flower(a)~=is_flower(b) then
return is_flower(a) -- then flowers
end
-- otherwise normals: sort descending by level
return a:GetLevel()>b:GetLevel()
end)
-- 2) Find the index of the last dynamic card
local level_prune_index=0
for i, c in ipairs(candidates) do
if is_mono(c) or is_flower(c) then
level_prune_index=i
end
end
-- 3) Invoke the core DFS, passing last_dyn along
return Synchro.CanCompleteSelection(
candidates,target_level,
tuner_filter,non_tuner_filter,tc,
tuner_min,tuner_max,
non_tuner_min,non_tuner_max,
base_mapper,
pre_select or {},
1,
state or { -- initial state
possible_sums={[0]=true},
tuner_count=0,
non_tuner_count=0,
level_mapper=base_mapper,
level_mapper_priority=0,
},
{
level_prune_index=level_prune_index
}
)
end
--- Check if there exists a valid Synchro material selection from candidates (including current selected), --- Check if there exists a valid Synchro material selection from candidates (including current selected),
--- satisfying tuner/non-tuner counts and total level, supporting multiple possible levels per card. --- satisfying tuner/non-tuner counts and total level, supporting multiple possible levels per card.
--- ---
...@@ -3491,24 +3547,16 @@ end ...@@ -3491,24 +3547,16 @@ end
--- @param non_tuner_max integer|table -- Maximum number of non-tuner materials allowed. --- @param non_tuner_max integer|table -- Maximum number of non-tuner materials allowed.
--- @param base_mapper fun(card:Card,tc:Card):integer[] --- @param base_mapper fun(card:Card,tc:Card):integer[]
--- -- Function returning possible levels for a card. --- -- Function returning possible levels for a card.
--- @param selected? Card[] -- Currently selected material cards. --- @param selected Card[] -- Currently selected material cards.
--- @param index? integer -- Current index in candidates for DFS (default 1). --- @param index integer -- Current index in candidates for DFS (default 1).
--- @param state? table -- DFS state table containing: --- @param state table -- DFS state table containing:
--- -- sum (integer): current total level sum, --- -- sum (integer): current total level sum,
--- -- tuner_count (integer): current tuner count, --- -- tuner_count (integer): current tuner count,
--- -- non_tuner_count (integer): current non-tuner count. --- -- non_tuner_count (integer): current non-tuner count.
--- @param prune_indexes table
--- @return boolean -- True if a valid selection exists, false otherwise. --- @return boolean -- True if a valid selection exists, false otherwise.
function Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_tuner_filter,tc, function Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_tuner_filter,tc,
tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper,selected,index,state) tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper,selected,index,state,prune_indexes)
index=index or 1
selected=selected or {}
state=state or {
possible_sums={[0]=true},
tuner_count=0,
non_tuner_count=0,
priority=0,
level_mapper=base_mapper,
}
--- Mono Synchron (priority=2) > Flower Cardian (1) > normal (0) --- Mono Synchron (priority=2) > Flower Cardian (1) > normal (0)
local mapper = state.level_mapper local mapper = state.level_mapper
...@@ -3525,6 +3573,12 @@ function Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_t ...@@ -3525,6 +3573,12 @@ function Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_t
return false return false
end end
local prune_level=target_level
-- prune after all level dynamic cards consumed
if index<prune_indexes.level_prune_index then
prune_level=0xff -- infinity
end
local mc=candidates[index] local mc=candidates[index]
local tuner_inc=tuner_filter(mc,tc) and 1 or 0 local tuner_inc=tuner_filter(mc,tc) and 1 or 0
local non_tuner_inc=non_tuner_filter(mc,tc) and 1 or 0 local non_tuner_inc=non_tuner_filter(mc,tc) and 1 or 0
...@@ -3534,7 +3588,7 @@ function Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_t ...@@ -3534,7 +3588,7 @@ function Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_t
-- 1) MonoSynchron branch (priority<2 → first Mono; priority==2 → full Mono) -- 1) MonoSynchron branch (priority<2 → first Mono; priority==2 → full Mono)
if mc:IsCode(56897896) then if mc:IsCode(56897896) then
if state.priority<2 then if state.level_mapper_priority<2 then
-- first Mono: that one keeps its real level, others=1 -- first Mono: that one keeps its real level, others=1
local firstMono=mc local firstMono=mc
local mono_mapper=function(c,tc_arg) local mono_mapper=function(c,tc_arg)
...@@ -3544,51 +3598,58 @@ function Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_t ...@@ -3544,51 +3598,58 @@ function Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_t
return {1} return {1}
end end
end end
local sums1=Synchro.Updatepossible_sums( -- reset your sums_so_far into a single bucket of (#selected)*1+self
state.possible_sums, local sums1={[#selected+mc:GetLevel()]=true}
mono_mapper(mc,tc), if next(sums1)~=nil then
target_level
)
if next(sums1) then
table.insert(variants,{ table.insert(variants,{
sums=sums1, possible_sums=sums1,
mapper=mono_mapper, level_mapper=mono_mapper,
priority=2, level_mapper_priority=2,
}) })
end end
elseif state.priority==2 then elseif state.level_mapper_priority==2 then
-- second (or later) Mono: full override—all cards=Level 1 -- second (or later) Mono: full override—all cards=Level 1
local full_mapper=function() return {1} end local full_mapper=function() return {1} end
-- reset your sums_so_far into a single bucket of (#selected+1)*1 -- reset your sums_so_far into a single bucket of (#selected+1)*1
local cnt=#selected+1 local cnt=#selected+1
local sums2={[cnt]=true} local sums2={[cnt]=true}
table.insert(variants,{ table.insert(variants,{
sums=sums2, possible_sums=sums2,
mapper=full_mapper, level_mapper=full_mapper,
priority=2, -- stays in Mono mode level_mapper_priority=2, -- stays in Mono mode
}) })
end end
end end
-- 1) Normal include branch
local lvls=mapper(mc,tc) if not mc:IsCode(56897896) then
local sums_norm=Synchro.UpdatepossibleSums(state.possible_sums,lvls,target_level) -- 1) Normal include branch
if next(sums_norm)then local lvls=mapper(mc,tc)
table.insert(variants,{sums=sums_norm,mapper=mapper}) local sums_norm=Synchro.UpdatepossibleSums(state.possible_sums,lvls,prune_level)
if next(sums_norm) then
table.insert(variants,{possible_sums=sums_norm,level_mapper=mapper})
end
end end
-- 2) override if Flower Cardian -- 2) override if Flower Cardian
if mc:IsCode(57261568,33541430,89818984) then if mc:IsCode(57261568,33541430,89818984) then
local cnt=#selected+1 if state.level_mapper_priority<1 then
local sums_ovr={[2*cnt]=true} local cnt=#selected+1
table.insert(variants,{sums=sums_ovr,mapper=function() return{2} end}) local sums_ovr={[2*cnt]=true}
table.insert(variants,{
possible_sums=sums_ovr,
level_mapper=function() return{2} end,
level_mapper_priority=1
})
end
end end
for _,var in ipairs(variants) do for _,var in ipairs(variants) do
local new_state={ local new_state={
possible_sums=var.sums, possible_sums=var.possible_sums,
tuner_count=state.tuner_count+tuner_inc, tuner_count=state.tuner_count+tuner_inc,
non_tuner_count=state.non_tuner_count+non_tuner_inc, non_tuner_count=state.non_tuner_count+non_tuner_inc,
level_mapper=var.mapper, level_mapper=var.level_mapper,
level_mapper_priority=var.level_mapper_priority,
} }
table.insert(selected,mc) table.insert(selected,mc)
...@@ -3596,7 +3657,7 @@ function Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_t ...@@ -3596,7 +3657,7 @@ function Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_t
candidates,target_level, candidates,target_level,
tuner_filter,non_tuner_filter,tc, tuner_filter,non_tuner_filter,tc,
tuner_min,tuner_max,non_tuner_min,non_tuner_max, tuner_min,tuner_max,non_tuner_min,non_tuner_max,
base_mapper,selected,index+1,new_state base_mapper,selected,index+1,new_state,prune_indexes
) )
then then
table.remove(selected) table.remove(selected)
...@@ -3607,7 +3668,7 @@ function Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_t ...@@ -3607,7 +3668,7 @@ function Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_t
-- exclude branch -- exclude branch
if Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_tuner_filter,tc, if Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_tuner_filter,tc,
tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper,selected,index+1,state) then tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper,selected,index+1,state,prune_indexes) then
return true return true
end end
...@@ -3627,7 +3688,7 @@ function Synchro.SynCondition(tuner_filter,non_tuner_filter,tuner_min,tuner_max, ...@@ -3627,7 +3688,7 @@ function Synchro.SynCondition(tuner_filter,non_tuner_filter,tuner_min,tuner_max,
table.insert(candidates,mc) table.insert(candidates,mc)
end end
return Synchro.CanCompleteSelection(candidates,target_level,tuner_filter,non_tuner_filter,c,tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper) return Synchro.FindValidSelection(candidates,target_level,tuner_filter,non_tuner_filter,c,tuner_min,tuner_max,non_tuner_min,non_tuner_max,base_mapper)
end end
end end
...@@ -3647,17 +3708,17 @@ function Synchro.SynTarget(tuner_filter,non_tuner_filter,tuner_min,tuner_max,non ...@@ -3647,17 +3708,17 @@ function Synchro.SynTarget(tuner_filter,non_tuner_filter,tuner_min,tuner_max,non
local sg_arr=GroupToArray(sg) local sg_arr=GroupToArray(sg)
local cg_arr=GroupToArray(mg-sg) local cg_arr=GroupToArray(mg-sg)
local target_level=tc:GetLevel() local target_level=tc:GetLevel()
for _, candidate in ipairs(cg_arr) do for _,candidate in ipairs(cg_arr) do
-- simulate adding candidate to sg_arr -- simulate adding candidate to sg_arr
local test_selection = {} local test_selection={}
for _, card in ipairs(sg_arr) do table.insert(test_selection, card) end for _, card in ipairs(sg_arr) do table.insert(test_selection,card) end
table.insert(test_selection, candidate) table.insert(test_selection,candidate)
-- build rest_candidates without candidate -- build rest_candidates without candidate
local rest_candidates = {} local rest_candidates={}
for _, other in ipairs(cg_arr) do for _, other in ipairs(cg_arr) do
if other~=candidate then if other~=candidate then
table.insert(rest_candidates, other) table.insert(rest_candidates,other)
end end
end end
...@@ -3665,16 +3726,15 @@ function Synchro.SynTarget(tuner_filter,non_tuner_filter,tuner_min,tuner_max,non ...@@ -3665,16 +3726,15 @@ function Synchro.SynTarget(tuner_filter,non_tuner_filter,tuner_min,tuner_max,non
test_selection, test_selection,
tuner_filter,non_tuner_filter, tuner_filter,non_tuner_filter,
base_mapper, base_mapper,
tc,target_level tc,0xff
) )
for _,init_state in ipairs(base_states)do for _,init_state in ipairs(base_states) do
if Synchro.CanCompleteSelection( if Synchro.FindValidSelection(
rest_candidates,target_level, rest_candidates,target_level,
tuner_filter,non_tuner_filter,tc, tuner_filter,non_tuner_filter,tc,
tuner_min,tuner_max,non_tuner_min,non_tuner_max, tuner_min,tuner_max,non_tuner_min,non_tuner_max,
base_mapper,test_selection,1,init_state base_mapper,test_selection,init_state)
)
then then
addable:AddCard(candidate) addable:AddCard(candidate)
break break
...@@ -3740,7 +3800,7 @@ function Synchro.IsSelectionValid(selection,target_level,tuner_filter,non_tuner_ ...@@ -3740,7 +3800,7 @@ function Synchro.IsSelectionValid(selection,target_level,tuner_filter,non_tuner_
selection, selection,
tuner_filter,non_tuner_filter, tuner_filter,non_tuner_filter,
Synchro.LevelMapper, Synchro.LevelMapper,
tc,target_level tc,0xff
) )
for _,state in ipairs(states)do for _,state in ipairs(states)do
if not Synchro.ExceedsMax(state.tuner_count,tuner_max) then if not Synchro.ExceedsMax(state.tuner_count,tuner_max) then
...@@ -3793,29 +3853,50 @@ function Synchro.LevelMapper(card,tc) ...@@ -3793,29 +3853,50 @@ function Synchro.LevelMapper(card,tc)
return levels return levels
end end
function Synchro.UpdatepossibleSums(possible_sums, card_levels, target_level) function Synchro.UpdatepossibleSums(possible_sums,card_levels,prune_level)
local new_sums={} local new_sums={}
for sum, _ in pairs(possible_sums) do for sum, _ in pairs(possible_sums) do
for _, lvl in ipairs(card_levels) do for _, lvl in ipairs(card_levels) do
local newSum=sum+lvl local newSum=sum+lvl
if newSum<=target_level then if newSum<=prune_level then
new_sums[newSum] = true new_sums[newSum]=true
end end
end end
end end
return new_sums return new_sums
end end
function Synchro.BuildStatesFromSelection(selection,tuner_filter,non_tuner_filter,base_mapper,tc,target_level) function Synchro.BuildStatesFromSelection(selection,tuner_filter,non_tuner_filter,base_mapper,tc,prune_level)
local states={ local states={
{ {
possible_sums={[0]=true}, possible_sums={[0]=true},
tuner_count=0, tuner_count=0,
non_tuner_count=0, non_tuner_count=0,
level_mapper=base_mapper level_mapper=base_mapper,
level_mapper_priority=0,
} }
} }
-- 1) Sort candidates: Mono first, then Flower, then normals
local function is_mono(c)
return c:IsCode(56897896)
end
local function is_flower(c)
return c:IsCode(57261568, 33541430, 89818984)
end
table.sort(selection,function(a,b)
if is_mono(a)~=is_mono(b) then
return is_mono(a) -- monos first
end
if is_flower(a)~=is_flower(b) then
return is_flower(a) -- then flowers
end
-- otherwise normals: sort descending by level
return a:GetLevel()>b:GetLevel()
end)
for idx,card in ipairs(selection)do for idx,card in ipairs(selection)do
local next_states={} local next_states={}
...@@ -3824,27 +3905,68 @@ function Synchro.BuildStatesFromSelection(selection,tuner_filter,non_tuner_filte ...@@ -3824,27 +3905,68 @@ function Synchro.BuildStatesFromSelection(selection,tuner_filter,non_tuner_filte
local non_tuner_inc=non_tuner_filter(card,tc) and 1 or 0 local non_tuner_inc=non_tuner_filter(card,tc) and 1 or 0
local mapper=st.level_mapper local mapper=st.level_mapper
-- normal branch -- 1) MonoSynchron branch (priority<2 → first Mono; priority==2 → full Mono)
local lvls=mapper(card,tc) if card:IsCode(56897896) then
local sums_norm=Synchro.UpdatepossibleSums(st.possible_sums,lvls,target_level) if st.level_mapper_priority<2 then
if next(sums_norm) then -- first Mono: that one keeps its real level, others=1
table.insert(next_states,{ local firstMono=card
possible_sums=sums_norm, local mono_mapper=function(c,tc_arg)
tuner_count=st.tuner_count+tuner_inc, if c==firstMono then
non_tuner_count=st.non_tuner_count+non_tuner_inc, return {c:GetLevel()}
level_mapper=mapper, else
}) return {1}
end
end
local sums1={[idx-1+card:GetLevel()]=true}
table.insert(next_states,{
possible_sums=sums1,
tuner_count=st.tuner_count+tuner_inc,
non_tuner_count=st.non_tuner_count+non_tuner_inc,
level_mapper=mono_mapper,
level_mapper_priority=2,
})
elseif st.level_mapper_priority==2 then
-- second (or later) Mono: full override—all cards=Level 1
local full_mapper=function() return {1} end
-- reset your sums_so_far into a single bucket of idx*1
local sums2={[idx]=true}
table.insert(next_states,{
possible_sums=sums2,
tuner_count=st.tuner_count+tuner_inc,
non_tuner_count=st.non_tuner_count+non_tuner_inc,
level_mapper=full_mapper,
level_mapper_priority=2, -- stays in Mono mode
})
end
end
if not card:IsCode(56897896) then
-- normal branch
local lvls=mapper(card,tc)
local sums_norm=Synchro.UpdatepossibleSums(st.possible_sums,lvls,prune_level)
if next(sums_norm)~=nil then
table.insert(next_states,{
possible_sums=sums_norm,
tuner_count=st.tuner_count+tuner_inc,
non_tuner_count=st.non_tuner_count+non_tuner_inc,
level_mapper=mapper,
level_mapper_priority=st.level_mapper_priority,
})
end
end end
-- override level mapper branch if Flower Cardian -- override level mapper branch if Flower Cardian
if card:IsCode(57261568,33541430,89818984) then if card:IsCode(57261568,33541430,89818984) then
local sums_ovr={[2*idx]=true} if st.level_mapper_priority<1 then
table.insert(next_states,{ local sums_ovr={[2*idx]=true}
possible_sums=sums_ovr, table.insert(next_states,{
tuner_count=st.tuner_count+tuner_inc, possible_sums=sums_ovr,
non_tuner_count=st.non_tuner_count+non_tuner_inc, tuner_count=st.tuner_count+tuner_inc,
level_mapper=function() return {2} end, non_tuner_count=st.non_tuner_count+non_tuner_inc,
}) level_mapper=function() return {2} end,
level_mapper_priority=1,
})
end
end end
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