From 4a8a0482a5902cfc55b9d78cb4884c56de45f89c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Elio=20Petten=C3=B2?= Date: Thu, 4 Nov 2021 09:35:49 +0000 Subject: [PATCH] Avoid using locally-defined callbacks for `yesno`. Since most of the callbacks do not rely on the local variables at all, there's little value in using locally defined callbacks over instance methods. This enables the ability to save and restore the state of the game even in the middle of a question (including the initial "WOULD YOU LIKE INSTRUCTIONS?") While this is not generally possible in the normal play, this change enables using this implementation of python-adventure in ephemeral environments where players bring their own state. --- adventure/game.py | 125 +++++++++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 62 deletions(-) diff --git a/adventure/game.py b/adventure/game.py index 5ac0610..935d3f1 100644 --- a/adventure/game.py +++ b/adventure/game.py @@ -410,15 +410,9 @@ def finish_turn(self, obj=None): #2600 hint.turn_counter = 0 if self.should_offer_hint(hint, obj): hint.turn_counter = 0 + self.current_hint = hint - def callback(yes): - if yes: - self.write(hint.message) - hint.used = True - else: - self.write_message(54) - - self.yesno(hint.question, callback) + self.yesno(hint.question, self.hint_callback) return else: hint.turn_counter = 0 @@ -434,6 +428,14 @@ def callback(yes): if self.knife_location and self.knife_location is not self.loc: self.knife_location = None + def hint_callback(self, yes): + if yes: + self.write(self.current_hint.message) + self.current_hint.used = True + else: + self.write_message(54) + self.current_hint = None + # The central do_command() method, that should be called over and # over again with words supplied by the user. @@ -794,28 +796,28 @@ def die(self): #99 self.score_and_exit() return - def callback(yes): - if yes: - self.write_message(80 + self.deaths * 2) - if self.deaths < self.max_deaths: - if self.bottle.contents is not None: - self.bottle.contents.hide() - self.is_dead = False - if self.lamp.is_toting: - self.lamp.prop = 0 - for obj in self.inventory: - if obj is self.lamp: - obj.drop(self.rooms[1]) - else: - obj.drop(self.oldloc2) - self.loc = self.rooms[3] - self.describe_location() - return - else: - self.write_message(54) - self.score_and_exit() + self.yesno(self.messages[79 + self.deaths * 2], self.dead_callback) - self.yesno(self.messages[79 + self.deaths * 2], callback) + def dead_callback(self, yes): + if yes: + self.write_message(80 + self.deaths * 2) + if self.deaths < self.max_deaths: + if self.bottle.contents is not None: + self.bottle.contents.hide() + self.is_dead = False + if self.lamp.is_toting: + self.lamp.prop = 0 + for obj in self.inventory: + if obj is self.lamp: + obj.drop(self.rooms[1]) + else: + obj.drop(self.oldloc2) + self.loc = self.rooms[3] + self.describe_location() + return + else: + self.write_message(54) + self.score_and_exit() # Verbs. @@ -1153,22 +1155,7 @@ def t_attack(self, verb, obj): #9124 (but control goes to 9120 first) if self.dragon.prop != 0: self.write_message(167) else: - def callback(yes): - self.write(obj.messages[1]) - obj.prop = 2 - obj.is_fixed = True - oldroom1 = obj.rooms[0] - oldroom2 = obj.rooms[1] - newroom = self.rooms[ (oldroom1.n + oldroom2.n) // 2 ] - obj.drop(newroom) - self.rug.prop = 0 - self.rug.is_fixed = False - self.rug.drop(newroom) - for oldroom in (oldroom1, oldroom2): - for o in self.objects_at(oldroom): - o.drop(newroom) - self.move_to(newroom) - self.yesno(self.messages[49], callback, casual=True) + self.yesno(self.messages[49], self.dragon_callback, casual=True) return elif obj is self.troll: self.write_message(157) @@ -1178,6 +1165,22 @@ def callback(yes): self.write_message(44) self.finish_turn() + def dragon_callback(self, yes): + self.write(self.dragon.messages[1]) + self.dragon.prop = 2 + self.dragon.is_fixed = True + oldroom1 = self.dragon.rooms[0] + oldroom2 = self.dragon.rooms[1] + newroom = self.rooms[ (oldroom1.n + oldroom2.n) // 2 ] + self.dragon.drop(newroom) + self.rug.prop = 0 + self.rug.is_fixed = False + self.rug.drop(newroom) + for oldroom in (oldroom1, oldroom2): + for o in self.objects_at(oldroom): + o.drop(newroom) + self.move_to(newroom) + def i_pour(self, verb): #9130 if self.bottle.contents is None: self.ask_verb_what(verb) @@ -1319,11 +1322,12 @@ def t_throw(self, verb, obj): #9170 self.t_attack(verb, None) def i_quit(self, verb): #8180 - def callback(yes): - self.write_message(54) - if yes: - self.score_and_exit() - self.yesno(self.messages[22], callback) + self.yesno(self.messages[22], self.quit_callback) + + def quit_callback(self, yes): + self.write_message(54) + if yes: + self.score_and_exit() def t_find(self, verb, obj): #9190 if obj.is_toting: @@ -1453,11 +1457,7 @@ def i_score(self, verb): #8240 score, max_score = self.compute_score(for_score_command=True) self.write('If you were to quit now, you would score {}' ' out of a possible {}.\n'.format(score, max_score)) - def callback(yes): - self.write_message(54) - if yes: - self.score_and_exit() - self.yesno(self.messages[143], callback) + self.yesno(self.messages[143], self.quit_callback) def i_fee(self, verb): #8250 for n in range(5): @@ -1511,13 +1511,7 @@ def t_read(self, verb, obj): #9270 return self.i_see_no(obj.names[0]) elif (obj is self.oyster and not self.hints[2].used and self.oyster.is_toting): - def callback(yes): - if yes: - self.hints[2].used = True - self.write_message(193) - else: - self.write_message(54) - self.yesno(self.messages[192], callback) + self.yesno(self.messages[192], self.oyster_callback) elif obj is self.oyster and self.hints[2].used: self.write_message(194) elif obj is self.message: @@ -1530,6 +1524,13 @@ def callback(yes): self.write(verb.default_message) self.finish_turn() + def oyster_callback(self, yes): + if yes: + self.hints[2].used = True + self.write_message(193) + else: + self.write_message(54) + def t_break(self, verb, obj): #9280 if obj is self.vase and self.vase.prop == 0: self.write_message(198)