demiurge 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +5 -0
- data/.yardopts +5 -0
- data/AUTHORS.txt +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/CONCEPTS.md +271 -0
- data/Gemfile +4 -0
- data/HACKING.md +34 -0
- data/LICENSE.txt +21 -0
- data/README.md +181 -0
- data/RELOADING.md +94 -0
- data/Rakefile +10 -0
- data/SECURITY.md +103 -0
- data/WORLD_FILES.md +134 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/demiurge.gemspec +31 -0
- data/exe/demirun +16 -0
- data/lib/demiurge/action_item.rb +643 -0
- data/lib/demiurge/agent.rb +338 -0
- data/lib/demiurge/container.rb +194 -0
- data/lib/demiurge/dsl.rb +583 -0
- data/lib/demiurge/exception.rb +170 -0
- data/lib/demiurge/inert_state_item.rb +21 -0
- data/lib/demiurge/intention.rb +164 -0
- data/lib/demiurge/location.rb +85 -0
- data/lib/demiurge/notification_names.rb +93 -0
- data/lib/demiurge/tmx.rb +439 -0
- data/lib/demiurge/util.rb +67 -0
- data/lib/demiurge/version.rb +4 -0
- data/lib/demiurge/zone.rb +108 -0
- data/lib/demiurge.rb +812 -0
- metadata +165 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 16771a3630ea74f9412194ba68ec9ebc5181380c
|
4
|
+
data.tar.gz: 7bd716fe644a7be1e32bd49ab0d39d4cc66a0e97
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b10caf567ea6f50864c594e22ac16708407e325ec72a543ec403a7439ede2c512c82f6bb383dc019ba343cd71dbd131fdc87b99a4a5108be7e3c7dc2fd6bac62
|
7
|
+
data.tar.gz: 4ec6595a79d26d53fb40c04725820239b434195b3979583f589a0615d07339cf104680b62cb5669bdb3851b2588f560a9d7b3f39a3fa6f97d152eac4a33c6226
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/AUTHORS.txt
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
The core Demiurge engine tries to use only CC0-licensed content -- in
|
2
|
+
effect, public domain. But it's nice to credit people when they make
|
3
|
+
things for you. In that spirit:
|
4
|
+
|
5
|
+
Thanks to Jurkan, author of collision.png, a simple CC0-licensed collision-layer tileset.
|
6
|
+
Thanks to Hyptosis of lorestrome.com for CC0-licensed content including portraits and MageCity tilesets.
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at the.codefolio.guy@gmail.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: http://contributor-covenant.org
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/CONCEPTS.md
ADDED
@@ -0,0 +1,271 @@
|
|
1
|
+
# Demiurge Simulated Worlds
|
2
|
+
|
3
|
+
Demiurge is a great way to prototype and develop an interesting
|
4
|
+
simulated world. It's intended to be flexible, powerful and easy to
|
5
|
+
tie into other systems.
|
6
|
+
|
7
|
+
Let's talk about the components of a Demiurge world and what they do.
|
8
|
+
|
9
|
+
## Engines, State, Ticks
|
10
|
+
|
11
|
+
A single Demiurge simulation is called an Engine. It can be loaded
|
12
|
+
from World Files and state.
|
13
|
+
|
14
|
+
World Files determine the behavior of the world - what kinds of
|
15
|
+
entities does the world contain? How do they act? What are the rules
|
16
|
+
of physics that define that world?
|
17
|
+
|
18
|
+
State determines the current situation of that world. If your world
|
19
|
+
physics allows any number of rabbits in a particular field, how many
|
20
|
+
are there right now and where are they?
|
21
|
+
|
22
|
+
A single step of simulation is called a "tick", like the ticking of a
|
23
|
+
clock.
|
24
|
+
|
25
|
+
The world "entity" for a thing in the world is fairly vague. It may
|
26
|
+
refer to an "item", a "creature", an "area" (another vague word) or
|
27
|
+
something else. An entity is "a thing or things in the world" rather
|
28
|
+
than one specific abstraction that Demiurge defines. Entities
|
29
|
+
generally can act and be acted on, can pick things up and be picked
|
30
|
+
up, can take place in a location or be that location. In general, a
|
31
|
+
single individual entity will only do a few of those things, though.
|
32
|
+
|
33
|
+
## Intentions, Actions and Events
|
34
|
+
|
35
|
+
A world may contain unchanging things, usually represented as
|
36
|
+
rules. It may contain changeable and movable items. And it may contain
|
37
|
+
items or creatures that act on their own. Demiurge can distinguish
|
38
|
+
between these categories, but it usually does so by distinguishing
|
39
|
+
between "rules" and "state" rather than between "intelligent" and
|
40
|
+
"unintelligent." Intelligence is mostly a matter of how complex the
|
41
|
+
rules are, and what objects they tend to affect.
|
42
|
+
|
43
|
+
A Demiurge Engine normally moves forward in discrete steps. The
|
44
|
+
current state is examined to create a list of Intentions, which do not
|
45
|
+
(yet) change state. The Intentions are then resolved into
|
46
|
+
notifications and state changes. One full state/intention/event cycle
|
47
|
+
is a tick.
|
48
|
+
|
49
|
+
Demiurge doesn't require that ticks occur at particular times
|
50
|
+
according to a real-world clock. You might choose to create entities
|
51
|
+
and rules that care about a real-world clock, but Demiurge doesn't
|
52
|
+
care. Ticks can be evenly spaced or not, as long as your entities'
|
53
|
+
rules reflect that.
|
54
|
+
|
55
|
+
## State Items, and the Difference Between Rules and State
|
56
|
+
|
57
|
+
Rules exist entirely within World Files and the Demiurge framework
|
58
|
+
itself. The effects of rules can change according to current state,
|
59
|
+
but the rules themselves are in the World Files and do not depend on
|
60
|
+
state.
|
61
|
+
|
62
|
+
State in Demiurge must be serializable as JSON. That gives a
|
63
|
+
combination of numbers, strings, true/false/undefined special values,
|
64
|
+
lists and objects (dictionaries/hashes) as the set of all state
|
65
|
+
data. Each State Item gets a chunk of state and manages its own
|
66
|
+
rules. Each State Item's item name must be unique. There may be lots
|
67
|
+
of a particular *kind* of state item, but each one gets its own unique
|
68
|
+
name and its own chunk of state.
|
69
|
+
|
70
|
+
A "State Item" applies rules to state. As a programmatic object, it
|
71
|
+
can apply its rules (which are fixed) to its state (which can change
|
72
|
+
at any time).
|
73
|
+
|
74
|
+
This abstraction makes it easy to consider hypotheticals -- to ask,
|
75
|
+
"if the state were different in this way, how would that change the
|
76
|
+
world?"
|
77
|
+
|
78
|
+
## Item Naming and Instances
|
79
|
+
|
80
|
+
A Demiurge entity (including Zones, Locations, Agents and many others)
|
81
|
+
must have a single, fully unique name within a given Engine. In World
|
82
|
+
Files, normally a human has to declare the name and that name needs to
|
83
|
+
be unique.
|
84
|
+
|
85
|
+
Names have a few restrictions. You can use alphanumeric characters
|
86
|
+
(letters and numbers, including Unicode letters and numbers) along
|
87
|
+
with spaces, dashes and underscores in the names. But other
|
88
|
+
punctuation including quotes, hash signs, dollar signs and so on
|
89
|
+
aren't permitted. These names are used internally as unique
|
90
|
+
identifiers and you don't need to worry about showing them to humans,
|
91
|
+
so don't worry about not being able to put punctuation you care about
|
92
|
+
in the names. The names are case-sensitive -- that is, "Bobo" and
|
93
|
+
"boBo" are completely different items because an upper-case and
|
94
|
+
lower-case letter count as different from each other.
|
95
|
+
|
96
|
+
Certain items, such as Zones in World Files may be reopened by
|
97
|
+
declaring another item (e.g. another Zone) with the same name. But if
|
98
|
+
so, they aren't two different Zones with the same name. Instead, the
|
99
|
+
files declare a single Zone across multiple files. That's perfectly
|
100
|
+
legal, just as you may declare a room in one World File while
|
101
|
+
declaring creatures and items inside it in another World File. But
|
102
|
+
it's all a single room, even if it's declared in multiple places for
|
103
|
+
human convenience. If you're used to programming with Ruby classes,
|
104
|
+
this idea of "reopening" the same zone in a new file will probably
|
105
|
+
seem very familiar.
|
106
|
+
|
107
|
+
Sometimes you want to declare an object and then have a lot of
|
108
|
+
them. Something like a wooden spoon, a low-level slime monster or a
|
109
|
+
player body object may get just one declaration in the World Files for
|
110
|
+
a lot of individual objects in the world. Differences in state or
|
111
|
+
appearance can add variation where you need it without requiring
|
112
|
+
giant, bloated World Files with fifteen identical slime monsters that
|
113
|
+
just have a "7" or a "12" after their name.
|
114
|
+
|
115
|
+
There are a few kinds of special punctuation in names and name-like
|
116
|
+
things that Demiurge may use for itself. For instance, a Position (see
|
117
|
+
later in this file) is a location's item name followed by a pound sign
|
118
|
+
and then some additional information, such as
|
119
|
+
"my\_room#25,71". Certain special objects and other things in Demiurge
|
120
|
+
can use other punctuation (e.g. colon or dollar-sign), but these
|
121
|
+
shouldn't occur in human-named objects in World Files.
|
122
|
+
|
123
|
+
## Events and State Changes
|
124
|
+
|
125
|
+
Often an Intention turns into a change of state. For example, an item
|
126
|
+
is picked up, or a person moves from one location to another. When
|
127
|
+
that occurs, there may also be one or more notifications. The state
|
128
|
+
change is what it sounds like - if a person moves from one place to
|
129
|
+
another, their "location" is part of their state, and it's different
|
130
|
+
after the tick than it was before.
|
131
|
+
|
132
|
+
A Notification doesn't necessarily involve a change of state, though
|
133
|
+
the two will often happen together. The Notification doesn't cause the
|
134
|
+
state change, though it may be the result of one. A Notification is
|
135
|
+
simply a discrete that can be perceived in the world. A continuous,
|
136
|
+
ongoing event is state, not a Notification, though if it begins, ends
|
137
|
+
or changes significantly it may *cause* a Notification.
|
138
|
+
|
139
|
+
If a person moves from one room to another, their location changes and
|
140
|
+
so their state changes. There is also likely to be a Notification
|
141
|
+
associated with it - a detectable, trackable event which can be
|
142
|
+
watched for by other reactive entities in the world.
|
143
|
+
|
144
|
+
A Notification doesn't have to involve a state change, though. For
|
145
|
+
instance, if a character looks around shiftily or grins momentarily,
|
146
|
+
that doesn't necessarily change any recorded part of their state. But
|
147
|
+
another character may watch for the Notification and if they detect
|
148
|
+
it, they may react to it.
|
149
|
+
|
150
|
+
## The Cycle of a Tick
|
151
|
+
|
152
|
+
Initially, the state is effectively frozen - nothing should change
|
153
|
+
it. It may be literally kept immutable in the program, depending on
|
154
|
+
required efficiency.
|
155
|
+
|
156
|
+
For each tick, code runs to generate Intentions on the part of any
|
157
|
+
entities that can act. Anything that will change state or create a
|
158
|
+
Notification requires an Intention.
|
159
|
+
|
160
|
+
Then, in some order of precedence, these Intentions are resolved one
|
161
|
+
at a time.
|
162
|
+
|
163
|
+
First an Intention is "validated" - can it happen at all? If not, it
|
164
|
+
is discarded as impossible, undesirable or otherwise "not going to
|
165
|
+
happen" with no effects of any kind.
|
166
|
+
|
167
|
+
At this point, the state becomes changeable again. This may involve
|
168
|
+
unfreezing or copying.
|
169
|
+
|
170
|
+
Then an Intention is offered - other entities may attempt to block,
|
171
|
+
modify or otherwise interfere with what occurs. This may result in the
|
172
|
+
Intention being blocked as in the validation stage (another entity
|
173
|
+
effectively makes its result impossible, resulting in nothing
|
174
|
+
happening) or its effects may be modified and/or other effects may
|
175
|
+
immediately occur as a result.
|
176
|
+
|
177
|
+
As that process resolves, the Intention may modify state. It may also
|
178
|
+
send Notifications. In general, a Notification reflects a completed
|
179
|
+
operation and the receiver can only react, not change or block the
|
180
|
+
action. While a Notification allows the receiver to modify state, that
|
181
|
+
receiver should only modify its own state or send additional
|
182
|
+
Notifications - it should not take "instant reactions", which should
|
183
|
+
be resolved in the offer/modify/veto stage.
|
184
|
+
|
185
|
+
After all these Notifications have resolved, including any
|
186
|
+
Notifications raised in response to other Notifications, the tick
|
187
|
+
begins again with the new state, which may be frozen during the early
|
188
|
+
Intention phases.
|
189
|
+
|
190
|
+
## Zones, Location and Position
|
191
|
+
|
192
|
+
Location in Demiurge starts with the Zone. A Zone is a top-level
|
193
|
+
entity that manages state and flow of execution roughly independently
|
194
|
+
of other zones.
|
195
|
+
|
196
|
+
Different Zones may have very different "physics" between them - a
|
197
|
+
Zone might be entirely text descriptions, while a different Zone is
|
198
|
+
managed entirely in 2D tile graphics, for instance and a third Zone
|
199
|
+
could be an HTML UI. It's possible to do that within a single Zone in
|
200
|
+
some cases, if the Zone's "physics" permit it, but such changes are
|
201
|
+
expected between Zones.
|
202
|
+
|
203
|
+
A Location within a Zone may have some difference, but needs to
|
204
|
+
cooperate effectively with the Zone and with other Locations
|
205
|
+
inside. In a 2D tile-based Zone, it may be important that Zone
|
206
|
+
pathfinding works across multiple Locations, for instance. In a
|
207
|
+
text-based Zone of mostly-independent locations, there may be a
|
208
|
+
notification system that allows events in adjacent rooms to be visible
|
209
|
+
in certain other rooms as text notifications.
|
210
|
+
|
211
|
+
In general, a Zone defines the top-level "physics" and the nature of
|
212
|
+
space and location within itself, and Locations coordinate to make
|
213
|
+
that happen. Technically Locations are optional - it's possible for a
|
214
|
+
Zone to skip Locations entirely. But ordinarily there is some form of
|
215
|
+
subdivision.
|
216
|
+
|
217
|
+
Locations are also allowed to contain other Locations, and may do so
|
218
|
+
or not depending on the nature of their Zone.
|
219
|
+
|
220
|
+
When one asks for an entity's "location", one may mean "what entity
|
221
|
+
inside a Zone is it contained in?" However, there is not always a
|
222
|
+
well-defined answer to that question. For instance, an "infinite
|
223
|
+
space" Zone with no sub-locations that handles all object interactions
|
224
|
+
directly may not have "Location" sub-objects within itself at
|
225
|
+
all. What "location" is somebody at within the Zone? The Demiurge
|
226
|
+
entity in question is just the Zone, since there are no smaller
|
227
|
+
Location entities within it.
|
228
|
+
|
229
|
+
And within a Location, an entity may occupy different positions. In a
|
230
|
+
box of 3D space or a 2D tile map or a MUD-style room with objects
|
231
|
+
inside, a given entity may be at "x: 27.4, y:-1547.2, z: 297.0" or "x:
|
232
|
+
27, y: 5" or "next to the gray lamp."
|
233
|
+
|
234
|
+
The Demiurge class "Demiurge::Location" is basically advisory -
|
235
|
+
locations within a Zone aren't required to belong to that class, may
|
236
|
+
be part of a tree of different location objects or may not exist at
|
237
|
+
all.
|
238
|
+
|
239
|
+
As a result, a "location" in Demiurge is about author intention, not
|
240
|
+
really about what Demiurge does with the object in question. The Zone
|
241
|
+
defines what being a location means, and it may vary widely from Zone
|
242
|
+
to Zone.
|
243
|
+
|
244
|
+
But then, how does one specify? With a Position.
|
245
|
+
|
246
|
+
A Position is given relative to a Zone or an object inside the Zone,
|
247
|
+
such as a Location (if one exists.) It is of the form
|
248
|
+
"item\_name#coordinates" where "item\_name" is a canonical
|
249
|
+
Demiurge item name, instanced or non-instanced. The coordinates may be
|
250
|
+
in a form appropriate to their zone such as "7,25" or
|
251
|
+
"29.45/81.6/Kappa" or "left\_of/gray\_greasy\_lamp". The coordinates
|
252
|
+
should not contain a pound-sign, a dollar sign or other characters
|
253
|
+
that aren't legal in a Demiurge item name.
|
254
|
+
|
255
|
+
## The Admin Zone and Positionless Actions
|
256
|
+
|
257
|
+
Sometimes, a thing happens that doesn't belong in any specific game
|
258
|
+
zone. A player might fail to create a new account - what zone would
|
259
|
+
that belong in? An admin might reload the whole world, which isn't
|
260
|
+
specific to any one zone. An error might occur that can't be traced to
|
261
|
+
any specific zone.
|
262
|
+
|
263
|
+
When that happens, a special zone name, "admin", is used. There cannot
|
264
|
+
be an "admin" zone in a world file. Instead, "admin" is the name of an
|
265
|
+
automatic InertStateItem which holds system information like how many
|
266
|
+
total ticks have passed in the world, and the current notification_id
|
267
|
+
and intention_id for queueing.
|
268
|
+
|
269
|
+
Positionless occurrences like the examples above (e.g. account
|
270
|
+
creation failures) will appear to occur in this nonexistent "admin"
|
271
|
+
zone.
|
data/Gemfile
ADDED
data/HACKING.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# Hacking Demiurge
|
2
|
+
|
3
|
+
When in doubt: read the source, tests and examples of course, just
|
4
|
+
like any other code.
|
5
|
+
|
6
|
+
## State and JSON
|
7
|
+
|
8
|
+
Demiurge is architected in such a way that StateItems contain logic
|
9
|
+
about how to manipulate state. StateItems contain current state and
|
10
|
+
can calculate new Intentions and apply Actions.
|
11
|
+
|
12
|
+
State can be serialized and swapped out at any time, so StateItems
|
13
|
+
must be able to be disposable and replaceable. Since it's hard to
|
14
|
+
serialize a procedure as JSON, generally StateItems define actions in
|
15
|
+
their World Files or Ruby code, and the StateItem contains the names
|
16
|
+
of the actions. The actual Ruby procedures are either part of the
|
17
|
+
StateItem subclass Ruby code or they're stored as a proc in the engine
|
18
|
+
itself.
|
19
|
+
|
20
|
+
Similarly, serialized state data often contains item names rather than
|
21
|
+
actual items. Names are easily serialized and easily handled with a
|
22
|
+
minimum of fuss, while structures and code are both messy.
|
23
|
+
|
24
|
+
## Zones and Top-Level State
|
25
|
+
|
26
|
+
If every StateItem was guaranteed a call every tick, simulation would
|
27
|
+
slow to a crawl very rapidly as the world expanded. Instead, certain
|
28
|
+
top-level StateItems called "zones" are guaranteed to be called every
|
29
|
+
tick and they decide how to manage the flow of execution to their
|
30
|
+
contents.
|
31
|
+
|
32
|
+
In general, a Zone manages whether to call various sub-items or
|
33
|
+
agents, or whether to only call them sometimes, or whether to quiesce
|
34
|
+
them completely.
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Noah Gibbs
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
# Demiurge
|
2
|
+
|
3
|
+
Demiurge is an experimental game state and simulation library.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'demiurge'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install demiurge
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
See test mini-games in the test directory. For more information, see
|
24
|
+
lib/demiurge/engine.rb.
|
25
|
+
|
26
|
+
For longer-term usage, Demiurge will normally be part of a larger
|
27
|
+
program. Its intent is to manage behavior and state for a game or
|
28
|
+
similar simulated world. In those cases, Demiurge will normally be
|
29
|
+
required as a gem by its application, using normal "require
|
30
|
+
'demiurge'"-style declarations. You can see what that looks like by
|
31
|
+
examining test/example mini-worlds in the relevant Demiurge
|
32
|
+
directories.
|
33
|
+
|
34
|
+
If Demiurge is primarily managing a simulated world and you want to
|
35
|
+
view the results, you'll need a display library to make its output
|
36
|
+
visible. Currently that means Demiurge-CreateJS, which displays the
|
37
|
+
results in your browser as a simulated world.
|
38
|
+
|
39
|
+
Please note that it is very, very difficult to separate the specifics
|
40
|
+
of behavior from the specifics of output and display - entities simply
|
41
|
+
*behave* differently in a text-only world with generalized "locations"
|
42
|
+
than they do in a 2D grid or a 3D world with collisions. As a result,
|
43
|
+
even if your preferred method of output isn't as specific as "Unreal
|
44
|
+
Engine" or "browser game" or "MUD-style text game," your simulation is
|
45
|
+
going to have a strong "flavor" of whatever underlying physics you
|
46
|
+
select. There is no such thing as "just plain physics, with no strong
|
47
|
+
bias that changes the behavior of agents within it."
|
48
|
+
|
49
|
+
This README doesn't tell you everything about creating and simulating
|
50
|
+
a world with Demiurge. See CONCEPTS.md for an initial grounding in
|
51
|
+
those ideas.
|
52
|
+
|
53
|
+
## Demiurge DSL (World Files)
|
54
|
+
|
55
|
+
Demiurge contains an optional Domain-Specific Language (also called a
|
56
|
+
"DSL") which can be used to specify your simulated world and its rules
|
57
|
+
and behaviors. The "test" directory contains some examples of these
|
58
|
+
files.
|
59
|
+
|
60
|
+
These DSLs may specify various sorts of locations and agents that roam
|
61
|
+
them - the idea is that the world files should specify enough details
|
62
|
+
to simulate the "world" fully, without containing too much additional
|
63
|
+
detail on how to supply the results. Since many formats tend to pack
|
64
|
+
this information together (e.g. TMX files contain layout and collision
|
65
|
+
data required for simulation, but also links to image files for
|
66
|
+
display) the Demiurge engine will often link to the display
|
67
|
+
information without using it. This permits a display layer on top of
|
68
|
+
Demiurge, such as Demiurge-CreateJS, to make use of the display
|
69
|
+
information alongside the simulation data.
|
70
|
+
|
71
|
+
## Specific Technologies: 2D Tile Maps
|
72
|
+
|
73
|
+
Remember that "no such thing as just plain physics" bit above? As a
|
74
|
+
consequence, Demiurge contains support for specific, non-abstract
|
75
|
+
physics bits like "2d grid of defined terrains," also called a tilemap
|
76
|
+
or tiled terrain.
|
77
|
+
|
78
|
+
There are standards for tilemaps, such as TMX format and the Tiled map
|
79
|
+
editor (http://mapeditor.org). TMX support also, not coincidentally,
|
80
|
+
gives you a fairly rich source of existing media to use (e.g. The Mana
|
81
|
+
Project and Source of Tales.) Please be careful to appropriately
|
82
|
+
respect the licensing of this media, which requires an acknowledgement
|
83
|
+
to the original authors for your graphics and map files.
|
84
|
+
|
85
|
+
2D tile-based media is rich enough to provide interesting simulation
|
86
|
+
and AI behaviors without being *so* interesting that your agent code
|
87
|
+
can't be in scripting languages and spends all its time doing
|
88
|
+
pathfinding, as would be the case with most open 3D environments.
|
89
|
+
|
90
|
+
## Specific Technologies: Serializability and Immutability
|
91
|
+
|
92
|
+
One of the hard challenges in game- and world-based AI is how to make
|
93
|
+
it easy to create new content, primarily in the form of reactions and
|
94
|
+
behavior. Those reactions and behavior are most frequently expressed
|
95
|
+
as some form of code/scripts.
|
96
|
+
|
97
|
+
Reactions and behavior can take many forms. Two common ones are called
|
98
|
+
Intentions and Actions by Demiurge. An Intention is generated by an
|
99
|
+
artificial intelligence based on examining its current situation. For
|
100
|
+
instance, "I am hungry and I remember food in the next room, so I
|
101
|
+
intend to move in that direction." An Intention will examine the state
|
102
|
+
of the world, but will not normally change it.
|
103
|
+
|
104
|
+
An Action is normally the result of an Intention, and it applies that
|
105
|
+
intention to the simulated world. An Action will frequently change the
|
106
|
+
state of the world, such as by moving an agent within the world, or by
|
107
|
+
moving other non-agent items in the world (e.g. eating food, picking up a
|
108
|
+
stick, etc.) An Action may also frequently be thwarted (e.g. an item
|
109
|
+
is too heavy, food is not where it was suspected or remembered,
|
110
|
+
somebody has pushed their way into the hall ahead of you and you may
|
111
|
+
not pass.)
|
112
|
+
|
113
|
+
Immutable structures provide great verifiability and terrible
|
114
|
+
performance. The code snippets can generate a second, modified version
|
115
|
+
of each structure, but must copy nearly the entirety of it. You may be
|
116
|
+
certain that no old state is being modified in a sloppy way, and
|
117
|
+
memory usage and garbage collection time are both very high.
|
118
|
+
|
119
|
+
Mutable structures allow easy in-place modification for great
|
120
|
+
performance, but they're hard to lock down when mutability isn't
|
121
|
+
wanted (e.g. when verifying if an action is allowed to take place.)
|
122
|
+
|
123
|
+
Demiurge attempts to handle this by making the code immutable per run
|
124
|
+
of the world, and to store state data in sometimes-mutable
|
125
|
+
JSON-serializable structures.
|
126
|
+
|
127
|
+
It is assumed but only sometimes verified that when calculating
|
128
|
+
Intentions the state of the world isn't altered. It is assumed that
|
129
|
+
the behaviors are replicatable -- that random numbers generated from
|
130
|
+
seeds are used in a way that is replicatable from run to run, for
|
131
|
+
instance, or non-random behaviors reliably calculate the same
|
132
|
+
intention from the same preconditions.
|
133
|
+
|
134
|
+
This provides a compromise between full immutability (slow
|
135
|
+
performance, great verifiability) and full mutability (fast
|
136
|
+
performance, terrible verifiability) by switching back and forth
|
137
|
+
between them on demand.
|
138
|
+
|
139
|
+
## Development
|
140
|
+
|
141
|
+
Demiurge is not yet ready for "pristine" production usage. It's not
|
142
|
+
yet ready for you to just drop it in and use it unchanged. For that
|
143
|
+
reason, assume you'll need to do some Demiurge development for
|
144
|
+
yourself, whether or not you ever contribute it upstream.
|
145
|
+
|
146
|
+
For more information on Demiurge's architecture, see the HACKING.md
|
147
|
+
document in this directory.
|
148
|
+
|
149
|
+
After checking out the repo, run `bin/setup` to install
|
150
|
+
dependencies. Then, run `rake test` to run the tests. You can also run
|
151
|
+
`bin/console` for an interactive prompt that will allow you to
|
152
|
+
experiment.
|
153
|
+
|
154
|
+
To install this gem onto your local machine, run `bundle exec rake
|
155
|
+
install`. To release a new version, update the version number in
|
156
|
+
`version.rb`, and then run `bundle exec rake release`, which will
|
157
|
+
create a git tag for the version, push git commits and tags, and push
|
158
|
+
the `.gem` file to [rubygems.org](https://rubygems.org).
|
159
|
+
|
160
|
+
## Contributing
|
161
|
+
|
162
|
+
Bug reports and pull requests are welcome on GitHub at
|
163
|
+
https://github.com/noahgibbs/demiurge. This project is intended to be
|
164
|
+
a safe, welcoming space for collaboration, and contributors are
|
165
|
+
expected to adhere to the
|
166
|
+
[Contributor Covenant](http://contributor-covenant.org) code of
|
167
|
+
conduct. See CODE\_OF\_CONDUCT.md.
|
168
|
+
|
169
|
+
## References, Influences and Sources of Media
|
170
|
+
|
171
|
+
* OpenGameArt and the Liberated Pixel Cup
|
172
|
+
* Source of Tales
|
173
|
+
* The Tiled Map Editor
|
174
|
+
* The Mana World - https://github.com/themanaworld
|
175
|
+
* The Mana Project
|
176
|
+
* Evol Online
|
177
|
+
|
178
|
+
## License
|
179
|
+
|
180
|
+
The gem is available as open source under the terms of the
|
181
|
+
[MIT License](http://opensource.org/licenses/MIT).
|