Skip to content

Commit 4de1ba6

Browse files
committed
updates on New_event_style after rebasing
1 parent 0c9040f commit 4de1ba6

15 files changed

+8327
-0
lines changed
Lines changed: 382 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,382 @@
1+
"""
2+
.. _simple_game:
3+
4+
A Simple Game
5+
=============
6+
7+
This simple game takes place in a typical house and consists in
8+
finding the right food item and cooking it.
9+
10+
Here's the map of the house.
11+
12+
::
13+
14+
Bathroom
15+
+
16+
|
17+
+
18+
Bedroom +--+ Kitchen +----+ Backyard
19+
+ +
20+
| |
21+
+ +
22+
Living Room Garden
23+
24+
"""
25+
import argparse
26+
from typing import Mapping, Optional
27+
28+
import textworld
29+
from textworld.challenges import register
30+
31+
from textworld import GameOptions
32+
from textworld.generator.game import Quest, EventCondition
33+
34+
from textworld.utils import encode_seeds
35+
36+
37+
def build_argparser(parser=None):
38+
parser = parser or argparse.ArgumentParser()
39+
40+
group = parser.add_argument_group('Simple game settings')
41+
group.add_argument("--rewards", required=True, choices=["dense", "balanced", "sparse"],
42+
help="The reward frequency: dense, balanced, or sparse.")
43+
group.add_argument('--goal', required=True, choices=["detailed", "brief", "none"],
44+
help="The description of the game's objective shown at the beginning of the game:"
45+
" detailed, bried, or none")
46+
group.add_argument('--test', action="store_true",
47+
help="Whether this game should be drawn from the test distributions of games.")
48+
49+
return parser
50+
51+
52+
def make_game(settings: Mapping[str, str], options: Optional[GameOptions] = None) -> textworld.Game:
53+
""" Make a simple game.
54+
55+
Arguments:
56+
settings: Difficulty settings (see notes).
57+
options:
58+
For customizing the game generation (see
59+
:py:class:`textworld.GameOptions <textworld.generator.game.GameOptions>`
60+
for the list of available options).
61+
62+
Returns:
63+
Generated game.
64+
65+
Notes:
66+
The settings that can be provided are:
67+
68+
* rewards : The reward frequency: dense, balanced, or sparse.
69+
* goal : The description of the game's objective shown at the
70+
beginning of the game: detailed, bried, or none.
71+
* test : Whether this game should be drawn from the test
72+
distributions of games.
73+
"""
74+
metadata = {} # Collect infos for reproducibility.
75+
metadata["desc"] = "Simple game"
76+
metadata["seeds"] = options.seeds
77+
metadata["world_size"] = 6
78+
metadata["quest_length"] = None # TBD
79+
80+
rngs = options.rngs
81+
rng_quest = rngs['quest']
82+
83+
# Make the generation process reproducible.
84+
textworld.g_rng.set_seed(2018)
85+
86+
M = textworld.GameMaker(options)
87+
88+
# Start by building the layout of the world.
89+
bedroom = M.new_room("bedroom")
90+
kitchen = M.new_room("kitchen")
91+
livingroom = M.new_room("living room")
92+
bathroom = M.new_room("bathroom")
93+
backyard = M.new_room("backyard")
94+
garden = M.new_room("garden")
95+
96+
# Connect rooms together.
97+
bedroom_kitchen = M.connect(bedroom.east, kitchen.west)
98+
M.connect(kitchen.north, bathroom.south)
99+
M.connect(kitchen.south, livingroom.north)
100+
kitchen_backyard = M.connect(kitchen.east, backyard.west)
101+
M.connect(backyard.south, garden.north)
102+
103+
# Add doors.
104+
bedroom_kitchen.door = M.new(type='d', name='wooden door')
105+
kitchen_backyard.door = M.new(type='d', name='screen door')
106+
107+
kitchen_backyard.door.add_property("closed")
108+
109+
# Design the bedroom.
110+
drawer = M.new(type='c', name='chest drawer')
111+
trunk = M.new(type='c', name='antique trunk')
112+
bed = M.new(type='s', name='king-size bed')
113+
bedroom.add(drawer, trunk, bed)
114+
115+
# Close the trunk and drawer.
116+
trunk.add_property("closed")
117+
drawer.add_property("closed")
118+
119+
# - The bedroom's door is locked
120+
bedroom_kitchen.door.add_property("locked")
121+
122+
# Design the kitchen.
123+
counter = M.new(type='s', name='counter')
124+
stove = M.new(type='s', name='stove')
125+
kitchen_island = M.new(type='s', name='kitchen island')
126+
refrigerator = M.new(type='c', name='refrigerator')
127+
kitchen.add(counter, stove, kitchen_island, refrigerator)
128+
129+
# - Add some food in the refrigerator.
130+
apple = M.new(type='f', name='apple')
131+
milk = M.new(type='f', name='milk')
132+
refrigerator.add(apple, milk)
133+
134+
# Design the bathroom.
135+
toilet = M.new(type='c', name='toilet')
136+
sink = M.new(type='s', name='sink')
137+
bath = M.new(type='c', name='bath')
138+
bathroom.add(toilet, sink, bath)
139+
140+
toothbrush = M.new(type='o', name='toothbrush')
141+
sink.add(toothbrush)
142+
soap_bar = M.new(type='o', name='soap bar')
143+
bath.add(soap_bar)
144+
145+
# Design the living room.
146+
couch = M.new(type='s', name='couch')
147+
low_table = M.new(type='s', name='low table')
148+
tv = M.new(type='s', name='tv')
149+
livingroom.add(couch, low_table, tv)
150+
151+
remote = M.new(type='o', name='remote')
152+
low_table.add(remote)
153+
bag_of_chips = M.new(type='f', name='half of a bag of chips')
154+
couch.add(bag_of_chips)
155+
156+
# Design backyard.
157+
bbq = M.new(type='s', name='bbq')
158+
patio_table = M.new(type='s', name='patio table')
159+
chairs = M.new(type='s', name='set of chairs')
160+
backyard.add(bbq, patio_table, chairs)
161+
162+
# Design garden.
163+
shovel = M.new(type='o', name='shovel')
164+
tomato = M.new(type='f', name='tomato plant')
165+
pepper = M.new(type='f', name='bell pepper')
166+
lettuce = M.new(type='f', name='lettuce')
167+
garden.add(shovel, tomato, pepper, lettuce)
168+
169+
# Close all containers
170+
for container in M.findall(type='c'):
171+
container.add_property("closed")
172+
173+
# Set uncooked property for to all food items.
174+
foods = M.findall(type='f')
175+
for food in foods:
176+
food.add_property("edible")
177+
178+
food_names = [food.name for food in foods]
179+
180+
# Shuffle the position of the food items.
181+
rng_quest.shuffle(food_names)
182+
183+
for food, name in zip(foods, food_names):
184+
food.orig_name = food.name
185+
food.infos.name = name
186+
187+
# The player starts in the bedroom.
188+
M.set_player(bedroom)
189+
190+
# Quest
191+
walkthrough = []
192+
193+
# Part I - Escaping the room.
194+
# Generate the key that unlocks the bedroom door.
195+
bedroom_key = M.new(type='k', name='old key')
196+
M.add_fact("match", bedroom_key, bedroom_kitchen.door)
197+
198+
# Decide where to hide the key.
199+
if rng_quest.rand() > 0.5:
200+
drawer.add(bedroom_key)
201+
walkthrough.append("open chest drawer")
202+
walkthrough.append("take old key from chest drawer")
203+
bedroom_key_holder = drawer
204+
else:
205+
trunk.add(bedroom_key)
206+
walkthrough.append("open antique trunk")
207+
walkthrough.append("take old key from antique trunk")
208+
bedroom_key_holder = trunk
209+
210+
# Unlock the door, open it and leave the room.
211+
walkthrough.append("unlock wooden door with old key")
212+
walkthrough.append("open wooden door")
213+
walkthrough.append("go east")
214+
215+
# Part II - Find food item.
216+
# 1. Randomly pick a food item to cook.
217+
food = rng_quest.choice(foods)
218+
219+
if settings["test"]:
220+
TEST_FOODS = ["garlic", "kiwi", "carrot"]
221+
food.infos.name = rng_quest.choice(TEST_FOODS)
222+
223+
# Retrieve the food item and get back in the kitchen.
224+
# HACK: handcrafting the walkthrough.
225+
if food.orig_name in ["apple", "milk"]:
226+
rooms_to_visit = []
227+
doors_to_open = []
228+
walkthrough.append("open refrigerator")
229+
walkthrough.append("take {} from refrigerator".format(food.name))
230+
elif food.orig_name == "half of a bag of chips":
231+
rooms_to_visit = [livingroom]
232+
doors_to_open = []
233+
walkthrough.append("go south")
234+
walkthrough.append("take {} from couch".format(food.name))
235+
walkthrough.append("go north")
236+
elif food.orig_name in ["bell pepper", "lettuce", "tomato plant"]:
237+
rooms_to_visit = [backyard, garden]
238+
doors_to_open = [kitchen_backyard.door]
239+
walkthrough.append("open screen door")
240+
walkthrough.append("go east")
241+
walkthrough.append("go south")
242+
walkthrough.append("take {}".format(food.name))
243+
walkthrough.append("go north")
244+
walkthrough.append("go west")
245+
246+
# Part II - Cooking the food item.
247+
walkthrough.append("put {} on stove".format(food.name))
248+
# walkthrough.append("cook {}".format(food.name))
249+
# walkthrough.append("eat {}".format(food.name))
250+
251+
# 2. Determine the winning condition(s) of the subgoals.
252+
quests = []
253+
bedroom_key_holder
254+
255+
if settings["rewards"] == "dense":
256+
# Finding the bedroom key and opening the bedroom door.
257+
# 1. Opening the container.
258+
quests.append(
259+
Quest(win_events=[
260+
EventCondition(conditions={M.new_fact("open", bedroom_key_holder)})
261+
])
262+
)
263+
264+
# 2. Getting the key.
265+
quests.append(
266+
Quest(win_events=[
267+
EventCondition(conditions={M.new_fact("in", bedroom_key, M.inventory)})
268+
])
269+
)
270+
271+
# 3. Unlocking the bedroom door.
272+
quests.append(
273+
Quest(win_events=[
274+
EventCondition(conditions={M.new_fact("closed", bedroom_kitchen.door)})
275+
])
276+
)
277+
278+
# 4. Opening the bedroom door.
279+
quests.append(
280+
Quest(win_events=[
281+
EventCondition(conditions={M.new_fact("open", bedroom_kitchen.door)})
282+
])
283+
)
284+
285+
if settings["rewards"] in ["dense", "balanced"]:
286+
# Escaping out of the bedroom.
287+
quests.append(
288+
Quest(win_events=[
289+
EventCondition(conditions={M.new_fact("at", M.player, kitchen)})
290+
])
291+
)
292+
293+
if settings["rewards"] in ["dense", "balanced"]:
294+
# Opening doors.
295+
for door in doors_to_open:
296+
quests.append(
297+
Quest(win_events=[
298+
EventCondition(conditions={M.new_fact("open", door)})
299+
])
300+
)
301+
302+
if settings["rewards"] == "dense":
303+
# Moving through places.
304+
for room in rooms_to_visit:
305+
quests.append(
306+
Quest(win_events=[
307+
EventCondition(conditions={M.new_fact("at", M.player, room)})
308+
])
309+
)
310+
311+
if settings["rewards"] in ["dense", "balanced"]:
312+
# Retrieving the food item.
313+
quests.append(
314+
Quest(win_events=[
315+
EventCondition(conditions={M.new_fact("in", food, M.inventory)})
316+
])
317+
)
318+
319+
<<<<<<< HEAD
320+
=======
321+
322+
if settings["rewards"] in ["dense", "balanced"]:
323+
# Retrieving the food item.
324+
quests.append(
325+
Quest(win_events=[
326+
EventCondition(conditions={M.new_fact("in", food, M.inventory)})
327+
])
328+
)
329+
330+
>>>>>>> acf2275... The new style of TRACEABLE PROPOSITIONS and comprehenssive updates to adapt the new Predicate, Proposition, & Signature styles. This new framework can track a proposition through the time.
331+
if settings["rewards"] in ["dense", "balanced", "sparse"]:
332+
# Putting the food on the stove.
333+
quests.append(
334+
Quest(win_events=[
335+
EventCondition(conditions={M.new_fact("on", food, stove)})
336+
])
337+
)
338+
339+
# 3. Determine the losing condition(s) of the game.
340+
quests.append(
341+
Quest(fail_events=[
342+
EventCondition(conditions={M.new_fact("eaten", food)})
343+
])
344+
)
345+
346+
# Set the subquest(s).
347+
M.quests = quests
348+
349+
# - Add a hint of what needs to be done in this game.
350+
objective = "The dinner is almost ready! It's only missing a grilled {}."
351+
objective = objective.format(food.name)
352+
note = M.new(type='o', name='note', desc=objective)
353+
kitchen_island.add(note)
354+
355+
M.set_walkthrough(walkthrough)
356+
game = M.build()
357+
358+
if settings["goal"] == "detailed":
359+
# Use the detailed version of the objective.
360+
pass
361+
elif settings["goal"] == "brief":
362+
# Use a very high-level description of the objective.
363+
game.objective = objective
364+
elif settings["goal"] == "none":
365+
# No description of the objective.
366+
game.objective = ""
367+
368+
game.metadata.update(metadata)
369+
uuid = "tw-simple-r{rewards}+g{goal}+{dataset}-{flags}-{seeds}"
370+
uuid = uuid.format(rewards=str.title(settings["rewards"]), goal=str.title(settings["goal"]),
371+
dataset="test" if settings["test"] else "train",
372+
flags=options.grammar.uuid,
373+
seeds=encode_seeds([options.seeds[k] for k in sorted(options.seeds)]))
374+
game.metadata["uuid"] = uuid
375+
return game
376+
377+
378+
# Register this simple game.
379+
register(name="tw-simple",
380+
desc="Generate simple challenge game",
381+
make=make_game,
382+
add_arguments=build_argparser)

0 commit comments

Comments
 (0)