Beta Testing, Day -1! (Patreon)
Content
...for about three hours before we got more reports of AI inactivity and a fatal error caused by the things we did to fix AI inefficiency and a minor error after alpha...
this is why we have multiple waves.... it's okay.... it's fine......................
but i'm not here to talk about the beta today. i'm here to talk about the day before the beta. beta testing, day negative one.
--
so i'm sitting there, binary code on my titties, and i'm looking at this topic Azery posted about the AI switching. and i'm just. i'm just sad you know, because, you know, you put so much time, so much energy, into-- into loving someone, and they just-- they just throw it all away in an instant..... like this deadbeat AI code. i thought what we had was special. i thought we might be happy with one another. but i see now those were just a naive girl's delusions...
so like why this, right, i'm looking down the scores that we've got in that debug, and i even recreate the scenario in that battle on my own end. still... with the amount of debugging we're currently doing for switches, it's hard to tell why a certain score ends up the way it does-- we just know that it did.
realizing that as iffy as switching has been this is probably going to be a recurring problem. sooOO00OOooOO00OOooooo... let's get some more comprehensive debuggery going. I've posted this in the past, I think, but in our SwitchTo script, which decides which Pokemon to send out once it knows it needs to, there are various sections:
- defense (looks at resistances and player's revealed moves)
- offense (looks at own moves and player's type)
- roles (when to sweep/lay hazards/stallbreak, etc)
- weather (send out pokemon who benefit from it)
- moves (actually very small section, looks for opportunities for conditions)
- abilities (actually very larg section)
- items (not much here)
- fields (only if the trainer is top skill)
so i asked the code to start telling me what it thought of each individual section for each pokemon, instead of just the final score.
this was incredibly helpful, and should have been done 6000 years ago.
i noticed something immediately-- in telling me what it thought of each section's scores, I learned that it was not thinking of the offensive section very much at all. in fact in all 6 cases of luna's team, the offensive section wasn't contributing to the score in the slightest. considering that defense + offense are supposed to make up the bulk of the score, with the rest just being nudges here and there, this was a huge problem.
in retrospect it makes sense. i designed this system so it has a lot of additions and not very many subtractions-- and yet we were frequently seeing scores dip below 0. also the upper end of scores we saw was rarely breaching 150. that was a lot lower than i expected, but at the time i assumed my estimates were just incredibly wrong. that'll teach me to trust code.
so i throw in some debug messages to see where the offensive part of the code is messing up. the offensive part works like this:
offense:
- ---check BP of each attacking move
- ------if that move would be SE, double bp.
- ------if the move is NVE, half bp.
- ------if the move is physical and pokemon is burned, half bp.
- ------consider enemy abilities unless low skill
- ------if high skill, consider STAB too.
- ---score += strongest move's BP (including type effect alteration)
- ---if this pokemon would be faster than the player's, like it more
basically we want to very roughly figure out what the best thing each pokemon could do to the opponent with each of its moves is is. so in order to do this, specifically the "each move" part, we use a loop that repeats the code for each move. hang onto that thought. we'll come back to it later-- cuz loops always bring you back, you know?
what i find from my debug messages is that it's correctly figuring out how strong each move, but somehow that value isn't making it to the main switch score variable... should be simple enough... sure enough-- there's a typo. we use a variable called "maxbasedam" (damage) to keep track of which move is the current winner as far being strongest. when it came time to add maxbasedam into the switch score, it was typed as "maxebasedam". shucks. that's all it takes really.
the entire offensive portion of the switchto method was rendered 100% useless by one misplaced keystroke. that's fine-- it happens. what bothers me is that it took us three waves to catch it. i think i summed up my feelings on this matter pretty eloquently to cross as i was explaining it to him at the time. i believe i put it like this: "aaaaaaaaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
but hey man it's cool. it's okay. it's fine. it's fucking fine. a man-- is a dick. is a chicken. is a dad... valium, speculum, whatever-- whatever. just delete the 'e'. move on with life. test to make sure it's okay. see, look, it's okay, those scores are much higher--
?
much, muuuuuuch higher.
our score range was something like -100 to 150 before. after removing one single 'e' keystroke. our scores are looking more in the range of 700-1000+.

that's too much... that's way too much. what's up.
well i tried a little harder, and by that i mean i actually didn't have to try when i had half a clue of what i was looking for. now, my boy marcello does some gr8/8 work, and i appreciate it a pretty damn lot. so i'm not tryna roast him here... but i am sayin' that on whatever day he wrote this code he must've really wanted the offensive section of the method to shine.
because the way he wrote it, typos aside, it was applying the offensive score eight times over.
the reason is because-- remember our loop? it processes the code once for each move. we've got four moves, right? so that accounts for four of the the times. the correct solution to that is to move the part that adds the score up, outside of the loop so it only processes onces it's done.
...turns out he had already done that too...
...which meant it added the score it added to the switch method back again after the loop was done, effectively doubling whatever the score had become by that point.
four times times two. offensive takes the stage.
anyway, super duper easy fix-- after clearing the line in the loop it worked like a charm. we were getting scores ranged anywhere 150-350 which is about what i had in mind when designing it. yay! that also means that roles/abilities/fields etc will stack up reasonably against it.
so i tested against luna. in azery's post he reports her sending in sableye against his houndoom, rather than tyrantiar-- which i had recreated before. looking at the scores after the fixes, it seemed like luna knew t-tar was a much better idea after all, so i was hopeful when testing in-game, she'd have her act together.
she sends in honchkrow.
what?
that's not right-- azery reports oneshotting that thing with his houndoom. i check the scores. honchkrow wins out over tyrantiar by a difference of 10 points.
...wait a second...
i click a move to see what happens.
honchkrow oneshots houndoom and ends up sweeping half my test team with moxie. all right, luna. all right.
it's apparent to me that azery's houndoom was a lot faster than mine-- but that's okay. because i realize that if my test houndoom was faster, honchkrow wouldnt have gotten the score boost, so tyranitar would have been sent in instead... in other words the AI was correctly capitalizing on a sweep opportunity i hadn't even realized, without putting themselves at needless risk in azery's case.
much better.
...but really we should've noticed this like.. back in supervised testing... zzzzzz