screwlisp proposes kittens

Leonardo Calculus Knowledge Representation: Running and rendering the Plant Insect Bird simulation once

๐Ÿชด๐ŸŒณ๐ŸŽ„๐ŸŒฒ๐ŸŒดโธ™๐Ÿƒ๐Ÿฅฌ๐Ÿฅ•๐Ÿฅฆ๐Ÿ๐Ÿ€๐Ÿ‚๐Ÿ‰๐Ÿ๐ŸŽ๐Ÿ๐ŸŒต๐ŸŒฟ๐Ÿฅ—๐Ÿฅ’๐Ÿฅ”๐Ÿˆ๐ŸŒ๐ŸŽ‹๐Ÿ„๐Ÿชต๐Ÿฅ๐Ÿซ๐Ÿซ’๐Ÿ ๐Ÿ“๐Ÿฅฅ๐Ÿ‹๐Ÿ‡๐Ÿฅœ๐Ÿชท๐Ÿ‘๐Ÿ๐ŸŽƒ๐Ÿฅ’๐ŸŒพ๐ŸŒฝ๐ŸŒนโš˜๐Ÿ’ฎ๐Ÿ’๐ŸŽ•๐Ÿฅ€๐Ÿถ๐Ÿต๐ŸŒฑ๐ŸŒป๐ŸŒท๐Ÿซ˜๐Ÿ›๐Ÿชฑ๐Ÿฆ‹๐Ÿชฒ๐Ÿ๐Ÿชฐ๐Ÿž๐Ÿœ๐ŸฆŸ๐Ÿ•ท๐Ÿฆ€๐Ÿฆž๐Ÿชณ๐ŸŒ๐Ÿš๐Ÿฆ‚๐Ÿ•ธ๐Ÿฆ๐Ÿงš๐Ÿฅ๐Ÿฆ๐Ÿฆ…๐Ÿ”๐Ÿ“๐Ÿฆ†๐Ÿฆข๐Ÿค๐Ÿฃ๐Ÿฆƒ๐Ÿ•Š๐Ÿง๐Ÿฆ‰๐Ÿฆซ๐Ÿฆฉ๐Ÿฆš๐Ÿฆค

Alright, now getting to video visualization of our Plant Insect Bird Braitenbergian simulation game. When freshly starting emacs, I visited the last article in emacs eww in order to just-press-F8-over-and-over in eev style to load everything, though I found that eev ditches the non-printing eev-mode red star character, so I had to make the buffer editable and write that in myself.

I think most of whatโ€™s remaining to do is add a fall-off-table-edge action, maybe called deluge, that nils organisms outside some bounding rectangle to run periodically, so that I donโ€™t experience infinite-ish entity growth. Then, since the leonardo system enforces latin1 script, I was thinking about adding a char-code property to organism, actually, letโ€™s just do that here and now (setup from the last article I linked)

Add display char-code attribute to organism

addmember (get organism attributes) char-code

writefil organisms

loadk organisms

(get organism attributes)

ses.016) loadk organisms
Load-ef: organisms at ../../../demus/Organisms/organisms.leo

ses.017) (get organism attributes)
  => {x-position y-position starvation-rate current-direction opening-angle sensor-scale natality-rate mortality-rate propagation-distance eating-distance lethality-rate prey-species sensor-weights char-code}

where I guess the video display, whatever, will use code-char on the organismโ€™s char-code attribute. So ๐Ÿ˜บ is 128570.

CL-USER> (princ (code-char 128570))
๐Ÿ˜บ
#\U01F63A

in a unicode-extended lisp. (Our Leonardo system is strictly latin1, but video is going to be external to our individual.).

deluge action for enforcing falling-off-the-table

put deluge type lispdef

addmember (get organisms contents) deluge

writefil organisms

And writing it into #p"~/leocommunity/Plantworld/demus/Organisms/organisms.leo":

---------------------------------------------------------
-- deluge

[: type lispdef]
[: latest-rearchived nil]

