demiurge 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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).
|