Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Y
ygopro-scripts-888
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vee4
ygopro-scripts-888
Commits
4451e60b
Commit
4451e60b
authored
Jun 24, 2025
by
Vury Leo
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
multi level
parent
7c961424
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
177 additions
and
47 deletions
+177
-47
procedure.lua
procedure.lua
+177
-47
No files found.
procedure.lua
View file @
4451e60b
...
...
@@ -3474,48 +3474,94 @@ function Synchro.AddSynchroProcedure(c,params)
c
:
RegisterEffect
(
e1
)
end
--- DFS helper: check if partial selection + candidates can form valid Synchro material group
--- @param candidates table -- array of candidate cards
--- @param targetLevel integer -- required total level
--- 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.
---
--- @param candidates Card[] -- Array of candidate material cards.
--- @param targetLevel integer -- Required total level for Synchro Summon.
--- @param tunerFilter fun(card:Card,targetCard:Card):boolean
--- -- Function to identify tuner materials.
--- @param nonTunerFilter fun(card:Card,targetCard:Card):boolean
--- @param targetCard Card -- the Synchro monster being summoned
--- @param tunerMin integer
--- @param tunerMax integer|table
--- @param nonTunerMin integer
--- @param nonTunerMax integer|table
--- @param selected table -- array of currently selected cards
--- @param index integer -- current index in candidates array for DFS, default 1
--- @param currentSum integer -- current sum of levels, default 0
--- @return boolean
function
Synchro
.
CanCompleteSelection
(
candidates
,
targetLevel
,
tunerFilter
,
nonTunerFilter
,
targetCard
,
tunerMin
,
tunerMax
,
nonTunerMin
,
nonTunerMax
,
selected
,
index
,
currentSum
)
index
=
index
or
1
currentSum
=
currentSum
or
0
selected
=
selected
or
{}
if
currentSum
>
targetLevel
then
return
false
end
--- -- Function to identify non-tuner materials.
--- @param targetCard Card -- The Synchro monster being summoned.
--- @param tunerMin integer -- Minimum number of tuner materials required.
--- @param tunerMax integer|table -- Maximum number of tuner materials allowed.
--- @param nonTunerMin integer -- Minimum number of non-tuner materials required.
--- @param nonTunerMax integer|table -- Maximum number of non-tuner materials allowed.
--- @param levelMapper fun(card:Card,targetCard:Card):integer[]
--- -- Function returning possible levels for a card.
--- @param selected? Card[] -- Currently selected material cards.
--- @param index? integer -- Current index in candidates for DFS (default 1).
--- @param state? table -- DFS state table containing:
--- -- sum (integer): current total level sum,
--- -- tunerCount (integer): current tuner count,
--- -- nonTunerCount (integer): current non-tuner count.
--- @return boolean -- True if a valid selection exists, false otherwise.
function
Synchro
.
CanCompleteSelection
(
candidates
,
targetLevel
,
tunerFilter
,
nonTunerFilter
,
targetCard
,
tunerMin
,
tunerMax
,
nonTunerMin
,
nonTunerMax
,
levelMapper
,
selected
,
index
,
state
)
index
=
index
or
1
selected
=
selected
or
{}
state
=
state
or
{
possibleSums
=
{[
0
]
=
true
},
tunerCount
=
0
,
nonTunerCount
=
0
,
}
if
Synchro
.
ExceedsMax
(
state
.
tunerCount
,
tunerMax
)
then
return
false
end
if
Synchro
.
ExceedsMax
(
state
.
nonTunerCount
,
nonTunerMax
)
then
return
false
end
if
index
>#
candidates
then
return
Synchro
.
IsSelectionValid
(
selected
,
targetLevel
,
tunerFilter
,
nonTunerFilter
,
targetCard
,
tunerMin
,
tunerMax
,
nonTunerMin
,
nonTunerMax
)
-- check if targetLevel achievable exactly
if
state
.
possibleSums
[
targetLevel
]
and
state
.
tunerCount
>=
tunerMin
and
state
.
nonTunerCount
>=
nonTunerMin
then
return
true
end
return
false
end
local
card
=
candidates
[
index
]
table.insert
(
selected
,
card
)
if
Synchro
.
CanCompleteSelection
(
candidates
,
targetLevel
,
tunerFilter
,
nonTunerFilter
,
targetCard
,
tunerMin
,
tunerMax
,
nonTunerMin
,
nonTunerMax
,
selected
,
index
+
1
,
currentSum
+
card
:
GetLevel
())
then
local
card
=
candidates
[
index
]
local
lvls
=
levelMapper
(
card
,
targetCard
)
local
tunerInc
=
tunerFilter
(
card
,
targetCard
)
and
1
or
0
local
nonTunerInc
=
nonTunerFilter
(
card
,
targetCard
)
and
1
or
0
local
newPossibleSums
=
Synchro
.
UpdatePossibleSums
(
state
.
possibleSums
,
lvls
,
targetLevel
)
if
next
(
newPossibleSums
)
then
-- push state
local
prevPossibleSums
=
state
.
possibleSums
local
prevTunerCount
=
state
.
tunerCount
local
prevNonTunerCount
=
state
.
nonTunerCount
state
.
possibleSums
=
newPossibleSums
state
.
tunerCount
=
state
.
tunerCount
+
tunerInc
state
.
nonTunerCount
=
state
.
nonTunerCount
+
nonTunerInc
table.insert
(
selected
,
card
)
if
Synchro
.
CanCompleteSelection
(
candidates
,
targetLevel
,
tunerFilter
,
nonTunerFilter
,
targetCard
,
tunerMin
,
tunerMax
,
nonTunerMin
,
nonTunerMax
,
levelMapper
,
selected
,
index
+
1
,
state
)
then
table.remove
(
selected
)
-- pop state
state
.
possibleSums
=
prevPossibleSums
state
.
tunerCount
=
prevTunerCount
state
.
nonTunerCount
=
prevNonTunerCount
return
true
end
table.remove
(
selected
)
return
true
-- pop state
state
.
possibleSums
=
prevPossibleSums
state
.
tunerCount
=
prevTunerCount
state
.
nonTunerCount
=
prevNonTunerCount
end
table.remove
(
selected
)
if
Synchro
.
CanCompleteSelection
(
candidates
,
targetLevel
,
tunerFilter
,
nonTunerFilter
,
targetCard
,
tunerMin
,
tunerMax
,
nonTunerMin
,
nonTunerMax
,
selected
,
index
+
1
,
currentSum
)
then
-- Option: exclude this card
if
Synchro
.
CanCompleteSelection
(
candidates
,
targetLevel
,
tunerFilter
,
nonTunerFilter
,
targetCard
,
tunerMin
,
tunerMax
,
nonTunerMin
,
nonTunerMax
,
levelMapper
,
selected
,
index
+
1
,
state
)
then
return
true
end
return
false
end
--- Synchro condition generator using tuner/non-tuner min/max counts and filters
function
Synchro
.
SynCondition
(
tunerFilter
,
nonTunerFilter
,
tunerMin
,
tunerMax
,
nonTunerMin
,
nonTunerMax
)
return
function
(
e
,
c
,
smat
,
mg
,
min
,
max
)
...
...
@@ -3529,14 +3575,13 @@ function Synchro.SynCondition(tunerFilter,nonTunerFilter,tunerMin,tunerMax,nonTu
table.insert
(
candidates
,
card
)
end
return
Synchro
.
CanCompleteSelection
(
candidates
,
targetLevel
,
tunerFilter
,
nonTunerFilter
,
c
,
tunerMin
,
tunerMax
,
nonTunerMin
,
nonTunerMax
,
{},
1
,
0
)
return
Synchro
.
CanCompleteSelection
(
candidates
,
targetLevel
,
tunerFilter
,
nonTunerFilter
,
c
,
tunerMin
,
tunerMax
,
nonTunerMin
,
nonTunerMax
,
Synchro
.
LevelMapper
)
end
end
function
Synchro
.
SynTarget
(
tunerFilter
,
nonTunerFilter
,
tunerMin
,
tunerMax
,
nonTunerMin
,
nonTunerMax
)
return
function
(
e
,
tp
,
eg
,
ep
,
ev
,
re
,
r
,
rp
,
chk
,
c
,
smat
,
mg
,
min
,
max
)
local
tc
=
c
local
mg
=
Duel
.
GetMatchingGroup
(
function
(
mc
)
return
mc
:
IsCanBeSynchroMaterial
(
mc
,
tc
)
end
,
tc
:
GetOwner
(),
LOCATION_MZONE
+
LOCATION_HAND
,
0
,
nil
)
return
function
(
e
,
tp
,
eg
,
ep
,
ev
,
re
,
r
,
rp
,
chk
,
tc
,
smat
,
mg
,
min
,
max
)
mg
=
mg
or
Duel
.
GetMatchingGroup
(
function
(
mc
)
return
mc
:
IsCanBeSynchroMaterial
(
mc
,
tc
)
end
,
tc
:
GetOwner
(),
LOCATION_MZONE
+
LOCATION_HAND
,
0
,
nil
)
local
sg
=
Group
.
CreateGroup
()
local
function
GroupToArray
(
group
)
...
...
@@ -3556,16 +3601,16 @@ function Synchro.SynTarget(tunerFilter,nonTunerFilter,tunerMin,tunerMax,nonTuner
for
_
,
card
in
ipairs
(
sg_arr
)
do
table.insert
(
testSelection
,
card
)
end
table.insert
(
testSelection
,
candidate
)
-- build
testC
andidates without candidate
local
testC
andidates
=
{}
-- build
rest_c
andidates without candidate
local
rest_c
andidates
=
{}
for
_
,
other
in
ipairs
(
cg_arr
)
do
if
other
~=
candidate
then
table.insert
(
testC
andidates
,
other
)
if
other
~=
candidate
then
table.insert
(
rest_c
andidates
,
other
)
end
end
if
Synchro
.
CanCompleteSelection
(
testC
andidates
,
rest_c
andidates
,
targetLevel
,
tunerFilter
,
nonTunerFilter
,
...
...
@@ -3574,9 +3619,10 @@ function Synchro.SynTarget(tunerFilter,nonTunerFilter,tunerMin,tunerMax,nonTuner
tunerMax
,
nonTunerMin
,
nonTunerMax
,
Synchro
.
LevelMapper
,
testSelection
,
1
,
0
Synchro
.
BuildStateFromSelection
(
testSelection
,
tunerFilter
,
nonTunerFilter
,
Synchro
.
LevelMapper
,
tc
,
targetLevel
)
)
then
addable
:
AddCard
(
candidate
)
end
...
...
@@ -3637,14 +3683,98 @@ function Synchro.GetDisplayMax(tunerMax,nonTunerMax)
end
function
Synchro
.
IsSelectionValid
(
selection
,
targetLevel
,
tunerFilter
,
nonTunerFilter
,
targetCard
,
tunerMin
,
tunerMax
,
nonTunerMin
,
nonTunerMax
)
local
tunerCount
,
nonTunerCount
,
levelSum
=
0
,
0
,
0
for
_
,
card
in
ipairs
(
selection
)
do
if
tunerFilter
(
card
,
targetCard
)
then
tunerCount
=
tunerCount
+
1
elseif
nonTunerFilter
(
card
,
targetCard
)
then
nonTunerCount
=
nonTunerCount
+
1
else
return
false
end
levelSum
=
levelSum
+
card
:
GetLevel
()
end
if
tunerCount
<
tunerMin
or
(
tunerMax
~=
Synchro
.
Infinite
and
tunerCount
>
tunerMax
)
then
return
false
end
if
nonTunerCount
<
nonTunerMin
or
(
nonTunerMax
~=
Synchro
.
Infinite
and
nonTunerCount
>
nonTunerMax
)
then
return
false
end
return
levelSum
==
targetLevel
local
state
=
Synchro
.
BuildStateFromSelection
(
selection
,
tunerFilter
,
nonTunerFilter
,
Synchro
.
LevelMapper
,
targetCard
,
targetLevel
)
-- check if targetLevel achievable exactly
if
Synchro
.
ExceedsMax
(
state
.
tunerCount
,
tunerMax
)
then
return
false
end
if
Synchro
.
ExceedsMax
(
state
.
nonTunerCount
,
nonTunerMax
)
then
return
false
end
if
state
.
possibleSums
[
targetLevel
]
and
state
.
tunerCount
>=
tunerMin
and
state
.
nonTunerCount
>=
nonTunerMin
then
return
true
end
return
false
end
--- Returns a list of possible levels this card can be treated as when used as Synchro material.
--- @param card Card -- The candidate material card.
--- @param targetCard Card -- The Synchro monster being summoned.
--- @return integer[] -- Array of possible level integers (e.g., {1} or {1,2}).
function
Synchro
.
LevelMapper
(
card
,
targetCard
)
Debug
.
Message
(
string.format
(
"lvel mapper for %d"
,
card
:
GetCode
()))
local
levelDict
=
{}
local
effs
=
{
card
:
IsHasEffect
(
EFFECT_SYNCHRO_LEVEL
)}
Debug
.
Message
(
string.format
(
"lvel mapper for %d, effs %d"
,
card
:
GetCode
(),
#
effs
))
if
#
effs
>
0
then
local
val
=
effs
[
1
]:
GetValue
()(
effs
[
1
],
targetCard
)
Debug
.
Message
(
string.format
(
"lvel mapper for %d, effs %d"
,
card
:
GetCode
(),
#
effs
))
if
type
(
val
)
==
"table"
then
for
_
,
v
in
ipairs
(
val
)
do
levelDict
[
v
]
=
true
end
elseif
type
(
val
)
==
"number"
then
if
val
>=
(
1
<<
16
)
then
-- compatibility
val
=
val
>>
16
end
Debug
.
Message
(
string.format
(
"add additional level %d"
,
val
))
levelDict
[
val
]
=
true
end
end
-- Always include original level
levelDict
[
card
:
GetLevel
()]
=
true
-- Convert dictionary keys back to array
local
levels
=
{}
for
lvl
,
_
in
pairs
(
levelDict
)
do
table.insert
(
levels
,
lvl
)
end
Debug
.
Message
(
string.format
(
"lvel mapper result for %d, %d"
,
card
:
GetCode
(),
#
levels
))
return
levels
end
function
Synchro
.
UpdatePossibleSums
(
possibleSums
,
cardLevels
,
targetLevel
)
local
newSums
=
{}
for
sum
,
_
in
pairs
(
possibleSums
)
do
for
_
,
lvl
in
ipairs
(
cardLevels
)
do
local
newSum
=
sum
+
lvl
if
newSum
<=
targetLevel
then
newSums
[
newSum
]
=
true
end
end
end
return
newSums
end
function
Synchro
.
BuildStateFromSelection
(
sg_arr
,
tunerFilter
,
nonTunerFilter
,
levelMapper
,
targetCard
,
targetLevel
)
local
possibleSums
=
{[
0
]
=
true
}
local
tunerCount
=
0
local
nonTunerCount
=
0
for
_
,
card
in
ipairs
(
sg_arr
)
do
local
levels
=
levelMapper
(
card
,
targetCard
)
possibleSums
=
Synchro
.
UpdatePossibleSums
(
possibleSums
,
levels
,
targetLevel
)
if
next
(
possibleSums
)
==
nil
then
-- no possible sums from current selection, invalid state
assert
(
false
)
return
{}
end
if
tunerFilter
(
card
,
targetCard
)
then
tunerCount
=
tunerCount
+
1
elseif
nonTunerFilter
(
card
,
targetCard
)
then
nonTunerCount
=
nonTunerCount
+
1
else
assert
(
false
)
return
{}
-- invalid material type
end
end
return
{
possibleSums
=
possibleSums
,
tunerCount
=
tunerCount
,
nonTunerCount
=
nonTunerCount
,
}
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment