Skip to content

Commit c61a739

Browse files
committed
Merge in the logic docs from microsoft#186
1 parent 3a25b39 commit c61a739

File tree

6 files changed

+704
-0
lines changed

6 files changed

+704
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,5 @@ tmp/*
2525
/dist
2626
/wheelhouse
2727
tw_games/
28+
docs/build/
29+
docs/src/
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
Chapter 3 : How To Design A New Game
2+
==============================================
3+
To design a new game, TextWorld framework provides a library to make a game called `GameMaker`. This library requires
4+
to use game logic and text grammar files which we already discussed about them in previous two chapters. By default,
5+
it employs the built-in versions of these two files. If the new design of the game requires the customized version of
6+
them, they should be addressed and imported to the GameMaker. Thus, the first action, needs to be taken, is importation
7+
of the path in which the customized files are stored. The following three lines of code provide this information for
8+
GameMaker library.
9+
10+
.. code-block:: bash
11+
12+
from textworld.generator.data import KnowledgeBase
13+
14+
PATH = pjoin(os.path.dirname(__file__), 'textworld_data')
15+
kb = KnowledgeBase.load(target_dir=PATH)
16+
17+
To handcraft a new game, the next is to create an object of GameMaker and start creating rooms and elements of the game.
18+
Assume that our handcrafting game is happening in a spaceship and includes two rooms and there is two doors in the game,
19+
one connects these two rooms and one is on the second room opening to outside (nowhere in this scenario). The `player`
20+
is in the first room and both doors are locked. There is a key and a push button matched with each of these doors. The
21+
goal of the game is to find the keys and go out from the second room. The two rooms and the doors are added to the
22+
world by following block of codes.
23+
24+
.. code-block:: bash
25+
26+
from textworld import GameMaker
27+
28+
# ===== World, Rooms, and Doors Design =============================================================================
29+
gm = GameMaker(kb=kb, theme='Spaceship')
30+
room_1 = gm.new_room("Sleep Station")
31+
room_2 = gm.new_room("Control Room")
32+
room_3 = gm.new_room("Space")
33+
34+
corridor1 = gm.connect(room_1.east, room_2.west)
35+
doorA = gm.new_door(corridor1, name="door A")
36+
gm.add_fact("locked", doorA) # Add a fact about the door, e.g. here it is locked.
37+
38+
corridor2 = gm.connect(room_2.east, room_3.west)
39+
doorB = gm.new_door(corridor2, name="door B")
40+
gm.add_fact("locked", doorB)
41+
42+
which the `new_room` method is designed to create and add a room to the world; the assigned name of the room should be
43+
imported to the method. `Connect` method is used to connect two rooms to each other. The two inputs of this method
44+
are those rooms which are connected in addition to the direction that the connection is occurred; e.g. here room_1 is
45+
connected to room_2 from its "east" side. If there is a door between two rooms, i.e. the connection includes a door;
46+
`new_door` defines this door and asks to describe the location of the door and its name. The final step is adding the
47+
initial state (i.e. fact) of the door to the game, by using `add_fact`. Facts are basically the state of each element
48+
when the game starts.
49+
50+
Now, let's define a key and a table in the Sleep station, in which the key is on the table and it is matched with door
51+
A. The method to create both of these elements is `new`. In this method, the type of new element is defined according
52+
to the type definition of the corresponding element at logic files (.twl file). Also, if the designer wants to add some
53+
description to the element it can add it by the `.info.desc` code. This description is displayed any time that the
54+
player imports `look {.}` command. The newly created item should be located somewhere at the world and if it requires
55+
initial state setup, that is defined as well (see `add` and `add_fact` methods). Look the following example
56+
57+
.. code-block:: bash
58+
59+
# ===== Box and Key Design =========================================================================================
60+
table = gm.new(type='s') # Table is a supporter which is fixed in place in the Sleep Station.
61+
table.infos.desc = "It is a metal sturdy table."
62+
room_1.add(table)
63+
64+
key = gm.new(type='k', name="electronic key")
65+
key.infos.desc = "This key opens the door into the control room area."
66+
table.add(key)
67+
68+
gm.add_fact("match", key, doorA) # Tell the game 'Electronic key' is matching with door A's lock
69+
70+
From above code, the key is similarly designed and it is on the table. The key and its corresponding door should be
71+
defined by `add_fact` function again, while the fact is `match`, be advised that match fact accepts two inputs. as a
72+
recall, we defined `on(o, s)` as a predicate which means the object is on the supporter (table here), since the key is
73+
defined as a sub-category of object, the `table.add(key)` syntax models this predicate. For the push button, we assume
74+
that it is in room_2. As we observed so far, adding a push button is similar to the rest and just requires `new` method.
75+
76+
.. code-block:: bash
77+
78+
# ===== Push Button Design =========================================================================================
79+
push_button = gm.new(type='b', name="exit push button")
80+
push_button.infos.desc = "This push button is a an object which opens door B."\
81+
"This push button is installed on the wall at the control room."
82+
gm.add_fact("unpushed", push_button)
83+
room_2.add(push_button)
84+
85+
The player and its inventory are also two important parts of the world which should be defined for the game. If the
86+
designer doesn't define where the player is, then the game will put it automatically at the first designed room. When a
87+
player is set by `set_player` command its location is assigned. The graphical representation of the world is also
88+
available by using `render` method. We recommend the readers of this tutorial, to check all above mentioned methods to
89+
find out more details of how they can be employed more flexible within the design of a new game. The last but not least,
90+
the `quest_record` method compiles the new game, generates the world, and starts the game to play. At each state the game,
91+
the player can see the description of the scene and all the corresponding avaialble actions which transforms the player
92+
to another state.
93+
94+
.. code-block:: bash
95+
96+
# ===== Player and Inventory Design ================================================================================
97+
gm.set_player(room_1)
98+
99+
gm.render(interactive=True)
100+
101+
gm.record_quest()
102+
103+
The visualization of this game is illustrated at below figure,
104+
105+
.. |game_sample| image:: ./images/GameDesign.png
106+
:alt: Game version
107+
108+
+------------------+
109+
| |game_sample| |
110+
+==================+
111+
| Game |
112+
+------------------+
113+
114+
This tutorial tried to shed a light to Textworld framework and elaborates how new games can be handcrafted using this
115+
framework and cooperate with the customized logic and grammar files.
116+
For further questions please communicate with the technical team of TextWorld project at Microsoft, via ...
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
Chapter 2 : How To Design A New Text Grammar
2+
==============================================
3+
In addition to logic files, each game requires a grammar file in which it describes various sentences to be used within
4+
the game. For example, when the player enters a room, a few lines of the greetings to the game, introduction of the
5+
room, the items inside the room, etc. are displayed for the player. This text is compiled by a word parser at Inform7
6+
using a customized text-grammar file. This file also should be designed by the designer of the game and stored with
7+
`.twg` extension.
8+
9+
To describe this file, it is better to start with greetings. Greetings is a set of various sentences which will be
10+
picked by the parser randomly and will be displayed on output anytime the player either enters into the game or enters
11+
into a room. The greeting should include a general description about the state of the game, the room, or the current
12+
elements of the game. If the generated sentence requires importation of elements or status of the game, that should
13+
also be coded into the sentence. The question is how? Here, we practice writing such sentences.
14+
15+
Let's first explore a fixed type of greetings.
16+
17+
.. code-block:: bash
18+
19+
GREETING : GREETING!;GREETINGS TREKKIE!;HELLO ASTRONAUT!;ALRIGHT THEN!; HEY TREKKIE
20+
21+
Here, `GREETING` is the code to call the greeting sentence and the right side of semicolon is an array-like of different
22+
options that the parser can pick between them; e.g. in above example, there are five different options and each time the
23+
parser randomly picks one of them as the greeting of the game. Each of these five has the same probability; thus, if we
24+
want to increase the probability of one item, we can repeat that as much as we wish. Moreover, each phrase above is
25+
fixed and will be used as it is. However, it is possible to have a sentence which can be reformed based on the
26+
situation. Following is an example of flexible greeting,
27+
28+
.. code-block:: bash
29+
30+
Flex_greeting : #GREETING#, it is TextWorld
31+
32+
This example explains that we may have "Greeting!, it is TextWorld" or "HEY TREKKIE!, it is TextWorld", or any other
33+
combinations that we can mix and match from "Flex_greeting" and "GREETING". In other words, any word (or combination of
34+
words which are attached by hyphen) and comes in between "#", is like a symbol of another vector of phrases and is
35+
replaced by the parser with one of the phrases from that vector. Following is another example of the creation of the
36+
flexible sentence:
37+
38+
.. code-block:: bash
39+
40+
dec : #GREETING# #dec_type##suffix_(r)#;#dec_type##suffix_(r)#
41+
42+
dec_type : #reg-0#;#difficult-0#
43+
suffix_(r) : . Okay, just remember what is your mission here to do, and everything will go great.; \
44+
. You try to gain information on your surroundings by using a technique you call 'looking.'; \
45+
. You can barely contain your excitement.;
46+
. The room seems oddly familiar, as though it were only superficially different from the other rooms in the spacecraft.; \
47+
. You decide to just list off a complete list of everything you see in the module, because hey, why not?;
48+
49+
reg-0 : #01#;#02#
50+
difficult-0 : #03#
51+
52+
01 : #dec_find-yourself# in a (name);#dec_guess-what# (name)
53+
02 : Well, here we are in #dec_a_the# (name)
54+
03 : You're now in #dec_a_the# (name)
55+
56+
dec_find-yourself : You #dec_what#
57+
dec_guess-what : #dec_well-guess#, you are in #dec_a_the# place we're calling #dec_a_the#
58+
dec_a_the : a;the
59+
dec_what : are;find yourself;arrive
60+
dec_well-guess : Guess what;Well how about that;Well I'll be
61+
62+
In this example, assume that the #GREETING# #dec_type##suffix_(r)# is randomly picked, to replace GREETING, dec_type,
63+
and suffix_(r) variables, respectively, the "HELLO ASTRONAUT!", "reg-0", and ". Okay, just remember what is your mission
64+
here to do, and everything will go great." are chosen. To replace reg-0, the parser randomly picks "02", and to replace
65+
"02", the "Well, here we are in #dec_a_the# (name)" is selected. In the latter choice of phrase we have two type of
66+
variables, one is "dec_a_the" and the other is "(name)". The first has already described and let's assume that "the" is
67+
picked. For the second, the (name) is replaced by the name of a room that the player is in. Rooms and their names are
68+
described in next chapter. Finally, the created sentence is as follows:
69+
70+
.. code-block:: bash
71+
72+
HELLO ASTRONAUT! Well, here we are in the (name). Okay, just remember what is your mission here to do, and everything will go great.
73+
74+
This sentence is made for a sample state and anytime the game reaches to this state the (name) is replace with the
75+
corresponding room's name and is printed on the screen. To increase the variety of the outputs, a designer can expand
76+
those sentence block to more and more options. However, it is always important to notice that these sentences
77+
should comply with the scenario of the game in general and the specific scene of the game in each state. We recommend
78+
to make a good use of general sentences, and specific type of sentences which can be fed by variable from the game
79+
state (between parentheses variables). Following this advice can give better sentence in accordance to the game story.
80+
81+
Although the design of a text-grammar file is more depend on the designer's preference rather than the logic file, yet,
82+
there are some sections which should be considered in .twg file. The fundamental sections are named as
83+
84+
1. Expandables : All required combinations, structures, etc of words, letters, and numbers which are used in the whole text of the grammar.
85+
2. Verbs : All verbs which are used as action or simply as verb in the text are collected.
86+
3. Types & Variables : Type of objects and variables of the game are defined and coded.
87+
4. Objects Garmmar : The grammar of each object of the game is defined in this section.
88+
5. Room Description Grammar : All the texts which are used to describe the game inside different rooms are defined and expanded.
89+
6. Instructions Grammar : The grammar of instructions for compound commands, etc are described.
90+
91+
Expandables are all the variables which comes in between "#"s and expand to create a sentence. Verbs are also some sort
92+
of expandable in which different synonyms and tense of the verb and its corresponding synonyms are clarified to be used
93+
in text creation and hesitate from repeating a verb frequently, see below example for "take" verb,
94+
95+
.. code-block:: bash
96+
97+
take : #take_syn_v# the #obj_types# from the (r).;#take_syn_v# the #obj_types# that's in the (r).
98+
take_syn_v : take;retrieve;grab
99+
take_syn_pp : taken;got;picked
100+
taking : taking;getting;picking
101+
102+
take/s : #take_syn_v# the #obj_types# from the #on_var#.
103+
104+
take/c : #take_syn_v# the #obj_types# from the #on_var#.
105+
106+
"take_syn_v" and "take_syn_pp" respectively refer to the list of synonyms and the past participle of those
107+
synonyms; the ing-form of the verb is the following line. Similar to the logic file description, if we have to assign a
108+
word in different application, like take vs. take from a table, these two can be distinguished by assigning different
109+
code words for each set. To understand this, take a look at above example and compare the definition of "take" with
110+
"take/s".
111+
112+
Types of all elements in the game can be coded for the grammar to address much easier. For example, "obj_types : (o|k|f)"
113+
indicates all the object, key, or food with the `obj_types`, while "on_types : (c|s)" refers to container or supporter
114+
types which object-like can be put `on` it. Recall that the left-side of the semicolon is just a symbolic way of
115+
representing something which comes on the left-side; so, it is just for text generation and there is no logic behind it.
116+
117+
In "Objects Grammar" section, every element of the game can have their own grammar and customized nouns and adjectives
118+
to create more sense of the world that the designer tries to build. As an instance, a room can generally be expanded by
119+
an adjective and a noun; if the game refers to an office (work type of room), then the list of adjective-noun pairs
120+
could be different, and based on the game story, the designer can add as much as combinations she/he wishes, to add
121+
more flavour to her/his game. Below is a good example of how different rooms can be assigned with their
122+
own grammar,
123+
124+
.. code-block:: bash
125+
# --- Rooms ---------------------------------------------------------------------
126+
## List each type of room with a ';' between each
127+
## Each roomType must have specific rooms
128+
### Creating a room: first, take the name of the roomtype as listed under #room_type# (let's call it X for now).
129+
### Then, create three symbols with this: X_(r), X_(r)_noun, and X_(r)_adj.
130+
### X_(r) will always be composed of X_(r)_adj | X_(r)_noun. If you want to subdivide a roomtype into two or more variants, you can add _type1, _type2, etc at the end of the noun and adj symbols.
131+
### Make sure that these changes are also accounted for in the X_(r) token.
132+
133+
room_type : clean;cook;rest;work;storage
134+
135+
(r) : #(r)_adj# | #(r)_noun#
136+
(r)_noun : sleep station;crew cabin;washroom;closet;kitchenette;module;lab;lounge
137+
(r)_adj : nondescript;plain
138+
139+
### > Rest Room
140+
### >> Sleep Room
141+
rest_(r) : #rest_(r)_adj_type_1# | #rest_(r)_noun_type_1#;#rest_(r)_adj_type_2# | #rest_(r)_noun_type_2#
142+
143+
rest_(r)_noun_type_1 : sleep station;sleep station;sleep station;sleeping bag;crew cabin
144+
rest_(r)_adj_type_1 : cozy;relaxing;pleasant;sleepy
145+
### >> fun with friends
146+
rest_(r)_noun_type_2 : lounge;playroom;recreation zone;crew cabin;crew cabin;crew cabin
147+
rest_(r)_adj_type_2 : fun;entertaining;exciting;well lit;silent
148+
149+
Majority of the text which is created by the parser belongs to the description of a room. The Room Description Grammar
150+
expands all the grammar which is used for a room to describe the room as well as the scenario at that room. This process
151+
is very similar to what we described in Greetings section.
152+
153+
Last but not least is the "Instructions Grammar". This part basically includes all the required grammatical structures
154+
which the text-based game needs to compound two actions (like unlock and open), separate two sentence from each other or
155+
to connect them with a word, etc. which are important in the expansion of the sentences all over the game. Following is
156+
a few examples of what is designed for the Spaceship game:
157+
158+
.. code-block:: bash
159+
# --- Compound Command Description Functions ------------------------------------
160+
ig_unlock_open : open the locked #lock_types# using the (k).; \
161+
unlock and open the #lock_types#.; \
162+
unlock and open the #lock_types# using the (k).; \
163+
open the #lock_types# using the (k).
164+
ig_unlock_open_take : open the locked #lock_types# using the (k) and take the #obj_types_no_key#.; \
165+
unlock the #lock_types# and take the #obj_types_no_key#.; \
166+
unlock the #lock_types# using the (k), and take the #obj_types_no_key#.; \
167+
take the #obj_types_no_key# from within the locked #lock_types#.
168+
169+
# --- Separators -----------------------------------------------------------------
170+
## *--- Action separators
171+
action_separator_take : #afterhave# #take_syn_pp# the #obj_types#, ; \
172+
#after# #taking# the #obj_types#, ; \
173+
With the #obj_types#, ; \
174+
If you can get your hands on the #obj_types#, ; \
175+
#emptyinstruction#;
176+
action_separator_eat : #afterhave# #eat_syn_pp# the #eat_types#, ; \
177+
#after# #eating# the #obj_types#, ; \
178+
#emptyinstruction#;
179+
180+
## *--- Separator Symbols
181+
afterhave : After you have;Having;Once you have;If you have
182+
after : After;
183+
184+
For further details on these expandables, please check the TextWorld's Spaceship game.

0 commit comments

Comments
 (0)