(leodef deluge deluge (xmin xmax ymin ymax)
 (loop
  :for organism :in (cdadr (get 'world 'contents))
  :unless (and (< xmin (get organism 'x-position) xmax)
  	     (< ymin (get organism 'y-position) ymax))
  :do (setf (get organism 'type) nil)))

ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo

writefil organisms

loadk organisms

hopefully that will do.

ses.026) (get world contents)
  => <world>

ses.027) put parrot type bird
put: parrot type bird

ses.028) put parrot x-position -10
put: parrot x-position -10

ses.029) put parrot y-position 0
put: parrot y-position 0

ses.030) addmember (get world contents) parrot

ses.031) deluge -5 5 -5 5

ses.032) (get parrot type)
  => nil

seems so.

A literally so random-new-organism maker

put random-new-organism type lispdef

addmember (get organisms contents) random-new-organism

writefil organisms

---------------------------------------------------------
-- random-new-organism

[: type lispdef]
[: latest-rearchived nil]

(leodef random-new-organism random-new-organism ()
	(let* ((type (nth (random 3)
			  '(plant insect bird)))
	       (x-position (random 100))
	       (y-position (random 100))
	       (starvation-rate (random 100))
	       (current-direction
		 (nth (random 8)
		      '(e ne n nw w sw s se)))
	       (opening-angle
		 (+ 23 (random (- 180 23))))
	       (sensor-scale
		 (1+ (random 8)))
	       (natality-rate
		 (random 100))
	       (mortality-rate
		 (random 100))
	       (propagation-distance
		 (1+ (random 8)))
	       (lethality-rate
		 (random 100))
	       (prey-species
		 `(set&
		   ,(nth
		     (random 8)
		     '(()
		       (plant)
		       (insect)
		       (bird)
		       (plant insect)
		       (plant bird)
		       (bird insect)
		       (plant bird insect)))))
	       (sensor-weights
		 `(seq&
		   (
		    (seq& (plant ,(- (random 10) 5)))
		    (seq& (insect ,(- (random 10) 5)))
		    (seq& (bird ,(- (random 10) 5)))
		    )))
	       (char-code
		 (let ((plants '(129716 127795 127876 127794
				 127796 11801 127811 129388
				 129365 129382 127809 127808
				 127810 127817 127823 127822
				 127821 127797 127807 129367
				 129362 129364 127816 127820
				 127883 127812 129717 129373
				 129744 129746 127840 127827
				 129381 127819 127815 129372
				 129719 127825 127824 127875
				 129362 127806 127805 127801
				 9880 128174 128144 127893
				 129344 127990 127989 127793
				 127803 127799 129752 129361))
		       (insects
			 '(128027 129713 129419 129714 128029
			   129712 128030 128028 129439 128375
			   129408 129438 129715 128012 128026
			   129410 128376 129424 129498))
		       (birds
			 '(128037 128038 129413 128020 128019
			   129414 129442 128036 128035 129411
			   128330 128039 129417 129451
			   129449 129434 129444)))
		   (case type
		     (plant
		      (nth (random (length plants)) plants))
		     (insect
		      (nth (random (length insects))
			   insects))
		     (bird
		      (nth (random (length birds))
			   birds)))))
	       (sym (intern
		     (symbol-name
		      (gensym (symbol-name type))))))
	  (setf (symbol-plist sym)
		`(type
		  ,type
		  x-position ,x-position
		  y-position ,y-position
		  starvation-rate ,starvation-rate
		  current-direction ,current-direction
		  opening-angle ,opening-angle
		  sensor-scale ,sensor-scale
		  natality-rate ,natality-rate
		  mortality-rate ,mortality-rate
		  propagation-distance ,propagation-distance
		  lethality-rate ,lethality-rate
		  prey-species ,prey-species
		  sensor-weights ,sensor-weights
		  char-code ,char-code))
	  (nconc (cdadr (get 'world 'contents))
	 	   (list sym))
	  (print sym)
	  (print (symbol-plist sym))
	  (values sym)))

ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo

Got slightly carried away just brainstorming unicode codes for plants/insects/birds.

Annoyingly non-portable copy-to-gnu-emacs definition

. (defun world-to-emacs () (swank:eval-in-emacs `(setq *world* ',(loop :for thing :in (cdadr (get 'world 'contents)) :collect (symbol-plist thing)))))

Since cle uses 'read-line, we need to pitch just one line. Sorry for the overflowing line.

A bunch of new organisms

First off, I noticed that mortality-rate is overwhelmingly high, and secondarily, cannibalistic organisms will eat themselves if they are the oldest available prey-species at hand.

Still, I felt like it was possible that an unattended search would turn up some quasistable alien ecologies.

I might use the senesce action to control the total population size- i.e. if there are more than a thousand entities, call senesce until there are below a thousand entities. This means there is differential survival rates between species of culls.

Maybe tomorrow, we can look at some planned dynamics as well as the silliness of these random ones. Iโ€™m pretty sure that a mixture of very prolific plants with a high propagation-range + short-sighted/short-propagation herbivorous insects will naturally form quasi-stable wavefronts, that would then be able to host bird species. But it would be fun if something emerges out of randomness.

ses.065) (get world contents)
  => <world parrot>

ses.066) random-new-organism

PLANT39744 
(type plant x-position 20 y-position 23 starvation-rate 96 current-direction nw
 opening-angle 170 sensor-scale 4 natality-rate 57 mortality-rate 74
 propagation-distance 1 lethality-rate 54 prey-species (set& (plant bird))
 sensor-weights (seq& ((seq& (plant 0)) (seq& (insect -3)) (seq& (bird 3))))
 char-code 127820) PLANT39744

ses.067) (get world contents)
  => <world parrot PLANT39744>

ses.068) random-new-organism

PLANT39761 
(type plant x-position 96 y-position 43 starvation-rate 75 current-direction e
 opening-angle 143 sensor-scale 7 natality-rate 19 mortality-rate 76
 propagation-distance 3 lethality-rate 42 prey-species (set& (plant insect))
 sensor-weights (seq& ((seq& (plant -2)) (seq& (insect -4)) (seq& (bird 3))))
 char-code 129344) PLANT39761

ses.069) random-new-organism

BIRD39770 
(type bird x-position 74 y-position 41 starvation-rate 76 current-direction sw
 opening-angle 27 sensor-scale 6 natality-rate 17 mortality-rate 13
 propagation-distance 4 lethality-rate 83 prey-species (set& (plant bird))
 sensor-weights (seq& ((seq& (plant 4)) (seq& (insect 4)) (seq& (bird 3))))
 char-code 129436) BIRD39770

ses.070) random-new-organism

INSECT39779 
(type insect x-position 71 y-position 60 starvation-rate 26 current-direction
 nw opening-angle 50 sensor-scale 8 natality-rate 2 mortality-rate 5
 propagation-distance 2 lethality-rate 46 prey-species (set& (bird insect))
 sensor-weights (seq& ((seq& (plant 4)) (seq& (insect 2)) (seq& (bird -3))))
 char-code 129408) INSECT39779

ses.071) random-new-organism

