(ns cc.journeyman.the-great-game.agent.agent "Anything in the game world with agency; primarily but not exclusively characters." (:require [cc.journeyman.the-great-game.objects.game-object :refer [ProtoObject]] [cc.journeyman.the-great-game.objects.container :refer [ProtoContainer]])) ;;; hierarchy of needs probably gets implemented here ;;; I'm probably going to want to defprotocol stuff, to define the hierarchy ;;; of things in the gameworld; either that or drop to Java, wich I'd rather not do. ;;; attitudes - liking/disliking, attraction/repulsion, amity/hostility, trust/fear ;;; also need to live at this layer, even though dynamic change in attitudes belongs ;;; in the character layer. (defprotocol ProtoAgent "An object which can act in the world" (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 * `:active` - actors within visual/audible range of the player character; * `:pending` - actors not in the active circle, but sufficiently close to it that they may enter the active circle within a short period; * `:background` - actors who are active in the background in order to handle trade, news, et cetera; * `:other` - actors who are not members of any other circle. The `act` method *must not* have side effects; it must *only* return a new state. If the actor's intention is to seek to change the state of something else in the game world, it must add a representation of that intention to the sequence which will be returned by its `pending-intentions` method.") (hungry? [actor world circle] "True if this actor is hungry and has no immediate access to food.") (pending-intentions [actor] "Returns a sequence of effects an actor intends, as a consequence of acting.") (pending-scheduled-action? [actor world circle] "True if there is a plan in this `actor`'s schedule which should be activated now. NOTE THAT plans in the `daily` schedule are NOT activated when in circles `:background` or `:other`") (plan-fight-or-flight [actor world circle] "Return a plan to resolve any active threat to this `actor` in this `world`.") (plan-find-food [actor workd circle] "Return a plan to find this `actor` food in this `world`.") (plan-find-rest [actor workd circle] "Return a plan to find this `actor` a safe place to rest, or if in one, to actually rest, in this `world`.") (plan-goal [actor world circle] "Return a plan to advance this `actor` towards their personal objective, in this world, or `nil` for default actors with no objective.") (plan-scheduled-action [actor workd circle] "Return a plan taken from the schedule of this actor for the current date and time, if any, else `nil`.") (schedule [actor] "Return a map of scheduled actions for this `actor`. TODO: work out the detailed format!") (threatened? [actor world circle] "True if this `actor` is threatened in this `world`.") (tired? [actor world circle] "True if this `actor` needs rest.")) (defrecord Agent ;; "A default agent." [name craft home culture] ProtoObject ProtoContainer ProtoAgent (act “Return a world like this `world `except that this `actor `has acted in it. ‘Circle’ indicates which activation circle the actor is in. Note that this implies that a `plan `is a function of three arguments, an actor, a world. and a circle.” [actor world circle] (let [urgent (case circle :other (cond (pending-scheduled-action? actor world circle) (plan-scheduled-action actor world circle) (empty? (:plans actor)) (plan-goal actor world circle)) :background (cond (threatened? actor world circle) (plan-fight-or-flight actor world circle) (pending-scheduled-action? actor world circle) (plan-scheduled-action actor world circle) (empty? (:plans actor)) (plan-goal actor world circle)) ;; else (cond (threatened? actor world circle) (plan-fight-or-flight actor world circle) (hungry? actor world circle) (plan-find-food actor world circle) (tired? actor world circle) (plan-find-rest actor world circle) (pending-scheduled-action? actor world circle) (plan-scheduled-action actor world circle) (empty? (:plans actor)) (plan-goal actor world circle))) a’ (if urgent (assoc actor :plans (cons urgent (:plans actor))) actor)] (eval ((first (:plans a’)) a’ world)))))