Skip to content

Instantly share code, notes, and snippets.

@luckytyphlosion
Last active May 28, 2023 01:38
Show Gist options
  • Save luckytyphlosion/2fe5df87c9c6db8a4677dbb8a39f1a26 to your computer and use it in GitHub Desktop.
Save luckytyphlosion/2fe5df87c9c6db8a4677dbb8a39f1a26 to your computer and use it in GitHub Desktop.
EurandomDX_folder_gen_explanation

anyway, there are 3 categories

ranged chips, constrained chips, and nonattacking chips
and within each category there are three ranks
high, medium, and low
ranged chips are chips that you can basically hit from anywhere more or less or have a high AOE
this includes all the meta chips but also non-meta chips that still can hit relatively well
high, medium, and low corresponds to how well it hits + how much damage it does
so something like bblstar1 is still considered medium even though it does low damage since it can hit well
constrained chips are your swords, golmhit, tornado, gundels, and conditional chips like sumnblk and darkmech series
these are harder to hit
if you have too many of these in a folder then the match pacing goes down
finally nonattacking chips are non-attacking
so the way the algorithm works is
first generate between 1 and 2 pas
oh yeah also I have categories for megas, pseudomegas, gigas, and pas, which also have ranks. but those aren't too important and are added relatively independently

        pa_type = weighted_random({
            HIGH_PA: 0.3,
            MEDIUM_PA: 0.2,
            LOW_PA: 0.1,
            HIGH_HIGH_PA: 0.2,
            HIGH_MEDIUM_PA: 0.2
        })

these are the weights for how PAs are chosen
so e.g. it's 30% to have only one high rank PA, so your flamehooks, powerwaves, parashells. your big damage stuff
but you can also have a 20% chance of getting two high rank pas, or one high rank one medium rank

                if chosen_pa_1_name != chosen_pa_2["name"]:
                    if (chosen_pa_1_name == "FlmHook" and chosen_pa_2["name"] == "MstrCros") or (chosen_pa_1_name == "MstrCros" and chosen_pa_2["name"] == "FlmHook"):
                        if chosen_pa_1_name == "FlmHook":
                            flmhook_pa = chosen_pa_1
                        else:
                            flmhook_pa = chosen_pa_2
    
                        if flmhook_pa["parts"][0]["name"] != "FireHit3":
                            break
                    else:
                        break

bonus meme: needing to check if we're adding flmhook and mastercross into the folder
so after that we choose the number of megas in the folder, either 3 or 4
if we add a pseudo mega in the folder (most 50+MB chips that aren't megas), at a 20% rate for 1
then there's the initial generation step
you can glean over the calls and see the weightings: https://github.com/luckytyphlosion/bn6-eurandom-dx/blob/main/gen_folder/gen_folder.py#L584

the gist is that 1 PA folders have more ranged chips to compensate for not having as much big damage
and that 2 PA folders have more constrained chips since most of the damage is from the PAs
the initial chips chosen are completely random and independent of each other, without looking at synergies
then we have the main loop
er no
we add the giga then, because the logic is easier to deal with
there's also a hardcoded chance of adding in area and area returning chips
as well as other hardcoded chances for uninstall, invisible, antidmg, and lifeaura

then there's the main loop
the 1 PA 2 PA folder "feel" logic applies to the main loop
the code is super complex and poorly written but the gist is:

  • look at all the current chips in the folder, including PAs
  • look at all the possible chips we can add. this includes all standard chips which are not already in the folder, including PA components, and there's a random chance to allow adding in megas for each iteration (and maybe other stuff I forget)

and then you match all folder chips with all possible chips and tally up all possible synergies the folder chip has with the candidate chip
these synergies are listed in the sorted_chips.yml file

"necessity", "reliability", "bonus", "counter", "effectcounter"

these are the 5 synergies
necessity is a special case. if a chip is added and the chip has a necessity, the algorithm will immediately add a chip which satisfies that necessity if one isn't in the folder
for example, adding in a fire chip if blackbomb is added
reliability indicates effects that help confirm the chip
so e.g. paralysis helps a lot of chips in confirming

bonus indicates combos, like fire on grass, or elec on bubbled, or even specific combos like tornado and airspin
counter indicates that the chip is countered by certain effects. so circgun is countered by broken panels
effectcounter indicates that the chip's effect is countered, but not the chip damage itself. so cornshot won't spread grass on broken panels, but it will still do damage

so yes, the algorithm basically tries to find synergies, and tallies them up, weighting stuff like reliability and bonus more than counter (because we don't want too many counters in a folder otherwise it ruins match pacing)
there are also additional checks for synergies like requiring it being on-code for stuff like bubbled or immobilization (I don't remember the full details)
but finally it gets a list of all candidate chips and their weights and does a weighted random to choose the chip
and so I could debug the process, the algorithm spits out a log for why it weights certain chips and why it chose a chip
here's an example of such a log: https://cdn.discordapp.com/attachments/978447194275336242/1112191582590996480/bn6f_eurandom_V_chip_weights_log.txt

finally once it chooses the chip it randomly chooses to add between 1 and 2 copies of the chip
(only 1 if it can't add in any more due to chip quantity restrictions)
and it does this whole loop until there are enough "free slots" filled (so minus megas and pseudo megas that have yet to be added)
and after all the free slots are filled, the megas and pseudo megas are added, with no synergy but only high ranks are allowed to be added

and I also didn't mention two things, which are:
when determining if the chip is already in the folder (and thus we don't add another copy), the algorithm looks at the chip family, not the individual chip. so we don't go add FireHit2 and FireHit3 into a folder
and I also added an additional multiplier, seen in the debug log as "keeping usage even". this multiplier is larger for underused chips, and smaller for overused chips, and will count the exact chip and code (unlike the family thing I just talked about). this additional multiplier also exists for the initial generation, but is even more stricter: it will only look at chips that have never been added to a folder. once all chips of the category have been added, it also weights positively against underused chips, and negatively against overused chips
the reason I added this multiplier is because a lot of chips don't really have any synergies
like sandworm
which literally does nothing interesting
it just does damage
so you gotta force the algorithm to add these so you don't get a million folders with aquadragon and bblstar, chips with very in-demand effects
but I think that's more or less it. there's definitely stuff I missed, so go read the source code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment