Add Licensing and Contributing
[clnl] / src / main / clnl / nvm / base.lisp
1 ; Copyright 2022 Frank Duncan (frank@consxy.com) under AGPL3.  See distributed LICENSE.txt.
2 (in-package #:clnl-nvm)
3
4 (defvar *current-id* 0)
5
6 (defvar *turtles* nil)
7 (defvar *turtles-own-vars* nil)
8 (defvar *patches-own-vars* nil)
9 (defvar *patches* nil)
10 (defvar *myself* nil)
11 (defvar *self* nil)
12 (defvar *dimensions* nil)
13 (defvar *globals* nil)
14 (defvar *topology* :torus)
15 (defvar *ticks* nil)
16 (defvar *breeds* nil)
17
18 (define-condition stop nil nil)
19 (define-condition death nil nil)
20
21 (defmacro with-stop-handler (&rest forms)
22  "MACRO WITH-STOP-HANDLER &rest FORMS => HANDLED-FORM
23
24 ARGUMENTS AND VALUES:
25
26   FORMS: body to be handled
27   HANDLED-FORM: body with handling
28
29 DESCRIPTION:
30
31   WITH-STOP-HANDLER is a convenience macro to handle when
32   programs issue a stop condition.  When one does, a simple
33   :stop is returned."
34  `(handler-case (progn ,@forms) (stop (s) (declare (ignore s)) :stop)))
35
36 (defmacro with-stop-and-death-handler (&rest forms)
37  `(handler-case
38    (progn ,@forms)
39    (stop (s) (declare (ignore s)) :stop)
40    (death (d) (declare (ignore d)) :death)))
41
42 (defmacro defcommand (name args docstring &rest body)
43  `(defun ,name ,args ,docstring ,@body :undefined))
44
45 (defstruct turtle who breed color heading xcor ycor (label "") label-color size shape own-vars)
46 (defstruct patch color xcor ycor own-vars turtles)
47
48 (defun agentset-list (agentset)
49  (cond
50   ((eql agentset :turtles) *turtles*)
51   ((eql agentset :patches) *patches*)
52   ((and (listp agentset) (eql :agentset (car agentset))) (cddr agentset))
53   ((find agentset *breeds* :key #'car)
54    (remove agentset *turtles* :key #'turtle-breed :test-not #'eql))
55   (t (error "Doesn't seem to be an agentset: ~A" agentset))))
56
57 (defun agentset-breed (agentset)
58  (cond
59   ((eql agentset :turtles) :turtles)
60   ((eql agentset :patches) :patches)
61   ((find agentset *breeds* :key #'car) agentset)
62   ((and (listp agentset) (eql :agentset (car agentset))) (second agentset))
63   (t (error "Doesn't seem to be an agentset: ~A" agentset))))
64
65 (defun list->agentset (list breed)
66  (append (list :agentset breed) list))
67
68 (defun agentset-p (o)
69  (or
70   (eql o :turtles)
71   (eql o :patches)
72   (find o *breeds* :key #'car)
73   (and (listp o) (eql :agentset (car o)))))
74
75 (defun agent-p (o)
76  (or (turtle-p o) (patch-p o)))
77
78 (defun breed-p (breed)
79  (find breed *breeds* :key #'car))
80
81 (defun breed-default-shape (breed)
82  (second (find breed *breeds* :key #'car)))
83
84 (defsetf breed-default-shape (breed) (shape)
85  `(setf (second (find ,breed *breeds* :key #'car)) ,shape))