Add Licensing and Contributing
[clnl] / src / main / clnl / nvm / agent.lisp
1 ; Copyright 2022 Frank Duncan (frank@consxy.com) under AGPL3.  See distributed LICENSE.txt.
2 (in-package #:clnl-nvm)
3
4 (defun agent-value (var &optional (agent *self*))
5  "AGENT-VALUE VAR &optional AGENT => RESULT
6
7 ARGUMENTS AND VALUES:
8
9   VAR: A variable name
10   AGENT: an agent, defaulting to *self*
11   RESULT: the value of VAR
12
13 DESCRIPTION:
14
15   AGENT-VALUE is the general agent variable access function.  For many
16   NetLogo reporters, the compilation results is AGENT-VALUE.  The list of
17   valid values are any builtin variable in the NetLogo dictionary, as well
18   as any *-own variable.
19
20   See http://ccl.northwestern.edu/netlogo/docs/dictionary.html for builtins"
21  (agent-value-inner agent (intern (string-upcase var) :keyword)))
22
23 (defsetf agent-value (var &optional (agent '*self*)) (new-value)
24  `(set-agent-value-inner ,agent ,var ,new-value))
25
26 (defgeneric set-agent-value-inner (agent var new-value))
27 (defgeneric agent-value-inner (agent var))
28
29 (defmacro defagent-value (type symb &optional accessor)
30  (let
31   ((accessor (or accessor (intern (format nil "~A-~A" type symb))))
32    (agent (gensym))
33    (var (gensym))
34    (new-val (gensym)))
35   `(progn
36     (defmethod agent-value-inner ((,agent ,type) (,var (eql ,symb))) (,accessor ,agent))
37     (defmethod set-agent-value-inner ((,agent ,type) (,var (eql ,symb)) ,new-val) (setf (,accessor ,agent) ,new-val)))))
38
39 ; Don't want the setter for :who
40 (defmethod agent-value-inner ((turtle turtle) (var (eql :who))) (turtle-who turtle))
41
42 (defmethod agent-value-inner ((turtle turtle) (var (eql :pcolor)))
43  (patch-color (patch-at (turtle-xcor turtle) (turtle-ycor turtle))))
44
45 (defmethod set-agent-value-inner ((turtle turtle) (var (eql :pcolor)) new-val)
46  (setf (patch-color (patch-at (turtle-xcor turtle) (turtle-ycor turtle))) new-val))
47
48 (defagent-value patch :pcolor patch-color)
49
50 (defagent-value turtle :color)
51 (defagent-value turtle :label)
52 (defagent-value turtle :label-color)
53 (defagent-value turtle :size)
54
55 (defmethod agent-value-inner ((turtle turtle) var)
56  (when (not (find var *turtles-own-vars*)) (error "~S is not a turtle variable" var))
57  (or (getf (turtle-own-vars turtle) var) 0d0))
58
59 (defmethod set-agent-value-inner ((turtle turtle) var new-val)
60  (when (not (find var *turtles-own-vars*)) (error "~S is not a turtle variable" var))
61  (if (getf (turtle-own-vars turtle) var)
62   (setf (getf (turtle-own-vars turtle) var) new-val)
63   (setf (turtle-own-vars turtle) (append (list var new-val) (turtle-own-vars turtle)))))
64
65 (defmethod agent-value-inner ((patch patch) var)
66  (when (not (find var *patches-own-vars*)) (error "~S is not a patch variable" var))
67  (or (getf (patch-own-vars patch) var) 0d0))
68
69 (defmethod set-agent-value-inner ((patch patch) var new-val)
70  (when (not (find var *patches-own-vars*)) (error "~S is not a patch variable" var))
71  (if (getf (patch-own-vars patch) var)
72   (setf (getf (patch-own-vars patch) var) new-val)
73   (setf (patch-own-vars patch) (append (list var new-val) (patch-own-vars patch)))))