diff options
author | Bryan Bishop <kanzure@gmail.com> | 2013-09-08 17:11:17 -0700 |
---|---|---|
committer | Bryan Bishop <kanzure@gmail.com> | 2013-09-08 17:11:17 -0700 |
commit | 87ab004d7014e1826a43f751c8a34e4b470faab3 (patch) | |
tree | 5d19a8bb6e8a77b3a0a89e5b7bac87a2baa1b641 | |
parent | c5983b0ddc6efd59e72c64bafc95af5b8fd93d86 (diff) | |
parent | 15c04c9885c639bd9b52cd94f6dc5442df52fab0 (diff) |
Merge pull request #19 from kanzure/vba-automation
More VBA automation.
-rw-r--r-- | tests/vba_tests.py | 106 | ||||
-rw-r--r-- | vba.py | 131 | ||||
-rw-r--r-- | vba_autoplayer.py | 563 |
3 files changed, 524 insertions, 276 deletions
diff --git a/tests/vba_tests.py b/tests/vba_tests.py new file mode 100644 index 0000000..a257f20 --- /dev/null +++ b/tests/vba_tests.py @@ -0,0 +1,106 @@ +""" +Tests for VBA automation tools +""" + +import unittest + +import vba + +try: + import vba_autoplayer +except ImportError: + import autoplayer as vba_autoplayer + +vba_autoplayer.vba = vba + +def setup_wram(): + """ + Loads up some default addresses. Should eventually be replaced with the + actual wram parser. + """ + wram = {} + wram["PlayerDirection"] = 0xd4de + wram["PlayerAction"] = 0xd4e1 + wram["MapX"] = 0xd4e6 + wram["MapY"] = 0xd4e7 + return wram + +def bootstrap(): + """ + Every test needs to be run against a certain minimum context. That context + is constructed by this function. + """ + + # reset the rom + vba.shutdown() + vba.load_rom() + + # skip=False means run the skip_intro function instead of just skipping to + # a saved state. + vba_autoplayer.skip_intro() + + state = vba.get_state() + + # clean everything up again + vba.shutdown() + + return state + +class VbaTests(unittest.TestCase): + # unittest in jython2.5 doesn't seem to have setUpClass ?? Man, why am I on + # jython2.5? This is ancient. + #@classmethod + #def setUpClass(cls): + # # get a good game state + # cls.state = bootstrap() + # + # # figure out addresses + # cls.wram = setup_wram() + + # FIXME: work around jython2.5 unittest + state = bootstrap() + wram = setup_wram() + + def get_wram_value(self, name): + return vba.get_memory_at(self.wram[name]) + + def setUp(self): + # clean the state + vba.shutdown() + vba.load_rom() + + # reset to whatever the bootstrapper created + vba.set_state(self.state) + + def tearDown(self): + vba.shutdown() + + def test_movement_changes_player_direction(self): + player_direction = self.get_wram_value("PlayerDirection") + + vba.crystal.move("u") + + # direction should have changed + self.assertNotEqual(player_direction, self.get_wram_value("PlayerDirection")) + + def test_movement_changes_y_coord(self): + first_map_y = self.get_wram_value("MapY") + + vba.crystal.move("u") + + # y location should be different + second_map_y = self.get_wram_value("MapY") + self.assertNotEqual(first_map_y, second_map_y) + + def test_movement_ends_in_standing(self): + # should start with standing + self.assertEqual(self.get_wram_value("PlayerAction"), 1) + + vba.crystal.move("l") + + # should be standing + player_action = self.get_wram_value("PlayerAction") + self.assertEqual(player_action, 1) # 1 = standing + +if __name__ == "__main__": + unittest.main() @@ -115,7 +115,7 @@ except ImportError: print "Not loading the keyboard module (which uses networkx)." if not os.path.exists(rom_path): - raise Exception("rom_path is not configured properly; edit vba_config.py?") + raise Exception("rom_path is not configured properly; edit vba_config.py? " + str(rom_path)) def _check_java_library_path(): """ @@ -736,30 +736,112 @@ class cheats: """ Gb.cheatAddGameshark(code, description) -class crystal: +def get_stack(): + """ + Return a list of functions on the stack. + """ + addresses = [] + sp = registers.sp + + for x in range(0, 11): + sp = sp - (2 * x) + hi = get_memory_at(sp + 1) + lo = get_memory_at(sp) + address = ((hi << 8) | lo) + addresses.append(address) + return addresses + +class crystal: """ Just a simple namespace to store a bunch of functions for Pokémon Crystal. """ @staticmethod - def text_wait(step_size=10, max_wait=500): + def text_wait(step_size=1, max_wait=200, sfx_limit=0, debug=False, callback=None): """ Presses the "A" button when text is done being drawn to screen. + The `debug` parameter is only useful when debugging this function. It + enables the `max_wait` feature, which causes the function to exit + instead of hanging around. + + The `sfx_limit` parameter is useful for when the player is given an + item during the text. Set it to 1 to not treat the sound as the end of + text. The next loop around it will return to the normal behavior of the + function. + :param step_size: number of steps per wait loop :param max_wait: number of wait loops to perform """ - for x in range(0, max_wait): + while max_wait > 0: hi = get_memory_at(registers.sp + 1) lo = get_memory_at(registers.sp) address = ((hi << 8) | lo) - if address == 0xaef: - break + + if address in range(0xa1b, 0xa46) + range(0xaaf, 0xaf5): # 0xaef: + print "pressing, then breaking.. address is: " + str(hex(address)) + + # set CurSFX + set_memory_at(0xc2bf, 0) + + press("a", holdsteps=10, aftersteps=1) + + # check if CurSFX is SFX_READ_TEXT_2 + if get_memory_at(0xc2bf) == 0x8: + print "cursfx is set to SFX_READ_TEXT_2, looping.." + return crystal.text_wait(step_size=step_size, max_wait=max_wait, debug=debug, callback=callback, sfx_limit=sfx_limit) + else: + if sfx_limit > 0: + sfx_limit = sfx_limit - 1 + print "decreasing sfx_limit" + else: + # probably the last textbox in a sequence + print "cursfx is not set to SFX_READ_TEXT_2, so: breaking" + + break else: - nstep(step_size) + stack = get_stack() + + # yes/no box or the name selection box + if address in range(0xa46, 0xaaf): + print "probably at a yes/no box.. exiting." + break + + # date/time box (day choice) + # 0x47ab is the one from the intro, 0x49ab is the one from mom. + elif 0x47ab in stack or 0x49ab in stack: # was any([x in stack for x in range(0x46EE, 0x47AB)]) + print "probably at a date/time box ? exiting." + break - press("a", holdsteps=50, aftersteps=1) + # "How many minutes?" selection box + elif 0x4826 in stack: + print "probably at a \"How many minutes?\" box ? exiting." + break + + else: + nstep(step_size) + + # if there is a callback, then call the callback and exit when the + # callback returns True. This is especially useful during the + # OakSpeech intro where textboxes are running constantly, and then + # suddenly the player can move around. One way to detect that is to + # set callback to a function that returns + # "vba.get_memory_at(0xcfb1) != 0". + if callback != None: + result = callback() + if result == True: + print "callback returned True, exiting" + return + + # only useful when debugging. When this is left on, text that + # takes a while to print to screen will cause this function to + # exit. + if debug == True: + max_wait = max_wait - 1 + + if max_wait == 0: + print "max_wait was hit" @staticmethod def walk_through_walls_slow(): @@ -1025,6 +1107,39 @@ class crystal: set_memory(memory) + @staticmethod + def wait_for_script_running(debug=False, limit=1000): + """ + Wait until ScriptRunning isn't -1. + """ + while limit > 0: + if get_memory_at(0xd438) != 255: + print "script is done executing" + return + else: + step() + + if debug: + limit = limit - 1 + + if limit == 0: + print "limit ran out" + + @staticmethod + def move(cmd): + """ + Attempt to move the player. + """ + press(cmd, holdsteps=10, aftersteps=0) + press([]) + + memory = get_memory() + #while memory[0xd4e1] == 2 and memory[0xd042] != 0x3e: + while memory[0xd043] in [0, 1, 2, 3]: + #while memory[0xd043] in [0, 1, 2, 3] or memory[0xd042] != 0x3e: + nstep(10) + memory = get_memory() + class TestEmulator(unittest.TestCase): try: state = load_state("cheating-12") diff --git a/vba_autoplayer.py b/vba_autoplayer.py index caf76d5..9aa8f4a 100644 --- a/vba_autoplayer.py +++ b/vba_autoplayer.py @@ -19,6 +19,9 @@ def main(): # 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") @@ -62,6 +65,7 @@ def skip_intro(): """ Skip the game boot intro sequence. """ + # copyright sequence vba.nstep(400) @@ -76,79 +80,42 @@ def skip_intro(): # click "new game" vba.press("a", holdsteps=50, aftersteps=1) - # Are you a boy? Or are you a girl? - vba.nstep(145) - - # pick "boy" - vba.press("a", holdsteps=50, aftersteps=1) - - # .... + # skip text up to "Are you a boy? Or are you a girl?" vba.crystal.text_wait() - vba.crystal.text_wait() + # select "Boy" + vba.press("a", holdsteps=50, aftersteps=1) - # What time is it? + # text until "What time is it?" vba.crystal.text_wait() - # DAY 10 o'clock + # select 10 o'clock vba.press("a", holdsteps=50, aftersteps=1) - # WHAT? DAY 10 o'clock? YES/NO. + # yes i mean it vba.press("a", holdsteps=50, aftersteps=1) - # How many minutes? 0 min. + # "How many minutes?" 0 min. vba.press("a", holdsteps=50, aftersteps=1) - # Whoa! 0 min.? YES/NO. + # "Who! 0 min.?" yes/no select yes vba.press("a", holdsteps=50, aftersteps=1) + # read text until name selection vba.crystal.text_wait() - vba.crystal.text_wait() - - # People call me - vba.crystal.text_wait() - vba.crystal.text_wait() - - # tures that we call - vba.crystal.text_wait() - - vba.crystal.text_wait() - vba.crystal.text_wait() - - vba.crystal.text_wait() - vba.crystal.text_wait() - - vba.crystal.text_wait() - - # everything about pokemon yet. - vba.crystal.text_wait() - vba.crystal.text_wait() - - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - - # Now, what did you say your name was? - vba.crystal.text_wait() - - # move down to "CHRIS" - vba.press("d") - vba.nstep(50) + # select "Chris" + vba.press("d", holdsteps=10, aftersteps=1) vba.press("a", holdsteps=50, aftersteps=1) - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() + def overworldcheck(): + """ + A basic check for when the game starts. + """ + return vba.get_memory_at(0xcfb1) != 0 - # wait until playable - # could be 150, but it sometimes takes longer?? - vba.nstep(200) + # go until the introduction is done + vba.crystal.text_wait(callback=overworldcheck) return @@ -157,280 +124,195 @@ def handle_mom(): """ Walk to mom. Handle her speech and questions. """ - vba.press("r"); vba.nstep(50) - vba.press("r"); vba.nstep(50) - vba.press("r"); vba.nstep(50) - vba.press("r"); vba.nstep(50) - vba.press("r"); vba.nstep(50) - vba.press("u"); vba.nstep(50) - vba.press("u"); vba.nstep(50) - vba.press("u"); vba.nstep(50) - vba.press("u"); vba.nstep(50) - - # wait for next map to load - vba.nstep(50) - vba.press("d"); vba.nstep(50) - vba.press("d"); vba.nstep(50) - vba.press("d"); vba.nstep(50) + vba.crystal.move("r") + vba.crystal.move("r") + vba.crystal.move("r") + vba.crystal.move("r") - # walk into mom's line of sight - vba.press("d"); vba.nstep(50) + vba.crystal.move("u") + vba.crystal.move("u") + vba.crystal.move("u") - vba.nstep(50) - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() + vba.crystal.move("d") + vba.crystal.move("d") - # What day is it? SUNDAY. - vba.press("a", holdsteps=50, aftersteps=1) + # move into mom's line of sight + vba.crystal.move("d") - # SUNDAY, is it? YES/NO - vba.press("a", holdsteps=50, aftersteps=1) + # let mom talk until "What day is it?" + vba.crystal.text_wait() - vba.nstep(200) + # "What day is it?" Sunday + vba.press("a", holdsteps=10) # Sunday - # is it DST now? YES/NO. - vba.press("a", holdsteps=50, aftersteps=1) + vba.crystal.text_wait() - # 10:06 AM DST, is that OK? YES/NO. - vba.press("a", holdsteps=50, aftersteps=1) + # "SUNDAY, is it?" yes/no + vba.press("a", holdsteps=10) # yes vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - # know how to use the PHONE? YES/NO. - vba.press("a", holdsteps=50, aftersteps=1) + # "Is it Daylight Saving Time now?" yes/no + vba.press("a", holdsteps=10) # yes vba.crystal.text_wait() - vba.crystal.text_wait() - 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() - vba.press("a", holdsteps=50, aftersteps=1) + # press yes + vba.press("a", holdsteps=10) - # have to wait for her to move back :( - vba.nstep(50) + # wait until mom is done talking + vba.crystal.text_wait() - # face down - vba.press("d"); vba.nstep(50) + # wait until the script is done running + vba.crystal.wait_for_script_running() return @skippable -def handle_elm(starter_choice): +def walk_into_new_bark_town(): """ - Walk to Elm's Lab and get a starter. + Walk outside after talking with mom. """ - # walk down - vba.press("d"); vba.nstep(50) - vba.press("d"); vba.nstep(50) - - # face left - vba.press("l"); vba.nstep(50) - - # walk left - vba.press("l"); vba.nstep(50) - vba.press("l"); vba.nstep(50) - - # face down - vba.press("d"); vba.nstep(50) - - # walk down - vba.press("d"); vba.nstep(50) - - # walk down to warp to outside - vba.press("d"); vba.nstep(50) - vba.nstep(10) + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("l") + vba.crystal.move("l") - vba.press("l", holdsteps=10, aftersteps=50) - vba.press("l", holdsteps=10, aftersteps=50) - vba.press("l", holdsteps=10, aftersteps=50) + # walk outside + vba.crystal.move("d") - vba.press("l", holdsteps=10, aftersteps=50) - vba.press("l", holdsteps=10, aftersteps=50) - vba.press("l", holdsteps=10, aftersteps=50) - vba.press("l", holdsteps=10, aftersteps=50) - - vba.press("u", holdsteps=10, aftersteps=50) - vba.press("u", holdsteps=10, aftersteps=50) - - # warp into elm's lab (bottom left warp) - vba.press("u", holdsteps=5, aftersteps=50) +@skippable +def handle_elm(starter_choice): + """ + Walk to Elm's Lab and get a starter. + """ - # let the script play - vba.nstep(200) + # 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") - vba.crystal.text_wait() - # I needed to ask you a fa + # walk into the lab + vba.crystal.move("u") - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() + # talk to elm vba.crystal.text_wait() - vba.nstep(50) - - # YES/NO. - vba.press("a") + # "that I recently caught." yes/no + vba.press("a", holdsteps=10) # yes + # talk to elm some more vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - - vba.press("a") + # talking isn't done yet.. vba.crystal.text_wait() vba.crystal.text_wait() - vba.press("a") - 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() - for x in range(0, 8): # was 15 - vba.crystal.text_wait() + # move toward the pokeballs + vba.crystal.move("r") - vba.nstep(50) - vba.press("a") - vba.nstep(100) + # move to cyndaquil + vba.crystal.move("r") - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() + moves = 0 - # Go on! Pick one. - vba.nstep(100) - vba.press("a"); vba.nstep(50) - - vba.press("r"); vba.nstep(50) - vba.press("r"); vba.nstep(50) - - right = 0 - if starter_choice in [1, "cyndaquil"]: - right = 0 - elif starter_choice in [2, "totodile"]: - right = 1 - elif starter_choice in [3, "chikorita"]: - right = 2 + if starter_choice.lower() == "cyndaquil": + moves = 0 + if starter_choice.lower() == "totodile": + moves = 1 else: - raise Exception("bad starter") - - for each in range(0, right): - vba.press("r"); vba.nstep(50) + moves = 2 - # look up - vba.press("u", holdsteps=5, aftersteps=50) + for each in range(0, moves): + vba.crystal.move("r") - # get menu - vba.press("a", holdsteps=5, aftersteps=50) + # face the pokeball + vba.crystal.move("u") - # let the image show - vba.nstep(100) + # select it + vba.press("a", holdsteps=10, aftersteps=0) + # wait for the image to pop up vba.crystal.text_wait() - vba.crystal.text_wait() - - # YES/NO. - vba.press("a") + # wait for the image to close vba.crystal.text_wait() + + # wait for the yes/no box vba.crystal.text_wait() - # received.. music is playing. - vba.press("a") + # press yes + vba.press("a", holdsteps=10, aftersteps=0) + + # wait for elm to talk a bit vba.crystal.text_wait() - # YES/NO (nickname) + # TODO: why didn't that finish his talking? vba.crystal.text_wait() - vba.press("b") + # give a nickname? yes/no + vba.press("d", holdsteps=10, aftersteps=0) # move to "no" + vba.press("a", holdsteps=10, aftersteps=0) # no - # get back to elm - vba.nstep(100) - vba.nstep(100) - - vba.crystal.text_wait() - vba.crystal.text_wait() - vba.crystal.text_wait() + # TODO: why didn't this wait until he was completely done? vba.crystal.text_wait() vba.crystal.text_wait() - # phone number.. - vba.press("a") + # get the phone number vba.crystal.text_wait() - vba.nstep(100) - vba.press("a") - vba.nstep(300) - vba.press("a") - vba.nstep(100) - vba.crystal.text_wait() - vba.crystal.text_wait() + # talk with elm a bit more vba.crystal.text_wait() - # I'm counting on you! - vba.nstep(200) - vba.press("a") - vba.nstep(50) - - # look down - vba.press("d", holdsteps=5, aftersteps=50) - - # walk down - vba.press("d", holdsteps=10, aftersteps=50) + # TODO: and again.. wtf? + vba.crystal.text_wait() - vba.press("d", holdsteps=10, aftersteps=50) - vba.press("d", holdsteps=10, aftersteps=50) - vba.press("d", holdsteps=10, aftersteps=50) - vba.press("d", holdsteps=10, aftersteps=50) + # wait until the script is done running + vba.crystal.wait_for_script_running() - vba.crystal.text_wait() - vba.crystal.text_wait() + # move down + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("d") - vba.press("a") - vba.nstep(50) - vba.press("a") + # 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() - vba.press("a") - vba.nstep(50) + # wait for the script to end + vba.crystal.wait_for_script_running() - vba.crystal.text_wait() - vba.press("a") - - vba.nstep(100) + vba.crystal.move("d") + vba.crystal.move("d") + vba.crystal.move("d") - vba.press("d", holdsteps=10, aftersteps=50) - vba.press("d", holdsteps=10, aftersteps=50) - vba.press("d", holdsteps=10, aftersteps=50) - vba.press("d", holdsteps=10, aftersteps=50) + # go outside + vba.crystal.move("d") - # step outside - vba.nstep(40) + return @skippable def new_bark_level_grind(level): @@ -445,24 +327,169 @@ def new_bark_level_grind(level): new_bark_level_grind_walk_to_grass(skip=False) # TODO: walk around in grass, handle battles - # TODO: heal at the lab, then repeat entire function + 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_travel_to_grass(): +def new_bark_level_grind_walk_to_grass(): """ - Move to just above the grass. + Move to just above the grass from outside Elm's lab. """ - vba.press("d", holdsteps=10, aftersteps=50) - vba.press("d", holdsteps=10, aftersteps=50) - vba.press("d", holdsteps=10, aftersteps=50) - - vba.press("l", holdsteps=10, aftersteps=50) - vba.press("l", holdsteps=10, aftersteps=50) - vba.press("l", holdsteps=10, aftersteps=50) - vba.press("l", holdsteps=10, aftersteps=50) - vba.press("d", holdsteps=10, aftersteps=50) - vba.press("d", holdsteps=10, aftersteps=50) + 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() |