I am moving ahead with testing the technical ideas of Nth Society using a simple text adventure engine. Since my first and most recent post I decided to lay out some of the development plan as it may of interest to people.
This is broken into 4 areas:
- Time aware objects
- Self-acting objects
- Map grid spec
- Event notification levels
I'll conclude the discussion with a short look at the program control flow using a diagram.
Prelude
This should not be taken as final but as a detailed suggestion for discussion. Please engage with me in the comments if you have an opinion, I'd really like to read what you think.
Time aware objects
When a player acts on an object (or if it acts on itself) it will always be with respect to time. That is, the time the act happens will be a factor in the processing of the act.
f(t) → ?
We can think of the act as a function f of t, i.e. time, giving some resulting state.
There are cases when time is irrelevant. For this we would use:
f(t) → n
where n is a constant. Note that it is not that the n is permanent, but that time is irrelevant in it's state consideration. An example is if you look at a book. The pages do not change over time, the book remains the same, at least for the kinds of time periods we're talking about (days, months).
What about a piece of fruit? Let's take for granted constant environmental conditions, then we could have this function mapping:
f(t) → ripen_decay(t - t₀)
where t₀ is the "starting time" of the fruit (when it was picked), and ripen_decay is the function governing the state of the fruit. Since growth and decay tend to happen at an exponent rate when ideally bounded, we would expect the fruit to follow this, but it would require some investigation to model.
In the game all objects (including players) can process their events while aware of time. This is an obvious requirement, but I'm just making it explicit.
A piece of fruit decays if left on a table for days, and we can simplify things by assuming that broadly there is no interaction with it and the general environment without an active agent. That is, if we come back to the table after two weeks, the only thing the fruit will have affected is itself. This is the most simple case. When we come back after any length of time, after a certain point there is a dried stain where the fruit once sat on the table.
See image reference [1] at end of post.
Self-acting objects and area replay
From a computational simulation perspective, we need objects to be able to act on themselves. That is, that they do things without player interaction.
Even if an object does not move around, it may need to produce an event (i.e. run some code) at a certain time. For example, a fruit falling from a tree.
This is a good case because it shows us that the code only needs to be run in real time (i.e. when it is scheduled to happen) if there is a dependence on the action. For example, if you are standing right by the tree, you will see and hear the fruit fall, even if you are not paying attention to it. We can use "paying attention to" as short hand for querying the object about it's state.
However if you are a mile away, and the fruit falls, you do not need to know it happened. Only upon arriving at the tree do you need the event to have taken place, as the fruit should be on the ground instead of still in the tree.
What we can do to simulate this efficiently is that when you come close to objects they replay their state up to the present moment, saving processing of far away events. Once the state is known, it can be broadcast the rest of the network (other players) so they do not need to perform this. Hopefully we will also be able to use a kind of "sharding" so that this kind of processing can be shared between players in an area.
Some events happen over a large area, such as weather. Because of this kind of thing, the area for an object needs to be clearly defined, and can be large, but will mostly be small.
Note on interconnectedness
This model assumes little or no interconnectedness between non-actor objects. For example, it does not allow for the case where the tree bears fruit, it spreads its seed by the wind, and more trees grow some distance away, and on and on, with no actors ever visiting that area.
Rather this case would be modelled either by spontaneous tree growth in that area based on a preset pattern of growth, or by introducing NPC animals to do that kind of propagation work.
Let me know if you think this is good enough, or not, I'm of the position that it is enough for now, but I can see it's limitations, and I think I can live with them.
Map grid spec
To simplify processing, we specify that the map (the entire area of the game) be divided as a grid into sub-areas called segments.
In the text adventure version of the game engine, these are analogous to "rooms" in the typical text adventure, the often physically bounded space in which a set of objects reside, and actions can be done. It is the smallest piece of physical space.
It should be allowed to have movement within a segment, but for the purposes of the text adventure engine this does not need to be very meaningful. When the engine is graduated to 3D MineTest, or even something else, it will be more important.
Event notification levels
Events happen on objects. So when a player picks up an apple, an event is processed on that object:
apple.event("pick up", player_personz, time_now)
The code for what happens, if anything, is bundled with the object. So in essence it is the apple that knows how to be picked up!
Say you then drop the apple. As in the example of the fruit falling from the tree, another person in the vicinity would expect to hear it hit the ground or floor. It wouldn't be very loud so someone in the next room, or down the street would not hear it.
We can generalize this to the idea of event notification. I propose we have the following levels:
- Internal - thoughts, feelings, bodily feedback, etc.
- Quiet - need to be nearby
- Loud - need to be in an adjacent segment or two
- Very loud - need to be within 4 segments
- Ultra loud - need to be within 10 segments
Something like that. I created this diagram to illustrate the radial distance using fixed large square segments.
So dropping an apple might send out two notifications:
- Internal: "You dropped the apple."
- Quiet: "You hear an apple hid the ground."
I could be also a rule that only the closest notification if observed if there is more than one level of notification transmitted. For example, if a player says something aloud, the event could have two levels of notification:
- Quiet: "[The words the players is saying]"
- Loud: "[Player] is talking nearby"
If you are close to [Player] then you will just want to see the words. If you are kinda close you can only see "[Player] is talking nearby".
Program control flow
See the following diagram for a sketch of the program control flow
Checking commands before sending to the network
When you do something as a player the game will first check if it's valid, to save network bandwidth in sending clearly invalid commands.
Commands are only processed after network confirmation
This will slow things down, but it's the safest way to be sure of a correct timestamp. I don't see this as a final solution, I hope there are ways to get an immediate timestamp which is either known to be correct or within acceptable error bounds.
Listen for state changes to output
Events are processed, and when a relevant notification is observed, it is shown to the user in text output.
Serialize state to file
The game state should be periodically written to file. This is to protect against system failure, as well as to serve to other players on the network on request.
Image references
[1] Joseph T. Kider Jr., Samantha Raja, and Norman I. Badler, "Fruit Senescence and Decay Simulation", . April 2011
All others except Nth Society logos are original and my own work, no copyright is claimed on them, they are CC0.