Ajarmar / universal-pokemon-randomizer-zx

Public repository of source code for the Universal Pokemon Randomizer ZX
GNU General Public License v3.0
612 stars 156 forks source link

[Contribution Idea] Add minimum AI Level option for trainers #162

Closed spaceonaut closed 3 years ago

spaceonaut commented 3 years ago

Is your idea a new setting, a change to an existing setting, or something else? Please describe clearly: There appears to be a field in TrainerPokemon for Gens 3-6 called AILevel. I'm guessing this controls the AI choosing moves randomly (0) to being really smart (250).

It could be interesting to add a minimum value to this for all trainers to make the AI a bit tougher.

What problem would your contribution solve? Please describe: This would allow a customizable difficulty level in the opponent's pokemon.

Additional context:

Ajarmar commented 3 years ago

Thanks, but without a good understanding of how the trainer AI levels actually work in the games, we wouldn't want this as a setting. It's easy to say "higher number = probably smarter", but that might not always be true, and it probably works differently between generations.

spaceonaut commented 3 years ago

If more research were done, would you be willing to reconsider this option?

FrostedGeulleisia commented 3 years ago

Off the top of my head, all I remember is that the Champion typically has the highest AI value for single battles, and that value is typically 7. This value doesn't always work well though, specifically in multi battles - where they can end up attacking their own ally iirc, but you could see how pk3DS devs did it, at least for gens 6/7.

Ajarmar commented 3 years ago

If more research were done, would you be willing to reconsider this option?

Definitely possible, but I think it'd only make sense as a setting if it actually makes a noticeable difference.

Off the top of my head, all I remember is that the Champion typically has the highest AI value for single battles, and that value is typically 7. This value doesn't always work well though, specifically in multi battles - where they can end up attacking their own ally iirc, but you could see how pk3DS devs did it, at least for gens 6/7.

This might be accurate for Gen 6/7, but it's definitely not accurate for some other gens where the AI levels are numbers like 0, 50, 100, etc. The "attacking own allies" thing that you mention is actually something that we had to fix for the "Double Battle Mode" setting, and it's fixed by setting a completely different flag. I think all of this goes to show that it's a lot more complicated than "higher number = smarter".

FrostedGeulleisia commented 3 years ago

This might be accurate for Gen 6/7, but it's definitely not accurate for some other gens where the AI levels are numbers like 0, 50, 100, etc. The "attacking own allies" thing that you mention is actually something that we had to fix for the "Double Battle Mode" setting, and it's fixed by setting a completely different flag. I think all of this goes to show that it's a lot more complicated than "higher number = smarter".

Fair, not every game is equal after all. If I find a bit of time I might look into this, as I'd actually appreciate this being an option too (maybe alongside max IVs on trainer Pokémon, but that's not for this thread). Though in each case the Champion still has the highest AI out of single battle trainers, maybe excluding DP, as I heard Cynthia there doesn't use any remotely smart AI? I only heard this once though and from my experience her AI was average, but certainly not Bug Catcher-tier. Also note that in generations 1 and 2 at least, AI types are very specific, some are reserved for specific trainer classes and focus on say, using X Attacks or another focusing on Dire Hits, this option wouldn't work well in those generations probably, 3-5 on the other hand could work better.

tom-overton commented 3 years ago

Responding late, but trainer level is a bitfield in Gens 6/7, so just increasing it does nothing unless you are accurately accounting for the proper bits. Going from 7 to 8 might actually make the AI dumber since it unsets multiple bits.

I'd only be willing to accept a PR for this if it was submitted along with documentation that describes how trainer AI works in each generation, since it may vary wildly in its implementation over the years.

spaceonaut commented 3 years ago

Was doing some analysis on SoulSilver. Trainers have a bit field that probably impacts their Pokemon (possibly the IVs, EVs, etc), as well as the individual Trainer Pokemon have an "AI Value". Here are the distributions for both of those: AI_Frequency bitfield_frequency

I find those groupings interesting. My current hypothesis of the AI value is that if it's 0, the moves picked are basically random (I'm still collecting data on that). If that hypothesis is true, then the vast majority of trainers are just picking their moves randomly.

I realize that the trainer bitfield could impact things, as well as the trainer class itself (e.g. each of the gym leaders appears to have their own class id, so maybe that allows the programmers to have a distinct strategy for those pivotal fights), so some experimental data will help solidify things.

Is this the type of documentation (as well as deriving what the bits in the bitfield) that you would want @tom-overton?

spaceonaut commented 3 years ago

Well, I'm glad I experimented. I gave Youngster Joey (the first non rival fight in SS) a level 50 mew with Bite, Headbutt, Recover, Double Team and gave myself a level 100 mew with Splash and Recover. I then did several battles lasting 30 rounds each.

By setting the first byte, called "ai level" to 250 and comparing it to what it normally is (0), I didn't notice any differences on move usage distribution, but I did notice the moves hit harder when that value was set to 250.

My mew had an 18 IV in defense, for total defense of 223 and took the following average damage when that first byte was 0:

When that first byte was 250:

