diff options
author | Bryan Bishop <kanzure@gmail.com> | 2013-09-08 22:52:50 -0500 |
---|---|---|
committer | Bryan Bishop <kanzure@gmail.com> | 2013-09-08 22:52:50 -0500 |
commit | 72cdd7ba645e02c928fd56def4465e38e4c03709 (patch) | |
tree | a3f6411a4170d07a67e1ae03155176a72f535b8f /pokemontools/vba/vba_autoplayer.py | |
parent | 5ce5342833f8170390c0112ed6047243e67465a9 (diff) |
move vba/ -> pokemontools/vba/
Diffstat (limited to 'pokemontools/vba/vba_autoplayer.py')
-rw-r--r-- | pokemontools/vba/vba_autoplayer.py | 495 |
1 files changed, 495 insertions, 0 deletions
diff --git a/pokemontools/vba/vba_autoplayer.py b/pokemontools/vba/vba_autoplayer.py new file mode 100644 index 0000000..9aa8f4a --- /dev/null +++ b/pokemontools/vba/vba_autoplayer.py @@ -0,0 +1,495 @@ +# -*- coding: utf-8 -*- +""" +Programmatic speedrun of Pokémon Crystal +""" +import os + +# bring in the emulator and basic tools +import vba + +def main(): + """ + Start the game. + """ + vba.load_rom() + + # get past the opening sequence + skip_intro() + + # walk to mom and handle her text + handle_mom() + + # walk outside into new bark town + walk_into_new_bark_town() + + # walk to elm and do whatever he wants + handle_elm("totodile") + + new_bark_level_grind(10, skip=False) + +def skippable(func): + """ + Makes a function skippable. + + Saves the state before and after the function runs. + Pass "skip=True" to the function to load the previous save + state from when the function finished. + """ + def wrapped_function(*args, **kwargs): + skip = True + + if "skip" in kwargs.keys(): + skip = kwargs["skip"] + del kwargs["skip"] + + # override skip if there's no save + if skip: + full_name = func.__name__ + "-end.sav" + if not os.path.exists(os.path.join(vba.save_state_path, full_name)): + skip = False + + return_value = None + + if not skip: + vba.save_state(func.__name__ + "-start", override=True) + return_value = func(*args, **kwargs) + vba.save_state(func.__name__ + "-end", override=True) + elif skip: + vba.set_state(vba.load_state(func.__name__ + "-end")) + + return return_value + return wrapped_function + +@skippable +def skip_intro(): + """ + Skip the game boot intro sequence. + """ + + # copyright sequence + vba.nstep(400) + + # skip the ditto sequence + vba.press("a") + vba.nstep(100) + + # skip the start screen + vba.press("start") + vba.nstep(100) + + # click "new game" + vba.press("a", holdsteps=50, aftersteps=1) + + # skip text up to "Are you a boy? Or are you a girl?" + vba.crystal.text_wait() + + # select "Boy" + vba.press("a", holdsteps=50, aftersteps=1) + + # text until "What time is it?" + vba.crystal.text_wait() + + # select 10 o'clock + vba.press("a", holdsteps=50, aftersteps=1) + + # yes i mean it + vba.press("a", holdsteps=50, aftersteps=1) + + # "How many minutes?" 0 min. + vba.press("a", holdsteps=50, aftersteps=1) + + # "Who! 0 min.?" yes/no select yes + vba.press("a", holdsteps=50, aftersteps=1) + + # read text until name selection + vba.crystal.text_wait() + + # select "Chris" + vba.press("d", holdsteps=10, aftersteps=1) + vba.press("a", holdsteps=50, aftersteps=1) + + def overworldcheck(): + """ + A basic check for when the game starts. + """ + return vba.get_memory_at(0xcfb1) != 0 + + # go until the introduction is done + vba.crystal.text_wait(callback=overworldcheck) + + return + +@skippable +def handle_mom(): + """ + Walk to mom. Handle her speech and questions. + """ + + vba.crystal.move("r") + vba.crystal.move("r") + vba.crystal.move("r") + vba.crystal.move("r") + + vba.crystal.move("u") + vba.crystal.move("u") + vba.crystal.move("u") + + vba.crystal.move("d") + vba.crystal.move("d") + + # move into mom's line of sight + vba.crystal.move("d") + + # let mom talk until "What day is it?" + vba.crystal.text_wait() + + # "What day is it?" Sunday + vba.press("a", holdsteps=10) # Sunday + + vba.crystal.text_wait() + + # "SUNDAY, is it?" yes/no + vba.press("a", holdsteps=10) # yes + + vba.crystal.text_wait() + + # "Is it Daylight Saving Time now?" yes/no + vba.press("a", holdsteps=10) # yes + + vba.crystal.text_wait() + + # "AM DST, is that OK?" yes/no + vba.press("a", holdsteps=10) # yes + + # text until "know how to use the PHONE?" yes/no + vba.crystal.text_wait() + + # press yes + vba.press("a", holdsteps=10) + + # wait until mom is done talking + vba.crystal.text_wait() + + # wait until the script is done running + vba.crystal.wait_for_script_running() + + return + +@skippable +def walk_into_new_bark_town(): + """ + Walk outside after talking with mom. + """ + + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("l") + vba.crystal.move("l") + + # walk outside + vba.crystal.move("d") + +@skippable +def handle_elm(starter_choice): + """ + Walk to Elm's Lab and get a starter. + """ + + # walk to the lab + vba.crystal.move("l") + vba.crystal.move("l") + vba.crystal.move("l") + vba.crystal.move("l") + vba.crystal.move("l") + vba.crystal.move("l") + vba.crystal.move("l") + vba.crystal.move("u") + vba.crystal.move("u") + + # walk into the lab + vba.crystal.move("u") + + # talk to elm + vba.crystal.text_wait() + + # "that I recently caught." yes/no + vba.press("a", holdsteps=10) # yes + + # talk to elm some more + vba.crystal.text_wait() + + # talking isn't done yet.. + vba.crystal.text_wait() + vba.crystal.text_wait() + vba.crystal.text_wait() + + # wait until the script is done running + vba.crystal.wait_for_script_running() + + # move toward the pokeballs + vba.crystal.move("r") + + # move to cyndaquil + vba.crystal.move("r") + + moves = 0 + + if starter_choice.lower() == "cyndaquil": + moves = 0 + if starter_choice.lower() == "totodile": + moves = 1 + else: + moves = 2 + + for each in range(0, moves): + vba.crystal.move("r") + + # face the pokeball + vba.crystal.move("u") + + # select it + vba.press("a", holdsteps=10, aftersteps=0) + + # wait for the image to pop up + vba.crystal.text_wait() + + # wait for the image to close + vba.crystal.text_wait() + + # wait for the yes/no box + vba.crystal.text_wait() + + # press yes + vba.press("a", holdsteps=10, aftersteps=0) + + # wait for elm to talk a bit + vba.crystal.text_wait() + + # TODO: why didn't that finish his talking? + vba.crystal.text_wait() + + # give a nickname? yes/no + vba.press("d", holdsteps=10, aftersteps=0) # move to "no" + vba.press("a", holdsteps=10, aftersteps=0) # no + + # TODO: why didn't this wait until he was completely done? + vba.crystal.text_wait() + vba.crystal.text_wait() + + # get the phone number + vba.crystal.text_wait() + + # talk with elm a bit more + vba.crystal.text_wait() + + # TODO: and again.. wtf? + vba.crystal.text_wait() + + # wait until the script is done running + vba.crystal.wait_for_script_running() + + # move down + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("d") + + # move into the researcher's line of sight + vba.crystal.move("d") + + # get the potion from the person + vba.crystal.text_wait() + vba.crystal.text_wait() + + # wait for the script to end + vba.crystal.wait_for_script_running() + + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("d") + + # go outside + vba.crystal.move("d") + + return + +@skippable +def new_bark_level_grind(level): + """ + Do level grinding in New Bark. + + Starting just outside of Elm's Lab, do some level grinding until the first + partymon level is equal to the given value.. + """ + + # walk to the grass area + new_bark_level_grind_walk_to_grass(skip=False) + + # TODO: walk around in grass, handle battles + walk = ["d", "d", "u", "d", "u", "d"] + for direction in walk: + vba.crystal.move(direction) + + # wait for wild battle to completely start + vba.crystal.text_wait() + + attacks = 5 + + while attacks > 0: + # FIGHT + vba.press("a", holdsteps=10, aftersteps=1) + + # wait to select a move + vba.crystal.text_wait() + + # SCRATCH + vba.press("a", holdsteps=10, aftersteps=1) + + # wait for the move to be over + vba.crystal.text_wait() + + hp = ((vba.get_memory_at(0xd218) << 8) | vba.get_memory_at(0xd217)) + print "enemy hp is: " + str(hp) + + if hp == 0: + print "enemy hp is zero, exiting" + break + else: + print "enemy hp is: " + str(hp) + + attacks = attacks - 1 + + while vba.get_memory_at(0xd22d) != 0: + vba.press("a", holdsteps=10, aftersteps=1) + + # wait for the map to finish loading + vba.nstep(50) + + print "okay, back in the overworld" + + # move up + vba.crystal.move("u") + vba.crystal.move("u") + vba.crystal.move("u") + vba.crystal.move("u") + + # move into new bark town + vba.crystal.move("r") + vba.crystal.move("r") + vba.crystal.move("r") + vba.crystal.move("r") + vba.crystal.move("r") + vba.crystal.move("r") + vba.crystal.move("r") + vba.crystal.move("r") + vba.crystal.move("r") + vba.crystal.move("r") + + # move up + vba.crystal.move("u") + vba.crystal.move("u") + vba.crystal.move("u") + vba.crystal.move("u") + vba.crystal.move("u") + + # move to the door + vba.crystal.move("r") + vba.crystal.move("r") + vba.crystal.move("r") + + # walk in + vba.crystal.move("u") + + # move up to the healing thing + vba.crystal.move("u") + vba.crystal.move("u") + vba.crystal.move("u") + vba.crystal.move("u") + vba.crystal.move("u") + vba.crystal.move("u") + vba.crystal.move("u") + vba.crystal.move("u") + vba.crystal.move("u") + vba.crystal.move("l") + vba.crystal.move("l") + + # face it + vba.crystal.move("u") + + # interact + vba.press("a", holdsteps=10, aftersteps=1) + + # wait for yes/no box + vba.crystal.text_wait() + + # press yes + vba.press("a", holdsteps=10, aftersteps=1) + + # TODO: when is healing done? + + # wait until the script is done running + vba.crystal.wait_for_script_running() + + # wait for it to be really really done + vba.nstep(50) + + vba.crystal.move("r") + vba.crystal.move("r") + + # move to the door + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("d") + + # walk out + vba.crystal.move("d") + + # check partymon1 level + if vba.get_memory_at(0xdcfe) < level: + new_bark_level_grind(level, skip=False) + else: + return + +@skippable +def new_bark_level_grind_walk_to_grass(): + """ + Move to just above the grass from outside Elm's lab. + """ + + vba.crystal.move("d") + vba.crystal.move("d") + + vba.crystal.move("l") + vba.crystal.move("l") + + vba.crystal.move("d") + vba.crystal.move("d") + + vba.crystal.move("l") + vba.crystal.move("l") + + # move to route 29 past the trees + vba.crystal.move("l") + vba.crystal.move("l") + vba.crystal.move("l") + vba.crystal.move("l") + vba.crystal.move("l") + vba.crystal.move("l") + vba.crystal.move("l") + vba.crystal.move("l") + vba.crystal.move("l") + + # move to just above the grass + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("d") + +if __name__ == "__main__": + main() |