Skip to content

Commit 92edc7c

Browse files
committed
Adding GameOptions and the notion of extra_info, i.e. commands that are issued at every step
1 parent 4a8d333 commit 92edc7c

30 files changed

+713
-460
lines changed

scripts/tw-make

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
# Copyright (c) Microsoft Corporation. All rights reserved.
44
# Licensed under the MIT license.
55

6-
6+
import os
77
import argparse
8+
from os.path import join as pjoin
9+
810
import numpy as np
911

1012
import textworld
@@ -14,8 +16,8 @@ def parse_args():
1416
general_parser = argparse.ArgumentParser(add_help=False)
1517

1618
general_group = general_parser.add_argument_group('General settings')
17-
general_group.add_argument("--output", default="./gen_games/", metavar="PATH",
18-
help="Output folder to save generated game files.")
19+
general_group.add_argument("--output", default="./tw_games/", metavar="PATH",
20+
help="Path where to save the generated game.")
1921
general_group.add_argument('--seed', type=int)
2022
general_group.add_argument("--view", action="store_true",
2123
help="Display the resulting game.")
@@ -64,18 +66,21 @@ if __name__ == "__main__":
6466

6567
print("Global seed: {}".format(args.seed))
6668

67-
grammar_flags = {
68-
"theme": args.theme,
69-
"include_adj": args.include_adj,
70-
"only_last_action": args.only_last_action,
71-
"blend_instructions": args.blend_instructions,
72-
"blend_descriptions": args.blend_descriptions,
73-
"ambiguous_instructions": args.ambiguous_instructions,
74-
}
69+
options = textworld.GameOptions()
70+
options.grammar_options.theme = args.theme
71+
options.grammar_options.include_adj = args.include_adj
72+
options.grammar_options.only_last_action = args.only_last_action
73+
options.grammar_options.blend_instructions = args.blend_instructions
74+
options.grammar_options.blend_descriptions = args.blend_descriptions
75+
options.grammar_options.ambiguous_instructions = args.ambiguous_instructions
7576

7677
if args.subcommand == "custom":
77-
game_file, game = textworld.make(args.world_size, args.nb_objects, args.quest_length, args.quest_breadth, grammar_flags,
78-
seed=args.seed, games_dir=args.output)
78+
options.nb_rooms = args.world_size
79+
options.nb_objects = args.nb_objects
80+
options.quest_length = args.quest_length
81+
options.quest_breadth = args.quest_breadth
82+
options.seeds = args.seed
83+
game_file, game = textworld.make(options, args.output)
7984

8085
elif args.subcommand == "challenge":
8186
_, challenge, level = args.challenge.split("-")
@@ -84,8 +89,8 @@ if __name__ == "__main__":
8489

8590
level = int(level.lstrip("level"))
8691
make_game = textworld.challenges.CHALLENGES[challenge]
87-
game = make_game(level=level, grammar_flags=grammar_flags, seeds=args.seed)
88-
game_file = textworld.generator.compile_game(game, games_folder=args.output)
92+
game = make_game(level, options)
93+
game_file = textworld.generator.compile_game(game, args.output)
8994

9095
print("Game generated: {}".format(game_file))
9196
if args.verbose:

scripts_dev/benchmark_framework.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,36 @@
11
# Copyright (c) Microsoft Corporation. All rights reserved.
22
# Licensed under the MIT license.
33

4-
54
import time
65
import argparse
6+
from os.path import join as pjoin
77

88
import textworld
99
from textworld import g_rng
1010
from textworld.generator import World
1111

12+
from textworld.generator.game import GameOptions
13+
1214

1315
def generate_never_ending_game(args):
1416
g_rng.set_seed(args.seed)
1517
msg = "--max-steps {} --nb-objects {} --nb-rooms {} --quest-length {} --quest-breadth {} --seed {}"
1618
print(msg.format(args.max_steps, args.nb_objects, args.nb_rooms, args.quest_length, args.quest_breadth, g_rng.seed))
1719
print("Generating game...")
1820

19-
grammar_flags = {}
20-
game = textworld.generator.make_game(args.nb_rooms, args.nb_objects, args.quest_length, args.quest_breadth, grammar_flags)
21+
options = GameOptions()
22+
options.nb_rooms = args.nb_rooms
23+
options.nb_objects = args.nb_objects
24+
options.quest_length = args.quest_length
25+
options.quest_breadth = args.quest_breadth
26+
27+
game = textworld.generator.make_game(options)
2128
if args.no_quest:
2229
game.quests = []
2330

