Here's what I'm playtesting with so far. Chances to switch have been reduced:
-->toxic poison - changed probability from 50% to 34%
-->super effective moves - probability weight reduced by 25%
-->only switch out from low HP if player outspeeds enemy
-->an enemy mon is flagged when sent out; non-volatile status or low hp cannot initiate switching until the player sends out a new mon (which clears the flag).
The code can be seen in the latest
commit to master_dev and lite_dev. I had to move some stuff out of core.asm to make room in the memory bank.
EDIT: Another change I've added. If a super effective move instigates the AI to switch, the mon getting sent back gets flagged while it is benched. The scoring system applies a penalty for this flag. Once again, switching flags are cleared when the player sends out a new mon. The idea is that since the enemy mon was recalled due to taking a super effective hit, the scoring system for choosing what to send out should be dissuaded from sending it out again if the player's mon hasn't changed. This will help the AI account for player mons with type coverage.
Mono-type teams (like swimmers) are kind of hosed since nothing they switch to is particularly good if you have a stab super effective move, but then again they were always hosed in that way. They probably won't switch from super-effective moves anyway due to how the scoring works.
EDIT 2: Another change. I found it was possible to cheese using the sleep status again (it's very powerful in gen 1). The switching AI now has a 12.5% chance to switch a sleeping mon each turn that it's sleep counter is > 3. The idea is to simulate a situation where the opponent is hoping his active mon wakes up, but there's a chance he gets impatient and switches. The cutoff of 3 is so the opponent doesn't use Rest and then switch for the lols. 12.5% is chosen to help reduce situations of switching back and forth between sleeping mons (switching in gen 1 does not decrement the sleep counter).