Skip to content

Commit

Permalink
Merge pull request #27 from TwitchPlaysPokemon/v0.9.11.0
Browse files Browse the repository at this point in the history
V0.9.11.0
  • Loading branch information
ferraro2 authored Aug 3, 2022
2 parents 93996b2 + 66c67c6 commit 272785d
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 86 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# pbrEngine
Abstraction layer for Pokemon Battle Revolution to automate Pokemon matches for TwitchPlaysPokemon, based on PyDolphinWatch

Warning: main.py is not currently functional.
6 changes: 4 additions & 2 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from pbrEngine import Colosseums

with open("testpkmn.yaml", encoding="utf-8") as f:
yaml_data = yaml.load_all(f)
yaml_data = yaml.safe_load_all(f)
data = [pokecat.instantiate_pokeset(pokecat.populate_pokeset(single_set)) for single_set in yaml_data]
# reduce by shinies
#data = [d for d in data if not d["shiny"]]
Expand Down Expand Up @@ -75,7 +75,7 @@ def onState(state):
pbr.matchStart()


def onAttack(side, slot, moveindex, movename, success, teams, obj):
def onAttack(side, slot, movename, success, teams, slotConvert, obj):
mon = pbr.match.teams[side][slot]
display.addEvent("%s (%s) uses %s." % (mon["ingamename"], side, movename))

Expand Down Expand Up @@ -131,6 +131,8 @@ def onCrash(reason):
checker.reset()


# FIXME: Add operating instructions and make this work. How does it
# start Dolphin? Some other parts have probably fallen out of date too.
def main():
global checker, display, pbr
#logging.basicConfig(level=logging.DEBUG, stream=sys.stdout)
Expand Down
46 changes: 46 additions & 0 deletions pbrEngine/abstractions/match.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,57 @@ def teamsCopy(self):
return {"blue": list(self.teamsLive["blue"]), "red": list(self.teamsLive["red"])}

def getFrozenSlotConverter(self):
"""Return a slot converter function for the game state at current time."""
slotSOMap = deepcopy(self.slotSOMap)

def frozenSlotConverter(convertTo, slotOrTeamOrTeams, side=None):
"""Function to convert from starting order to ingame order, and vice versa.
Args:
<convertTo> Either `SO` (starting order) or `IGO` (ingame order)
<slotOrTeamOrTeams> This arg is not modified. It is either:
slot: An integer team index.
team: A list of pokesets in a team.
teams: A dict containing a `blue` team and a `red` team.
<side> `blue` or `red`, indicating the side of the slot or team
that was passed as <slotOrTeamOrTeams>. Not applicable if
the `teams` dict was passed.
Returns:
If a slot was passed: An integer team index.
If a team was passed: A shallow copy of the re-ordered team.
If a teams dict was passed: A new dict with shallow copies of
both re-ordered teams.
"""
return self.slotConvert(convertTo, slotOrTeamOrTeams, side, slotSOMap)
return frozenSlotConverter

def slotConvert(self, convertTo, slotOrTeamOrTeams, side=None, slotSOMap=None):
"""Function to convert from starting order to ingame order, and vice versa.
Args:
<convertTo> Either `SO` (starting order) or `IGO` (ingame order)
<slotOrTeamOrTeams> This arg is not modified. It is either:
slot: An integer team index.
team: A list of pokesets in a team.
teams: A dict containing a `blue` team and a `red` team.
<side> `blue` or `red`, indicating the side of the slot or team
that was passed as <slotOrTeamOrTeams>. Not applicable if
the `teams` dict was passed.
<slotSOMap> Slot map to use for the conversion. If not provided, this
function uses self.slotSOMap for this value, which converts
ordering according to the LIVE game state.
To convert ordering according to game state at time X, deepcopy
self.slotSOMap at time X and pass that as this argument. Equivalently,
call getFrozenSlotConverter at time X and use the function returned.
Returns:
If a slot was passed: An integer team index.
If a team was passed: A shallow copy of the re-ordered team.
If a teams dict was passed: A new dict with shallow copies of
both re-ordered teams.
"""
convertTo = convertTo.upper()
convertTo = ("SO" if convertTo == "STARTING" else
"IGO" if convertTo == "INGAME" else convertTo)
Expand Down Expand Up @@ -137,6 +182,7 @@ def switched(self, side, slot_active, pkmn_name):
it out, then do the same for their new slot 1. So it is still one swap at a time.
'''
logger.debug(f"Detected switch: {side}, {pkmn_name} in active slot {slot_active}")
# The inactive slot is whatever slot <pkmn_name> was in prior to the switch.
slot_inactive = self.getSlotFromIngamename(side, pkmn_name)
if slot_inactive == slot_active:
logger.error("Detected switch, but active Pokemon are unchanged.")
Expand Down
46 changes: 46 additions & 0 deletions pbrEngine/activePkmn.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,24 @@ def __init__(self, side, slot, addr, startingPokeset, dolphin, debugCallback):
self.fields["STATUS"] = 0
self.fields["TOXIC_COUNTUP"] = 0
self.fields["FORM"] = 0
ivs = startingPokeset["ivs"]["hp"]
ivs <<= 5
ivs += startingPokeset["ivs"]["atk"]
ivs <<= 5
ivs += startingPokeset["ivs"]["def"]
ivs <<= 5
ivs += startingPokeset["ivs"]["spe"]
ivs <<= 5
ivs += startingPokeset["ivs"]["spA"]
ivs <<= 5
ivs += startingPokeset["ivs"]["spD"]
ivs <<= 2
self.fields["IVS_COMBINED"] = ivs
self.fields["STAT_ATK"] = startingPokeset["stats"]["atk"]
self.fields["STAT_DEF"] = startingPokeset["stats"]["def"]
self.fields["STAT_SPE"] = startingPokeset["stats"]["spe"]
self.fields["STAT_SPA"] = startingPokeset["stats"]["spA"]
self.fields["STAT_SPD"] = startingPokeset["stats"]["spD"]

for i in range(0, 4):
try:
Expand Down Expand Up @@ -181,6 +199,34 @@ def updatePokeset(self, pokeset, ppOnly):
nonvolatile["tox"] = (1 + self.fields["TOXIC_COUNTUP"]
if bool(stByte & 0x80) else 0)

if "IVS_COMBINED" in self.fields:
ivsCombined = self.fields["IVS_COMBINED"]
ivs = pokeset["ivs"]

ivsCombined >>= 2
ivs["spD"] = ivsCombined & 31
ivsCombined >>= 5
ivs["spA"] = ivsCombined & 31
ivsCombined >>= 5
ivs["spe"] = ivsCombined & 31
ivsCombined >>= 5
ivs["def"] = ivsCombined & 31
ivsCombined >>= 5
ivs["atk"] = ivsCombined & 31
ivsCombined >>= 5
ivs["hp"] = ivsCombined & 31

stats = pokeset["stats"]
if "STAT_ATK" in self.fields:
stats["atk"] = self.fields["STAT_ATK"]
if "STAT_DEF" in self.fields:
stats["def"] = self.fields["STAT_DEF"]
if "STAT_SPE" in self.fields:
stats["spe"] = self.fields["STAT_SPE"]
if "STAT_SPA" in self.fields:
stats["spA"] = self.fields["STAT_SPA"]
if "STAT_SPD" in self.fields:
stats["spD"] = self.fields["STAT_SPD"]

# pokeset["status"] = {
# "slp": 0,
Expand Down
Loading

0 comments on commit 272785d

Please sign in to comment.