From 32d6d71e6c5d7f428ee15fb7d64ae4cba4890bc8 Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Thu, 10 Jun 2021 12:35:55 +0100 Subject: [PATCH 1/2] All but one test on gossip.news-items pass Ran 23 tests containing 105 assertions. 1 failures, 0 errors. --- .gitignore | 8 +- ....the-great-game.buildings.rectangular.html | 2 +- ...yman.the-great-game.gossip.news-items.html | 24 ++-- ...cc.journeyman.the-great-game.playroom.html | 2 +- .../cc.journeyman.the-great-game.utils.html | 2 +- docs/codox/index.html | 2 +- .../the_great_game/gossip/news_items.clj | 116 +++++++++++------- src/cc/journeyman/the_great_game/playroom.clj | 38 +++--- src/cc/journeyman/the_great_game/utils.clj | 16 +++ .../the_great_game/gossip/news_items_test.clj | 64 ++++++++-- 10 files changed, 185 insertions(+), 89 deletions(-) diff --git a/.gitignore b/.gitignore index 6b0fff5..8c0f0c9 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,10 @@ libopenal64.so .settings/ .classpath -.project \ No newline at end of file +.project + +.calva/ +.lsp/ + + +*.so diff --git a/docs/codox/cc.journeyman.the-great-game.buildings.rectangular.html b/docs/codox/cc.journeyman.the-great-game.buildings.rectangular.html index 19bbb30..f40f9d0 100644 --- a/docs/codox/cc.journeyman.the-great-game.buildings.rectangular.html +++ b/docs/codox/cc.journeyman.the-great-game.buildings.rectangular.html @@ -29,4 +29,4 @@
  • crafts to which it is appropriate;
  • cultures to which it is appropriate.
  • -

    Each generated building will be of one family, and will comprise modules taken only from that family.

    *crafts*

    dynamic

    Crafts which affect building types in the game. See Populating a game world. TODO: placeholder

    *cultures*

    dynamic

    Cultures which affect building families. TODO: placeholder

    *terrain-types*

    dynamic

    Types of terrain which affect building families. TODO: This is a placeholder; a more sophisticated model will be needed.

    build!

    (build! holding terrain culture craft size)

    Builds a building, and returns a data structure which represents it. In building the building, it adds a model of the building to the representation of the world, so it does have a side effect.

    building-family

    (building-family terrain culture craft gene)

    A building family is essentially a collection of models of building modules which can be assembled to create buildings of a particular structural and architectural style.

    \ No newline at end of file +

    Each generated building will be of one family, and will comprise modules taken only from that family.

    *crafts*

    dynamic

    Crafts which affect building types in the game. See Populating a game world. TODO: placeholder

    *cultures*

    dynamic

    Cultures which affect building families. TODO: placeholder

    *terrain-types*

    dynamic

    Types of terrain which affect building families. TODO: This is a placeholder; a more sophisticated model will be needed.

    build!

    (build! holding terrain culture craft size)

    Builds a building, and returns a data structure which represents it. In building the building, it adds a model of the building to the representation of the world, so it does have a side effect.

    building-family

    (building-family terrain culture craft gene)

    A building family is essentially a collection of models of building modules which can be assembled to create buildings of a particular structural and architectural style.

    \ No newline at end of file diff --git a/docs/codox/cc.journeyman.the-great-game.gossip.news-items.html b/docs/codox/cc.journeyman.the-great-game.gossip.news-items.html index 9d3f18a..8042fd0 100644 --- a/docs/codox/cc.journeyman.the-great-game.gossip.news-items.html +++ b/docs/codox/cc.journeyman.the-great-game.gossip.news-items.html @@ -1,19 +1,22 @@ -cc.journeyman.the-great-game.gossip.news-items documentation

    cc.journeyman.the-great-game.gossip.news-items

    Categories of news events interesting to gossip agents.

    +cc.journeyman.the-great-game.gossip.news-items documentation

    cc.journeyman.the-great-game.gossip.news-items

    Using news items (propositions) to transfer knowledge between gossip agents.

    +

    Status

    +

    What is here is essentially working. It’s not, however, working with the rich data objects which will be needed, and it’s not yet nearly efficient enough, but it allows knowledge to propagate through the world procedurally, at a rate limited by the speed of movement of the gossip agents.

    +

    Discussion

    The ideas here are based on the essay The spread of knowledge in a large game world, q.v.; they’ve advanced a little beyond that and will doubtless advance further in the course of writing and debugging this namespace.

    A news item is a map with the keys:

      -
    • date - the date on which the reported event happened;
    • +
    • date - the date on which the reported event is claimed to have happened;
    • nth-hand - the number of agents the news item has passed through;
    • verb - what it is that happened (key into news-topics);

    plus other keys taken from the keys value associated with the verb in news-topics.

    Notes:

    -

    TODO
    This namespace at present considers the :knowledge of a gossip to be a flat list of propositions, each of which must be checked every time any new proposition is offered. This is woefully inefficient.

    compatible-item?

    (compatible-item? new-item known-item)

    True if new-item is identical with, or less specific than, known-item.

    -

    If we already know ‘Bad Joe killed Sweet Daisy’, there’s no point in learning that ‘someone killed Sweet Daisy’, but there is point in learning ‘someone killed Sweet Daisy with poison’.

    compatible-value?

    (compatible-value? new-value known-value)

    True if known-value is the same as new-value, or, for each key present in new-value, has the same value for that key.

    -

    The rationale here is that if new-value contains new or different information, it’s worth learning; otherwise, not.

    degrade-character

    (degrade-character gossip character)

    Return a character specification like this character, but comprising only those properties this gossip is interested in.

    degrade-location

    (degrade-location gossip location)

    Return a location specification like this location, but comprising only those elements this gossip is interested in. If none, return nil.

    inc-or-one

    (inc-or-one val)

    If this val is a number, return that number incremented by one; otherwise, return 1. TODO: should probably be in utils.

    infer

    (infer item rule)

    Infer a new knowledge item from this item, following this rule

    interest-in-character

    (interest-in-character gossip character)

    Integer representation of how interesting this character is to this gossip. TODO: this assumes that characters are passed as keywords, but, as documented above, they probably have to be maps, to allow for degradation.

    interest-in-location

    (interest-in-location gossip location)

    Integer representation of how interesting this location is to this gossip.

    interesting-character?

    (interesting-character? gossip character)

    Boolean representation of whether this character is interesting to this gossip.

    interesting-item?

    (interesting-item? gossip item)

    True if anything about this news item is interesting to this gossip.

    interesting-location?

    (interesting-location? gossip item)

    True if the location of this news item is interesting to this gossip.

    interesting-object?

    (interesting-object? gossip object)

    TODO: write docs

    interesting-topic?

    (interesting-topic? gossip topic)

    TODO: write docs

    known-item?

    (known-item? gossip item)

    True if this news item is already known to this gossip.

    -

    This means that the gossip already knows an item which identifiably has the same or more specific values for all the keys of this item except :nth-hand, :confidence and :learned-from.

    learn-news-item

    (learn-news-item gossip item)(learn-news-item gossip item follow-inferences?)

    Return a gossip like this gossip, which has learned this news item if it is of interest to them.

    make-all-inferences

    (make-all-inferences item)

    Return a list of knowledge entries that can be inferred from this news item.

    news-topics

    Topics of interest to gossip agents. Topics are keyed in this map by their verbs. The keys associated with each topic are the extra pieces of information required to give context to a gossip item. Generally:

    +

    TODO
    This namespace at present considers the :knowledge of a gossip to be a flat list of propositions, each of which must be checked every time any new proposition is offered. This is woefully inefficient.

    all-known-verbs

    All verbs currently known to the gossip system.

    compatible-item?

    (compatible-item? new-item known-item)

    True if new-item is identical with, or less specific than, known-item.

    +

    If we already know ‘Bad Joe killed Sweet Daisy’, there’s no point in learning that ‘someone killed Sweet Daisy’, but there is point in learning ‘someone killed Sweet Daisy with poison’.

    compatible-value?

    (compatible-value? new-value known-value)

    True if known-value is the same as new-value, or, for each key present in new-value, has the same value for that key.

    +

    The rationale here is that if new-value contains new or different information, it’s worth learning; otherwise, not.

    degrade-character

    (degrade-character gossip character)

    Return a character specification like this character, but comprising only those properties this gossip is interested in.

    degrade-location

    (degrade-location gossip location)

    Return a location specification like this location, but comprising only those elements this gossip is interested in. If none, return nil.

    degrade-news-item

    (degrade-news-item gossip item)

    TODO: write docs

    infer

    (infer item rule)

    Infer a new knowledge item from this item, following this rule.

    interest-in-character

    (interest-in-character gossip character)

    Integer representation of how interesting this character is to this gossip. TODO: this assumes that characters are passed as keywords, but, as documented above, they probably have to be maps, to allow for degradation.

    interest-in-location

    (interest-in-location gossip location)

    Integer representation of how interesting this location is to this gossip.

    interesting-character?

    (interesting-character? gossip character)

    Boolean representation of whether this character is interesting to this gossip.

    interesting-item?

    (interesting-item? gossip item)

    True if anything about this news item is interesting to this gossip.

    interesting-location?

    (interesting-location? gossip location)

    True if the location of this news item is interesting to this gossip.

    interesting-object?

    (interesting-object? gossip object)

    TODO: write docs

    interesting-topic?

    (interesting-topic? gossip topic)

    TODO: write docs

    interesting-verb?

    (interesting-verb? gossip verb)

    Is this verb interesting to this gossip?

    known-item?

    (known-item? gossip item)

    True if this news item is already known to this gossip.

    +

    This means that the gossip already knows an item which identifiably has the same or more specific values for all the keys of this item except :nth-hand, :confidence and :learned-from.

    learn-news-item

    (learn-news-item gossip item)(learn-news-item gossip item follow-inferences?)

    Return a gossip like this gossip, which has learned this news item if it is of interest to them.

    make-all-inferences

    (make-all-inferences item)

    Return a set of knowledge entries that can be inferred from this news item.

    news-topics

    Topics of interest to gossip agents. Topics are keyed in this map by their verbs. The keys associated with each topic are the extra pieces of information required to give context to a gossip item. Generally:

    • actor is the id of the character who it is reported performed the action;
    • other is the id of the character on whom it is reported the action was performed;
    • @@ -21,12 +24,11 @@
    • object is an object (or possibly list of objects?) relevant to the action;
    • price is special to buy/sell, but of significant interest to merchants.
    -

    Notes

    -

    Characters

    +

    Characters

    TODO but note that at most all the receiver can learn about a character from a news item is what the giver knows about that character, degraded by what the receiver finds interesting about them. If we just pass the id here, then either the receiver knows everything in the database about the character, or else the receiver knows nothing at all about the character. Neither is desirable. Further thought needed.

    By implication, the character values passed should include all the information the giver knows about the character; that can then be degraded as the receiver stores only that segment which the receiver finds interesting.

    -

    Locations

    +

    Locations

    A ‘location’ value is a list comprising at most the x/y coordinate location and the ids of the settlement and region (possibly hierarchically) that contain the location. If the x/y is not local to the home of the receiving agent, they won’t remember it and won’t pass it on; if any of the ids are not interesting So location information will degrade progressively as the item is passed along.

    It is assumed that the :home of a character is a location in this sense.

    -

    Inferences

    -

    If an agent learns that Adam has married Betty, they can infer that Betty has married Adam; if they learn that Charles killed Dorothy, that Dorothy has died. I’m not convinced that my representation of inferences here is ideal.

    \ No newline at end of file +

    Inferences

    +

    If an agent learns that Adam has married Betty, they can infer that Betty has married Adam; if they learn that Charles killed Dorothy, that Dorothy has died. I’m not convinced that my representation of inferences here is ideal.

    \ No newline at end of file diff --git a/docs/codox/cc.journeyman.the-great-game.playroom.html b/docs/codox/cc.journeyman.the-great-game.playroom.html index fe8bbe5..6cfc303 100644 --- a/docs/codox/cc.journeyman.the-great-game.playroom.html +++ b/docs/codox/cc.journeyman.the-great-game.playroom.html @@ -1,3 +1,3 @@ -cc.journeyman.the-great-game.playroom documentation

    cc.journeyman.the-great-game.playroom

    TODO: write docs

    app

    TODO: write docs

    init

    (init)

    TODO: write docs

    simple-update

    (simple-update tpf)

    TODO: write docs

    \ No newline at end of file +cc.journeyman.the-great-game.playroom documentation

    cc.journeyman.the-great-game.playroom

    TODO: write docs

    app

    TODO: write docs

    init

    (init)

    TODO: write docs

    simple-update

    (simple-update tpf)

    TODO: write docs

    \ No newline at end of file diff --git a/docs/codox/cc.journeyman.the-great-game.utils.html b/docs/codox/cc.journeyman.the-great-game.utils.html index d44da8a..8304424 100644 --- a/docs/codox/cc.journeyman.the-great-game.utils.html +++ b/docs/codox/cc.journeyman.the-great-game.utils.html @@ -1,3 +1,3 @@ -cc.journeyman.the-great-game.utils documentation

    cc.journeyman.the-great-game.utils

    TODO: write docs

    cyclic?

    (cyclic? route)

    True if two or more elements of route are identical

    deep-merge

    (deep-merge & maps)

    make-target-filter

    (make-target-filter targets)

    Construct a filter which, when applied to a list of maps, will pass those which match these targets, where each target is a tuple [key value].

    value-or-default

    (value-or-default m k dflt)

    Return the value of this key k in this map m, or this dflt value if there is none.

    \ No newline at end of file +cc.journeyman.the-great-game.utils documentation

    cc.journeyman.the-great-game.utils

    TODO: write docs

    cyclic?

    (cyclic? route)

    True if two or more elements of route are identical

    deep-merge

    (deep-merge & maps)

    inc-or-one

    (inc-or-one val)

    If this val is a number, return that number incremented by one; otherwise, return 1. TODO: should probably be in utils.

    make-target-filter

    (make-target-filter targets)

    Construct a filter which, when applied to a list of maps, will pass those which match these targets, where each target is a tuple [key value].

    truthy?

    (truthy? val)

    Returns true unless val is nil, false or an empty sequence. Otherwise always ‘false’; never any other value.

    value-or-default

    (value-or-default m k dflt)

    Return the value of this key k in this map m, or this dflt value if there is none.

    \ No newline at end of file diff --git a/docs/codox/index.html b/docs/codox/index.html index c5e9a95..90e4395 100644 --- a/docs/codox/index.html +++ b/docs/codox/index.html @@ -1,3 +1,3 @@ -The-great-game 0.1.2-SNAPSHOT

    The-great-game 0.1.2-SNAPSHOT

    Released under the GNU General Public License,version 2.0 or (at your option) any later version

    Prototype code towards the great game I've been writing about for ten years, and know I will never finish.

    Installation

    To install, add the following dependency to your project or build file:

    [journeyman-cc/the-great-game "0.1.2-SNAPSHOT"]

    Topics

    Namespaces

    cc.journeyman.the-great-game.agent.agent

    Anything in the game world with agency; primarily but not exclusively characters.

    Public variables and functions:

    cc.journeyman.the-great-game.buildings.module

    A module of a building; essentially something like a portacabin, which can be assembled together with other modules to make a complete building.

    Public variables and functions:

      cc.journeyman.the-great-game.buildings.rectangular

      Build buildings with a generally rectangular floow plan.

      cc.journeyman.the-great-game.gossip.gossip

      Interchange of news events between gossip agents.

      Public variables and functions:

      cc.journeyman.the-great-game.holdings.holding

      TODO: write docs

      Public variables and functions:

      cc.journeyman.the-great-game.location.location

      TODO: write docs

      Public variables and functions:

      cc.journeyman.the-great-game.merchants.markets

      Adjusting quantities and prices in markets.

      Public variables and functions:

      cc.journeyman.the-great-game.merchants.merchant-utils

      Useful functions for doing low-level things with merchants.

      cc.journeyman.the-great-game.merchants.merchants

      Trade planning for merchants, primarily.

      Public variables and functions:

      cc.journeyman.the-great-game.merchants.planning

      Trade planning for merchants, primarily. This follows a simple-minded generate-and-test strategy and currently generates plans for all possible routes from the current location. This may not scale. Also, routes do not currently have cost or risk associated with them.

      cc.journeyman.the-great-game.merchants.strategies.simple

      Default trading strategy for merchants.

      Public variables and functions:

      cc.journeyman.the-great-game.objects.container

      TODO: write docs

      Public variables and functions:

      cc.journeyman.the-great-game.objects.game-object

      Anything at all in the game world

      Public variables and functions:

      cc.journeyman.the-great-game.playroom

      TODO: write docs

      Public variables and functions:

      cc.journeyman.the-great-game.world.heightmap

      Functions dealing with the tessellated multi-layer heightmap.

      cc.journeyman.the-great-game.world.location

      Functions dealing with location in the world.

      Public variables and functions:

      cc.journeyman.the-great-game.world.mw

      Functions dealing with building a great game world from a MicroWorld world.

      Public variables and functions:

        cc.journeyman.the-great-game.world.routes

        Conceptual (plan level) routes, represented as tuples of location ids.

        Public variables and functions:

        cc.journeyman.the-great-game.world.run

        Run the whole simulation

        Public variables and functions:

        cc.journeyman.the-great-game.world.world

        Access to data about the world

        Public variables and functions:

        \ No newline at end of file +The-great-game 0.1.2-SNAPSHOT

        The-great-game 0.1.2-SNAPSHOT

        Released under the GNU General Public License,version 2.0 or (at your option) any later version

        Prototype code towards the great game I've been writing about for ten years, and know I will never finish.

        Installation

        To install, add the following dependency to your project or build file:

        [journeyman-cc/the-great-game "0.1.2-SNAPSHOT"]

        Topics

        Namespaces

        cc.journeyman.the-great-game.agent.agent

        Anything in the game world with agency; primarily but not exclusively characters.

        Public variables and functions:

        cc.journeyman.the-great-game.buildings.module

        A module of a building; essentially something like a portacabin, which can be assembled together with other modules to make a complete building.

        Public variables and functions:

          cc.journeyman.the-great-game.buildings.rectangular

          Build buildings with a generally rectangular floow plan.

          cc.journeyman.the-great-game.gossip.gossip

          Interchange of news events between gossip agents.

          Public variables and functions:

          cc.journeyman.the-great-game.holdings.holding

          TODO: write docs

          Public variables and functions:

          cc.journeyman.the-great-game.location.location

          TODO: write docs

          Public variables and functions:

          cc.journeyman.the-great-game.merchants.markets

          Adjusting quantities and prices in markets.

          Public variables and functions:

          cc.journeyman.the-great-game.merchants.merchant-utils

          Useful functions for doing low-level things with merchants.

          cc.journeyman.the-great-game.merchants.merchants

          Trade planning for merchants, primarily.

          Public variables and functions:

          cc.journeyman.the-great-game.merchants.planning

          Trade planning for merchants, primarily. This follows a simple-minded generate-and-test strategy and currently generates plans for all possible routes from the current location. This may not scale. Also, routes do not currently have cost or risk associated with them.

          cc.journeyman.the-great-game.merchants.strategies.simple

          Default trading strategy for merchants.

          Public variables and functions:

          cc.journeyman.the-great-game.objects.container

          TODO: write docs

          Public variables and functions:

          cc.journeyman.the-great-game.objects.game-object

          Anything at all in the game world

          Public variables and functions:

          cc.journeyman.the-great-game.playroom

          TODO: write docs

          Public variables and functions:

          cc.journeyman.the-great-game.world.heightmap

          Functions dealing with the tessellated multi-layer heightmap.

          cc.journeyman.the-great-game.world.location

          Functions dealing with location in the world.

          Public variables and functions:

          cc.journeyman.the-great-game.world.mw

          Functions dealing with building a great game world from a MicroWorld world.

          Public variables and functions:

            cc.journeyman.the-great-game.world.routes

            Conceptual (plan level) routes, represented as tuples of location ids.

            Public variables and functions:

            cc.journeyman.the-great-game.world.run

            Run the whole simulation

            Public variables and functions:

            cc.journeyman.the-great-game.world.world

            Access to data about the world

            Public variables and functions:

            \ No newline at end of file diff --git a/src/cc/journeyman/the_great_game/gossip/news_items.clj b/src/cc/journeyman/the_great_game/gossip/news_items.clj index 18600de..1be80a3 100644 --- a/src/cc/journeyman/the_great_game/gossip/news_items.clj +++ b/src/cc/journeyman/the_great_game/gossip/news_items.clj @@ -1,6 +1,15 @@ (ns cc.journeyman.the-great-game.gossip.news-items "Using news items (propositions) to transfer knowledge between gossip agents. + ## Status + + What is here is essentially working. It's not, however, working with the + rich data objects which will be needed, and it's not yet nearly efficient + enough, but it allows knowledge to propagate through the world procedurally, + at a rate limited by the speed of movement of the gossip agents. + + ## Discussion + The ideas here are based on the essay [The spread of knowledge in a large game world](The-spread-of-knowledge-in-a-large-game-world.html), q.v.; they've advanced a little beyond that and will doubtless @@ -8,7 +17,7 @@ A news item is a map with the keys: - * `date` - the date on which the reported event happened; + * `date` - the date on which the reported event is claimed to have happened; * `nth-hand` - the number of agents the news item has passed through; * `verb` - what it is that happened (key into `news-topics`); @@ -23,9 +32,9 @@ proposition is offered. This is woefully inefficient. " (:require [cc.journeyman.the-great-game.world.location :refer [distance-between]] [cc.journeyman.the-great-game.time :refer [game-time]] + [cc.journeyman.the-great-game.utils :refer [inc-or-one truthy?]] [taoensso.timbre :as l])) - (def news-topics "Topics of interest to gossip agents. Topics are keyed in this map by their `verbs`. The `keys` associated with each topic are the extra pieces @@ -40,9 +49,7 @@ action; * `price` is special to buy/sell, but of significant interest to merchants. - ## Notes - - ### Characters + ## Characters *TODO* but note that at most all the receiver can learn about a character from a news item is what the giver knows about that character, degraded by @@ -56,7 +63,7 @@ as the receiver stores only that segment which the receiver finds interesting. - ### Locations + ## Locations A 'location' value is a list comprising at most the x/y coordinate location and the ids of the settlement and region (possibly hierarchically) that contain @@ -66,12 +73,11 @@ It is assumed that the `:home` of a character is a location in this sense. - ### Inferences + ## Inferences If an agent learns that Adam has married Betty, they can infer that Betty has married Adam; if they learn that Charles killed Dorothy, that Dorothy has died. - I'm not convinced that my representation of inferences here is ideal. - " + I'm not convinced that my representation of inferences here is ideal." {;; A significant attack is interesting whether or not it leads to deaths :attack {:verb :attack :keys [:actor :other :location]} ;; Deaths of characters may be interesting @@ -95,7 +101,7 @@ {:verb :sex} {:verb :sex :actor :other :other :actor}]} ;; Merchants, especially, are interested in prices in other markets - :sell {:verb :sell :keys [:actor :other :object :location :price]} + :sell {:verb :sell :keys [:actor :other :object :location :quantity :price]} ;; Sex can juicy gossip, although not normally if the participants are in an ;; established sexual relationship. :sex {:verb :sex :keys [:actor :other :location] @@ -110,6 +116,11 @@ :inferences [{:verb :war :actor :other :other :actor}]}}) +(def all-known-verbs + "All verbs currently known to the gossip system." + (set (keys news-topics))) + + (defn interest-in-character "Integer representation of how interesting this `character` is to this `gossip`. @@ -118,8 +129,11 @@ [gossip character] (count (concat - (filter #(= (:actor % character)) (:knowledge gossip)) - (filter #(= (:other % character)) (:knowledge gossip))))) + ;; TODO: we ought also check the relationships of the gossip. + ;; Are relationships just propositions in the knowledge base? + (filter #(= (:actor %) character) (:knowledge gossip)) + (filter #(= (:other %) character) (:knowledge gossip))))) + (defn interesting-character? "Boolean representation of whether this `character` is interesting to this @@ -135,10 +149,13 @@ (and (map? location) (number? (:x location)) (number? (:y location))) (if-let [home (:home gossip)] (let [d (distance-between location home) - i (/ 10000 d) ;; 10000 at metre scale is 10km; interest should + i (if + (zero? d) 1 + (/ 10000 d)) + ;; 10000 at metre scale is 10km; interest should ;;fall off with distance from home, but possibly on a log scale ] - (if (> i 1) i 0)) + (if (>= i 1) i 0)) 0) (coll? location) (reduce @@ -152,6 +169,7 @@ #(some (fn [x] (= x location)) (:location %)) (cons {:location (:home gossip)} (:knowledge gossip)))))) +;; (distance-between {:x 25 :y 37} {:x 25 :y 37}) ;; (interest-in-location {:home [{0, 0} :test-home] :knowledge []} [:test-home]) (defn interesting-location? @@ -169,6 +187,17 @@ ;; TODO: Not yet (really) implemented true) +(defn interesting-verb? + "Is this `verb` interesting to this `gossip`?" + [gossip verb] + (let [vs (:interesting-verbs gossip)] + (truthy? + (if (set? vs) + (vs verb) + false)))) + +;; (interesting-verb? {:interesting-verbs #{:kill :sell}} :sell) + (defn compatible-value? "True if `known-value` is the same as `new-value`, or, for each key present in `new-value`, has the same value for that key. @@ -191,16 +220,14 @@ learning that 'someone killed Sweet Daisy', but there is point in learning 'someone killed Sweet Daisy _with poison_'." [new-item known-item] - (if + (truthy? (reduce #(and %1 %2) (map #(if (known-item %) ;; if known-item has this key (compatible-value? (new-item %) (known-item %)) true) - (remove #{:nth-hand :confidence :learned-from} (keys new-item)))) - true - false)) + (remove #{:nth-hand :confidence :learned-from} (keys new-item)))))) (defn known-item? "True if this news `item` is already known to this `gossip`. @@ -209,18 +236,17 @@ the same _or more specific_ values for all the keys of this `item` except `:nth-hand`, `:confidence` and `:learned-from`." [gossip item] - (if + (truthy? (reduce #(or %1 %2) false - (filter true? (map #(compatible-item? item %) (:knowledge gossip)))) - true - false)) + (filter true? (map #(compatible-item? item %) (:knowledge gossip)))))) (defn interesting-item? "True if anything about this news `item` is interesting to this `gossip`." [gossip item] (and (not (known-item? gossip item)) + (interesting-verb? gossip item) ;; news is only interesting if the topic is. (or (interesting-character? gossip (:actor item)) (interesting-character? gossip (:other item)) @@ -228,15 +254,6 @@ (interesting-object? gossip (:object item)) (interesting-topic? gossip (:verb item))))) -(defn inc-or-one - "If this `val` is a number, return that number incremented by one; otherwise, - return 1. TODO: should probably be in `utils`." - [val] - (if - (number? val) - (inc val) - 1)) - (defn infer "Infer a new knowledge item from this `item`, following this `rule`." [item rule] @@ -281,6 +298,26 @@ location))] (when-not (empty? l) l))) +(defn degrade-news-item + [gossip item] + (assoc + item + :nth-hand (inc-or-one (:nth-hand item)) + :time-stamp (if + (number? (:time-stamp item)) + (:time-stamp item) + (game-time)) + :location (degrade-location gossip (:location item)) + :actor (degrade-character gossip (:actor item)) + :other (degrade-character gossip (:other item)) + ;; TODO: do something to degrade confidence in the item, + ;; probably as a function of the provider's confidence in + ;; the item and the gossip's trust in the provider + )) + +;; (degrade-news-item {:home [{:x 25 :y 37} :auchencairn :scotland]} +;; {:verb :marry :actor :adam :other :belinda :location [{:x 25 :y 37} :auchencairn :scotland]}) + (defn learn-news-item "Return a gossip like this `gossip`, which has learned this news `item` if it is of interest to them." @@ -289,20 +326,7 @@ ([gossip item follow-inferences?] (if (interesting-item? gossip item) - (let [item' (assoc - item - :nth-hand (inc-or-one (:nth-hand item)) - :time-stamp (if - (number? (:time-stamp item)) - (:time-stamp item) - (game-time)) - :location (degrade-location gossip (:location item)) - :actor (degrade-character gossip (:actor item)) - :other (degrade-character gossip (:other item)) - ;; TODO: do something to degrade confidence in the item, - ;; probably as a function of the provider's confidence in - ;; the item and the gossip's trust in the provider - ) + (let [item' (degrade-news-item gossip item) g (assoc gossip :knowledge @@ -313,7 +337,7 @@ (assoc g :knowledge - (concat (:knowledge g) (make-all-inferences item))) + (concat (:knowledge g) (make-all-inferences item'))) g))) gossip)) diff --git a/src/cc/journeyman/the_great_game/playroom.clj b/src/cc/journeyman/the_great_game/playroom.clj index 4ab671a..ad2cb2f 100644 --- a/src/cc/journeyman/the_great_game/playroom.clj +++ b/src/cc/journeyman/the_great_game/playroom.clj @@ -37,7 +37,7 @@ :init init :update simple-update) -(start app) +;; (start app) ;; Reinitialises the running app ;;(run app @@ -45,28 +45,28 @@ ;; By default, there is a Fly Camera attached to the app that you can control with W, A, S and D keys. ;; Let's increase its movement speed. Now, you fly faster :) - (run app - (set* (fly-cam) :move-speed 15)) + ;; (run app + ;; (set* (fly-cam) :move-speed 15)) ;; Updates the app -(run app - (let [{:keys [cube]} (get-state)] - (set* cube :local-translation (add (get* cube :local-translation) 1 1 1)))) +;; (run app +;; (let [{:keys [cube]} (get-state)] +;; (set* cube :local-translation (add (get* cube :local-translation) 1 1 1)))) ;; Updates the app adding a second cube -(run app - (let [cube (geo "jMonkey cube" (box 1 1 1)) - mat (unshaded-mat)] - (set* mat :texture "ColorMap" (load-texture "textures/Monkey.jpg")) - (setc cube - :material mat - :local-translation [-3 0 0]) - (add-to-root cube) - (set-state :cube2 cube))) +;; (run app +;; (let [cube (geo "jMonkey cube" (box 1 1 1)) +;; mat (unshaded-mat)] +;; (set* mat :texture "ColorMap" (load-texture "textures/Monkey.jpg")) +;; (setc cube +;; :material mat +;; :local-translation [-3 0 0]) +;; (add-to-root cube) +;; (set-state :cube2 cube))) ;; We added the new cube, but it's not rotating. We need to update the simple-update fn. - (defn simple-update [tpf] - (let [{:keys [cube cube2]} (get-state)] - (rotate cube 0 (* 2 tpf) 0) - (rotate cube2 0 (* 2 tpf) 0))) + ;; (defn simple-update [tpf] + ;; (let [{:keys [cube cube2]} (get-state)] + ;; (rotate cube 0 (* 2 tpf) 0) + ;; (rotate cube2 0 (* 2 tpf) 0))) diff --git a/src/cc/journeyman/the_great_game/utils.clj b/src/cc/journeyman/the_great_game/utils.clj index ff00cee..a25545f 100644 --- a/src/cc/journeyman/the_great_game/utils.clj +++ b/src/cc/journeyman/the_great_game/utils.clj @@ -43,3 +43,19 @@ ;; (value-or-default {:x 0 :y 0 :altitude 7} :altitude 8) ;; (value-or-default {:x 0 :y 0 :altitude 7} :alt 8) ;; (value-or-default nil :altitude 8) + +(defn truthy? + "Returns `true` unless `val` is `nil`, `false` or an empty sequence. + Otherwise always 'false'; never any other value." + [val] + (and (or val false) true)) + + +(defn inc-or-one + "If this `val` is a number, return that number incremented by one; otherwise, + return 1. TODO: should probably be in `utils`." + [val] + (if + (number? val) + (inc val) + 1)) diff --git a/test/cc/journeyman/the_great_game/gossip/news_items_test.clj b/test/cc/journeyman/the_great_game/gossip/news_items_test.clj index 50f062a..0a81179 100644 --- a/test/cc/journeyman/the_great_game/gossip/news_items_test.clj +++ b/test/cc/journeyman/the_great_game/gossip/news_items_test.clj @@ -1,8 +1,49 @@ (ns cc.journeyman.the-great-game.gossip.news-items-test (:require [clojure.test :refer [deftest is testing]] [cc.journeyman.the-great-game.gossip.news-items :refer - [compatible-item? degrade-location infer interest-in-location interesting-location? - learn-news-item make-all-inferences]])) + [all-known-verbs compatible-item? degrade-location infer + interest-in-character interesting-character? interest-in-location + interesting-location? learn-news-item make-all-inferences]])) + +(deftest interesting-character-tests + (testing "To what degree characters are of interest to the gossip" + (let [expected 1 + gossip {:home [{0, 0} :test-home] + :interesting-verbs all-known-verbs + ;; already knows about adam + :knowledge [{:verb :sell :actor :adam :other :charles :object :wheat :quantity 10 :price 5 :location [:test-home]}]} + actual (interest-in-character + gossip + :adam)] + (is (= actual expected))) + (let [expected 0 + gossip {:home [{0, 0} :test-home] + :interesting-verbs all-known-verbs + ;; already knows about adam + :knowledge [{:verb :sell :actor :adam :other :charles :object :wheat :quantity 10 :price 5 :location [:test-home]}]} + actual (interest-in-character + gossip + :dorothy)] + (is (= actual expected)))) + (testing "Whether characters are of interest to the gossip" + (let [expected true + gossip {:home [{0, 0} :test-home] + :interesting-verbs all-known-verbs + ;; already knows about adam + :knowledge [{:verb :sell :actor :adam :other :charles :object :wheat :quantity 10 :price 5 :location [:test-home]}]} + actual (interesting-character? + gossip + :adam)] + (is (= actual expected))) + (let [expected false + gossip {:home [{0, 0} :test-home] + :interesting-verbs all-known-verbs + ;; already knows about adam + :knowledge [{:verb :sell :actor :adam :other :charles :object :wheat :quantity 10 :price 5 :location [:test-home]}]} + actual (interesting-character? + gossip + :dorothy)] + (is (= actual expected))))) (deftest compatible-item-test (testing "Compatible item: items are identical" @@ -128,17 +169,17 @@ (deftest inference-tests (testing "Ability to infer new knowledge from news items: single rule tests" - (let [expected {:verb :marry, :actor :belinda, :other :adam} + (let [expected {:verb :marry, :actor :belinda, :other :adam, :nth-hand 1} item {:verb :marry :actor :adam :other :belinda} rule {:verb :marry :actor :other :other :actor} actual (infer item rule)] (is (= actual expected))) - (let [expected {:verb :attack, :actor :adam, :other :belinda} + (let [expected {:verb :attack, :actor :adam, :other :belinda, :nth-hand 1} item {:verb :rape :actor :adam :other :belinda} rule {:verb :attack} actual (infer item rule)] (is (= actual expected))) - (let [expected {:verb :sex, :actor :belinda, :other :adam} + (let [expected {:verb :sex, :actor :belinda, :other :adam, :nth-hand 1} item {:verb :rape :actor :adam :other :belinda} rule {:verb :sex :actor :other :other :actor} actual (infer item rule)] @@ -149,15 +190,22 @@ {:verb :attack, :actor :adam, :other :belinda, :location :test-home, :nth-hand 1}} ;; dates will not be and cannot be expected to be equal actual (set (make-all-inferences - {:verb :rape :actor :adam :other :belinda :location :test-home :nth-hand 1}))] + {:verb :rape :actor :adam :other :belinda :location :test-home}))] (is (= actual expected))))) (deftest learn-tests (testing "Learning from an interesting news item." (let [expected {:home [{0 0} :test-home] - :knowledge [{:verb :sex, :actor :adam, :other :belinda, :location [:test-home], :nth-hand 1} + :interesting-verbs all-known-verbs + :knowledge [{:verb :sell :actor :adam :other :charles :object :wheat :quantity 10 :price 5 :location [:test-home]} + {:verb :sex, :actor :adam, :other :belinda, :location [:test-home], :nth-hand 1} {:verb :sex, :actor :belinda, :other :adam, :location [:test-home], :nth-hand 1}]} + gossip {:home [{0, 0} :test-home] + :interesting-verbs all-known-verbs + ;; already knows about adam + :knowledge [{:verb :sell :actor :adam :other :charles :object :wheat :quantity 10 :price 5 :location [:test-home]}]} actual (learn-news-item - {:home [{0, 0} :test-home] :knowledge []} + gossip {:verb :sex :actor :adam :other :belinda :location [:test-home]})] (is (= actual expected))))) + From 3327ddc524a3e91e59e724ccfef8b84386ef040f Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Wed, 23 Jun 2021 09:58:42 +0100 Subject: [PATCH 2/2] More work on buildings, and on documentation --- .gitignore | 6 + .../the_great_game/buildings/module.clj.html | 251 +++ .../buildings/rectangular.clj.html | 224 +-- .../the_great_game/gossip/news_items.clj.html | 1358 +++++++++-------- .../the_great_game/location/location.clj.html | 6 - .../the_great_game/playroom.clj.html | 102 +- .../journeyman/the_great_game/utils.clj.html | 48 + docs/cloverage/index.html | 93 +- docs/codox/Baking-the-world.html | 2 +- docs/codox/Canonical-dictionary.html | 2 +- docs/codox/Dynamic-consequences.html | 2 +- docs/codox/Game_Play.html | 2 +- ...p_scripted_plot_and_Johnny_Silverhand.html | 2 +- docs/codox/Organic_Quests.html | 2 +- docs/codox/Pathmaking.html | 2 +- docs/codox/Populating-a-game-world.html | 2 +- docs/codox/Roadmap.html | 2 +- docs/codox/Settling-a-game-world.html | 2 +- docs/codox/Simulation-layers.html | 2 +- ...ad-of-knowledge-in-a-large-game-world.html | 2 +- docs/codox/Uncanny_dialogue.html | 2 +- .../Voice-acting-considered-harmful.html | 2 +- docs/codox/building_on_microworld.html | 2 +- ...journeyman.the-great-game.agent.agent.html | 2 +- ...eyman.the-great-game.buildings.module.html | 2 +- ....the-great-game.buildings.rectangular.html | 2 +- ...urneyman.the-great-game.gossip.gossip.html | 2 +- ...yman.the-great-game.gossip.news-items.html | 2 +- ...eyman.the-great-game.holdings.holding.html | 2 +- ...yman.the-great-game.location.location.html | 2 +- ...yman.the-great-game.merchants.markets.html | 2 +- ...e-great-game.merchants.merchant-utils.html | 2 +- ...an.the-great-game.merchants.merchants.html | 2 +- ...man.the-great-game.merchants.planning.html | 2 +- ...reat-game.merchants.strategies.simple.html | 2 +- ...yman.the-great-game.objects.container.html | 2 +- ...an.the-great-game.objects.game-object.html | 2 +- ...cc.journeyman.the-great-game.playroom.html | 2 +- .../cc.journeyman.the-great-game.time.html | 2 +- .../cc.journeyman.the-great-game.utils.html | 2 +- ...neyman.the-great-game.world.heightmap.html | 2 +- ...rneyman.the-great-game.world.location.html | 2 +- ...cc.journeyman.the-great-game.world.mw.html | 2 +- ...ourneyman.the-great-game.world.routes.html | 2 +- ...c.journeyman.the-great-game.world.run.html | 2 +- ...journeyman.the-great-game.world.world.html | 2 +- docs/codox/economy.html | 2 +- docs/codox/index.html | 2 +- docs/codox/intro.html | 2 +- .../modelling_trading_cost_and_risk.html | 2 +- docs/codox/naming-of-characters.html | 2 +- docs/codox/on-dying.html | 2 +- docs/codox/sandbox.html | 2 +- docs/codox/sexual-dimorphism.html | 2 +- project.clj | 23 +- workspace.code-workspace | 27 +- 56 files changed, 1279 insertions(+), 951 deletions(-) create mode 100644 docs/cloverage/cc/journeyman/the_great_game/buildings/module.clj.html diff --git a/.gitignore b/.gitignore index 8c0f0c9..8b36a8a 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,9 @@ libopenal64.so *.so + +docs/cloverage/codecov.json + +docs/cloverage/coverage.xml + +src/cc/journeyman/the_great_game/cloverage.clj diff --git a/docs/cloverage/cc/journeyman/the_great_game/buildings/module.clj.html b/docs/cloverage/cc/journeyman/the_great_game/buildings/module.clj.html new file mode 100644 index 0000000..55ed3f9 --- /dev/null +++ b/docs/cloverage/cc/journeyman/the_great_game/buildings/module.clj.html @@ -0,0 +1,251 @@ + + + + cc/journeyman/the_great_game/buildings/module.clj + + + + 001  (ns cc.journeyman.the-great-game.buildings.module +
            + + 002   +
            + + 003    "A module of a building; essentially something like a portacabin, which can be +
            + + 004     assembled together with other modules to make a complete building. +
            + + 005    +
            + + 006     Modules need to include +
            + + 007   +
            + + 008     1. Ground floor modules, having external doors; +
            + + 009     2. Craft modules -- workshops -- which will normally be ground floor (except +
            + + 010        weavers) and may have the constraint that no upper floor module can cover them; +
            + + 011     3. Upper floor modules, having NO external doors (but linking internal doors); +
            + + 012     4. Roof modules +
            + + 013      +
            + + 014     **Role** must be one of: +
            + + 015      +
            + + 016     1. `:primary` a ground floor main entrance module +
            + + 017     2. `:secondary` a module which can be upper or ground floor +
            + + 018     3. `:upper` a module which can only be on an upper floor, for example one +
            + + 019        with a projecting gallery, balcony or overhang. +
            + + 020      +
            + + 021     Other values for `role` will emerge. +
            + + 022      +
            + + 023     **Exits** must be a sequence of keywords taken from the following list: +
            + + 024      +
            + + 025     1. `:left` an exit in the centre of the left wall +
            + + 026     2. `:left-front` an exit in the centre of the left half of the front wall +
            + + 027     3. `:front` an exit in the centre of the front wall +
            + + 028     4. `:right-front` an exit in the centre of the right half of the front wall +
            + + 029     5. `:right` an exit in the centre of the right wall +
            + + 030     6. `:right-back` an exit in the centre of the right half of the back wall +
            + + 031     7. `:left-back` an exit in the centre of the back wall +
            + + 032         +
            + + 033     A module placed on an upper floor must have no exit which opens beyond the  +
            + + 034     footprint of the floor below - no doors into mid air! However, it is allowable  +
            + + 035     (and indeed is necessary) to allow doors into roof spaces if the adjacent +
            + + 036     module on the same floor does not yet exist, since otherwise it would be  +
            + + 037     impossible to access a new room which might later be built there. +
            + + 038      +
            + + 039     **Load** must be a small integer indicating both the weight of the module and  +
            + + 040     the total amount of weight it can support. So for example a stone-built module +
            + + 041     might have a `load` value of 4, a brick built one of 3, and a half-timbered one  +
            + + 042     of 2, and a tent of 0. This means a stone ground floor module could support one  +
            + + 043     further floor of stone or brick, or two further floors of half timbered  +
            + + 044     construction; while a brick built ground floor could support a single brick or  +
            + + 045     half-timbered upper floor but not a stone one, and a half-timbered ground floor +
            + + 046     could only support a half timbered upper floor. +
            + + 047      +
            + + 048     There also needs to be an undercroft or platform module, such that the area of  +
            + + 049     the top of the platform is identical with the footprint of the building, and  +
            + + 050     the altitude of the top of the platform is equal to the altitude of the  +
            + + 051     terrain at the heighest corner of the building; so that the actual  +
            + + 052     building doesn't float in the air, and also so that none of the doors or windows +
            + + 053     are partly underground. +
            + + 054   +
            + + 055     Each module needs to wrap an actual 3d model created in Blender or whatever,  +
            + + 056     and have a list of optional **textures** with which that model can be rendered.  +
            + + 057     So an upper floor bedroom module might have the following renders: +
            + + 058   +
            + + 059     1. Bare masonry - constrained to upland or plateau terrain, and to coastal culture +
            + + 060     2. Painted masonry - constrained to upland or plateau terrain, and to coastal culture +
            + + 061     3. Half-timbered - not available on plateau terrain +
            + + 062     4. Weatherboarded - constrained to forest terrain +
            + + 063     5. Brick - constrained to arable or arid terrain +
            + + 064   +
            + + 065     of course these are only examples, and also, it's entirely possible to have +
            + + 066     for example multiple different weatherboard renders for the same module.  +
            + + 067     There needs to be a way of rendering what can be built above what: for +
            + + 068     example, you can't have a masonry clad module over a half timbered one,  +
            + + 069     but you can have a half-timbered one over a masonry one.") +
            + + 070   +
            + + 071  (defrecord BuildingModule +
            + + 072    [model +
            + + 073     ^Double length +
            + + 074     ^Double width +
            + + 075     ^Double height +
            + + 076     ^Integer load  +
            + + 077     ^clojure.lang.Keyword role +
            + + 078     ^clojure.lang.IPersistentCollection textures +
            + + 079     ^clojure.lang.IPersistentCollection exits +
            + + 080     ] +
            + + 081    ) +
            + + diff --git a/docs/cloverage/cc/journeyman/the_great_game/buildings/rectangular.clj.html b/docs/cloverage/cc/journeyman/the_great_game/buildings/rectangular.clj.html index f276d7b..3ffd266 100644 --- a/docs/cloverage/cc/journeyman/the_great_game/buildings/rectangular.clj.html +++ b/docs/cloverage/cc/journeyman/the_great_game/buildings/rectangular.clj.html @@ -355,194 +355,104 @@ 117  
            - - 118  ;; TODO: So, modules need to contain + + 118   +
            + + 119  (defn building-family
            - 119  ;; + 120    "A building family is essentially a collection of models of building modules
            - 120  ;; 1. Ground floor modules, having external doors; + 121     which can be assembled to create buildings of a particular structural and
            - 121  ;; 2. Craft modules -- workshops -- which will normally be ground floor (except + 122     architectural style."
            - 122  ;; weavers) and may have the constraint that no upper floor module can cover them; + 123    [terrain culture craft gene] +
            + + 124    (let [candidates (filter #(and +
            + + 125                               ((:terrains %) terrain) +
            + + 126                               ((:crafts %) craft) +
            + + 127                               ((:cultures %) culture)) +
            + + 128                             (vals *building-families*))] +
            + + 129      (nth candidates (mod (Math/abs (.nextInt gene)) (count candidates))))) +
            + + 130   +
            + + 131  (building-family :arable :coastal :baker (MersenneTwister. 5)) +
            + + 132   +
            + + 133  (defn build! 
            - 123  ;; 3. Upper floor modules, having NO external doors (but linking internal doors); + 134    "Builds a building, and returns a data structure which represents it. In 
            - 124  ;; 4. Roof modules + 135     building the building, it adds a model of the building to the representation
            - 125  ;;  + 136     of the world, so it does have a side effect."
            - 126  ;; There also needs to be an undercroft or platform module, such that the area of  + 137    [holding terrain culture craft size] +
            + + 138    (if (satisfies? ProtoHolding holding) +
            + + 139    (let [location (.building-origin holding) +
            + + 140          gene (MersenneTwister. (int (+ (* (.easting location) 1000000) (.northing location)))) +
            + + 141          family (building-family terrain culture craft gene)] +
            + + 142    (if  +
            + + 143     (and (instance? ProtoLocation location) (:orientation location))
            - 127  ;; the top of the platform is identical with the footprint of the building, and  + 144      :stuff
            - 128  ;; the altitude of the top of the platform is equal to the altitude of the  + 145      :nonsense
            - 129  ;; terrain at the heighest corner of the building; so that the actual  + 146      ))
            - 130  ;; building doesn't float in the air, and also so that none of the doors or windows -
            - - 131  ;; are partly underground. -
            - - 132  ;; -
            - - 133  ;; Each module needs to wrap an actual 3d model created in Blender or whatever,  -
            - - 134  ;; and have a list of optional textures with which that model can be rendered.  -
            - - 135  ;; So an upper floor bedroom module might have the following renders: -
            - - 136  ;; -
            - - 137  ;; 1. Bare masonry - constrained to upland or plateau terrain, and to coastal culture -
            - - 138  ;; 2. Painted masonry - constrained to upland or plateau terrain, and to coastal culture -
            - - 139  ;; 3. Half-timbered - not available on plateau terrain -
            - - 140  ;; 4. Weatherboarded - constrained to forest terrain -
            - - 141  ;; 5. Brick - constrained to arable or arid terrain -
            - - 142  ;; -
            - - 143  ;; of course these are only examples, and also, it's entirely possible to have -
            - - 144  ;; for example multiple different weatherboard renders for the same module.  -
            - - 145  ;; There needs to be a way of rendering what can be built above what: for -
            - - 146  ;; example, you can't have a masonry clad module over a half timbered one,  -
            - - 147  ;; but you can have a half-timbered one over a masonry one + 147      :froboz))
            148  
            - - 149  (defn building-family -
            - 150    "A building family is essentially a collection of models of building modules -
            - - 151     which can be assembled to create buildings of a particular structural and -
            - - 152     architectural style." -
            - - 153    [terrain culture craft gene] -
            - - 154    (let [candidates (filter #(and -
            - - 155                               ((:terrains %) terrain) -
            - - 156                               ((:crafts %) craft) -
            - - 157                               ((:cultures %) culture)) -
            - - 158                             (vals *building-families*))] -
            - - 159      (nth candidates (mod (Math/abs (.nextInt gene)) (count candidates))))) + 149  ;; (def ol (cc.journeyman.the-great-game.location.location/OrientedLocation. 123.45 543.76 12.34 0.00 {}))
            - 160   -
            - - 161  (building-family :arable :coastal :baker (MersenneTwister. 5)) -
            - - 162   -
            - - 163  (defn build!  -
            - - 164    "Builds a building, and returns a data structure which represents it. In  -
            - - 165     building the building, it adds a model of the building to the representation -
            - - 166     of the world, so it does have a side effect." -
            - - 167    [holding terrain culture craft size] -
            - - 168    (if (satisfies? ProtoHolding holding) -
            - - 169    (let [location (.building-origin holding) -
            - - 170          gene (MersenneTwister. (int (+ (* (.easting location) 1000000) (.northing location)))) -
            - - 171          family (building-family terrain culture craft gene)] -
            - - 172    (if  -
            - - 173     (and (instance? ProtoLocation location) (:orientation location)) -
            - - 174      :stuff -
            - - 175      :nonsense -
            - - 176      )) -
            - - 177      :froboz)) -
            - - 178   -
            - - 179  ;; (def ol (cc.journeyman.the-great-game.location.location/OrientedLocation. 123.45 543.76 12.34 0.00 {})) -
            - - 180   + 150  
            diff --git a/docs/cloverage/cc/journeyman/the_great_game/gossip/news_items.clj.html b/docs/cloverage/cc/journeyman/the_great_game/gossip/news_items.clj.html index 3a27e1d..30f677a 100644 --- a/docs/cloverage/cc/journeyman/the_great_game/gossip/news_items.clj.html +++ b/docs/cloverage/cc/journeyman/the_great_game/gossip/news_items.clj.html @@ -8,940 +8,1036 @@ 001  (ns cc.journeyman.the-great-game.gossip.news-items

            - 002    "Categories of news events interesting to gossip agents. + 002    "Using news items (propositions) to transfer knowledge between gossip agents.
            003     
            - 004     The ideas here are based on the essay [The spread of knowledge in a large + 004     ## Status
            - 005     game world](The-spread-of-knowledge-in-a-large-game-world.html), q.v.;  + 005     
            - 006     they've advanced a little beyond that and will doubtless + 006     What is here is essentially working. It's not, however, working with the 
            - 007     advance further in the course of writing and debugging this namespace. + 007     rich data objects which will be needed, and it's not yet nearly efficient  +
            + + 008     enough, but it allows knowledge to propagate through the world procedurally, +
            + + 009     at a rate limited by the speed of movement of the gossip agents.
            - 008   + 010  
            - 009     A news item is a map with the keys: + 011     ## Discussion
            - 010    + 012     
            - 011     * `date` - the date on which the reported event happened; + 013     The ideas here are based on the essay [The spread of knowledge in a large
            - 012     * `nth-hand` - the number of agents the news item has passed through; + 014     game world](The-spread-of-knowledge-in-a-large-game-world.html), q.v.; 
            - 013     * `verb` - what it is that happened (key into `news-topics`); + 015     they've advanced a little beyond that and will doubtless +
            + + 016     advance further in the course of writing and debugging this namespace.
            - 014   + 017  
            - 015     plus other keys taken from the `keys` value associated with the verb in + 018     A news item is a map with the keys:
            - 016     `news-topics`. + 019   
            - 017      + 020     * `date` - the date on which the reported event is claimed to have happened;
            - 018     ## Notes: + 021     * `nth-hand` - the number of agents the news item has passed through;
            - 019      -
            - - 020     *TODO*    -
            - - 021     This namespace at present considers the `:knowledge` of a gossip to be a flat -
            - - 022     list of propositions, each of which must be checked every time any new -
            - - 023     proposition is offered. This is woefully inefficient. " -
            - - 024    (:require [cc.journeyman.the-great-game.world.location :refer [distance-between]] -
            - - 025              [cc.journeyman.the-great-game.time :refer [game-time]])) + 022     * `verb` - what it is that happened (key into `news-topics`);
            - 026   + 023   +
            + + 024     plus other keys taken from the `keys` value associated with the verb in +
            + + 025     `news-topics`. +
            + + 026      +
            + + 027     ## Notes: +
            + + 028      +
            + + 029     *TODO*    +
            + + 030     This namespace at present considers the `:knowledge` of a gossip to be a flat +
            + + 031     list of propositions, each of which must be checked every time any new +
            + + 032     proposition is offered. This is woefully inefficient. " +
            + + 033    (:require [cc.journeyman.the-great-game.world.location :refer [distance-between]] +
            + + 034              [cc.journeyman.the-great-game.time :refer [game-time]] +
            + + 035              [cc.journeyman.the-great-game.utils :refer [inc-or-one truthy?]] +
            + + 036              [taoensso.timbre :as l]))
            - 027   + 037  
            - 028  (def news-topics + 038  (def news-topics
            - 029    "Topics of interest to gossip agents. Topics are keyed in this map by + 039    "Topics of interest to gossip agents. Topics are keyed in this map by
            - 030    their `verbs`. The `keys` associated with each topic are the extra pieces + 040    their `verbs`. The `keys` associated with each topic are the extra pieces
            - 031    of information required to give context to a gossip item. Generally: + 041    of information required to give context to a gossip item. Generally:
            - 032   + 042  
            - 033    * `actor` is the id of the character who it is reported performed the + 043    * `actor` is the id of the character who it is reported performed the
            - 034    action; + 044    action;
            - 035    * `other` is the id of the character on whom it is reported the action + 045    * `other` is the id of the character on whom it is reported the action
            - 036    was performed; + 046    was performed;
            - 037    * `location` is the place at which the action was performed; + 047    * `location` is the place at which the action was performed;
            - 038    * `object` is an object (or possibly list of objects?) relevant to the + 048    * `object` is an object (or possibly list of objects?) relevant to the
            - 039    action; + 049    action;
            - 040    * `price` is special to buy/sell, but of significant interest to merchants. + 050    * `price` is special to buy/sell, but of significant interest to merchants.
            - 041   + 051  
            - 042    ## Notes + 052    ## Characters
            - 043   + 053  
            - 044    ### Characters + 054    *TODO* but note that at most all the receiver can learn about a character +
            + + 055    from a news item is what the giver knows about that character, degraded by +
            + + 056    what the receiver finds interesting about them. If we just pass the id here, +
            + + 057    then either the receiver knows everything in the database about the +
            + + 058    character, or else the receiver knows nothing at all about the character. +
            + + 059    Neither is desirable. Further thought needed.
            - 045   + 060  
            - 046    *TODO* but note that at most all the receiver can learn about a character + 061    By implication, the character values passed should include *all* the
            - 047    from a news item is what the giver knows about that character, degraded by + 062    information the giver knows about the character; that can then be degraded
            - 048    what the receiver finds interesting about them. If we just pass the id here, + 063    as the receiver stores only that segment which the receiver finds
            - 049    then either the receiver knows everything in the database about the -
            - - 050    character, or else the receiver knows nothing at all about the character. -
            - - 051    Neither is desirable. Further thought needed. -
            - - 052   -
            - - 053    By implication, the character values passed should include *all* the -
            - - 054    information the giver knows about the character; that can then be degraded -
            - - 055    as the receiver stores only that segment which the receiver finds -
            - - 056    interesting. -
            - - 057   -
            - - 058    ### Locations -
            - - 059   -
            - - 060    A 'location' value is a list comprising at most the x/y coordinate location -
            - - 061    and the ids of the settlement and region (possibly hierarchically) that contain -
            - - 062    the location. If the x/y is not local to the home of the receiving agent, they -
            - - 063    won't remember it and won't pass it on; if any of the ids are not interesting -
            - - 064    So location information will degrade progressively as the item is passed along. + 064    interesting.
            065  
            - 066    It is assumed that the `:home` of a character is a location in this sense. + 066    ## Locations
            067  
            - 068    ### Inferences + 068    A 'location' value is a list comprising at most the x/y coordinate location +
            + + 069    and the ids of the settlement and region (possibly hierarchically) that contain +
            + + 070    the location. If the x/y is not local to the home of the receiving agent, they +
            + + 071    won't remember it and won't pass it on; if any of the ids are not interesting +
            + + 072    So location information will degrade progressively as the item is passed along.
            - 069   + 073  
            - 070    If an agent learns that Adam has married Betty, they can infer that Betty has + 074    It is assumed that the `:home` of a character is a location in this sense. +
            + + 075  
            - 071    married Adam; if they learn that Charles killed Dorothy, that Dorothy has died. + 076    ## Inferences +
            + + 077  
            - 072    I'm not convinced that my representation of inferences here is ideal. + 078    If an agent learns that Adam has married Betty, they can infer that Betty has
            - 073    " + 079    married Adam; if they learn that Charles killed Dorothy, that Dorothy has died. +
            + + 080    I'm not convinced that my representation of inferences here is ideal."
            - 074    {;; A significant attack is interesting whether or not it leads to deaths + 081    {;; A significant attack is interesting whether or not it leads to deaths
            - 075     :attack {:verb :attack :keys [:actor :other :location]} + 082     :attack {:verb :attack :keys [:actor :other :location]}
            - 076      ;; Deaths of characters may be interesting + 083      ;; Deaths of characters may be interesting
            - 077     :die {:verb :die :keys [:actor :location]} + 084     :die {:verb :die :keys [:actor :location]}
            - 078      ;; Deliberate killings are interesting. + 085      ;; Deliberate killings are interesting.
            - 079     :kill {:verb :kill :keys [:actor :other :location] + 086     :kill {:verb :kill :keys [:actor :other :location]
            - 080            :inferences [{:verb :die :actor :other :other :nil}]} + 087            :inferences [{:verb :die :actor :other :other :nil}]}
            - 081      ;; Marriages may be interesting + 088      ;; Marriages may be interesting
            - 082     :marry {:verb :marry :keys [:actor :other :location] + 089     :marry {:verb :marry :keys [:actor :other :location]
            - 083             :inferences [{:verb :marry :actor :other :other :actor}]} + 090             :inferences [{:verb :marry :actor :other :other :actor}]}
            - 084      ;; The end of ongoing open conflict between to characters may be interesting + 091      ;; The end of ongoing open conflict between to characters may be interesting
            - 085     :peace {:verb :peace :keys [:actor :other :location] + 092     :peace {:verb :peace :keys [:actor :other :location]
            - 086             :inferences [{:verb :peace :actor :other :other :actor}]} + 093             :inferences [{:verb :peace :actor :other :other :actor}]}
            - 087      ;; Things related to the plot are interesting, but will require special + 094      ;; Things related to the plot are interesting, but will require special
            - 088      ;; handling. Extra keys may be required by particular plot events. + 095      ;; handling. Extra keys may be required by particular plot events.
            - 089     :plot {:verb :plot :keys [:actor :other :object :location]} + 096     :plot {:verb :plot :keys [:actor :other :object :location]}
            - 090      ;; Rapes are interesting. + 097      ;; Rapes are interesting.
            - 091     :rape {:verb :rape :keys [:actor :other :location] + 098     :rape {:verb :rape :keys [:actor :other :location]
            - 092             ;; Should you also infer from rape that actor is male and adult? + 099             ;; Should you also infer from rape that actor is male and adult?
            - 093            :inferences [{:verb :attack} + 100            :inferences [{:verb :attack}
            - 094                         {:verb :sex} + 101                         {:verb :sex}
            - 095                         {:verb :sex :actor :other :other :actor}]} + 102                         {:verb :sex :actor :other :other :actor}]}
            - 096      ;; Merchants, especially, are interested in prices in other markets + 103      ;; Merchants, especially, are interested in prices in other markets
            - - 097     :sell {:verb :sell :keys [:actor :other :object :location :price]} + + 104     :sell {:verb :sell :keys [:actor :other :object :location :quantity :price]}
            - 098      ;; Sex can juicy gossip, although not normally if the participants are in an + 105      ;; Sex can juicy gossip, although not normally if the participants are in an
            - 099      ;; established sexual relationship. + 106      ;; established sexual relationship.
            - 100     :sex {:verb :sex :keys [:actor :other :location] + 107     :sex {:verb :sex :keys [:actor :other :location]
            - 101           :inferences [{:verb :sex :actor :other :other :actor}]} + 108           :inferences [{:verb :sex :actor :other :other :actor}]}
            - 102      ;; Thefts are interesting. + 109      ;; Thefts are interesting.
            - 103     :steal {:verb :steal :keys [:actor :other :object :location]} + 110     :steal {:verb :steal :keys [:actor :other :object :location]}
            - 104      ;; The succession of rulers is interesting; of respected craftsmen, + 111      ;; The succession of rulers is interesting; of respected craftsmen,
            - 105      ;; potentially also interesting. + 112      ;; potentially also interesting.
            - 106     :succession {:verb :succession :keys [:actor :other :location :rank]} + 113     :succession {:verb :succession :keys [:actor :other :location :rank]}
            - 107      ;; The start of ongoing open conflict between two characters may be interesting. + 114      ;; The start of ongoing open conflict between two characters may be interesting.
            - 108     :war {:verb :war :keys [:actor :other :location] + 115     :war {:verb :war :keys [:actor :other :location]
            - 109           :inferences [{:verb :war :actor :other :other :actor}]}}) + 116           :inferences [{:verb :war :actor :other :other :actor}]}})
            - 110   + 117  
            - 111   + 118  
            - 112  (defn interest-in-character + 119  (def all-known-verbs 
            - 113    "Integer representation of how interesting this `character` is to this + 120    "All verbs currently known to the gossip system."
            - - 114    `gossip`. -
            - - 115    *TODO:* this assumes that characters are passed as keywords, but, as -
            - - 116    documented above, they probably have to be maps, to allow for degradation." -
            - - 117    [gossip character] -
            - - 118    (count -
            - - 119     (concat -
            - - 120      (filter #(= (:actor % character)) (:knowledge gossip)) -
            - - 121      (filter #(= (:other % character)) (:knowledge gossip))))) + + 121    (set (keys news-topics)))
            122  
            - - 123  (defn interesting-character? -
            - - 124    "Boolean representation of whether this `character` is interesting to this -
            - - 125    `gossip`." -
            - - 126    [gossip character] -
            - - 127    (> (interest-in-character gossip character) 0)) -
            - 128   + 123  
            - 129  (defn interest-in-location + 124  (defn interest-in-character
            - 130    "Integer representation of how interesting this `location` is to this + 125    "Integer representation of how interesting this `character` is to this
            - 131    `gossip`." + 126    `gossip`.
            - 132    [gossip location] -
            - - 133    (cond -
            - - 134      (and (map? location) (number? (:x location)) (number? (:y location))) -
            - - 135      (if-let [home (:home gossip)] -
            - - 136        (let [d (distance-between location home) -
            - - 137              i (/ 10000 d) ;; 10000 at metre scale is 10km; interest should + 127    *TODO:* this assumes that characters are passed as keywords, but, as
            - 138              ;;fall off with distance from home, but possibly on a log scale + 128    documented above, they probably have to be maps, to allow for degradation."
            - 139              ] + 129    [gossip character]
            - - 140          (if (> i 1) i 0)) -
            - - 141        0) -
            - - 142      (coll? location) + + 130    (count
            - 143      (reduce -
            - - 144       + -
            - - 145       (map -
            - - 146        #(interest-in-location gossip %) -
            - - 147        location)) + 131     (concat
            - 148      :else + 132      ;; TODO: we ought also check the relationships of the gossip.
            - - 149      (count + + 133      ;; Are relationships just propositions in the knowledge base?
            - - 150       (filter + + 134      (filter #(= (:actor %) character) (:knowledge gossip))
            - - 151        #(some (fn [x] (= x location)) (:location %)) -
            - - 152        (cons {:location (:home gossip)} (:knowledge gossip)))))) + + 135      (filter #(= (:other %) character) (:knowledge gossip)))))
            - 153   -
            - - 154  ;; (interest-in-location {:home [{0, 0} :test-home] :knowledge []} [:test-home]) + 136  
            - 155   + 137  
            - 156  (defn interesting-location? + 138  (defn interesting-character?
            - 157    "True if the location of this news `item` is interesting to this `gossip`." + 139    "Boolean representation of whether this `character` is interesting to this
            - 158    [gossip item] -
            - - 159    (> (interest-in-location gossip (:location item)) 0)) -
            - - 160   -
            - - 161  (defn interesting-object? + 140    `gossip`."
            - 162    [gossip object] -
            - - 163    ;; TODO: Not yet (really) implemented -
            - - 164    true) -
            - - 165   -
            - - 166  (defn interesting-topic? -
            - - 167    [gossip topic] -
            - - 168    ;; TODO: Not yet (really) implemented -
            - - 169    true) -
            - - 170   -
            - - 171  (defn compatible-value? -
            - - 172    "True if `known-value` is the same as `new-value`, or, for each key present -
            - - 173     in `new-value`, has the same value for that key.  -
            - - 174      -
            - - 175     The rationale here is that if `new-value` contains new or different  -
            - - 176     information, it's worth learning; otherwise, not." -
            - - 177    [new-value known-value] -
            - - 178    (or -
            - - 179     (= new-value known-value) -
            - - 180     ;; TODO: some handwaving here about being a slightly better descriptor -- -
            - - 181     ;; having more keys than might  -
            - - 182     (when (and (map? new-value) (map? known-value)) -
            - - 183       (every? true? (map #(= (new-value %) (known-value %)) -
            - - 184                          (keys new-value)))))) -
            - - 185   -
            - - 186  (defn compatible-item? -
            - - 187    "True if `new-item` is identical with, or less specific than, `known-item`. -
            - - 188      -
            - - 189     If we already know 'Bad Joe killed Sweet Daisy', there's no point in  -
            - - 190     learning that 'someone killed Sweet Daisy', but there is point in learning -
            - - 191     'someone killed Sweet Daisy _with poison_'." -
            - - 192    [new-item known-item] -
            - - 193    (reduce + 141    [gossip character]
            - 194     #(and %1 %2) + 142    (> (interest-in-character gossip character) 0))
            - - 195     (map #(if + + 143  
            - - 196            (known-item %) ;; if known-item has this key -
            - - 197             (compatible-value? (new-item %) (known-item %)) + + 144  (defn interest-in-location
            - 198             true) + 145    "Integer representation of how interesting this `location` is to this +
            + + 146    `gossip`." +
            + + 147    [gossip location] +
            + + 148    (cond +
            + + 149      (and (map? location) (number? (:x location)) (number? (:y location))) +
            + + 150      (if-let [home (:home gossip)] +
            + + 151        (let [d (distance-between location home) +
            + + 152              i (if +
            + + 153                 (zero? d) 1 +
            + + 154                 (/ 10000 d)) +
            + + 155              ;; 10000 at metre scale is 10km; interest should +
            + + 156              ;;fall off with distance from home, but possibly on a log scale +
            + + 157              ] +
            + + 158          (if (>= i 1) i 0)) +
            + + 159        0) +
            + + 160      (coll? location) +
            + + 161      (reduce +
            + + 162       + +
            + + 163       (map +
            + + 164        #(interest-in-location gossip %) +
            + + 165        location)) +
            + + 166      :else +
            + + 167      (count +
            + + 168       (filter
            - 199          (remove #{:nth-hand :confidence :learned-from} (keys new-item))))) + 169        #(some (fn [x] (= x location)) (:location %)) +
            + + 170        (cons {:location (:home gossip)} (:knowledge gossip)))))) +
            + + 171   +
            + + 172  ;; (distance-between {:x 25 :y 37} {:x 25 :y 37}) +
            + + 173  ;; (interest-in-location {:home [{0, 0} :test-home] :knowledge []} [:test-home]) +
            + + 174   +
            + + 175  (defn interesting-location? +
            + + 176    "True if the location of this news `item` is interesting to this `gossip`." +
            + + 177    [gossip location] +
            + + 178    (> (interest-in-location gossip location) 0)) +
            + + 179   +
            + + 180  (defn interesting-object? +
            + + 181    [gossip object] +
            + + 182    ;; TODO: Not yet (really) implemented +
            + + 183    true) +
            + + 184   +
            + + 185  (defn interesting-topic? +
            + + 186    [gossip topic] +
            + + 187    ;; TODO: Not yet (really) implemented +
            + + 188    true) +
            + + 189   +
            + + 190  (defn interesting-verb? +
            + + 191    "Is this `verb` interesting to this `gossip`?" +
            + + 192    [gossip verb] +
            + + 193    (let [vs (:interesting-verbs gossip)] +
            + + 194      (truthy? +
            + + 195       (if (set? vs) +
            + + 196         (vs verb) +
            + + 197         false)))) +
            + + 198   +
            + + 199  ;; (interesting-verb? {:interesting-verbs #{:kill :sell}} :sell)
            200  
            - 201  (defn known-item? + 201  (defn compatible-value?
            - 202    "True if this news `item` is already known to this `gossip`. + 202    "True if `known-value` is the same as `new-value`, or, for each key present
            - 203      + 203     in `new-value`, has the same value for that key. 
            - 204     This means that the `gossip` already knows an item which identifiably has + 204     
            - 205     the same _or more specific_ values for all the keys of this `item` except + 205     The rationale here is that if `new-value` contains new or different 
            - 206     `:nth-hand`, `:confidence` and `:learned-from`." + 206     information, it's worth learning; otherwise, not."
            - 207    [gossip item] + 207    [new-value known-value] +
            + + 208    (or
            - 208    (reduce -
            - - 209     #(or %1 %2) -
            - - 210     (filter true? (map #(compatible-item? item %) (:knowledge gossip))))) -
            - - 211   -
            - - 212  (defn interesting-item? + 209     (= new-value known-value)
            - 213    "True if anything about this news `item` is interesting to this `gossip`." + 210     ;; TODO: some handwaving here about being a slightly better descriptor --
            - 214    [gossip item] + 211     ;; having more keys than might 
            - - 215    (and (not (known-item? gossip item)) + + 212     (when (and (map? new-value) (map? known-value))
            - - 216         (or -
            - - 217          (interesting-character? gossip (:actor item)) -
            - - 218          (interesting-character? gossip (:other item)) -
            - - 219          (interesting-location? gossip (:location item)) -
            - - 220          (interesting-object? gossip (:object item)) -
            - - 221          (interesting-topic? gossip (:verb item))))) -
            - - 222   -
            - - 223  (defn infer -
            - - 224    "Infer a new knowledge item from this `item`, following this `rule`" -
            - - 225    [item rule] -
            - - 226    (reduce merge -
            - - 227            item -
            - - 228            (cons -
            - - 229             {:verb (:verb rule)} -
            - - 230             (map (fn [k] {k (apply (k rule) (list item))}) -
            - - 231                  (remove -
            - - 232                   #{:verb} -
            - - 233                   (keys rule)))))) -
            - - 234   -
            - - 235  (declare learn-news-item) -
            - - 236   -
            - - 237  (defn make-all-inferences -
            - - 238    "Return a list of knowledge entries that can be inferred from this news -
            - - 239    `item`." -
            - - 240    [item] -
            - - 241    (set -
            - - 242     (reduce -
            - - 243      concat -
            - - 244      (map -
            - - 245       #(:knowledge (learn-news-item {} (infer item %) false)) -
            - - 246       (:inferences (news-topics (:verb item))))))) -
            - - 247   -
            - - 248  (defn degrade-character -
            - - 249    "Return a character specification like this `character`, but comprising -
            - - 250    only those properties this `gossip` is interested in." -
            - - 251    [gossip character] -
            - - 252    ;; TODO: Not yet (really) implemented -
            - - 253    character) -
            - - 254   -
            - - 255  (defn degrade-location -
            - - 256    "Return a location specification like this `location`, but comprising -
            - - 257    only those elements this `gossip` is interested in. If none, return -
            - - 258    `nil`." -
            - - 259    [gossip location] -
            - - 260    (let [l (when -
            - - 261             (coll? location) -
            - - 262              (filter -
            - - 263               #(when (interesting-location? gossip %) %) -
            - - 264               location))] -
            - - 265      (when-not (empty? l) l))) -
            - - 266   -
            - - 267  (defn inc-or-one -
            - - 268    "If this `val` is a number, return that number incremented by one; otherwise, -
            - - 269     return 1. TODO: should probably be in `utils`." -
            - - 270    [val] -
            - - 271    (if + + 213       (every? true? (map #(= (new-value %) (known-value %))
            - 272     (number? val) -
            - - 273      (inc val) -
            - - 274      1)) + 214                          (keys new-value))))))
            - 275   + 215  
            - 276  (defn learn-news-item + 216  (defn compatible-item?
            - 277    "Return a gossip like this `gossip`, which has learned this news `item` if + 217    "True if `new-item` is identical with, or less specific than, `known-item`.
            - 278    it is of interest to them." + 218     
            - 279    ([gossip item] + 219     If we already know 'Bad Joe killed Sweet Daisy', there's no point in  +
            + + 220     learning that 'someone killed Sweet Daisy', but there is point in learning +
            + + 221     'someone killed Sweet Daisy _with poison_'." +
            + + 222    [new-item known-item] +
            + + 223    (truthy? +
            + + 224     (reduce +
            + + 225      #(and %1 %2)
            - 280     (learn-news-item gossip item true)) + 226      (map #(if +
            + + 227             (known-item %) ;; if known-item has this key +
            + + 228              (compatible-value? (new-item %) (known-item %))
            - 281    ([gossip item follow-inferences?] + 229              true) +
            + + 230           (remove #{:nth-hand :confidence :learned-from} (keys new-item)))))) +
            + + 231  
            - 282     (if + 232  (defn known-item? +
            + + 233    "True if this news `item` is already known to this `gossip`. +
            + + 234      +
            + + 235     This means that the `gossip` already knows an item which identifiably has +
            + + 236     the same _or more specific_ values for all the keys of this `item` except +
            + + 237     `:nth-hand`, `:confidence` and `:learned-from`." +
            + + 238    [gossip item] +
            + + 239    (truthy?
            - 283      (interesting-item? gossip item) + 240     (reduce
            - - 284       (let [item' (assoc + + 241      #(or %1 %2)
            - - 285                    item + + 242      false +
            + + 243      (filter true? (map #(compatible-item? item %) (:knowledge gossip)))))) +
            + + 244   +
            + + 245  (defn interesting-item? +
            + + 246    "True if anything about this news `item` is interesting to this `gossip`." +
            + + 247    [gossip item] +
            + + 248    (and (not (known-item? gossip item)) +
            + + 249         (interesting-verb? gossip item) ;; news is only interesting if the topic is. +
            + + 250         (or +
            + + 251          (interesting-character? gossip (:actor item)) +
            + + 252          (interesting-character? gossip (:other item)) +
            + + 253          (interesting-location? gossip (:location item)) +
            + + 254          (interesting-object? gossip (:object item))
            - 286                    :nth-hand (inc-or-one (:nth-hand item)) + 255          (interesting-topic? gossip (:verb item))))) +
            + + 256   +
            + + 257  (defn infer +
            + + 258    "Infer a new knowledge item from this `item`, following this `rule`." +
            + + 259    [item rule] +
            + + 260  ;;  (l/info "Applying rule '" rule "' to item '" item "'") +
            + + 261    (reduce merge +
            + + 262            item +
            + + 263            (cons +
            + + 264             {:verb (:verb rule) +
            + + 265              :nth-hand (inc-or-one (:nth-hand item))} +
            + + 266             (map (fn [k] {k (item (rule k))}) +
            + + 267                  (remove +
            + + 268                   #{:verb :nth-hand} +
            + + 269                   (keys rule)))))) +
            + + 270   +
            + + 271  (declare learn-news-item) +
            + + 272   +
            + + 273  (defn make-all-inferences +
            + + 274    "Return a set of knowledge entries that can be inferred from this news +
            + + 275    `item`." +
            + + 276    [item] +
            + + 277    (set +
            + + 278      (map +
            + + 279       #(infer item %) +
            + + 280       (:inferences (news-topics (:verb item)))))) +
            + + 281   +
            + + 282  (defn degrade-character +
            + + 283    "Return a character specification like this `character`, but comprising +
            + + 284    only those properties this `gossip` is interested in." +
            + + 285    [gossip character] +
            + + 286    ;; TODO: Not yet (really) implemented
            - 287                    :time-stamp (if + 287    character) +
            + + 288   +
            + + 289  (defn degrade-location +
            + + 290    "Return a location specification like this `location`, but comprising +
            + + 291    only those elements this `gossip` is interested in. If none, return +
            + + 292    `nil`." +
            + + 293    [gossip location] +
            + + 294    (let [l (when +
            + + 295             (coll? location) +
            + + 296              (filter +
            + + 297               #(when (interesting-location? gossip %) %) +
            + + 298               location))] +
            + + 299      (when-not (empty? l) l))) +
            + + 300   +
            + + 301  (defn degrade-news-item +
            + + 302    [gossip item] +
            + + 303    (assoc +
            + + 304     item
            - 288                                 (number? (:time-stamp item)) -
            - - 289                                  (:time-stamp item) -
            - - 290                                  (game-time)) -
            - - 291                    :location (degrade-location gossip (:location item)) -
            - - 292                    :actor (degrade-character gossip (:actor item)) -
            - - 293                    :other (degrade-character gossip (:other item)) -
            - - 294                    ;; TODO: do something to degrade confidence in the item, -
            - - 295                    ;; probably as a function of the provider's confidence in -
            - - 296                    ;; the item and the gossip's trust in the provider -
            - - 297                    ) -
            - - 298             g (assoc + 305     :nth-hand (inc-or-one (:nth-hand item))
            - 299                gossip + 306     :time-stamp (if
            - - 300                :knowledge -
            - - 301                (cons -
            - - 302                 item' + + 307                  (number? (:time-stamp item))
            - 303                 (:knowledge gossip)))] + 308                   (:time-stamp item)
            - 304         (if follow-inferences? + 309                   (game-time))
            - - 305           (assoc + + 310     :location (degrade-location gossip (:location item))
            - - 306            g + + 311     :actor (degrade-character gossip (:actor item)) +
            + + 312     :other (degrade-character gossip (:other item))
            - 307            :knowledge + 313                    ;; TODO: do something to degrade confidence in the item, +
            + + 314                    ;; probably as a function of the provider's confidence in +
            + + 315                    ;; the item and the gossip's trust in the provider +
            + + 316     )) +
            + + 317   +
            + + 318  ;; (degrade-news-item {:home [{:x 25 :y 37} :auchencairn :scotland]} +
            + + 319  ;;                   {:verb :marry :actor :adam :other :belinda :location [{:x 25 :y 37} :auchencairn :scotland]}) +
            + + 320   +
            + + 321  (defn learn-news-item +
            + + 322    "Return a gossip like this `gossip`, which has learned this news `item` if +
            + + 323    it is of interest to them." +
            + + 324    ([gossip item] +
            + + 325     (learn-news-item gossip item true)) +
            + + 326    ([gossip item follow-inferences?] +
            + + 327     (if +
            + + 328      (interesting-item? gossip item) +
            + + 329       (let [item' (degrade-news-item gossip item) +
            + + 330             g (assoc +
            + + 331                gossip +
            + + 332                :knowledge +
            + + 333                (cons +
            + + 334                 item' +
            + + 335                 (:knowledge gossip)))] +
            + + 336         (if follow-inferences? +
            + + 337           (assoc +
            + + 338            g +
            + + 339            :knowledge
            - 308            (concat (:knowledge g) (make-all-inferences item))) + 340            (concat (:knowledge g) (make-all-inferences item')))
            - 309           g))) + 341           g)))
            - - 310     gossip)) + + 342     gossip))
            - 311   + 343  
            - 312   + 344  
            - 313   + 345  
            diff --git a/docs/cloverage/cc/journeyman/the_great_game/location/location.clj.html b/docs/cloverage/cc/journeyman/the_great_game/location/location.clj.html index a27e3bf..ec74b4d 100644 --- a/docs/cloverage/cc/journeyman/the_great_game/location/location.clj.html +++ b/docs/cloverage/cc/journeyman/the_great_game/location/location.clj.html @@ -139,11 +139,5 @@ 045  
            - - 046   -
            - - 047  ;; (OrientedLocation. 123.45 543.76 12.34 0.00 {}) -
            diff --git a/docs/cloverage/cc/journeyman/the_great_game/playroom.clj.html b/docs/cloverage/cc/journeyman/the_great_game/playroom.clj.html index a2574c4..8c3f407 100644 --- a/docs/cloverage/cc/journeyman/the_great_game/playroom.clj.html +++ b/docs/cloverage/cc/journeyman/the_great_game/playroom.clj.html @@ -37,22 +37,22 @@ 011  (defn init []
            - + 012    (let [cube (geo "jMonkey cube" (box 1 1 1))
            - + 013          mat  (unshaded-mat)]
            - + 014      (set* mat :texture "ColorMap" (load-texture "textures/Monkey.jpg"))
            - + 015      (set* cube :material mat)
            - + 016      (add-to-root cube)
            - + 017      {:cube cube}))
            @@ -88,7 +88,7 @@ 028  ;; We define the `app` var.
            - + 029  (defsimpleapp app
            @@ -112,17 +112,17 @@ 036                                               :height         600}}
            - + 037                 :init init
            - + 038                 :update simple-update)
            039  
            - - 040  (start app) + + 040  ;; (start app)
            041   @@ -145,11 +145,11 @@ 047   ;; Let's increase its movement speed. Now, you fly faster :)
            - - 048   (run app + + 048   ;; (run app
            - - 049        (set* (fly-cam) :move-speed 15)) + + 049   ;;      (set* (fly-cam) :move-speed 15))
            050   @@ -160,14 +160,14 @@ 052   ;; Updates the app 
            - - 053  (run app + + 053  ;; (run app
            - - 054       (let [{:keys [cube]} (get-state)] + + 054  ;;      (let [{:keys [cube]} (get-state)]
            - - 055         (set* cube :local-translation (add (get* cube :local-translation) 1 1 1)))) + + 055  ;;        (set* cube :local-translation (add (get* cube :local-translation) 1 1 1))))
            056   @@ -175,32 +175,32 @@ 057    ;; Updates the app adding a second cube
            - - 058  (run app -
            - - 059        (let [cube (geo "jMonkey cube" (box 1 1 1)) -
            - - 060              mat  (unshaded-mat)] -
            - - 061          (set* mat :texture "ColorMap" (load-texture "textures/Monkey.jpg")) -
            - - 062          (setc cube -
            - - 063                :material mat + + 058  ;; (run app
            - 064                :local-translation [-3 0 0]) + 059  ;;       (let [cube (geo "jMonkey cube" (box 1 1 1))
            - - 065          (add-to-root cube) + + 060  ;;             mat  (unshaded-mat)]
            - - 066          (set-state :cube2 cube))) + + 061  ;;         (set* mat :texture "ColorMap" (load-texture "textures/Monkey.jpg")) +
            + + 062  ;;         (setc cube +
            + + 063  ;;               :material mat +
            + + 064  ;;               :local-translation [-3 0 0]) +
            + + 065  ;;         (add-to-root cube) +
            + + 066  ;;         (set-state :cube2 cube)))
            067    @@ -208,17 +208,17 @@ 068   ;; We added the new cube, but it's not rotating. We need to update the simple-update fn.
            - - 069   (defn simple-update [tpf] + + 069   ;; (defn simple-update [tpf]
            - - 070     (let [{:keys [cube cube2]} (get-state)] + + 070   ;;   (let [{:keys [cube cube2]} (get-state)]
            - - 071       (rotate cube 0 (* 2 tpf) 0) + + 071   ;;     (rotate cube 0 (* 2 tpf) 0)
            - - 072       (rotate cube2 0 (* 2 tpf) 0))) + + 072   ;;     (rotate cube2 0 (* 2 tpf) 0)))
            diff --git a/docs/cloverage/cc/journeyman/the_great_game/utils.clj.html b/docs/cloverage/cc/journeyman/the_great_game/utils.clj.html index 640231f..d8c0be8 100644 --- a/docs/cloverage/cc/journeyman/the_great_game/utils.clj.html +++ b/docs/cloverage/cc/journeyman/the_great_game/utils.clj.html @@ -139,5 +139,53 @@ 045  ;; (value-or-default nil :altitude 8)
            + + 046   +
            + + 047  (defn truthy?  +
            + + 048    "Returns `true` unless `val` is `nil`, `false` or an empty sequence. +
            + + 049     Otherwise always 'false'; never any other value." +
            + + 050    [val] +
            + + 051    (and (or val false) true)) +
            + + 052   +
            + + 053   +
            + + 054  (defn inc-or-one +
            + + 055    "If this `val` is a number, return that number incremented by one; otherwise, +
            + + 056     return 1. TODO: should probably be in `utils`." +
            + + 057    [val] +
            + + 058    (if +
            + + 059     (number? val) +
            + + 060      (inc val) +
            + + 061      1)) +
            diff --git a/docs/cloverage/index.html b/docs/cloverage/index.html index 724b600..25f95c7 100644 --- a/docs/cloverage/index.html +++ b/docs/cloverage/index.html @@ -25,6 +25,17 @@ 100.00 % 4553 + + cc.journeyman.the-great-game.buildings.module
            2
            +100.00 % +
            2
            +100.00 % +8162 + cc.journeyman.the-great-game.buildings.rectangular
            6
            80.65 % -1802531 +1502531 cc.journeyman.the-great-game.gossip.gossip
            cc.journeyman.the-great-game.gossip.news-items
            437
            197
            -68.93 % + style="width:77.15582450832072%; + float:left;"> 510
            151
            +77.16 %
            82
            10
            38
            -70.77 % -31336130 + style="width:72.66187050359713%; + float:left;"> 101
            8
            30
            +78.42 % +34541139 cc.journeyman.the-great-game.holdings.holding
            10
            28.57 % -47814 +45714 cc.journeyman.the-great-game.merchants.markets
            cc.journeyman.the-great-game.playroom
            463
            75
            -86.06 % + style="width:56.92307692307692%; + float:left;"> 222
            168
            +56.92 %
            28
            5
            2
            -94.29 % -721235 + style="width:23.529411764705884%; + float:left;"> 4
            3
            10
            +41.18 % +721217 cc.journeyman.the-great-game.time
            cc.journeyman.the-great-game.utils
            70
            13
            -84.34 % + style="width:85.4368932038835%; + float:left;"> 88
            15
            +85.44 %
            20
            1
            -95.24 % -45521 + style="width:92.5925925925926%; + float:left;"> 25
            2
            +92.59 % +61827 cc.journeyman.the-great-game.world.heightmap
            Totals: -61.00 % +58.91 % -61.78 % +61.63 % diff --git a/docs/codox/Baking-the-world.html b/docs/codox/Baking-the-world.html index 7d2d95a..1d46de3 100644 --- a/docs/codox/Baking-the-world.html +++ b/docs/codox/Baking-the-world.html @@ -1,6 +1,6 @@ -Baking the world

            Baking the world

            +Baking the world

            Baking the world

            Wednesday, 8 May 2019

            Devorgilla’s Bridge in Dumfries, early fourteenth century

            Devorgilla’s Bridge in Dumfries, early fourteenth century. This clearly shows how a genetic buildings approach to bridges can be made to work: a single element is repeated to span the necessary distance. That element can be stretched vertically and laterally to match the location, and can be rendered in different stone finishes to match local geology.

            diff --git a/docs/codox/Canonical-dictionary.html b/docs/codox/Canonical-dictionary.html index b1b2312..a756c85 100644 --- a/docs/codox/Canonical-dictionary.html +++ b/docs/codox/Canonical-dictionary.html @@ -1,6 +1,6 @@ -A Canonical dictionary for this documentation

            A Canonical dictionary for this documentation

            +A Canonical dictionary for this documentation

            A Canonical dictionary for this documentation

            Where a word is used in the documentation for The Great Game and its related projects, this file describes the canonical meaning of that word. This is because a lot of the concepts in play are messy and ambiguous, so that at times even I am confused by what I mean. The presence of this file is an acknowledment of this difficulty, and an implicit admission that not all the documentation is, at this stage anyway, consistent.

            Actor

            An actor is a thing which performs actions within the game world. Thus a tree is (almost certainly) not an actor, and things like sheep and rabbits that run about are probably not actors, but an animal which may pro-actively interact with the player character (such as a predator, or a beast of burden, or even a prey species which may flee) is an actor. In god mode, if implemented, the player can inhabit any actor within the game world.

            diff --git a/docs/codox/Dynamic-consequences.html b/docs/codox/Dynamic-consequences.html index 3e99f8a..595965e 100644 --- a/docs/codox/Dynamic-consequences.html +++ b/docs/codox/Dynamic-consequences.html @@ -1,6 +1,6 @@ -On the consequences of a dynamic game environment for storytelling

            On the consequences of a dynamic game environment for storytelling

            +On the consequences of a dynamic game environment for storytelling

            On the consequences of a dynamic game environment for storytelling

            First, a framing disclaimer: in Racundra’s First Cruise, Arthur Ransome describes coming across a half built - and by the time he saw it, already obsolete - wooden sailing ship, in a Baltic forest. An old man was building it, by himself. He had been building it since he had been a young man. It’s clear that Ransome believed the ship would never be finished. It’s not clear whether the old man believed that it would, but nevertheless he was building it.

            I will never build a complete version of The Great Game; it will probably never even be a playable prototype. It is a minor side-project of someone who

              diff --git a/docs/codox/Game_Play.html b/docs/codox/Game_Play.html index a602b52..277ea9b 100644 --- a/docs/codox/Game_Play.html +++ b/docs/codox/Game_Play.html @@ -1,6 +1,6 @@ -Game Play

              Game Play

              +Game Play

              Game Play

              The principles of game play which I’m looking for are a reaction against all I see as wrong in modern video games. So let’s set out what these are:

              1. diff --git a/docs/codox/Gossip_scripted_plot_and_Johnny_Silverhand.html b/docs/codox/Gossip_scripted_plot_and_Johnny_Silverhand.html index 30a2724..69bafa6 100644 --- a/docs/codox/Gossip_scripted_plot_and_Johnny_Silverhand.html +++ b/docs/codox/Gossip_scripted_plot_and_Johnny_Silverhand.html @@ -1,6 +1,6 @@ -Gossip, scripted plot, and Johnny Silverhand

                Gossip, scripted plot, and Johnny Silverhand

                +Gossip, scripted plot, and Johnny Silverhand

                Gossip, scripted plot, and Johnny Silverhand

                I’ve been writing literally for years – since Voice acting considered harmful in 2015 – about game worlds in which the player speaks to non-player characters just by speaking the words they choose in their normal voice, and the non-player character replies using a pipeline that goes, essentially,

                1. Alexa/Siri style speech interpretation;
                2. diff --git a/docs/codox/Organic_Quests.html b/docs/codox/Organic_Quests.html index d2e0969..750f61d 100644 --- a/docs/codox/Organic_Quests.html +++ b/docs/codox/Organic_Quests.html @@ -1,6 +1,6 @@ -Organic Quests

                  Organic Quests

                  +Organic Quests

                  Organic Quests

                  The structure of a modern Role Playing Came revolves around ‘quests’: tasks that the player character is invited to do, either by the framing narrative of the game or by some non-player character (‘the Quest Giver’). Normally there is one core quest which provides the overarching narrative for the whole game. [Wikipedia](https://en.wikipedia.org/wiki/Quest_(gaming)) offers a typology of quests as follows:

                  1. Kill quests
                  2. diff --git a/docs/codox/Pathmaking.html b/docs/codox/Pathmaking.html index 3ad8777..703c9b3 100644 --- a/docs/codox/Pathmaking.html +++ b/docs/codox/Pathmaking.html @@ -1,6 +1,6 @@ -Pathmaking

                    Pathmaking

                    +Pathmaking

                    Pathmaking

                    NOTE: this file is called ‘pathmaking’, not ‘pathfinding’, because ‘pathfinding’ has a very specific meaning/usage in game design which is only part of what I want to talk about here.

                    Stages in creating routes between locations

                    see also Baking the world

                    diff --git a/docs/codox/Populating-a-game-world.html b/docs/codox/Populating-a-game-world.html index f529c56..e208fd9 100644 --- a/docs/codox/Populating-a-game-world.html +++ b/docs/codox/Populating-a-game-world.html @@ -1,6 +1,6 @@ -Populating a game world

                    Populating a game world

                    +Populating a game world

                    Populating a game world

                    Saturday, 6 July 2013

                    (You might want to read this essay in conjunction with my older essay, Settling a game world, which covers similar ground but which this hopefully advances on)

                    For an economy to work people have to be able to move between occupations to fill economic niches. In steady state, non player character (NPC) males become adult as ‘vagrants’, and then move through the state transitions described in this document. The pattern for females is different.

                    diff --git a/docs/codox/Roadmap.html b/docs/codox/Roadmap.html index 79a4459..f91d207 100644 --- a/docs/codox/Roadmap.html +++ b/docs/codox/Roadmap.html @@ -1,6 +1,6 @@ -Roadmap

                    Roadmap

                    +Roadmap

                    Roadmap

                    This document outlines a plan to move forward from where I am in June 2021.

                    JMonkeyEngine

                    JMonkeyEngine is not, at this time, an AAA game engine. But at the same time I’m never, really, going to build an AAA game. It is a working game engine which can display characters on screen in scenery and have them move around, and, actually, they can be fairly sophisticated. It will be resaonably easy to integrate Clojure code with JMonkeyEngine - easier than it would be to integrate either Clojure or Common Lisp with Unreal Engine or Unity 3D. As a significant added bonus, JMonkeyEngine is open source.

                    diff --git a/docs/codox/Settling-a-game-world.html b/docs/codox/Settling-a-game-world.html index fa2eeed..ec1a28b 100644 --- a/docs/codox/Settling-a-game-world.html +++ b/docs/codox/Settling-a-game-world.html @@ -1,6 +1,6 @@ -Settling a game world

                    Settling a game world

                    +Settling a game world

                    Settling a game world

                    Wednesday, 30 December 2009

                    This essay is part of a series with ‘Worlds and Flats’ and ‘The spread of knowledge in a large game world’; if you haven’t read those you may want to read them before reading this. This essay describes how a large world can come into being and can evolve. I’ve written again on this subject since - see ‘Populating a game world’)

                    Microworld

                    diff --git a/docs/codox/Simulation-layers.html b/docs/codox/Simulation-layers.html index dac2565..04b2072 100644 --- a/docs/codox/Simulation-layers.html +++ b/docs/codox/Simulation-layers.html @@ -1,6 +1,6 @@ -Simulation layers

                    Simulation layers

                    +Simulation layers

                    Simulation layers

                    In essence, the environment for The Great Game is broadly descended from games like the original Elite space trading game, and Sid Meier’s Pirates!, with some elements from political simulations like for example SimCity.

                    That is to say there is

                    An economy simulation

                    diff --git a/docs/codox/The-spread-of-knowledge-in-a-large-game-world.html b/docs/codox/The-spread-of-knowledge-in-a-large-game-world.html index d6084f2..7d6d15c 100644 --- a/docs/codox/The-spread-of-knowledge-in-a-large-game-world.html +++ b/docs/codox/The-spread-of-knowledge-in-a-large-game-world.html @@ -1,6 +1,6 @@ -The spread of knowledge in a large game world

                    The spread of knowledge in a large game world

                    +The spread of knowledge in a large game world

                    The spread of knowledge in a large game world

                    Saturday, 26 April 2008

                    part of the role of Dandelion, in The Witcher games, is to provide the player with news

                    Note

                    diff --git a/docs/codox/Uncanny_dialogue.html b/docs/codox/Uncanny_dialogue.html index 6793ccc..ca223fe 100644 --- a/docs/codox/Uncanny_dialogue.html +++ b/docs/codox/Uncanny_dialogue.html @@ -1,6 +1,6 @@ -The Uncanny Valley, and dynamically generated dialogue

                    The Uncanny Valley, and dynamically generated dialogue

                    +The Uncanny Valley, and dynamically generated dialogue

                    The Uncanny Valley, and dynamically generated dialogue

                    If the player is allowed to just speak arbitrary dialogue, then the conversation animation of the player character cannot be designed. If non-player characters are able to engage dynamically generated dialogue, in response to events in the game which are not scripted, then their conversation animation for those dialogues cannot be designed. So conversation animation must almost always be dynamically generated, largely from an augmented text of the speech act. With non-player characters, emotional content of a speech act can be generated by exactly the same process which generates the text. Extracting emotional content information from the player character’s voice may be more challenging.

                    It would be possible to avoid animating the player character’s face by using a first-person camera. However, I don’t personally find this makes for a very engaging game experience.

                    These thoughts were prompted by a very interesting video and Twitter thread about the perceived failings in the character animation system of Mass Effect Andromeda.

                    diff --git a/docs/codox/Voice-acting-considered-harmful.html b/docs/codox/Voice-acting-considered-harmful.html index e47d8c2..0e20790 100644 --- a/docs/codox/Voice-acting-considered-harmful.html +++ b/docs/codox/Voice-acting-considered-harmful.html @@ -1,6 +1,6 @@ -Voice acting considered harmful

                    Voice acting considered harmful

                    +Voice acting considered harmful

                    Voice acting considered harmful

                    Wednesday, 25 February 2015

                    The Witcher: Conversation with Kalkstein

                    Long, long, time ago, I can still remember when… we played (and wrote) adventure games where the user typed at a command line, and the system printed back at them. A Read-Eval-Print loop in the classic Lisp sense, and I wrote my adventure games in Lisp. I used the same opportunistic parser whether the developer was building the game Create a new room north of here called dungeon-3 the player was playing the game Pick up the rusty sword and go north or the player was talking to a non-player character Say to the wizard ‘can you tell me the way to the castle’ Of course, the parser didn’t ‘understand’ English. It worked on trees of words, in which terminal nodes were actions and branching nodes were key words, and it had the property that any word it didn’t recognise at that point in sentence was a noise word and could be ignored. A few special hacks (such as ‘the’, ‘a’, or ‘an’ was an indicator that what came next was probably a noun phrase, and thus that if there was more than one sword in the player’s immediate environment the one that was wanted was the one tagged with the adjective ‘rusty’), and you ended up with a parser that most of the time convincingly interpreted most of what the player threw at it.

                    diff --git a/docs/codox/building_on_microworld.html b/docs/codox/building_on_microworld.html index 60744ec..96ccdf2 100644 --- a/docs/codox/building_on_microworld.html +++ b/docs/codox/building_on_microworld.html @@ -1,6 +1,6 @@ -Building on Microworld

                    Building on Microworld

                    +Building on Microworld

                    Building on Microworld

                    In Settling a Game World I intended that a world should be populated by setting agents - settlers - to explore the map and select places to settle according to particular rules. In the meantime, I’ve built MicroWorld, a rule driven cellular automaton which makes a reasonably good job of modelling human settlement. It works, and I now plan to use it, as detailed in this note; but there are issues.

                    First and foremost, it’s slow, and both processor and memory hungry. That means that at continent scale, a cell of one kilometre square is the minimum size which is really possible, which isn’t small enough to create a settlement map of the density that a game will need. Even with 1 km cells, even on the most powerful machines I have access to, a continent-size map will take many days to run.

                    Of course it would be possible to do a run at one km scale top identify areas which would support settlement, and then to do a run on a ten metre grid on each of those areas to more precisely plot settlement. That’s an idea which I haven’t yet explored, which might prove fruitful.

                    diff --git a/docs/codox/cc.journeyman.the-great-game.agent.agent.html b/docs/codox/cc.journeyman.the-great-game.agent.agent.html index 95e3177..19ff454 100644 --- a/docs/codox/cc.journeyman.the-great-game.agent.agent.html +++ b/docs/codox/cc.journeyman.the-great-game.agent.agent.html @@ -1,6 +1,6 @@ -cc.journeyman.the-great-game.agent.agent documentation

                    cc.journeyman.the-great-game.agent.agent

                    Anything in the game world with agency; primarily but not exclusively characters.

                    ProtoAgent

                    protocol

                    An object which can act in the world

                    members

                    act

                    (act actor world circle)

                    Allow actor to do something in this world, in the context of this circle; return the new state of the actor if something was done, nil if nothing was done. Circle is expected to be one of

                    +cc.journeyman.the-great-game.agent.agent documentation

                    cc.journeyman.the-great-game.agent.agent

                    Anything in the game world with agency; primarily but not exclusively characters.

                    ProtoAgent

                    protocol

                    An object which can act in the world

                    members

                    act

                    (act actor world circle)

                    Allow actor to do something in this world, in the context of this circle; return the new state of the actor if something was done, nil if nothing was done. Circle is expected to be one of