Using a damage calculator, the average damage for Bite and Headbutt with 0 Attack IVs and 0 EVs is 25 and 14.31 respectively. With 31 Attack EVs, the average damage is 28.63 and 16.19.

I think this is reasonable evidence that the number affects the IVs of the pokemon. From a data structure design standpoint, this makes more sense anyway than having a different "AI" value for each mon, allowing the developers to say how strong an individual pokemon was.

TL;DR; we should definitely be sure we know what the numbers mean before changing them 😄

If I had to further speculate, the translation of that number to IVs would be simply doing an integer division by 8 (250 // 8 = 31)

tom-overton commented 3 years ago

@spaceonaut Yep, documentation like that is exactly what I had in mind. And nice job figuring out that the "AI Level" bytes were the IVs in this case! That should probably be changed at some point. I'm guessing that the data structure for HGSS looks somewhat similar to how it looks for FRLG; in that game, the Trainer Pokemon stored IVs, and the Trainer data stored the aiFlags, which basically determine the enemy's intelligence.

If you can determine the equivalent to aiFlags in all the games, then I think I'd be okay with this being a feature in the randomizer. You have an advantage with Gen 3 because the games have been decompiled, and pk3DS already parses a similar bitfield in Gens 6/7 (though similar to what you figured out today, it could totally be parsing them wrong!)

Your assumption about the IV field seems correct to me too, especially looking at the FRLG data. I don't think we actually do anything with the IV data in the randomizer today, but it would not surprise me if we were parsing it incorrectly.

Ajarmar commented 3 years ago

I figured I'll make my thoughts clear on this just so that you don't waste your time unnecessarily:

Because of how complex the trainer AI is as a concept (as well as how seemingly poorly understood it is, especially in later generations), a setting like this needs to make sure not to mislead the user. This is why it's so important that if this setting is to be implemented, it's properly researched beforehand so that we can ensure that:

  1. The improvements in a Trainer's AI by setting these flags are clearly conveyed to the user,
  2. The potential drawbacks of setting these flags are clearly conveyed to the user,
  3. It actually makes a noticeable difference when playing.

How the flags make the Trainer AI better wouldn't necessarily have to be described on a very detailed level in the randomizer since it may be too much information, but some shortened description would be necessary. I would imagine that how the mechanisms behind what the three "main" flags that can be seen in the Trainer data link above work can be gleaned from reading through the relevant files in the decomp (and then verifying this by testing in the actual games), but I don't think that it can be assumed that they will work exactly the same in later generations (in fact, due to additions of new Pokemon, moves and abilities, I think they necessarily do not).

When it comes to drawbacks, they should be described individually. Some examples of drawbacks are Gen 1's infamous "Good AI" using "super effective" status moves (i.e. spamming Agility against Poison-type Pokemon) and in Gen 3, the "smarter" AI likes to spam Splash if it has access to it (also occurs in other generations if I'm not mistaken). There could very well be more than these!

I think researching how the flags work and what potential drawbacks they have is a very tricky subject because not only is it unfeasible to test every possible case that might occur in a Trainer battle but even for the games that have decomps (Gens 1-3 as well as an unfinished decomp of D/P), while you probably can figure out the "main mechanisms" behind each flag, it's not gonna be immediately obvious what drawbacks exist just by reading the code. And then there's the games that don't even have decomps... it's a whole rabbit hole at that point. You could use an emulator with debugging capabilities combined with disassembling in Ghidra to try to figure things out but that seems like a gargantuan effort. I'm not sure about the best solution here.

My last concern is with whether or not the changes actually will be noticeable when you're playing the game. One of the issues with randomized Trainers/movesets is that they will not have movesets that are as finely tuned as the regular games - most (if not all) of the major Trainer battles (rivals, gym leaders, champions, etc) have custom movesets instead of just using their levelup learnsets, and these same Trainers are also typically the ones that have more of the AI flags set. So when their Pokemon and movesets are randomized, there may be a side effect of the "smarter AI" becoming less noticeable due to not having moves that are relevant for the AI flags, and I think this side effect will only be further exacerbated for regular Trainers because they typically have fewer Pokemon as well as relatively lower levels - so they have fewer opportunities to "perform well". If setting the AI flags only is rarely noticeable then I'd be sceptical of adding this as a feature (or, at the very least this fact would have to be very well conveyed to the user of the randomizer).

I hope I've made my thoughts clear with this - I'm not inherently opposed to adding this sort of feature to the randomizer, but I do think that it's a very complex topic and that it's necessary for us to actually understand what we're doing, and to somewhat convey this complexity to the user in order to not mislead them.

spaceonaut commented 3 years ago

@Ajarmar I think you are correct. I spent a little time trying to derive what the second least significant bit of the trainer flag was for soul silver. It seems to be something like "prefer strongest attack", but without the disassembly, that's hard to confirm. It took a while to find a good process for this and looking at the flags from FRLG, sussing out anything like that from observational data would take a lot of trial, effort, luck, and inspiration. I'll stop now while only one foot is in the rabbit hole.

I am pleased to have figured out how to control the IVs for trainers pokemon in Gen 4 though - that seems like an easier way to adjust the "difficulty" of battles with NPCs. I'll send a PR with that.