2431
game_name = "neverending"
25-
game_file = textworld.generator.compile_game(game, game_name, force_recompile=True, games_folder=args.output)
32+
path = pjoin(args.output, game_name + ".ulx")
33+
game_file = textworld.generator.compile_game(game, path, force_recompile=True)
2634
return game_file
2735

2836

@@ -59,7 +67,7 @@ def benchmark(game_file, args):
5967
game_state, reward, done = env.step(command)
6068

6169
if done:
62-
print("Win! Reset.")
70+
#print("Win! Reset.")
6371
env.reset()
6472
done = False
6573

tests/test_make_game.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,34 @@ def test_making_game_with_names_to_exclude():
1111
g_rng.set_seed(42)
1212

1313
with make_temp_directory(prefix="test_render_wrapper") as tmpdir:
14-
game_file1, game1 = textworld.make(2, 20, 3, 3, {"names_to_exclude": []},
15-
seed=123, games_dir=tmpdir)
16-
14+
options = textworld.GameOptions()
15+
options.nb_rooms = 2
16+
options.nb_objects = 20
17+
options.quest_length = 3
18+
options.quest_breadth = 3
19+
options.seeds = 123
20+
game_file1, game1 = textworld.make(options, path=tmpdir)
21+
22+
options2 = options.copy()
1723
game1_objects_names = [info.name for info in game1.infos.values() if info.name is not None]
18-
game_file2, game2 = textworld.make(2, 20, 3, 3, {"names_to_exclude": game1_objects_names},
19-
seed=123, games_dir=tmpdir)
24+
options2.grammar_options.names_to_exclude = game1_objects_names
25+
game_file2, game2 = textworld.make(options2, path=tmpdir)
2026
game2_objects_names = [info.name for info in game2.infos.values() if info.name is not None]
2127
assert len(set(game1_objects_names) & set(game2_objects_names)) == 0
2228

2329

2430
def test_making_game_is_reproducible_with_seed():
25-
grammar_flags = {}
2631
with make_temp_directory(prefix="test_render_wrapper") as tmpdir:
27-
game_file1, game1 = textworld.make(2, 20, 3, 3, grammar_flags, seed=123, games_dir=tmpdir)
28-
game_file2, game2 = textworld.make(2, 20, 3, 3, grammar_flags, seed=123, games_dir=tmpdir)
32+
options = textworld.GameOptions()
33+
options.nb_rooms = 2
34+
options.nb_objects = 20
35+
options.quest_length = 3
36+
options.quest_breadth = 3
37+
options.seeds = 123
38+
39+
game_file1, game1 = textworld.make(options, path=tmpdir)
40+
options2 = options.copy()
41+
game_file2, game2 = textworld.make(options2, path=tmpdir)
2942
assert game_file1 == game_file2
3043
assert game1 == game2
3144
# Make sure they are not the same Python objects.

tests/test_play_generated_games.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,15 @@ def test_play_generated_games():
1919
quest_length = rng.randint(2, 5)
2020
quest_breadth = rng.randint(3, 7)
2121
game_seed = rng.randint(0, 65365)
22-
grammar_flags = {} # Default grammar.
2322

2423
with make_temp_directory(prefix="test_play_generated_games") as tmpdir:
25-
game_file, game = textworld.make(world_size, nb_objects, quest_length, quest_breadth, grammar_flags,
26-
seed=game_seed, games_dir=tmpdir)
24+
options = textworld.GameOptions()
25+
options.nb_rooms = world_size
26+
options.nb_objects = nb_objects
27+
options.quest_length = quest_length
28+
options.quest_breadth = quest_breadth
29+
options.seeds = game_seed
30+
game_file, game = textworld.make(options, path=tmpdir)
2731

2832
# Solve the game using WalkthroughAgent.
2933
agent = textworld.agents.WalkthroughAgent()

tests/test_textworld.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@ class TestIntegration(unittest.TestCase):
1414

