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.gossip.news-items

      Categories of news events interesting to gossip agents.

      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.time

      TODO: write docs

      cc.journeyman.the-great-game.utils

      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.gossip.news-items

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

          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.time

          TODO: write docs

          cc.journeyman.the-great-game.utils

          TODO: write docs

          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))))) +