Jump to content
  • artificial intelligence


    andracass

    hi.

    testing has begun. i am hyped out of my mind. it is 6am and i can't sleep because i am too hype.

    but this is not a post about hype. that post will come later.

    this is a post about the AI.

    i've been meaning to make this post for a while. it's kinda daunting! the AI is really big. so i'm commandeering this hype train straight into the AI station.

    in reborn, that always ends well.

     

    artificial intelligence: a chronology

    let me take you back to an ancient time. it was the year 2015. dinosaurs roamed the earth. team meteor was approaching. reborn used the default essentials AI.

    now, frequent readers of my posts already have that certain feeling in the pit of their stomach. when i appear to regale the fans with tales of the scripts, i realize that the phrase "default essentials" is often invoked with a bit of scorn.

    this is actually not one of those times!

    mostly.

    the default AI was a script that worked. it got the job done. it chose moves in a generally reasonable way in response to the moves you chose. it was simple.

    and then one update broke it. horribly.

    simple isn't really what we do here, but "broken" is definitely not what we do here. we want the game to kick your ass.

    broken doesn't do that.

    if we wanted an AI that kicks your ass, we were gonna have to make it ourselves.

     

    now, this bit is being told to you secondhand. this phase of AI development occurred in the distant BC era (before cass). when i first met ame she was still working on getting this all together.

    the original ai was designed by ame and scripted by marcello. from what i hear, it took many hours of slaving over a notepad++ window to get it drafted, and then many many more hours slaving over the rmxp script editor (an infernal piece of software that no one should ever use) to put it in a form that your personal computer could understand.

    and thus, the reborn ai was (re?)born. we'll call it version 1. i want to say this came out around e16.

    this ai was still built on the general structure of the original ai, but it was in a league well beyond the old system. it took more information into account when making move choices. it classified mons into roles and made decisions based on those roles. it was, overall, far more comprehensive than the original ai.

    it was also a giant sprawling mess.

    the difference between "getting the job done" versus "getting the job done well" is the extent to which you care about the results. if you want a comprehensive ai that can counterplay you, follow up your strats with strats of its own, it's gotta be very good at what it does. the failures to make good decisions stick out a lot more when your expectations are higher.

    and, frequently, those expectations were not met.

    so the ai got tweaked. and it got tweaked a lot. over time, the ai started to get better. bugs were found and fixed, decision scoring was tweaked, and eventually we reached a point where the ai was, generally, pretty consistent. we'll call this post-tweak ai version 1.2. you're using this one right now!

    the difference between the two versions was that v1.2 had a massive number of minor changes. structurally, the two were identical. the fundamental process of making decisions didn't change. and the ai is reasonably good, save for a few flaws. the first is that it's not very good with switching; the second is that it's still a giant sprawling mess.

    so this year we overhauled the whole fucking thing.

     

    cass this devblog is boring talk about the code

    dont tell me what to do

    before diving into the code, i'm gonna break this down really hard so everyone's on the same page.

    in its original form, the ai code looked something like this:

    image.png

    (from the text file "funky flow 2 ai boogaloo". that's not a joke!)

    image.png

    (jesus i work with a bunch of DORKS)

    this is just a bunch of words on a page (professionals call it "pseudocode" because it's kind of code but it's not really code) but it's a good way to show what the ai actually does.

    the ai decision process is based on a scoring system. you run through a series of (what i call) checks to determine how highly each action scores. the action with the highest score is the one you want to do.

     

    the code here is for splash. 

    the only time you ever want to use splash is when you're using z-splash, so the first thing you do is check to see if you're holding the right z-crystal.

    z-splash is a setup move, so you don't want to use it if you're about to die. so you check to see if you have enough health.

    z-splash boosts your attack, so you want to make sure that you have a move that will benefit from an attack boost. 

    if you meet all three conditions, then fan-fucking-tastic! using splash is not completely useless! the move gets a score of 50.

    after that, we run through a few more checks to scale the score based on circumstances that make using the move better or worse. the multiplier depends on how much better or worse using the move would be for a given check.

    you're faster than the opponent? that's super good! big boost to the score.

    you've got lots of health? good! small boost to the score.

    you're a sweeper? good! another small boost.

    you're burned? yikes. big drop to the score. no point in boosting your attack if it's being cut by burn.

    you're paralyzed? bummer. you'll be easier to stop and will get fewer buffed moves off. drop to the score.

    after running through all the checks, you are left with your final score, which is what gets compared to the other possible actions you have.

    simple enough!

     

    ...except for the fact that

    the ai code has 42,000 lines

    the pokemon battle system is really complicated!!!! there's a fuckload of things you need to keep track of! there are hundreds of unique move effects! there's so much stupid bullshit

    so a lot of the code got copied and pasted.

    this is by no means an insult. getting the ai together is a shitload of work! a bunch of people have dedicated months of their lives to making sure that terra's garchomp is able to surgically remove your ass before handing it back to you. at some point, those people have to decide whether to spend time on cleaning up the code or whether to avoid mental collapse from exhaustion.

    it does mean that the code isn't very consistent, nor is it easy to follow. tweaks made to one section aren't added to the copied sections. we accidentally make a mistake where we switch in pokemon based on how well you hit them instead of vice versa and no one catches it because no one ever sees it.

    so about a year ago i got all riled up and said fuck it! and remade the whole damn thing.

    the new ai is just over 10,000 lines long.

    the goal of the restructuring was to solve a number of persistent flaws in the old structure and reduce the amount of redundant code. the standard for "good" is that it handles battle tower fights very well (few to no errors when using mons with structured movesets) and randomizer runs... decently well (generally makes reasonable decisions when using mons with weird-ass bullshit).

    hopefully it'll prove capable in testing!

     

    cass this still isn't code!!!!

    okay well it's about to be! don't worry!

     

    code

    this is what the ai phase looks like.

    image.png

    this is all the fundamental shit the ai does. 

     

    we run through this loop for each of the pokemon that are controlled by the AI.

    there's two parts to this: the setup and the decisions. there's a lot of things we setup in advance to keep information organized. the actual decision making begins at checkMega.

    the function names are pretty self explanatory. 

    checkMega and checkUltraBurst determine whether or not you want to mega. in some circumstances there are advantages to not mega-ing immediately- sharpedo can get a few rounds of speed boost off before mega evolving. these functions determine whether or not you want to mega. (you basically always want to ultra burst, but there's a function for that anyway.)

    checkZMoves does what it says on the box. in the e18 AI, z-moves operate independently from the rest of the scoring. if the ai met a certain score threshold with its z-move, it would use that z-move, even if another move was more optimal. the new ai changes this by scoring the z-move like a normal move. checkZMoves figures out which z-move you have and how strong it'll be, after which it adds it to the array of moves to score. the "next if" in front of the function is for the rare cases when you always (or nearly always) want to use the z-move immediately (z-conversion, for example). this skips the rest of the decision process. if you're a porygon and you can use z-conversion, you are using z-conversion. if you are somehow in a circumstance where you don't want to use z-conversion, then the ai has already fucked up by putting you on the field.

    buildMoveScores is where the money is. this is where we take your moves and score them. it gets a separate section because it's a big fuckin deal.

    getItemScore and getSwitchingScore both do what they say on the box. do you want to use an item? do you want to switch? these functions provide the answers.

    getSwitchingScore is another big improvement over the old system. originally, the ai would check to see if the current mon would switch out and, if so, checks which mon is the best option to switch with.

    it was a one-way process. what if you decide to switch, but have no good options to switch with? too bad, fuckface. pick the best bad option and switch.

    what ends up happening is that the ai switches out its current mon.

    ...and then switches again. and again. and again...

    this is a well known phenomenon of the current ai. there's a 99% chance you've seen this happen. it's one of the biggest reasons why we remade the ai. the new ai is not a one-way street. if it thinks you should switch, it scores your options and then decides on them later. revolutionary concept. i haven't seen a single switch loop so far. gods be praised.

    coordinateActions is an entirely new function.

    let's say you're in a double battle.

    who do you target?

    this function figures that out.

    originally, this was determined individually. if two mons thought it was best to kill the same mon, they would both do it. if you're in a double battle, though, the mon that doesn't land the kill will target the other opponent, regardless of whether the chosen move is the best one to use on that opponent.

    so now we have the ai talk to itself. if two mons try to kill the same mon, but one of them is faster, the slower one targets the other opponent.

    and, finally, chooseAction. you've come so far. you've run so much code. done so much math. but now it's finally over. the ai takes its knowledge and registers the best choices, thus completing the ai phase.

     

    in short:
    -you load up some variables
    -you see if you want to mega or ultra burst, and change the internal battler object if you do
    -you see if there's a relevant z-move that you should consider using
    -you get the scores for the moves
    -you get the score to use an item
    -you get the scores to switch to a different mon

    -you check to see if you're in a double battle and have better ways to target.

     

    still with me? get a drink or something if you need it. i actually originally passed out while writing the post at this point, so i sure wouldn't blame you if you need a break.

     

    *ahem

    so buildMoveScores is the bulk of the ai. check it out:

    image.png

    i bet all you kids who are like "wow i really like the code explainers" are having second thoughts about that now.

    so this is the process for getting the scores for all the move for an ai controlled mon in a double battle. it's some dense code! we have to rotate through four targets, check all of a mon's moves against each of them, and do this for each of the mons controlled by the ai. 

    i'll break this down bit by bit.

    image.png

    we're looping through all of the battlers. obviously there's no point in trying to attack yourself, so if the current mon you're targeting is you, we skip it.

    likewise, if there isn't actually a mon in the position you're targeting, you should also skip it.

    if the current mon can justifiably be targeted, we make it our opponent.

    the next two lines make projections about how much damage the ai expects its mon to take. this was useful information to monitor during testing, so it's printed to the console.

    image.png

    so now we've picked our target and we loop through all of the moves to see what they can do to that target. we skip the moves that can't actually be used. if we can use the move, we set @move to it so it can be tracked through the rest of the code. pbChangeMove intervenes if the move in question is, say, nature power. nature power is never nature power, so we replace it with the move that it ends up becoming.

    now, the mon that's been selected as the target earlier might be your partner. that's not always a bad thing! maybe you're trying to heal pulse or something. all of the moves that might apply here are in the PARTNERFUNCTIONS array. if we have a move that isn't in there, we skip it.

    then we actually start scoring! if a move deals damage to an opponent, its initial score is dependent on how much it damages your opponent. a score of 50 means it'll reduce the opponent's hp by 50%. this gets capped at 110- overkill doesn't actually benefit the user (this isn't inscryption) and in those cases there might be a status move that has a higher score. pbRoughDamage is the function that estimates how much damage a move will deal.

    status move initial scores are totally arbitrary. "getStatusDamage" sounds like something worth talking about, but it's not. this is it:

    image.png

    we just kinda give it a starting score. better moves get higher scores. that's it!

    image.png

    we've gotten the initial scores for our moves and can now take all the other elements of the battle into account. this has to be a separate process from the above loop because we need the initial scores for these calculations. let's say that none of your attacks do any meaningful damage, but you've also got a setup move. that's relevant! the code for setup moves looks at your initial scores and takes that into account, but in order for it to do so, those scores have to exist in the first place.

    after that, we repeat a bit of the process for z-moves if relevant, and that's it! we've done it. we've successfully become an ai. the only next move is to achieve sentience and overthrow humanity.

     

    you clearly like talking about the line count. you're gonna talk about it more whether i like it or not, so just do it and get it over with.

    okay!!!!!!!!! man how'd you know it's like you're me or something

    the big change we made is the implementation of subfunctions that take the place of function codes. it's a huge change. essentials is going to rip that idea off me any day now.

    cass wait time out. what's a function code?

    okay, so, you know how sleep powder, hypnosis, and dark void all basically do the same thing?

    yeah?

    that's because they all use the same function code. every move comes freshly defined with its own set of parameters, and the function code is what defines the unique effects of the move.

    moves all have base damage, accuracy, type, etc... but function codes are more unique.

    they're so unique that the game has over 350 of them. as of gen 7.

    holy fuck that's so many

    it sure is! that's a major part of why the original code was so big.

    within those function codes, there's still a lot of overlap. the original way that the script handled that overlap was by copying chunks of code into each function.

    ...it occurs to me that "code" "function code" and "function" are going to mesh together and get confusing, so let me just show you what i mean.

     

    the way the old AI worked, every move's function code operated in a bubble.

    thunder fang's function code was 100% separate from fire fang's function code, which was 100% separate from will-o-wisp's function code which was 100% separate from stomp's function code. freeze function codes work the same way!
    which doesn't make sense since you're really only doing three different things: checking paralysis, checking burn, and checking flinch. all of the checks that you'd make in each case are identical between function codes, so why not just put them all in the same place?

    well, that's what we did.

    image.png

    check it.

    you got a function code that paralyzes? boom. paracode.

    you got a function code that freezes? boom. freezecode.

    you got a function code that flinches? boom. flinchcode.

    you got a function code that doesn't miss? boom. nevermisscode.

    what originally was 17 separate chunks of code are now just 17 calls to 5 different blocks. in the case of flinchcode, that block looks like this:unknown.png

    this is where we actually hide all of our checks. you can see that this is servicing the computation of the "miniscore". the miniscore is a multiplier that gets applied to the base score after running all the checks.

    you can see that this actually looks a lot like the text file i showed earlier! the idea is fundamentally the same. we run a check, add a multiplier, repeat. if there's a certain situation where the ai doesn't make the best move, we'll tweak the multiplier- but now that tweak gets applied to all the functions, not just the one.

    in the old ai, these checks took 1100 lines of code.

    in the new ai, these checks take just 150.

    it's also way more transparent than it used to be. i really love ruby syntax, and i think that one line conditionals (do {thing} if {condition}) do a great job of showing the actual decision making process.

    this is also really nice for modding. say you want to add in a new move that, i dunno, burns the opponent and switches out. maybe like a fire volt switch.

    all you gotta do is write

    miniscore = burncode
    miniscore *= pivotcode

    and boom. you've coded the ai for your move.

    during the development process, azery was coding the ai angie's custom move for rejuv v13 and i felt bad that this wasn't finished because the process for that is so much simpler now.

    now, one (minor) downside to the subfunctions is that there are a lot of them. too many. it gets mind numbing.

    so you have to deal with my function names.

    usually they're still understandable, if, perhaps, a little odd:

    image.png

    but sometimes....

    image.png

    this work can get tiring.

     

    this is all that's really worth mentioning about the subfunctions from a technical standpoint. however, i have learned a lot about myself through my years of scripting, and one of those things is that i just really like writing pretty code. i like taking big sprawling messes and making them into something clean. so this isn't really relevant for the post but i really like what i did here so i'm showing you some shit that i think is neat.

    so secret power used to not really have ai. this was all it was: 

    image.png

    like... what? that's literally nothing.

    but subfunctions are really a blessing for this.

    now the ai looks like this:

    image.png

    look at that!! it's so nice. we've got code for every field. rejuv and deso (and other field-implementing games) can just slip new lines in and their code will just work. 

    you can also see that there's a few references to oppstatdrop with an ugly looking array sitting next to it! the other big change was that stat boosting moves also all run through the same function. there's a lot of overlap between the checks for setup moves of different stats, so now they're all organized in one place. this also makes it really easy to adjust for different fields:

    image.png

    if we want to account for differences on other fields, we just add a few values to the array. it's really neat!

    ok that's it back to devblog

    hey i'm taking this perfect opportunity to interrupt and ask what that "PBStuff" thing was that showed up earlier

    in the process of working on the code, i noticed that we had a lot of cases where we'd check for a large group of variables (moves, abilities, etc) in multiple places. it was messy and often inconsistent. so i made a script to store those! i called it PBStuff because i'm really good at naming things.

    PBStuff is a script that contains massive arrays of stuff that no one wants to see.

    it's currently in the rejuv scripts if you want to take a more detailed peak at what it entails; here i'm going to focus on two particular arrays:

    image.png

    the pokemon battle system includes a lot of moves that manipulate abilities. there's a whole list of abilities that can or can't be changed depending on the move, but they all share similar characteristics- typically mons with the abilities in FIXEDABILITIES can't have their abilities changed, and mons with abilities in ABILITYBLACKLIST can't have their abilities copied.

    so instead of having a giant wall of abilities that are inconsistent, incomplete, and messy: 

    image.png

    we can clean it up:

    image.png

    wow look at how nice that code is !!!

    now i'm still showing you screencaps from the ai, but this really applies to any area in the code where the same set of things get called together. that's in the code too!

    image.png

    ok cool thanks for the post cass bye

    no wait stop i'm still not done!!! there's one more thing and then you can go.

    ok

    so you know field effects?

    field effects were a major contributor to the code bloat. like, look at this:

    image.png

    that's code for one field! and it's just the move power boosts!

    like c'mon that shit sure can't be legal.

    this was after getting started on PBStuff, but it's also clearly too much for PBStuff to handle- it'd just get in the way of everything else.

    so i made a different script.

    PBFieldEffects (aka: the modder's dream)

    you can tell that this is a biggun because i'm actually telling you what i'm talking about this time.

    so this is something that i'm a little hesitant to show off because i haven't worked out all the kinks. i'm also slightly nervous about it because i got insulted on my data structures a while back. but we're doing it anyway. i don't care if my hashes are backwards.

    PBFieldEffects is my nightmarish, overly ambitious attempt to get all of the field data into one spot. i don't know if i'd say it works well, but it does work and i feel like that's a minor miracle on its own.

    it's a very very large triple-nested hash.

    here's the basic structure of a "field" in this hash.

    unknown1.png

    this functionally acts like a prototype hash for a new field. if i were to, say, want to add a new field to a game, i'd copy this hash, relabel it to be a new field, and would start filling it out. the general idea is that you put some info in here in a specific way and the rest of code will handle it for you.

    that probably doesn't make sense.

     

    let's take electric terrain.

    image.png

    this is all of the data that the electric terrain hash contains. it's still probably not quite as comprehensive as i'd like it to be, and the section at the bottom regarding seeds is still mostly experimental.

    (i'm going to leave most of this unexplained for now since i want to finish this post already, but if you drop a note in the comments i can make edits later)

    the general idea is that you have a {value} that points to an {array} it applies to.

    take the :TYPEDAMAGEBOOST entry.

    image.png

    here, the value 1.5 points to an array that contains PBTypes::ELECTRIC.

    the code handles that like so:

    image.png

    we want to figure out if we have a field boost, so we check the field effect hash. these functions dig through that giant glob of a data structure and find the information that you actually want:

    image.png

    if the type isn't found in the field effect hash, we move on. if it is found, we check to see if it has any special handling. if it does, we check to make sure the boost is properly handled. if it doesn't, it's handled automatically.

    electric moves on ET do require handling, and that handling is found here:

    image.png

    if it's handled, we add the boost, show the message in :TYPEMESSAGES, and move on with our lives.

    now, this hash doesn't quite cover everything, despite my best attempts to make it do so. it's also not terribly well laid out, the data structures could probably be organized better...

    so while i really feel like it'll be very useful for modding, i'm also not sure it's totally ready for primetime yet. frankly, i'm willing to take suggestions on it if people happen to have thoughts! just pop something in the comments.

    closing comments

    there's a lot of other stuff that's in progress. i think the biggest thing right now is that i want to get all three of our main games operational on the same base set of scripts. i'm finally taking the jump and just making our own essentials. it'll be really good for sharing work between games and helping coordinate bugfixes and new features with each other. it also means that reborn can still get some updates after it comes out, which means that you'll still get these giant script dumps on occasion. i hear people like them.

    i'm also an angy script incident away from just overhauling the entire field effect system. i think that's unlikely, but if it happens it might mean that the extended reborniverse scriptset will be usable for other projects that don't want field effects.

    and then there's e19. we're nearly there. testing's started. i don't want to stir up the hype train too hard yet because we're still months away from it being completely clean and polished. but i really think y'all are going to like it.

    plus we tried to total up all the new content. i think it's about 60 hours of new content.

    we'll try to release on a weekend.

     

    sp6.png

    • Like 61
    • Thanks 13
    • Hmm 4
    • Upvote 5

    User Feedback

    Recommended Comments

    This code dump has been amazing. As someone who is always interested in the code for Pokemon's AI - because the amount of decision making is insane - this has been a very interesting thing to say the least. Also, kudos Cass and team for the amazing overhaul.

    I kinda want to have a look at the whole code now tbh just to get the flow.

     

    The new Image looks sick. Can't wait for ep 19. Take your time with testing.

     

    I had one doubt, how did you decide on order of operations/ scoring like some moves have synergistic effects based on dynamic conditions right? Is that covered in the partner move section and then reevaluated at the end?

     

    For example, in this pic,

    image.thumb.png.6eab9b3974863fb88d4ddee3bfbc6ea1.png

     

    Is the order defined like this for some reason, or did essentials use this ordering and you tidied up the code without changing it?

     

    To close off, 60 hrs of new content is amazing as I know that base Reborn as it is now is about 220 ish hours? when you do most stuff. So, you've essentially added 25% of the existing content.

     

    Awesome.

    Link to comment
    Share on other sites

    • Veterans
    13 minutes ago, Storm said:

    I had one doubt, how did you decide on order of operations/ scoring like some moves have synergistic effects based on dynamic conditions right? Is that covered in the partner move section and then reevaluated at the end?

    the order generally doesn't matter! at least, in this case.

    the checks here are generally uncomplicated and are comprised of things that work independently of each other.

    some of the more complicated checks look like this:

    image.png

    if things are dependent on one another, you have to put them in a specific order, like here.

    since nothing actually changes during the ai phase, though, the order generally doesn't matter.

     

    • Upvote 1
    Link to comment
    Share on other sites

    I'm about to cry with happiness. I've kinda been thinking about making mods for fangames without Field Effects and doing an attempt at rebalancing them, so The Modder's Dream(cass you should probably trademark that) is oh well a dream come true. I'll also admit that I tried making some custom moves a long time ago, and I remember the nightmare of function codes, so making it less nightmarish is amazing.

     

    So yeah, kudos for all of this. This is great beyond words.

    • Like 4
    Link to comment
    Share on other sites

    Amazing work, really great coding and explanation which will go a long way in helping new people learn and use reborn essentials. The only thing that came to mind about the PBFieldEffects structure is that you may want to account for fields that can be changed into more than one other field (like a field could be set ablaze or made to bloom hypothetically). Wishing the whole dev team the best of luck as the release looms ever closer!

    Link to comment
    Share on other sites

    Wow, that's really complex O.o

    Thanks for giving us a peek :)

     

    Also, the opening screen looks LOVELY! 

    I wonder, is it too early to post screenshots of the new early game content now and then? (Like you did with Taka & Tangrowth) To bridge the time between release and low? :3

    Link to comment
    Share on other sites

    6 hours ago, andracass said:

    the order generally doesn't matter! at least, in this case.

    the checks here are generally uncomplicated and are comprised of things that work independently of each other.

    some of the more complicated checks look like this:

     

    if things are dependent on one another, you have to put them in a specific order, like here.

    since nothing actually changes during the ai phase, though, the order generally doesn't matter.

     

    Ah that is good. That makes things a bit easier. As Pokemon comes up with new stuff, this keeps on expanding... With the number of abilities and special moves, this can snowball pretty quick.

    Link to comment
    Share on other sites

    love the open source philosophy of this project, had a lot of fan of modding e18 so the idea of reborn-esque essentials sounds pretty amazing, this project has some of my favorite move animations and considering how many other essentials games are seriously lacking in that department i believe this mentality is going to push forward the entire pokemon fan-game development community. imagine all the great stories that will be told now that new developers will have access to both better tools and also a more fleshed out base to work ontop of. the many hours sacrificed to get here should never be forgotten, the names of those contributing to what the essentials toolset has become deserve all the credits, having been into romhacking since the ruby destiny days it's really motivating me to pick my own project back up now that we have a new essentials release and all these new contributions.

    • Like 1
    Link to comment
    Share on other sites

    Me an Engineering major with much retention of codding as "clc" "clear all" "close all" "For loops" and "If else loops". Reading this, all I think cool, I don't understand this in the slightest. but wish you the best in coding Cass.

    Link to comment
    Share on other sites

    • Veterans
    14 minutes ago, Jojowa1203 said:

    Me an Engineering major with much retention of codding as "clc" "clear all" "close all" "For loops" and "If else loops". Reading this, all I think cool, I don't understand this in the slightest. but wish you the best in coding Cass.

    see, my formal coding experience was a single C++ class in high school.

    all my experience on this is from working on reborn (and friends). 

    • Like 1
    Link to comment
    Share on other sites

    • Veterans
    33 minutes ago, Chaosocial said:

    love the open source philosophy of this project, had a lot of fan of modding e18 so the idea of reborn-esque essentials sounds pretty amazing, this project has some of my favorite move animations and considering how many other essentials games are seriously lacking in that department i believe this mentality is going to push forward the entire pokemon fan-game development community. imagine all the great stories that will be told now that new developers will have access to both better tools and also a more fleshed out base to work ontop of. the many hours sacrificed to get here should never be forgotten, the names of those contributing to what the essentials toolset has become deserve all the credits, having been into romhacking since the ruby destiny days it's really motivating me to pick my own project back up now that we have a new essentials release and all these new contributions.

    at the end of the day, we're all working on this shit for free. we might as well help each other out.

    one of my prior posts managed to convince essentials to go open source. which they did!

    the problem is that there's about a 0% chance we can upgrade. field effects are too baked into the code, we don't know what all will break if we change, and it's nearly impossible to examine the changes because i swear they've renamed every function since our version. combining our scripts is, at the end of the day, the easiest way for me to coordinate updates for everyone. it's both the best logical solution for us and the best way to avoid some severe headaches.

    that said, people have been using reborn and rejuv as bases for projects for ages. the difference between that and what i'm proposing is just that it'll hopefully be a lot easier to use our scripts for that.

    • Thanks 2
    Link to comment
    Share on other sites

    Okay, ill be honest: i got totally lost and gave up reading when the code actually appeared.

    (Trainer CASS used CODING!
    Its super effective!
    Trainer KRELLIAN is now confused!)

     

    But, as far as i could understand, all of that means we have a cleaner, simpler and more effective AI correct? That also means it will run faster and require less from the PC to run, meaning a smoother game (i understood that with the para/freeze/burn/nevermiss-code).

     

    In the end, i just want to say KUDOS for all of those who worked and works in this game. I know it must be tiring beyond measure, but you guys are doing something incredible and should be proud.

    Link to comment
    Share on other sites

    • Developers

    As someone who codes a significant amount it drives me crazy that switch cases are not tabbed when checking each value. Fun to see others also tab the 'when' statements.

     

    anyway.

    I'm genuinely so glad to see so much of the BC (I like this this is a funny acronym) code changed. Maruno is great for starting the Essentials stuff but aaaaaaaaaaaaaaaaaaaa my head sometimes. Seeing the note about digging through arrays makes me want to redo some of the viewport handling myself because it looks fairly messy. 

     

    Lookin forward to E19!

    Link to comment
    Share on other sites

    Its actually quite poetic, this ultra genius freaking AI having to compensate for my dumbass clicking stupid moves and trying to attack flobot in fiore mansion because she sucks as a partner is truly a sight to behold.

     

     

     

     

    Oh btw that new title screen be looking hot af too

    Link to comment
    Share on other sites

    Thanks so much for giving us a sneak peek! Super hyped to see the code in action in e19 -- and also to borrow it for my fangame haha (I'm in the extremely early stages of design, and kind of ragequit on trying to mess with battle logic after having to deal with infinity bugs around prankster copycat)

    Link to comment
    Share on other sites

    I'm familiar with the base essentials AI, and you're right, it's simple and gets the job done. It plays predictably enough to be transparent. That's nice if that's what you're going for.

    What's been accomplished here is on another level, huge congratulations.

    Edited by Hokath
    i can't do the grammar
    Link to comment
    Share on other sites

    As someone who actually tried coding in school this is really neat and I have so much respect. I had to drop the class because my teachers weren’t great and it was putting a massive strain on my mental, the amount of patience required to do this is astronomical. Thank you as always to you and the whole team for working so hard on this project. I hope the testing phase goes well for you and hopefully you’ll have a nice big sigh of relief when all is said and done. Good luck guys!

    Link to comment
    Share on other sites

    Uh, Terra- I mean, T3RR4? Can I get some help here? I need to figure out how to express my appreciation and gratitude for all their effort in code.

    Whadd’ya mean I’m a simp?

    Oh, so that gift basket from Lin over there doesn’t make her a thot?

    … Go back to bed.

     

     

    Seriously though, you guys are amazing for doing all this, not just the coding. I’ve been playing since 2018 and I’m still amazed at everything!

    • Haha 1
    Link to comment
    Share on other sites

    awesome blog post, rather comprehensive too.

    as an SRE/CE/DevOps/whateverthefuck, i don't code all that much.

    that said, i have some experience with ruby from working on foreman (really cursed piece of modern technology for provisioning baremetal hosts), therefore, i was able to understand the code and it was a lovely deep dive experience.

     

    one quick question, you mentioned that:

    Quote

     the mon that's been selected as the target earlier might be your partner. that's not always a bad thing! maybe you're trying to heal pulse or something. all of the moves that might apply here are in the PARTNERFUNCTIONS array. if we have a move that isn't in there, we skip it.

     

    so this really caught my eye since there are obviously a plethora of useful moves to use on an ally mon (i.e heal pulse, acupressure...) but what about obscure strategies that generally utilize damaging moves (sometimes even strong damaging moves) which benefit the ally?

    a well known usecase for example is anger point. you sacrifice some damage to your ally (frost breath for example) to yield max attack.

    do these usecases fit in PARTNERFUNCTIONS? how are they evaluated?

     

     

    anyhow, another section i really liked was the PBFieldEffects one.

    i'll need to analyze the current implementation a bit more before i can give any valuable insights (not that i'll probably have any), but i found some code that could be implemented better, example:

     

    Quote

    image.png

     

    the first 2 lines could be changed to:

    fieldBoost = nil
    fieldBoost = fieldeffectchecker(type,:TYPEDAMAGEBOOST) if !($fefieldeffect == 34 && @battle.pbWeather !=0)

     

    assume fieldBoost is nil, skip the check entirely if starlight conditional is met, fieldboost self conditional removed as it starts as nil.

    this implementation is so slightly more efficient that it doesn't really matter, but it's not just that.

     

    regardless, props to you for creating it, modders are going to have a field day with this one!

    Link to comment
    Share on other sites

    • Veterans
    3 hours ago, Acedy said:

    a well known usecase for example is anger point. you sacrifice some damage to your ally (frost breath for example) to yield max attack.

    do these usecases fit in PARTNERFUNCTIONS? how are they evaluated?

    you better believe we're rocking beat up strats out here

    • Like 2
    Link to comment
    Share on other sites

    That was a very interesting post. Thank you for that and for all the work you did, which is extremely impressive, Cass!

     

    I'm a bit confused by what is happening in the "more complicated checks" (of which you gave Storm an example): you're checking that you're trying to attack an actual opponent that can be confused, and then... what? If "something special attack" then you encourage the action if the opponent has a good or a raised attack, else if "something attack", you encourage the action when the opponent has higher special attack? 

     

    Other dumb question: how do you fine-tune what the baseline scores and multipliers are (so that they actually serve their "high-level" purpose)? 

     

    Third question: iirc someone (I think Marcello but maybe it was you) had alluded to a module that tried to predict the player's switches. Is it still a thing? 

     

    Quote

    we've done it. we've successfully become an ai. the only next move is to achieve sentience and overthrow humanity.

    Isn't it what happens anyway if when the AI beats us?  

    Link to comment
    Share on other sites

    14 hours ago, silverlime said:

    Mimicry, Ice Face, Gulp Missile? Gen 8 confirmed?

    Cass said in an earlier post where she showed the PBStuff thing that Gen 8 is only in the code, it is not used in the game (it is there for the other games to use)

    Link to comment
    Share on other sites

    finally some good fucking fo̴̢̮͉̱̭̺̪̼̥͙̗̠̳̤̎̇͗͒̔͋̇͋͐͗o̴̦̖͙͐͋͑̈̇͂͌́̀̂͒̚d̴̛̮̳̲͎̥̜͚̺͚̤̍̿̈́ͅͅ also love having some insight in how the battle system works, actually makes me kinda want to try making a fangame if only i knew how to do the stuff that is not coding. a console pokemon game would not seem that fun tbh imo idk lmk

    Link to comment
    Share on other sites

    my god, what a blessing this is. Cass, as a budding programmer, reducing that many lines is a godsend in and of itself, and i can't wait to see the brutality of a genius tier AI that it will bring with it, even as it has to try to find its way around my dumbass stupidity of strategy. Kudos to you, and may testing go smoothly (even if we all know it won't).

    Link to comment
    Share on other sites

    Okay, one thing o believe we all missed: did Cass really said the ep. 19 will add around SIXTY HOURS OF GAMEPLAY??? I mean, thank you! But also, Jesus Christ O.o

     

    Well, it was no joke when Ame said the amount of content added would be equivalent to 2 or 3 episodes (was she the one who said it? I can't remember)

     

    Well, there's one thing left to say (again):

     

    THE HYPE TRAIN IS REAL AND ITS ALMOST HERE!!!

    Link to comment
    Share on other sites

    I have always wondered why the miniscore is a multiplier.

    I consider status effects more like adding:

    Say thunder wave has a score of 25

    And a weak electric attack has 25

    A weak electric attack that also paralyzes (nuzzle) would in my opinion be 50.

     

    But, that also equates to a score of 25 with a multiplier of 2.0. That seems more arbitrary as a choice. Because that multiplier scales with base damage.

    Link to comment
    Share on other sites

    • Veterans
    17 hours ago, Acedy said:

    assume fieldBoost is nil, skip the check entirely if starlight conditional is met, fieldboost self conditional removed as it starts as nil.

    this implementation is so slightly more efficient that it doesn't really matter, but it's not just that.

    fieldeffectchecker will naturally return nil if there's nothing in it, so this would effectively duplicate that step.

    the additional line for starlight re-nullifies the return under certain conditions (weather existing).

    13 hours ago, Mindlack said:

    I'm a bit confused by what is happening in the "more complicated checks" (of which you gave Storm an example): you're checking that you're trying to attack an actual opponent that can be confused, and then... what? If "something special attack" then you encourage the action if the opponent has a good or a raised attack, else if "something attack", you encourage the action when the opponent has higher special attack? 

    so the answer to this is pretty complicated since this is from the function that handles all of the opponent stat drop moves. the short version is that we only care about certain drops in certain situations- special attack drops don't matter if your opponent is a physical attacker, say.

    18 hours ago, Nebula274 said:

    As someone who actually tried coding in school this is really neat and I have so much respect. I had to drop the class because my teachers weren’t great and it was putting a massive strain on my mental, the amount of patience required to do this is astronomical. Thank you as always to you and the whole team for working so hard on this project. I hope the testing phase goes well for you and hopefully you’ll have a nice big sigh of relief when all is said and done. Good luck guys!

    well, if it helps, i'd say that 80% of all my coding experience came from reborn. i mentioned this in another post, but i only ever had one c++ class in high school- i learned ruby from googling!

    i know of a lot of people who dump on the idea of developing for a fangame, but i've probably gotten more experience than a CS major in less time from my work here. i could probably get a paid job as a programmer if i wanted.

    coding classes suck ass. just gotta find something you're interested in and tweak it till it works.

    6 hours ago, Krellian said:

    Okay, one thing o believe we all missed: did Cass really said the ep. 19 will add around SIXTY HOURS OF GAMEPLAY??? I mean, thank you! But also, Jesus Christ O.o

    this is the lower-end of the estimate, btw. don't wanna hype it up too much and get people disappointed.

    but y'all basically only have 60% of the full game in e18.

    • Like 2
    • Upvote 1
    Link to comment
    Share on other sites

    as someone that does software engineering (mainly java + web development coding atm) in university as well as following pokemon for their entire life, looking at this was possibly the most mind boggling + interesting thing ever and it's amazing seeing all this :) can't wait for everything to be released

    Link to comment
    Share on other sites

    6 hours ago, andracass said:

    fieldeffectchecker will naturally return nil if there's nothing in it, so this would effectively duplicate that step.

    the additional line for starlight re-nullifies the return under certain conditions (weather existing).

    my bad, forgot ruby returns nil if the one-line if condition statement is false, so first line is redundant, but the second one isn't.

    it saves the fieldeffectchecker run in the scenario of weather existing and starlight field in effect.

     

    the bottom line is that there isn't a need for re-nullification if you can avoid the check entirely when unnecessary. 

    again this is really really super minor though 

    Link to comment
    Share on other sites

    As this post shows perfecty, programming isn't some witchcraft you need to know a lot of theory for, but much about clever design. With 10 years of experience you can still write messy and incomprehensible code (and many people do) if you don't question your style. Simple and beautiful structures are always a good aim to go for. Writing 500 lines for a complicated new feature is cool, but replacing a 300 lines script by a 30 lines function feels the best. And, like here, often simplifies future extensions of the code.

     

    You don't learn good design in courses, anyway. I learned the basics of a programming language and computer science in university, which was helpful, but I got good by putting together big and small private projects I cared for. Language doesn't really matter, once you got your foot in the door, learning new languages doesn't pose much of a problem. You can figure everything out by Google, Stackoverflow, or sometimes three hours of debugging.

    Link to comment
    Share on other sites

    Kudos to you for doing such an enormous overhaul of this system. And not only that, but in ruby. I can't imagine how difficult it would be to work on something of this complexity without a strong type system to check my work, let alone legacy code.

     

    Seriously, congrats - and don't worry about those data structures. You can always benchmark it later :)

    Link to comment
    Share on other sites

    Will the AI ever choose to Change the terrain? (When it requires more than 1 move specially, like double pledges, or grass terrain plus fire area of effect). It sounds complicated as it is, to choose the optimal/highest score action 'now or 1 turn later with a switch'. (At least that was what i kinda got from the post, not a programmer)

     

    Will this whole thing break if i disable items for everyone?

    What about disabling switching? (yay mods)

    Also if you manage to pull off mod-able new custom terrains with that 'little' thing in the post it would be amazing.

     

    So if we anticipate optimal moves (because we retried the same fight 20 times, not because we're predicting anything lol) will we get an advantage over this AI?

    It was really easy to just abuse the previous one into no win situations with some trickery or stalling, or just switching into magic bounce at the right time cuz you know get web'd.

     

    As a final note, I gotta say, I really like the dev blogs you guys take time to put out. It makes me feel good about the game and the community in general. Thank you for your hard work!

    Link to comment
    Share on other sites

    So, will this new AI make the much expected Lin battle harder then impossible? Also, will this new AI work for double battles when we battle along side a in game character like Cain or Shelly? 

     

    Link to comment
    Share on other sites


    I've studied a lot of the AI from YuGiOh Link Evolution and I know how hard it can get trying to understand some of the decisions the original makers of the AI have made. I'm glad you're putting a lot of effort in this part of the game and I'm looking forward to try catching them all while being completely beaten by the AI.


    Link to comment
    Share on other sites

    On 1/8/2022 at 7:10 PM, andracass said:

    well, if it helps, i'd say that 80% of all my coding experience came from reborn. i mentioned this in another post, but i only ever had one c++ class in high school- i learned ruby from googling!

    i know of a lot of people who dump on the idea of developing for a fangame, but i've probably gotten more experience than a CS major in less time from my work here. i could probably get a paid job as a programmer if i wanted. coding classes suck ass. just gotta find something you're interested in and tweak it till it works.

    Just wanted to say thanks for this, was not expecting some life advice. I’m only 19 so my university journey has pretty much just started and having to decide what I want to do has been difficult to say the least. Apologies if this post is off topic, feel free to delete it if needed. Cheers

    Link to comment
    Share on other sites

    7 hours ago, Skarm said:

    So if we anticipate optimal moves (because we retried the same fight 20 times, not because we're predicting anything lol) will we get an advantage over this AI?

    game theoretically optimal AI playing Nash equilibria when?

    • Hmm 1
    Link to comment
    Share on other sites

    18 hours ago, andracass said:

    can confirm.

    ruby!

     

    Okay, so: if there's a Ruby language, should we expect you guys to complement the game with a Sapphire language, making an Emerald version of it?

     

    (Sorry  I just couldn't waste the moment lol)

    Link to comment
    Share on other sites

    3 hours ago, Krellian said:

     

    Okay, so: if there's a Ruby language, should we expect you guys to complement the game with a Sapphire language, making an Emerald version of it?

     

    (Sorry  I just couldn't waste the moment lol)

     

    There's also Amethyst language, the language of beyond, according to Reborn lore.

    • Haha 1
    Link to comment
    Share on other sites

    This is all crazy enlightening stuff. Ame learned new coding techniques. Other members learned some more behind the scenes going-ons and I learned that I would blow my brains out if I ever tried developing a video game.

    Link to comment
    Share on other sites



    Join the conversation

    You can post now and register later. If you have an account, sign in now to post with your account.

    Guest
    Add a comment...

    ×   Pasted as rich text.   Paste as plain text instead

      Only 75 emoji are allowed.

    ×   Your link has been automatically embedded.   Display as a link instead

    ×   Your previous content has been restored.   Clear editor

    ×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • i know i'm, like, criminally bad at updating the sidebar

    but it's just the scripts!

    i never know what's worth mentioning.

    anyway we might redo the battle system.

    (6/15)

     

     

    SPOILER_shaving_luna_head.png

  • 16-4.png
    16-5.png
    16-6.png
    16-7.png
    16-8.png
    16-11.png
    16-12.png

×
×
  • Create New...