1515
def setUp(self):
1616
self.tmpdir = tempfile.mkdtemp(prefix="test_textworld")
17-
self.game_file, self.game = textworld.make(world_size=5, nb_objects=10,
18-
quest_length=10, grammar_flags={},
19-
seed=1234, games_dir=self.tmpdir)
17+
options = textworld.GameOptions()
18+
options.nb_rooms = 5
19+
options.nb_objects = 10
20+
options.quest_length = 10
21+
options.seeds = 1234
22+
self.game_file, self.game = textworld.make(options, path=self.tmpdir)
2023

2124
def tearDown(self):
2225
shutil.rmtree(self.tmpdir)

tests/test_tw-make.py

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# Licensed under the MIT license.
33

44
import os
5+
import glob
56
from subprocess import check_call
67
from os.path import join as pjoin
78

@@ -11,15 +12,51 @@
1112

1213

1314
def test_making_a_custom_game():
14-
with make_temp_directory(prefix="test_tw-make") as tmpdir:
15+
with make_temp_directory(prefix="test_tw-make") as tmpdir:
1516
output_folder = pjoin(tmpdir, "gen_games")
16-
command = ["tw-make", "custom", "--seed", "1234", "--output", output_folder]
17+
game_file = pjoin(output_folder, "game_1234.ulx")
18+
command = ["tw-make", "custom", "--seed", "1234", "--output", game_file]
1719
assert check_call(command) == 0
1820

1921
assert os.path.isdir(output_folder)
20-
game_file = pjoin(output_folder, "game_1234.ulx")
2122
assert os.path.isfile(game_file)
2223

2324
# Solve the game using WalkthroughAgent.
2425
agent = textworld.agents.WalkthroughAgent()
2526
textworld.play(game_file, agent=agent, silent=True)
27+
28+
with make_temp_directory(prefix="test_tw-make") as tmpdir:
29+
output_folder = pjoin(tmpdir, "gen_games")
30+
game_file = pjoin(output_folder, "game_1234") # Default extension is .ulx
31+
command = ["tw-make", "custom", "--seed", "1234", "--output", game_file]
32+
assert check_call(command) == 0
33+
34+
assert os.path.isdir(output_folder)
35+
assert os.path.isfile(game_file + ".ulx")
36+
37+
# Solve the game using WalkthroughAgent.
38+
agent = textworld.agents.WalkthroughAgent()
39+
textworld.play(game_file + ".ulx", agent=agent, silent=True)
40+
41+
with make_temp_directory(prefix="test_tw-make") as tmpdir:
42+
output_folder = pjoin(tmpdir, "gen_games", "")
43+
command = ["tw-make", "custom", "--seed", "1234", "--output", output_folder]
44+
assert check_call(command) == 0
45+
46+
assert os.path.isdir(output_folder)
47+
game_file = glob.glob(pjoin(output_folder, "*.ulx"))[0]
48+
49+
# Solve the game using WalkthroughAgent.
50+
agent = textworld.agents.WalkthroughAgent()
51+
textworld.play(game_file, agent=agent, silent=True)
52+
53+
with make_temp_directory(prefix="test_tw-make") as tmpdir:
54+
output_folder = pjoin(tmpdir, "gen_games")
55+
command = ["tw-make", "custom", "--seed", "1234", "--output", output_folder]
56+
assert check_call(command) == 0
57+
58+
assert os.path.isfile(output_folder + ".ulx")
59+
60+
# Solve the game using WalkthroughAgent.
61+
agent = textworld.agents.WalkthroughAgent()
62+
textworld.play(output_folder + ".ulx", agent=agent, silent=True)

tests/test_tw-play.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@
99

1010
def test_playing_a_game():
1111
with make_temp_directory(prefix="test_tw-play") as tmpdir:
12-
game_file, _ = textworld.make(5, 10, 5, 4, {}, seed=1234, games_dir=tmpdir)
12+
options = textworld.GameOptions()
13+
options.nb_rooms = 5
14+
options.nb_objects = 10
15+
options.quest_length = 5
16+
options.quest_breadth = 4
17+
options.seeds = 1234
18+
game_file, _ = textworld.make(options, path=tmpdir)
1319

1420
command = ["tw-play", "--max-steps", "100", "--mode", "random", game_file]
1521
assert check_call(command) == 0

textworld/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from textworld.utils import g_rng
77

88
from textworld.core import Environment, GameState, Agent
9-
from textworld.generator import Game, GameMaker
9+
from textworld.generator import Game, GameMaker, GameOptions
1010

1111
from textworld.generator import TextworldGenerationWarning
1212

0 commit comments

Comments
 (0)