diff options
Diffstat (limited to 'tests/test_vba.py')
-rw-r--r-- | tests/test_vba.py | 276 |
1 files changed, 228 insertions, 48 deletions
diff --git a/tests/test_vba.py b/tests/test_vba.py index 56a71e3..caa1867 100644 --- a/tests/test_vba.py +++ b/tests/test_vba.py @@ -4,81 +4,96 @@ Tests for VBA automation tools import unittest -import pokemontools.vba.vba as vba +from setup_vba import ( + vba, + autoplayer, + keyboard, +) -try: - import pokemontools.vba.vba_autoplayer -except ImportError: - import pokemontools.vba.autoplayer as vba_autoplayer - -vba_autoplayer.vba = vba +from bootstrapping import ( + bootstrap, + bootstrap_trainer_battle, +) def setup_wram(): """ Loads up some default addresses. Should eventually be replaced with the actual wram parser. """ + # TODO: this should just be parsed straight out of wram.asm wram = {} wram["PlayerDirection"] = 0xd4de wram["PlayerAction"] = 0xd4e1 wram["MapX"] = 0xd4e6 wram["MapY"] = 0xd4e7 + + wram["WarpNumber"] = 0xdcb4 + wram["MapGroup"] = 0xdcb5 + wram["MapNumber"] = 0xdcb6 + wram["YCoord"] = 0xdcb7 + wram["XCoord"] = 0xdcb8 + return wram -def bootstrap(): - """ - Every test needs to be run against a certain minimum context. That context - is constructed by this function. - """ +class OtherVbaTests(unittest.TestCase): + def test_keyboard_planner(self): + button_sequence = keyboard.plan_typing("an") + expected_result = ["select", "a", "d", "r", "r", "r", "r", "a"] - # reset the rom - vba.shutdown() - vba.load_rom() + self.assertEqual(len(expected_result), len(button_sequence)) + self.assertEqual(expected_result, button_sequence) - # skip=False means run the skip_intro function instead of just skipping to - # a saved state. - vba_autoplayer.skip_intro() +class VbaTests(unittest.TestCase): + cry = None + wram = None - state = vba.get_state() + @classmethod + def setUpClass(cls): + cls.bootstrap_state = bootstrap() - # clean everything up again - vba.shutdown() + cls.wram = setup_wram() - return state + cls.cry = vba.crystal() + cls.vba = cls.cry.vba -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() + cls.vba.state = cls.bootstrap_state - def get_wram_value(self, name): - return vba.get_memory_at(self.wram[name]) + @classmethod + def tearDownClass(cls): + cls.vba.shutdown() def setUp(self): - # clean the state - vba.shutdown() - vba.load_rom() - # reset to whatever the bootstrapper created - vba.set_state(self.state) + self.vba.state = self.bootstrap_state + + def get_wram_value(self, name): + return self.vba.memory[self.wram[name]] + + def check_movement(self, direction="d"): + """ + Check if (y, x) before attempting to move and (y, x) after attempting + to move are the same. + """ + start = (self.get_wram_value("MapY"), self.get_wram_value("MapX")) + self.cry.move(direction) + end = (self.get_wram_value("MapY"), self.get_wram_value("MapX")) + return start != end + + def bootstrap_name_prompt(self): + runner = autoplayer.SpeedRunner(cry=None) + runner.setup() + runner.skip_intro(stop_at_name_selection=True, skip=False, override=False) + + self.cry.vba.press("a", hold=20) - def tearDown(self): - vba.shutdown() + # wait for "Your name?" to show up + while "YOUR NAME?" not in self.cry.get_text(): + self.cry.step(count=50) def test_movement_changes_player_direction(self): player_direction = self.get_wram_value("PlayerDirection") - vba.crystal.move("u") + self.cry.move("u") # direction should have changed self.assertNotEqual(player_direction, self.get_wram_value("PlayerDirection")) @@ -86,7 +101,7 @@ class VbaTests(unittest.TestCase): def test_movement_changes_y_coord(self): first_map_y = self.get_wram_value("MapY") - vba.crystal.move("u") + self.cry.move("u") # y location should be different second_map_y = self.get_wram_value("MapY") @@ -96,11 +111,176 @@ class VbaTests(unittest.TestCase): # should start with standing self.assertEqual(self.get_wram_value("PlayerAction"), 1) - vba.crystal.move("l") + self.cry.move("l") # should be standing player_action = self.get_wram_value("PlayerAction") self.assertEqual(player_action, 1) # 1 = standing + def test_PlaceString(self): + self.cry.call(0, 0x1078) + + # where to draw the text + self.cry.registers["hl"] = 0xc4a0 + + # what text to read from + self.cry.registers["de"] = 0x1276 + + self.cry.vba.step(count=10) + + text = self.cry.get_text() + + self.assertTrue("TRAINER" in text) + + def test_speedrunner_constructor(self): + runner = autoplayer.SpeedRunner(cry=self.cry) + + def test_speedrunner_handle_mom(self): + # TODO: why can't i pass in the current state of the emulator? + runner = autoplayer.SpeedRunner(cry=None) + runner.setup() + runner.skip_intro(skip=True) + runner.handle_mom(skip=False) + + # confirm that handle_mom is done by attempting to move on the map + self.assertTrue(self.check_movement("d")) + + def test_speedrunner_walk_into_new_bark_town(self): + runner = autoplayer.SpeedRunner(cry=None) + runner.setup() + runner.skip_intro(skip=True) + runner.handle_mom(skip=True) + runner.walk_into_new_bark_town(skip=False) + + # test that the game is in a state such that the player can walk + self.assertTrue(self.check_movement("d")) + + # check that the map is correct + self.assertEqual(self.get_wram_value("MapGroup"), 24) + self.assertEqual(self.get_wram_value("MapNumber"), 4) + + def test_speedrunner_handle_elm(self): + runner = autoplayer.SpeedRunner(cry=None) + runner.setup() + runner.skip_intro(skip=True) + runner.handle_mom(skip=True) + runner.walk_into_new_bark_town(skip=False) + + # go through the Elm's Lab sequence + runner.handle_elm("cyndaquil", skip=False) + + # test again if the game is in a state where the player can walk + self.assertTrue(self.check_movement("u")) + + # check that the map is correct + self.assertEqual(self.get_wram_value("MapGroup"), 24) + self.assertEqual(self.get_wram_value("MapNumber"), 5) + + def test_moving_back_and_forth(self): + runner = autoplayer.SpeedRunner(cry=None) + runner.setup() + runner.skip_intro(skip=True) + runner.handle_mom(skip=True) + runner.walk_into_new_bark_town(skip=False) + + # must be in New Bark Town + self.assertEqual(self.get_wram_value("MapGroup"), 24) + self.assertEqual(self.get_wram_value("MapNumber"), 4) + + runner.cry.move("l") + runner.cry.move("l") + runner.cry.move("l") + runner.cry.move("d") + runner.cry.move("d") + + for x in range(0, 10): + runner.cry.move("l") + runner.cry.move("d") + runner.cry.move("r") + runner.cry.move("u") + + # must still be in New Bark Town + self.assertEqual(self.get_wram_value("MapGroup"), 24) + self.assertEqual(self.get_wram_value("MapNumber"), 4) + + def test_crystal_move_list(self): + runner = autoplayer.SpeedRunner(cry=None) + runner.setup() + runner.skip_intro(skip=True) + runner.handle_mom(skip=True) + runner.walk_into_new_bark_town(skip=False) + + # must be in New Bark Town + self.assertEqual(self.get_wram_value("MapGroup"), 24) + self.assertEqual(self.get_wram_value("MapNumber"), 4) + + first_map_x = self.get_wram_value("MapX") + + runner.cry.move(["l", "l", "l"]) + + # x location should be different + second_map_x = self.get_wram_value("MapX") + self.assertNotEqual(first_map_x, second_map_x) + + # must still be in New Bark Town + self.assertEqual(self.get_wram_value("MapGroup"), 24) + self.assertEqual(self.get_wram_value("MapNumber"), 4) + + def test_keyboard_typing_dumb_name(self): + self.bootstrap_name_prompt() + + name = "tRaInEr" + self.cry.write(name) + + # save this selection + self.cry.vba.press("a", hold=20) + + self.assertEqual(name, self.cry.get_player_name()) + + def test_keyboard_typing_cap_name(self): + names = [ + "trainer", + "TRAINER", + "TrAiNeR", + "tRaInEr", + "ExAmPlE", + "Chris", + "Kris", + "beepaaa", + "chris", + "CHRIS", + "Python", + "pYthon", + "pyThon", + "pytHon", + "pythOn", + "pythoN", + "python", + "PyThOn", + "Zot", + "Death", + "Hiro", + "HIRO", + ] + + self.bootstrap_name_prompt() + start_state = self.cry.vba.state + + for name in names: + print "Writing name: " + name + + self.cry.vba.state = start_state + + sequence = self.cry.write(name) + + print "sequence is: " + str(sequence) + + # save this selection + self.cry.vba.press("start", hold=20) + self.cry.vba.press("a", hold=20) + + pname = self.cry.get_player_name().replace("@", "") + self.assertEqual(name, pname) + if __name__ == "__main__": unittest.main() |