INSECT39788 
(type insect x-position 81 y-position 1 starvation-rate 97 current-direction ne
 opening-angle 172 sensor-scale 7 natality-rate 38 mortality-rate 51
 propagation-distance 7 lethality-rate 87 prey-species (set& (plant))
 sensor-weights (seq& ((seq& (plant 1)) (seq& (insect -4)) (seq& (bird 4))))
 char-code 129408) INSECT39788

ses.072) random-new-organism

INSECT39797 
(type insect x-position 46 y-position 52 starvation-rate 5 current-direction ne
 opening-angle 170 sensor-scale 1 natality-rate 50 mortality-rate 29
 propagation-distance 2 lethality-rate 90 prey-species (set& (plant bird))
 sensor-weights (seq& ((seq& (plant 0)) (seq& (insect -2)) (seq& (bird -5))))
 char-code 128026) INSECT39797

ses.073) (get world contents)
  => <world parrot PLANT39744 PLANT39761 BIRD39770 INSECT39779 INSECT39788 INSECT39797>

Actually driving the simulation

I guess I am going to sit in an embeddable common lisp image, and drive the Plantworld individual via the emacs-server, and print the state of the world.

eepitch-send (emacs lisp)

Like before

(defun eepitch-send
    (buffername line)
  (setq eepitch-buffer-name buffername)
  (setq line (eepitch-preprocess-line line))
  (eepitch-prepare)
(eepitch-line line))

