def make_game_directory(self): if UI.ask("No pythonwarrior directory found, \ would you like to create one?"): os.mkdir(Config.path_prefix + '/pythonwarrior') else: UI.puts('Unable to continue without directory.') raise Exception("Unable to continue without directory.")
def go_back_to_normal_mode(self): self.profile().enable_normal_mode() self.prepare_next_level() UI.puts('Another level has been added since you started epic, ' 'going back to normal mode') UI.puts('See the updated README in the ' 'pythonwarrior/%s directory' % self.profile().directory_name())
def setUp(self): self.ui = UI() self.config = Config self.config.delay = None self.out_stream = StringIO() self.in_stream = StringIO() self.config.out_stream = self.out_stream self.config.in_stream = self.in_stream
def start(self): UI.puts('Welcome to Python Warrior') if os.path.exists(Config.path_prefix + '/.profile'): self.profile = Profile.load(Config.path_prefix + '/.profile') else: if os.path.exists(Config.path_prefix + '/python-warrior'): shutil.move(Config.path_prefix + '/python-warrior', Config.path_prefix + '/pythonwarrior') if not os.path.exists(Config.path_prefix + '/pythonwarrior'): self.make_game_directory()
def play_normal_mode(self): if Config.practice_level: UI.puts("Unable to practice level while not in epic mode," "remove -l options") else: if self.current_level().number == 0: self.prepare_next_level() UI.puts("First level has been generated." "See the pythonwarrior/%s/README for instructions." % self.profile().directory_name()) else: self.play_current_level()
def start(self): UI.puts('Welcome to Python Warrior') if os.path.exists(Config.path_prefix + '/.profile'): self._profile = Profile.load(Config.path_prefix + '/.profile') else: if not os.path.exists(Config.path_prefix + '/pythonwarrior'): self.make_game_directory() if self.profile().epic: if self.profile().level_after_epic(): self.go_back_to_normal_mode() else: self.play_epic_mode() else: self.play_normal_mode()
def play(self, turns=1000, fxn=None): self.load_level() for turn in range(turns): if self.is_passed() or self.is_failed(): return UI.puts('- turn %d -' % (turn+1)) UI.write(self.floor.character) for unit in self.floor.units: unit.prepare_turn() for unit in self.floor.units: unit.perform_turn() if fxn: fxn() if self.time_bonus > 0: self.time_bonus -= 1
def play(self, turns=1000, fxn=None): self.load_level() for turn in range(turns): if self.is_passed() or self.is_failed(): return UI.puts('- turn %d -' % (turn + 1)) UI.write(self.floor.character) for unit in self.floor.units: unit.prepare_turn() for unit in self.floor.units: unit.perform_turn() if fxn: fxn() if self.time_bonus > 0: self.time_bonus -= 1
def request_next_level(self): if not Config.skip_input: if self.next_level(): if UI.ask('Would you like to continue on to the next level?'): self.prepare_next_level() UI.puts('See the updated README in the pythonwarrior/' + self.profile().directory_name() + ' directory') else: UI.puts('Staying on current level.' 'Try to earn more points next time.') else: UI.ask('Would you like to continue on to epic mode?') UI.puts('Sorry, epic mode is not yet enabled!')
def request_next_level(self): if not Config.skip_input: if self.next_level().exists(): if UI.ask('Would you like to continue on to the next level?'): self.prepare_next_level() UI.puts('See the updated README in the pythonwarrior/' + self.profile().directory_name() + ' directory') else: UI.puts('Staying on current level.' 'Try to earn more points next time.') else: if UI.ask('Would you like to continue on to epic mode?'): self.prepare_epic_mode() UI.puts('Run pythonwarrior again to play epic mode.') else: UI.puts("Staying on current level. " "Try to earn more points next time.")
def choose_profile(self): profile = UI.choose('profile', self.profiles() + [['new', 'New Profile']]) if profile == 'new': profile = self.new_profile() if filter(lambda prof: prof.player_path == profile.player_path, self.profiles()): if UI.ask('Are you sure you want to replace your existing' 'profile for this tower?'): UI.puts('Replacing existing profile.') return profile else: UI.puts('Not replacing profile.') raise Exception('Not replacing profile') else: return profile else: return profile
class TestUI(unittest.TestCase): def setUp(self): self.ui = UI() self.config = Config self.config.delay = None self.out_stream = StringIO() self.in_stream = StringIO() self.config.out_stream = self.out_stream self.config.in_stream = self.in_stream def test_should_add_puts_to_out_stream(self): self.ui.puts("hello") self.assertEqual(self.out_stream.getvalue(), "hello\n") def test_should_add_write_to_out_stream_without_newline(self): self.ui.write("hello") self.out_stream.seek(0) self.assertEqual(self.out_stream.getvalue(), "hello") def test_should_fetch_gets_from_in_stream(self): self.in_stream.write("bar") self.in_stream.seek(0) self.assertEqual(self.ui.gets(), "bar") def test_should_gets_should_return_empty_string_if_no_input(self): self.config.in_stream = None self.assertEqual(self.ui.gets(), "") def test_should_request_text_input(self): self.in_stream.write("bar") self.in_stream.seek(0) self.assertEqual(self.ui.request("foo"), "bar") self.assertEqual(self.out_stream.getvalue(), "foo\n") @mock.patch('pythonwarrior.ui.UI.request') def test_should_ask_for_yes_no_and_return_true_when_yes(self, mock_req): mock_req.return_value = 'y' self.assertTrue(self.ui.ask("foo?")) @mock.patch('pythonwarrior.ui.UI.request') def test_should_ask_for_yes_no_and_return_false_when_no(self, mock_req): mock_req.return_value = 'n' self.assertFalse(self.ui.ask("foo?")) @mock.patch('pythonwarrior.ui.UI.request') def test_should_ask_for_yes_no_and_return_false_for_any_input( self, mock_req): mock_req.return_value = 'aklhasdf' self.assertFalse(self.ui.ask("foo?")) @mock.patch('pythonwarrior.ui.UI.request') def test_should_present_multiple_options_and_return_selected_one( self, mock_req): mock_req.return_value = '2' self.assertEqual(self.ui.choose('item', ['foo', 'bar', 'test']), 'bar') output = self.out_stream.getvalue() assert '[1] foo' in output assert '[2] bar' in output assert '[3] test' in output @mock.patch('pythonwarrior.ui.UI.request') def test_choose_should_accept_array_as_option(self, mock_req): mock_req.return_value = 3 self.assertEqual( self.ui.choose('item', ['foo', 'bar', ['tower', 'easy']]), 'tower') assert '[3] easy' in self.out_stream.getvalue() @mock.patch('pythonwarrior.ui.UI.puts') @mock.patch('pythonwarrior.ui.UI.gets') @mock.patch('pythonwarrior.ui.UI.request') def test_choose_should_return_option_without_prompt_if_only_one_item( self, mock_req, mock_gets, mock_puts): self.assertEqual(self.ui.choose('item', ['foo']), 'foo') assert not mock_puts.called assert not mock_gets.called def test_choose_should_return_first_value_in_array_if_one_item(self): self.assertEqual(self.ui.choose('item', [['foo', 'bar']]), 'foo') @mock.patch('time.sleep') @mock.patch('pythonwarrior.ui.UI.puts') def test_should_delay_after_puts_when_specified(self, mock_puts, mock_sleep): self.config.delay = 1.3 self.ui.puts_with_delay('foo') mock_puts.assert_called_with('foo') mock_sleep.assert_called_with(1.3) @mock.patch('time.sleep') @mock.patch('pythonwarrior.ui.UI.puts') def test_should_not_delay_puts_when_no_delay(self, mock_puts, mock_sleep): self.ui.puts_with_delay('foo') mock_puts.assert_called_with('foo') assert not mock_sleep.called
def tally_points(self): score = 0 UI.puts('Level Score: %d' % self.warrior.score) score += self.warrior.score UI.puts('Time Bonus: %d' % self.time_bonus) score += self.time_bonus if not self.floor.other_units(): UI.puts('Clear Bonus: %d' % self.clear_bonus()) score += self.clear_bonus() if self.profile.epic: if self.grade_for(score): UI.puts('Level Grade: %s' % self.grade_for(score)) UI.puts('Total Score: %s' % self.score_calculation(self.profile.current_epic_score, score)) if self.ace_score: grade = (score / float(self.ace_score)) self.profile.current_epic_grades[self.number] = grade self.profile.current_epic_score += score else: UI.puts('Total Score: %s' % self.score_calculation(self.profile.score, score)) self.profile.score += score self.profile.abilities = self.warrior.abilities.keys()
def new_profile(self): profile = Profile() profile.tower_path = UI.choose('tower', self.towers()).path profile.warrior_name = UI.request('Enter a name for your warrior: ') return profile
def tally_points(self): score = 0 UI.puts('Level Score: %d' % self.warrior.score) score += self.warrior.score UI.puts('Time Bonus: %d' % self.time_bonus) score += self.time_bonus if not self.floor.other_units(): UI.puts('Clear Bonus: %d' % self.clear_bonus()) score += self.clear_bonus() if self.profile.epic: if self.grade_for(score): UI.puts('Level Grade: %s' % self.grade_for(score)) UI.puts( 'Total Score: %s' % self.score_calculation(self.profile.current_epic_score, score)) if self.ace_score: grade = (score / float(self.ace_score)) self.profile.current_epic_grades[self.number] = grade self.profile.current_epic_score += score else: UI.puts('Total Score: %s' % self.score_calculation(self.profile.score, score)) self.profile.score += score self.profile.abilities = self.warrior.abilities.keys()
def play_current_level(self): continue_play = True UI.puts("Starting level %d" % self.current_level().number) self.current_level().play() if self.current_level().is_passed(): if self.next_level().exists(): UI.puts("Success! You have found the stairs.") else: UI.puts("CONGRATULATIONS! You have climbed to the top " "of the tower and rescued the fair maiden Python") continue_play = False self.current_level().tally_points() if self.profile().epic: if self.final_report() and not continue_play: UI.puts(self.final_report()) else: self.request_next_level() else: continue_play = False UI.puts("Sorry, you failed level %d. " "Change your script and try again." % self.current_level().number) if (not Config.skip_input) and self.current_level().clue \ and UI.ask("Would you like to read the " "additional clues for this level?"): UI.puts(self.current_level().clue) return continue_play
def say(self, msg): UI.puts_with_delay("%(name)s %(msg)s" % { 'name': self.name(), 'msg': msg })
def say(self, msg): UI.puts_with_delay("%(name)s %(msg)s" % {'name': self.name(), 'msg': msg})