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 |