eepitch (common lisp)

but in this case I need to send strings, since the leonardo calculus often doesnโ€™t manifest in normal-looking s-expressions.

 (setq eepitch-buffer-name "*slime-repl ECL*")

'a

(defun e-e-str (buffername line)
  "'external-eepitch-send'
buffername	string (emacs buffer name string)
line		string (as eepitch)
"
  (require "asdf")
  (uiop:launch-program
   (let ((*print-pretty* nil))
    (format
      nil
      "emacsclient --eval '(eepitch-send ~s \"~a\")'"
buffername line))))
CL-USER> (e-e-str "*slime-repl ECL*" "`foo")
#<a UIOP/RUN-PROGRAM::PROCESS-INFO 0x7f9b62824a00>
CL-USER> `foo
FOO
CL-USER> 

everything seems to be going according to plan. However, this article has been a kind of run-on do-everything-that-hasnโ€™t-been-done, so let us try and wrap things up for now.

Print the world

Copy the world file to emacs

 (setq eepitch-buffer-name "*slime-repl ECL*")

(e-e-str "*slime-repl clisp*" ". (world-to-emacs)")

 (setq eepitch-buffer-name "*slime-repl ECL*")

(swank:eval-in-emacs '*world*)

Well, itโ€™s a hassle that those symbols got interned in SWANK-IO-PACKAGE.

*world*

(defun interpret-world (plists)
  (loop
   :with x-position
   := (intern "X-POSITION" "SWANK-IO-PACKAGE")
   :with y-position
   := (intern "Y-POSITION" "SWANK-IO-PACKAGE")
   :with char-code
   := (intern "CHAR-CODE" "SWANK-IO-PACKAGE")
   :for plist :in plists
   :collect
   `((,(getf plist x-position) ,(getf plist y-position))
     ,(code-char (getf plist char-code)))))

=>

(((20 23) #\U01F34C) ((96 43) #\U01F940) ((74 41) #\U01F99C)
 ((71 60) #\U01F980) ((81 1) #\U01F980) ((46 52) #\U01F41A))

of which, I can just print something like that. I recall the enclosure is 100x100.

(defun print-world (alist)
  (loop :for y :below 100 :do
	(loop 
	 :for x :below 100
	 :for ch := (cadr (assoc `(,x ,y) alist
				 :test 'equal))
	 :if ch :do (princ ch)
	 :else :do (princ #\Space)
	 :finally (terpri))))

so.

                                                                                                    
                                                                                 ๐Ÿฆ€                  
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                    ๐ŸŒ                                                                               
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                          ๐Ÿฆœ                         
                                                                                                    
                                                                                                ๐Ÿฅ€   
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                              ๐Ÿš                                                     
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                       ๐Ÿฆ€                            

Letโ€™s call this here, we implemented rendering states of the world in a separate lisp.

Conclusion

We saw our way to operating and accessing the Leonardo system simulation from a different, embeddable common lisp image in the same emacs, which is fundamental progress. We were able to render it.

The (random 100) mortality rates are very high: But maybe senesce can be repurposed as a randomly weighted culling. And there are oddities like cannibalistic species eating themselves.

I think this is the last of the desperate-scramble articles, given that there is a rendered unicode crab visible slightly up from here we got somewhere. It seems like all that is left tomorrow is to practice using our simulation, which should be more sane for you to read (sorry about your sanity hitherto).

Fin.

See you on the Mastodon thread to talk about it.

screwlisp proposes kittens