SHOW:
|
|
- or go back to the newest paste.
| 1 | modify in py.play part: | |
| 2 | elif action == "save": | |
| 3 | if upload_story: | |
| 4 | id = story_manager.story.save_to_local() | |
| 5 | console_print("Game saved.")
| |
| 6 | console_print("To load the game, type 'load' and enter the following ID: " + id)
| |
| 7 | else: | |
| 8 | console_print("Saving has been turned off. Cannot save.")
| |
| 9 | ||
| 10 | elif action =="load": | |
| 11 | load_ID = input("What is the ID of the saved game?")
| |
| 12 | result = story_manager.story.load_from_local(load_ID) | |
| 13 | console_print("\nLoading Game...\n")
| |
| 14 | console_print(result) | |
| 15 | ========================================================================================================================= | |
| 16 | ||
| 17 | modify in the story.maneger part | |
| 18 | ||
| 19 | from story.utils import * | |
| 20 | import json | |
| 21 | import uuid | |
| 22 | from subprocess import Popen | |
| 23 | import subprocess | |
| 24 | import os | |
| 25 | ||
| 26 | class Story(): | |
| 27 | ||
| 28 | def __init__(self, story_start, context ="", seed=None, game_state=None, upload_story=False): | |
| 29 | self.story_start = story_start | |
| 30 | self.context = context | |
| 31 | self.rating = -1 | |
| 32 | self.upload_story = upload_story | |
| 33 | ||
| 34 | # list of actions. First action is the prompt length should always equal that of story blocks | |
| 35 | self.actions = [] | |
| 36 | ||
| 37 | # list of story blocks first story block follows prompt and is intro story | |
| 38 | self.results = [] | |
| 39 | ||
| 40 | # Only needed in constrained/cached version | |
| 41 | self.seed = seed | |
| 42 | self.choices = [] | |
| 43 | self.possible_action_results = None | |
| 44 | self.uuid = None | |
| 45 | ||
| 46 | if game_state is None: | |
| 47 | game_state = dict() | |
| 48 | self.game_state = game_state | |
| 49 | self.memory = 20 | |
| 50 | ||
| 51 | def __del__(self): | |
| 52 | if self.upload_story: | |
| 53 | self.save_to_local() | |
| 54 | console_print("Game saved.")
| |
| 55 | console_print("To load the game, type 'load' and enter the following ID: " + self.uuid)
| |
| 56 | ||
| 57 | ||
| 58 | def init_from_dict(self, story_dict): | |
| 59 | self.story_start = story_dict["story_start"] | |
| 60 | self.seed = story_dict["seed"] | |
| 61 | self.actions = story_dict["actions"] | |
| 62 | self.results = story_dict["results"] | |
| 63 | self.choices = story_dict["choices"] | |
| 64 | self.possible_action_results = story_dict["possible_action_results"] | |
| 65 | self.game_state = story_dict["game_state"] | |
| 66 | self.context = story_dict["context"] | |
| 67 | self.uuid = story_dict["uuid"] | |
| 68 | ||
| 69 | if "rating" in story_dict.keys(): | |
| 70 | self.rating = story_dict["rating"] | |
| 71 | else: | |
| 72 | self.rating = -1 | |
| 73 | ||
| 74 | ||
| 75 | def initialize_from_json(self, json_string): | |
| 76 | story_dict = json.loads(json_string) | |
| 77 | self.init_from_dict(story_dict) | |
| 78 | ||
| 79 | def add_to_story(self, action, story_block): | |
| 80 | self.actions.append(action) | |
| 81 | self.results.append(story_block) | |
| 82 | ||
| 83 | def latest_result(self): | |
| 84 | ||
| 85 | mem_ind = self.memory | |
| 86 | if len(self.results) < 2: | |
| 87 | latest_result = self.story_start | |
| 88 | else: | |
| 89 | latest_result = self.context | |
| 90 | while mem_ind > 0: | |
| 91 | ||
| 92 | if len(self.results) >= mem_ind: | |
| 93 | latest_result += (self.actions[-mem_ind] + self.results[-mem_ind]) | |
| 94 | ||
| 95 | mem_ind -= 1 | |
| 96 | ||
| 97 | return latest_result | |
| 98 | ||
| 99 | def __str__(self): | |
| 100 | story_list = [self.story_start] | |
| 101 | for i in range(len(self.results)): | |
| 102 | story_list.append("\n" + self.actions[i] + "\n")
| |
| 103 | story_list.append("\n" + self.results[i])
| |
| 104 | ||
| 105 | return "".join(story_list) | |
| 106 | ||
| 107 | def to_json(self): | |
| 108 | story_dict = {}
| |
| 109 | story_dict["story_start"] = self.story_start | |
| 110 | story_dict["seed"] = self.seed | |
| 111 | story_dict["actions"] = self.actions | |
| 112 | story_dict["results"] = self.results | |
| 113 | story_dict["choices"] = self.choices | |
| 114 | story_dict["possible_action_results"] = self.possible_action_results | |
| 115 | story_dict["game_state"] = self.game_state | |
| 116 | story_dict["context"] = self.context | |
| 117 | story_dict["uuid"] = self.uuid | |
| 118 | story_dict["rating"] = self.rating | |
| 119 | ||
| 120 | return json.dumps(story_dict) | |
| 121 | ||
| 122 | def save_to_local(self): | |
| 123 | self.uuid = str(uuid.uuid1()) | |
| 124 | story_json = self.to_json() | |
| 125 | file_name = "AIDungeonSave_" + str(self.uuid) + ".json" | |
| 126 | f = open(file_name, "w") | |
| 127 | f.write(story_json) | |
| 128 | f.close() | |
| 129 | return self.uuid | |
| 130 | ||
| 131 | def load_from_local(self, save_name): | |
| 132 | file_name = "AIDungeonSave_" + save_name + ".json" | |
| 133 | exists = os.path.isfile(file_name) | |
| 134 | ||
| 135 | if exists: | |
| 136 | with open(file_name, 'r') as fp: | |
| 137 | game = json.load(fp) | |
| 138 | self.init_from_dict(game) | |
| 139 | return str(self) | |
| 140 | else: | |
| 141 | return "Error save not found." | |
| 142 | ||
| 143 | ||
| 144 | def save_to_storage(self): | |
| 145 | self.uuid = str(uuid.uuid1()) | |
| 146 | ||
| 147 | ||
| 148 | story_json = self.to_json() | |
| 149 | file_name = "story" + str(self.uuid) + ".json" | |
| 150 | f = open(file_name, "w") | |
| 151 | f.write(story_json) | |
| 152 | f.close() | |
| 153 | ||
| 154 | FNULL = open(os.devnull, 'w') | |
| 155 | p = Popen(['gsutil.cmd', 'cp', file_name, 'gs://aidungeonstories'], stdout=FNULL, stderr=subprocess.STDOUT) | |
| 156 | return self.uuid | |
| 157 | ||
| 158 | def load_from_storage(self, story_id): | |
| 159 | ||
| 160 | file_name = "story" + story_id + ".json" | |
| 161 | cmd = "gsutil.cmd cp gs://aidungeonstories/" + file_name + " ." | |
| 162 | os.system(cmd) | |
| 163 | exists = os.path.isfile(file_name) | |
| 164 | ||
| 165 | if exists: | |
| 166 | with open(file_name, 'r') as fp: | |
| 167 | game = json.load(fp) | |
| 168 | self.init_from_dict(game) | |
| 169 | return str(self) | |
| 170 | else: | |
| 171 | return "Error save not found." | |
| 172 | ||
| 173 | ||
| 174 | class StoryManager(): | |
| 175 | ||
| 176 | def __init__(self, generator): | |
| 177 | self.generator = generator | |
| 178 | self.story = None | |
| 179 | ||
| 180 | def start_new_story(self, story_prompt, context="", game_state=None, upload_story=False): | |
| 181 | block = self.generator.generate(context + story_prompt) | |
| 182 | block = cut_trailing_sentence(block) | |
| 183 | self.story = Story(context + story_prompt + block, context=context, game_state=game_state, upload_story=upload_story) | |
| 184 | return self.story | |
| 185 | ||
| 186 | def load_story(self, story, from_json=False): | |
| 187 | if from_json: | |
| 188 | self.story = Story("")
| |
| 189 | self.story.initialize_from_json(story) | |
| 190 | else: | |
| 191 | self.story = story | |
| 192 | return str(story) | |
| 193 | ||
| 194 | def json_story(self): | |
| 195 | return self.story.to_json() | |
| 196 | ||
| 197 | def story_context(self): | |
| 198 | return self.story.latest_result() | |
| 199 | ||
| 200 | ||
| 201 | class UnconstrainedStoryManager(StoryManager): | |
| 202 | ||
| 203 | def act(self, action_choice): | |
| 204 | ||
| 205 | result = self.generate_result(action_choice) | |
| 206 | self.story.add_to_story(action_choice, result) | |
| 207 | return result | |
| 208 | ||
| 209 | def generate_result(self, action): | |
| 210 | block = self.generator.generate(self.story_context() + action) | |
| 211 | return block | |
| 212 | ||
| 213 | ||
| 214 | class ConstrainedStoryManager(StoryManager): | |
| 215 | ||
| 216 | def __init__(self, generator, action_verbs_key="classic"): | |
| 217 | super().__init__(generator) | |
| 218 | self.action_phrases = get_action_verbs(action_verbs_key) | |
| 219 | self.cache = False | |
| 220 | self.cacher = None | |
| 221 | self.seed = None | |
| 222 | ||
| 223 | def enable_caching(self, credentials_file=None, seed=0, bucket_name="dungeon-cache"): | |
| 224 | self.cache = True | |
| 225 | self.cacher = Cacher(credentials_file, bucket_name) | |
| 226 | self.seed = seed | |
| 227 | ||
| 228 | def start_new_story(self, story_prompt, context="", game_state=None): | |
| 229 | if self.cache: | |
| 230 | return self.start_new_story_cache(story_prompt, game_state=game_state) | |
| 231 | else: | |
| 232 | return super().start_new_story(story_prompt, context=context, game_state=game_state) | |
| 233 | ||
| 234 | def start_new_story_generate(self, story_prompt, game_state=None): | |
| 235 | super().start_new_story(story_prompt, game_state=game_state) | |
| 236 | self.story.possible_action_results = self.get_action_results() | |
| 237 | return self.story.story_start | |
| 238 | ||
| 239 | def start_new_story_cache(self, story_prompt, game_state=None): | |
| 240 | ||
| 241 | response = self.cacher.retrieve_from_cache(self.seed, [], "story") | |
| 242 | if response is not None: | |
| 243 | story_start = story_prompt + response | |
| 244 | self.story = Story(story_start, seed=self.seed) | |
| 245 | self.story.possible_action_results = self.get_action_results() | |
| 246 | else: | |
| 247 | story_start = self.start_new_story_generate(story_prompt, game_state=game_state) | |
| 248 | self.story.seed = self.seed | |
| 249 | self.cacher.cache_file(self.seed, [], story_start, "story") | |
| 250 | ||
| 251 | return story_start | |
| 252 | ||
| 253 | def load_story(self, story, from_json=False): | |
| 254 | story_string = super().load_story(story, from_json=from_json) | |
| 255 | return story_string | |
| 256 | ||
| 257 | def get_possible_actions(self): | |
| 258 | if self.story.possible_action_results is None: | |
| 259 | self.story.possible_action_results = self.get_action_results() | |
| 260 | ||
| 261 | return [action_result[0] for action_result in self.story.possible_action_results] | |
| 262 | ||
| 263 | def act(self, action_choice_str): | |
| 264 | ||
| 265 | try: | |
| 266 | action_choice = int(action_choice_str) | |
| 267 | except: | |
| 268 | print("Error invalid choice.")
| |
| 269 | return None, None | |
| 270 | ||
| 271 | if action_choice < 0 or action_choice >= len(self.action_phrases): | |
| 272 | print("Error invalid choice.")
| |
| 273 | return None, None | |
| 274 | ||
| 275 | self.story.choices.append(action_choice) | |
| 276 | action, result = self.story.possible_action_results[action_choice] | |
| 277 | self.story.add_to_story(action, result) | |
| 278 | self.story.possible_action_results = self.get_action_results() | |
| 279 | return result, self.get_possible_actions() | |
| 280 | ||
| 281 | def get_action_results(self): | |
| 282 | if self.cache: | |
| 283 | return self.get_action_results_cache() | |
| 284 | else: | |
| 285 | return self.get_action_results_generate() | |
| 286 | ||
| 287 | def get_action_results_generate(self): | |
| 288 | action_results = [self.generate_action_result(self.story_context(), phrase) for phrase in self.action_phrases] | |
| 289 | return action_results | |
| 290 | ||
| 291 | def get_action_results_cache(self): | |
| 292 | response = self.cacher.retrieve_from_cache(self.story.seed, self.story.choices, "choices") | |
| 293 | ||
| 294 | if response is not None: | |
| 295 | print("Retrieved from cache")
| |
| 296 | return json.loads(response) | |
| 297 | else: | |
| 298 | print("Didn't receive from cache")
| |
| 299 | action_results = self.get_action_results_generate() | |
| 300 | response = json.dumps(action_results) | |
| 301 | self.cacher.cache_file(self.story.seed, self.story.choices, response, "choices") | |
| 302 | return action_results | |
| 303 | ||
| 304 | def generate_action_result(self, prompt, phrase, options=None): | |
| 305 | ||
| 306 | action_result = phrase + " " + self.generator.generate(prompt + " " + phrase, options) | |
| 307 | action, result = split_first_sentence(action_result) | |
| 308 | return action, result |