A lot more documentation and some experimentation

This commit is contained in:
Simon Brooke 2024-04-03 12:00:57 +01:00
parent 1429340e4c
commit 06ddd2aba6
14 changed files with 274 additions and 16 deletions

2
.gitignore vendored
View file

@ -50,3 +50,5 @@ docs/cloverage/codecov.json
docs/cloverage/coverage.xml
src/cc/journeyman/the_great_game/cloverage.clj
.DS_Store

33
doc/API Spec.md Normal file
View file

@ -0,0 +1,33 @@
# API Spec
If the Gossip system is ever to be deployed in practice at all, it will need to be deployed as a library add-on to someone else's game, since in practice The Great Game will never be even nearly finished. The game engine already knows many of the things the Gossip system needs to know; that we need to define is an interface which allows Gossip, considered as a subsystem, to query the game engine.
My preference is still that Gossip should be written in a Lisp-like language - and, for now, in Clojure - simply because that is most comfortable to me. It needs bidirectional socket communication with the game engine, over which it sends either [extensible data notation](https://github.com/edn-format/edn) or [JavaScript Object Notation](https://www.json.org/json-en.html), with a preference for the former.
## Tracking what happens in the world
Existing game engines don't tend to track in convenient form things which have happened off-camera - indeed, mostly, things don't happen at all when the player isn't present. They don't even track much that happens when the player is present, and they usually track what they do track in fairly ad-hoc ways. So generally Gossip-as-library will have to maintain its own history of what has happened, and who knows what about what has happened; and will have to model the major life events of non-player characters happening off-camera (if this is done at all) itself.
## Interrogating lore
Many games have a great deal of lore and many lore texts. It's reasonable to expect each non-player character to know a certain amount of lore, certainly lore which is local to their home location, or relevant to their trade. In order to make that available to Gossip, you probably need to construct a searchable corpus of all the lore, which can be simply queried.
That obviously then needs to be filtered by what the respondent can be expected to know, but that's a problem Gossip has to handle anyway.
## Interrogating the map
### get-character-location *id*
Returns the player location in the world of the character with the specified id, as at minimum a three dimensional coordinate tuple, with heading; optionally with hierarchical region ids.
### get-potential-auditors *id*
### get-potential-auditors *id*, *volume*
Return an ordered list of ids of characters spatially close to the character with the specified id, ordered by their likelihood of being the character addressed (i.e. preferring characters in front of the character with the specified id to those off to the side or behind, on a sort of cardioid pattern). The set is bounded by the distance at which speech is deemed to be intelligible, which may be a constant, or maybe modified by some modelling of ambient noise, or the volume of the character's speech act.
### get-potentially-aware *id*
### get-potentially-aware *id*, *volume*
As above, but return a list of ids of characters within a distance in which speech may be heard but not intelligibly.

View file

@ -29,7 +29,7 @@ I want the player to be able to interact with non-player characters (and, indeed
and it must be pretty clear that the full range of potential responses is extremely large. Consequently, it's impossible that all non-player character speech acts can be voice acted; rather, this sort of generated speech must be synthesised. But a consequence of this is that the non-player character's facial animation during the conversation also cannot be motion captured from a human actor; rather, it, too, must be synthesized.
This doesn't mean that speech acts by non-player characters which make plot points or advance the narrative can't be voice acted, but it does mean that the voice acting must be consistent with the simulated voice used for that non-player character - which is to say, probably, that the non-player character must use a synthetic voice derived from the voice of that particular voice actor.
This doesn't mean that speech acts by non-player characters which make plot points or advance the narrative can't be voice acted, but it does mean that the voice acting must be consistent with the simulated voice used for that non-player character - which is to say, probably, that the non-player character must use a synthetic voice derived from the voice performance of that particular voice actor in that role.
## Dynamic game environment
@ -39,7 +39,9 @@ My vision for The Great Game is different. It is that the economy - and with it,
## Plot follows player
As Role Playing Games have moved towards open worlds - where the player's movement in the environment is relatively unconstrained - the clockwork has become strained. The player has to get to particular locations where particular events happen, and so the player has to be very heavily signposted. Another solution - which I'd like to explore - is 'plot follows character'. The player is free to wander at will in the world, and plot relevant events will happen on their path. And by that I don't mean that we associate a set of non-player characters which each quest - as current Role Playing Games do - and then uproot the whole set from wherever they normally live in the world and dumping down in the player's path; but rather, for each role in a quest or plot event, we define a set of characteristics required to fulfill that role, and then, when the player comes to a place where there are a set of characters who have those characteristics, the quest or plot event will happen.
As Role Playing Games have moved towards open worlds - where the player's movement in the environment is relatively unconstrained - the clockwork has become strained. The player has to get to particular locations where particular events happen, and so the player has to be very heavily signposted. Sometimes the mark you have to hit to trigger the next advance of the plot can be extremely awkward; [an example from Cyberpunk 2077](https://youtu.be/GEYkuctBUYE?t=2990) is finding the right spot, in the quest 'They Won't Go When I Go', to trigger the button which raises the cross.
Another solution - which I'd like to explore - is 'plot follows character'. The player is free to wander at will in the world, and plot relevant events will happen on their path. And by that I don't mean that we associate a set of non-player characters which each quest - as current Role Playing Games do - and then uproot the whole set from wherever they normally live in the world and dumping down in the player's path; but rather, for each role in a quest or plot event, we define a set of characteristics required to fulfill that role, and then, when the player comes to a place where there are a set of characters who have those characteristics, the quest or plot event will happen.
## Cut scenes, cinematics and rewarding the player

View file

@ -1,7 +1,11 @@
# Further Reading
# Further Reading (and watching)
Work by other people which is relevant to what I'm doing, and which I should study.
## Modelling the natural environment
1. [Synthetic Silviculture: Multi-scale Modeling of Plant Ecosystems](https://storage.googleapis.com/pirk.io/projects/synthetic_silviculture/index.html) -- see also [this video](https://youtu.be/8YOpFsZsR9w).
1. [Synthetic Silviculture: Multi-scale Modeling of Plant Ecosystems](https://storage.googleapis.com/pirk.io/projects/synthetic_silviculture/index.html) -- see also [this video](https://youtu.be/8YOpFsZsR9w).
## Systemic games
1. [This video](https://youtu.be/SnpAAX9CkIc) is thought provoking with excellent examples.

View file

@ -0,0 +1,7 @@
# Game-engine integration
To build a game using these ideas we need a lot of things that are well understood and already implemented: rendering a world, moving models of characters in a world, and so on. This collection of technologies which allow us to realise an interactive realisation of a world is typically called a game engine.
It's my intention that the bits that I add to the mix should be open source in the hard sense of that phrase, fully free software released under GPL. They cannot therfore be directly linked to a proprietary game engine.
But the current state of play is that the best and easiest to work with game engines are not open source; and while I could build a demo game using, for example, the [Godot engine](https://godotengine.org/) or [jMonkeyEngine](https://jmonkeyengine.org/) the result wouldn't be as compelling and *I believe* the effort would be more considerable than if I use [Unreal Engine](https://www.unrealengine.com/en-US), which is my current plan.

55
doc/MVP-Roadmap.md Normal file
View file

@ -0,0 +1,55 @@
# Minimum Viable Product, and a road map
Right, I'm bogged down thinking about the immensity of what I want to build, so I'm achieving nothing. So the first thing I need to state is what the Minimum Viable Product is, and the second is to outline a rough road map which takes us forwards a few steps from the MVP.
The core idea here is to have a game world in which you can just say anything you like to game characters, and they can say sensible things back.
But actually, I know that speech to text can be reasonably effectively done; and I believe with a slightly lower degree of confidence that text to convincing speech can also be done.
I also know that the movement of a character around a convincing three dimensional representation of a world can be done, but that a great deal of effort is needed to build that world.
The minimum viable product does not need to demonstrate features which people have reasonable confidence can be done. What I need to demonstrate is the things which people haven't seen done, or haven't seen done well.
## Prototype one: the minimum viable product
The minimum viable product can have just a text adventure style interface:
> You are in the market square. It is mid morning. To the north is the guild hall; to the east there are market stalls; to the south is the residence; to the west is the bridge gate.
> There is a merchant here; there is a guardsman here.
To which the user can type (for example)
> Say to the guardsman, "Can you direct me to Master Dalwhiel's house?"
Within that interface, you should be able to interact with characters who:
1. have different levels of knowledge of the world, partly driven by their age, trade and personal history;
2. move about and exchange gossip, even when the player is not present to see/hear this;
3. have different attitudes towards the player and other characters, which will be modified by what they learn in gossip;
4. have their own hierarchies of needs, which they make plans to satisfy;
5. have homes and trades;
6. will respond to speech addressed to them by the player depending on their attitude to the player, how busy they are and their knowledge of the world; and
7. as a stretch goal, will have different dialects in which they will express their responses to the player.
There should be one or two multiple decision point quests in this world which can be resolved by talking to characters.
## Prototype two: adding organic quests
Extends prototype one only by adding [organic quests](Organic_Quests).
## Prototype three: voice interaction
Extends prototype two by adding speech to text, so that the player can directly talk (via a microphone) to characters, and text to speech, so that the system can voice the characters' responses.
Different characters should have different voices.
## Prototype four: performative speech
This one is hard because I'm not absolutely sure how I can do it, but I need characters' voices to convey emotion; the player needs to know from their voice whether they are angry, or frightened, or impatient, or bored.
## Prototype five traversible world
Now, a small section of a three dimensional open world, with at this stage simple block buildings that the player cannot enter, within which the characters act out their lives.
Stretch goal, [JALI](https://www.youtube.com/watch?v=uFIxiz0jwRE)-like lip sync.

View file

@ -4,7 +4,7 @@
The Great Game exists as a project on two levels. One one level, it's a framework for building algorithms to build much more vibrant, and thus enjoyable game worlds; at another level, it's about building a particular world, in which I want to tell stories.
The world in which I want to tell stories is a world which is based roughly on late bronze age to medieval Europe. It's a world in which the region known as 'The Coast' - the southern litoral of the continent - had been a mostly-peaceful matrideic dispersed agrarian tribal society, which had been invaded some hundreds of years past by a warrior tribe with substntially better military technology.
The world in which I want to tell stories is a world which is based roughly on late bronze age to medieval Europe. It's a world in which the region known as 'The Coast' -- the southern littoral of the continent -- had been a mostly-peaceful matrideic dispersed agrarian tribal society, which had been invaded some hundreds of years past by a warrior tribe with substantially better military technology.
These warrior tribesmen have settled down as local tyrants or robber barons, parasitising on the indigenous communities, and have evolved into an aristocratic ('Ariston') class. In the meantime, a mercantile class has grown up and established important long distance overland trade routes; and significant towns (called 'cities', but of only at most a few tens of thousand inhabitants) have grown up around markets.
@ -12,7 +12,7 @@ These mercantile cities have been under the governance of powerful aristons know
In the very earliest days of the warrior invasion, the warriors themselves fought against the indigenous peoples, who had very limited military equipment and tactics. Later, as they settled into Aristons, they fought by leading feudal levies of partially-trained peasants. Over the past hundred years or so, mercenary companies have emerged of specialist, trained warriors, and because these have more fighting experience (and often better equipment) they tend to beat feudal levies. These mercenary companies are base loosely on the condottierri of fourteenth century Italy.
So more and more, tyrranoi, rather than leading their own feudal levies, instead tax their peasantry mercantile class more and hire condottierri to fight their wars.
So more and more, tyrranoi, rather than leading their own feudal levies, instead tax their peasantry and mercantile class more and hire condottierri to fight their wars.
Mercenary companies evolve out of feudal levies, and in the period of The Great Game, are mostly owned and led by aristons who employ their soldiers by paying them a wage.
@ -24,4 +24,4 @@ One of the themes of the stories I want to tell is that this more democratic str
## Modelling democracy
If each individual character has a hierachy of needs, and plans actions based on that heirarchy of needs, then they have the mechanism in place to choose which of two options better conforms to their hierarchy of needs.
If each individual character has a hierarchy of needs, and plans actions based on that hierarchy of needs, then they have the mechanism in place to choose which of two options better conforms to their hierarchy of needs.

View file

@ -70,6 +70,23 @@
It's assumed that a journeyman scholar, presented with the opportunity, would prefer to become an apprentice magus than a master scholar.
### Related crafts
There are groups of crafts which should probably be seen as related crafts, where apprenticeship in one should serve as qualification to serve as journeyman in another. For example, there is a family of woodworking crafts, whose base is probably `Joiner`.
Crafts within this family include
* Boatwright
* Cabinetmaker
* Cartwright
* Cooper
* Lutanist
* Military Artificer
* Millwright
* Turner
So although I think these are separate crafts, all are Joiners; all can undertake construction joinery work; and a journeyman who has served as apprentice to any can serve as journeyman to any other. Since journeymen will typically serve under more than one master before settling down, it will be possible for one person to have served under masters in two different related trades and therefore be qualified to set up as a master of either.
A journeyman settles and becomes a master when he finds a location with at least the solo/min number of appropriate customer type who are not serviced by another master craftsman of the same craft; he also (obviously) needs to find enough free land to set up his dwelling. The radius within which his serviced customers must live may be a fixed 10Km or it may be variable dependent on craft. If there are unserviced customers within his service radius, the master craftsman may take on apprentices and journeymen to service the additional customers up to a fixed limit perhaps a maximum of four of each, perhaps variable by craft. If the number of customers falls, the master craftsman will first dismiss journeymen, and only in desperate circumstances dismiss apprentices. Every apprentice becomes a journeyman after three years service.
The list of crafts given here is illustrative, not necessarily exhaustive.

View file

@ -0,0 +1,54 @@
# Things Voice Interaction Enables
## Organic quest routing
In a world in which you can talk to non-player characters, and in which non-player characters know the directions to things which are local to their homes (and some, travellers, will be able to give you routes to things further away), when you need to get to your next waypoint you can just ask for directions. That much is easy.
But something much richer occurred to me.
Suppose you're entering a village, and you meet a random character. That character knows any local quest giver, and what it is that quest giver needs and, indeed, they know this whether the quest is scripted or organic.
So the random character could say
> Hello, I'm Tobias, and that my mill over there. Who might you be, stranger?
At which point you can either tell him, or not. Suppose you tell him, he could say
> Oh! I've heard of you. It's said you're very handy with a sword.
And you can reply however you like, acknowledging, or being modest, or perhaps even denying (although from this line of dialogue if you deny he'll think you're being modest, for reasons see later). He can then say, taking our example from the 'abducted child' quest in [the Introduction](intro,html),
> Thing is, old granny Grizzel's granddaughter Esmerelda has been abducted by bandits, and we've done a whip-around for a reward for someone who can rescue the girl.
At which point you may reply that you'll do it, or be non-committal, or say you won't. If you say you will, he can say,
> Well, you should talk to granny Grizzel, she lives in the white house by the crossroads, half a mile that-a-way (pointing).
If you say you won't, he can say,
> It would be a virtuous act, the old lady is fair desperate. If you should change your mind, you should talk to her; she lives in the white house by the crossroads, half a mile that-a-way (pointing).
OK, but what if, in the game world, the player character is not good with a sword? Well, the 'abducted child' quest can be resolved by violence; but it can also be resolved by persuasion, or by sneakiness, or by bribery. So suppose the player isn't (in the game) good with a sword, but is good at negotiation. Then in the initial approach, Tobias could say
> Oh! I've heard of you. It's said you're very handy at persuasion... Thing is, old granny Grizzel's granddaughter Esmerelda has been abducted by bandits, and we've done a whip-around for a ransom, but she's lacking someone who can negotiate for her.
It's the same quest, and, whatever Tobias has said, the player can still use either violence or persuasion or trickery to complete the quest (and gain appropriate reputation thereby), but it's flexible enough to adapt to the player's in-game persona, and it means we can direct the player to quest-givers without having to stick a bloody great icon on the quest giver's head.
So, to repeat for clarity: the idea is, if there is a quest in the vicinity, whether organic or scripted, all the quest giver's neighbours know about it, and will bring it up in conversation, introducing it and directing the player to the quest giver. And I believe that this can be done reasonably naturally.
## Command in Battles
Player characters in role playing games are often narratively great heroic leaders -- see any of the Dragon Age games but particularly Inquisition for examples of this -- but when it comes to a pitched battle all they can do is follow a scripted battle plan and fight individual actions, because in current generation role-playing games there is no effective user interface to allow strategic and tactical control of a battle.
So how would a real-world, before modern communications technology, war leader command a battle? Why, by observing the battle and talking to people, and those are both things that in our game the player can do.
So, there are two stages to battle communication: the first is the council of war, before the battle, in which the battle plan is agreed. For the non-player characters to have any significant input into this, we'd need a really good knowledge base of appropriate battle strategies with heuristics for which plan fits which sort of geography and which sort of enemy, but that could be quite fun to develop; but in principle it's sufficient for the player character to be able to say to each of the divisional captains "I want you to do this," and for each captain to say first "yes, I understand" (or "please clarify"), and then "yes, I will do it" (or "yes, I will try").
No battle plan, of course, survives first contact with the enemy. It must be possible to update the plan during the battle, and messengers were used to carry new orders from the commander to subordinates. That, of course, we can also do.
So, ideally (and in describing this I'll try to give 'less than ideal' alternatives where I see them), you can gather your captains to a council of war, either by speaking to them directly or by sending messengers round. At the council of war, non-player-character captains can suggest possible battle plans drawn from a common knowledge base, but can have individual levels of boldness or caution. However, if you've been appointed battle leader, then provided they're individually still loyal to you then they will ultimately agree to what you order.
When battle is joined you can either join in the fighting in the front line in which case your strategic overview is going to be very limited and you'll just have to hope your initial plan was good enough; or else you can sit on a hilltop overlooking the battlefield with your trumpeter and your messengers, and send messages to control the fight, but not actually take part much yourself (unless everything really goes to shit and your position is overrun).
In real world battles orders were often misunderstood; I don't think I should do anything special to model that. But orders (other than trumpet calls) will necessarily take finite time, and if the battlefront is really messed up messengers may fail to get through.

1
doc/genetic-buildings.md Symbolic link
View file

@ -0,0 +1 @@
workspace/blogiv/content/md/posts/2013-07-04-genetic-buildings.md

View file

@ -11,3 +11,9 @@ Time has passed; events in the game world have moved on. You can talk to your sa
So who are the non-enemies? It depends on context. If you have a party, and some of that party survived the fight, it's your party. Otherwise, if you're in a populated place, it's locals. If it's on a road or other route, it's passing merchants. If you're in the wilderness, a hunting party. It's a bunch of non-hostiles who might reasonably be expected to be around: that's what matters. It's about not breaking immersion.
Obviously losing a fight must have weight, it must have meaning, it must have in-game consequences; otherwise it is meaningless.
## Injury
Similarly to death, injury must have meaning. Any injury takes time to recover from. It takes a certain amount of time if you're able to rest somewhere safe, and considerably longer if you're not. If you fight while injured, you'll have less strength, less stramina, and probably also less agility. Depending where you're injured, there will be certain things you cannot do. If you fight while injured, also, your recovery time will be extended, even if you take no further injury.
Some serious injuries will lead to permanent scarring, and permanent loss of agility; you'll be just slightly slower in fights.

View file

@ -11,24 +11,24 @@
:output-path "docs/codox"
:source-uri "https://github.com/simon-brooke/the-great-game/blob/master/{filepath}#L{line}"}
:cucumber-feature-paths ["test/features/"]
:dependencies [;;[codox "0.10.7-cloverage"]
[com.taoensso/timbre "5.1.2"]
:dependencies [[com.taoensso/timbre "6.5.0"]
[environ "1.2.0"]
[jme-clj "0.1.13"]
;; [jme3-core "3.4.0-stable"]
[journeyman-cc/walkmap "0.1.0-SNAPSHOT"]
[me.raynes/fs "1.4.6"]
[mw-engine "0.1.6-SNAPSHOT"]
[mw-engine "0.1.6"]
[org.apache.commons/commons-math3 "3.6.1"] ;; for mersenne-twister implementation
[org.clojure/algo.generic "0.1.3"]
[org.clojure/clojure "1.10.3"]
[org.clojure/math.numeric-tower "0.0.5"]
[org.clojure/tools.namespace "1.1.1"]
[org.clojure/tools.reader "1.3.6"]]
[org.clojure/algo.generic "1.0.0"]
[org.clojure/clojure "1.11.2"]
[org.clojure/math.numeric-tower "0.1.0"]
[org.clojure/tools.namespace "1.5.0"]
[org.clojure/tools.reader "1.4.1"]]
:description "Prototype code towards the great game I've been writing about for ten years, and know I will never finish."
:license {:name "GNU General Public License,version 2.0 or (at your option) any later version"
:url "https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html"}
:plugins [[lein-cloverage "1.2.2"]
:plugins [[lein-adl "0.1.7"]
[lein-cloverage "1.2.2"]
[lein-codox "0.10.7-cloverage"]
[lein-cucumber "1.0.2"]
[lein-gorilla "0.4.0"]]

77
the-great-game.adl.xml Normal file
View file

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- DOCTYPE application PUBLIC "-//JOURNEYMAN//DTD ADL 1.4.1//EN"
"http://www.journeyman.cc/adl/stable/adl/schemas/adl-1.4.1.dtd" -->
<application xmlns="http://bowyer.journeyman.cc/adl/1.4.1/"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:adl="http://www.journeyman.cc/adl/1.4.1/" name="youyesyet" version="0.1.1">
<documentation>
At this stage, primarily a data-driven lore repository.
At some future stage, perhaps a specification for the game's internal state.
</documentation>
<group name="public">
<documentation>All users</documentation>
</group>
<entity table="objects" name="object">
<documentation>Physical opjects in the game world; it's probable that
properties like 'mesh' and 'skin' will end up here.</documentation>
<key>
<property required="true" type="integer" name="id" column="id" immutable="true" distinct="system">
<documentation>Note that this key is special, as for every instance of
a game object there will be an object record, and thus, for example,
every character will have exactly one object record associated with
it; thus, for example, the key value in the character table will be
the key value of the associated object record.</documentation>
<generator action="native"/>
</property>
</key>
<property required="true" type="boolean" default="false" name="container"/>
<property type="text" name="notes">
<description>Working notes about this object</description>
</property>
<property required="true" type="real" name="x">
<documentation>Easting from the origin, in metres.</documentation>
</property>
<property required="true" type="real" name="y">
<documentation>Northing from the origin, in metres.</documentation>
</property>
<property required="true" type="real" name="z">
<documentation>Altitude above the mean sea level, in metres.</documentation>
</property>
<property type="list" name="contents" entity="object">
<documentation>Contents of this object, if it is a container.</documentation>
</property>
<property type="entity" name="containedin" entity="object"/>
<!-- model? -->
<!-- texture? -->
</entity>
<entity table="agent" name="agent">
<documentation>An object with agency: a hierarchy of needs, a planning
process, locomotion.</document>
<key>
<property type="entity" name="id" entity="object"/>
</key>
<property type="entity" entity="species" name="species"/>
<property type="entity" entity="planner" name="planner">
<documentation>
The function used to plan the next action for this agent.
</documentation>
</property>
</entity>
<entity table="character" name="character">
<documentation>A character with a repertoire: knowledge, dialect, voice,
et cetera.</document>
<key>
<property type="entity" name="id" entity="object"/>
</key>
<property type="string" name="personal-name" size="80"/>
<property type="entity" entity="trade" name="trade"/>
<property type="entity" entity="rank" name="rank"/>
<property type="entity" entity="clan" name="clan"/>
<property type="entity" entity="character" name="father"/>
<property type="entity" entity="character" name="mother"/>
<property type="entity" entity="responder" name="responder"/>
</entity>
</application>