summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan Bishop <kanzure@gmail.com>2013-09-08 17:11:17 -0700
committerBryan Bishop <kanzure@gmail.com>2013-09-08 17:11:17 -0700
commit87ab004d7014e1826a43f751c8a34e4b470faab3 (patch)
tree5d19a8bb6e8a77b3a0a89e5b7bac87a2baa1b641
parentc5983b0ddc6efd59e72c64bafc95af5b8fd93d86 (diff)
parent15c04c9885c639bd9b52cd94f6dc5442df52fab0 (diff)
Merge pull request #19 from kanzure/vba-automation
More VBA automation.
-rw-r--r--tests/vba_tests.py106
-rw-r--r--vba.py131
-rw-r--r--vba_autoplayer.py563
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()
diff --git a/vba.py b/vba.py
index f0d8430..ea7bb2e 100644
--- a/vba.py
+++ b/vba.py
@@ -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()