<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-14701151</id><updated>2013-04-18T03:56:50.031+02:00</updated><category term='dto'/><category term='google-ai-challenge'/><category term='virtualbox'/><category term='bull'/><category term='emacs'/><category term='unreal-tournament'/><category term='zpng'/><category term='ogre'/><category term='sbcl'/><category term='ai'/><category term='gamebots'/><category term='proxybot'/><category term='politiek'/><category term='eclm'/><category term='png-read'/><category term='gtk'/><category term='clysma'/><category term='games'/><category term='lisp'/><category term='ai bots games'/><category term='common-lisp'/><category term='png'/><category term='nl'/><category term='amazon aws dropbox ec2 shell ssh'/><category term='ecl'/><category term='clois-lane'/><category term='black-tie'/><category term='okra'/><category term='vecto'/><category term='markdown'/><category term='ois'/><category term='windows'/><category term='machine-learning'/><category term='genetic-programming'/><category term='artificial-intelligence'/><category term='ilge2010'/><category term='starcraft-ai-competition'/><title type='text'>Ceci n'est pas un titre</title><subtitle type='html'>irregular rants and mind-farts</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default?start-index=26&amp;max-results=25'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>32</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-14701151.post-567556088139319209</id><published>2012-04-06T14:14:00.000+02:00</published><updated>2012-04-06T14:14:11.777+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ai bots games'/><title type='text'>Open Letter to Online Game Developers: Allow Bots</title><content type='html'>As someone which a strong interest (and little experience) in artificial intelligence I have a short and to the point request for online game developers: allow bots.&lt;br /&gt;&lt;br /&gt;Either have specific servers or, if you're single sharded, places in your game universe where bots are allowed.&amp;nbsp; Outside of those servers and places continue your battle against illegal macroing, gold farming and botting:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;In the bot-legal places do allow human players.&lt;/li&gt;
&lt;li&gt;When making a new account (or avatar) have a player flag it as being used by a bot.&amp;nbsp; It should still be able to be used by a human as well.&lt;/li&gt;
&lt;/ul&gt;
There's huge potential if people are able to legally run their AI projects in a gaming universe.&amp;nbsp; Witness the popularity of AI programming competitions like the &lt;a href="http://aichallenge.org/"&gt;Google AI Challenge&lt;/a&gt;, the &lt;a href="http://www.marioai.org/"&gt;Mario AI Competition&lt;/a&gt;, &lt;a href="http://code.google.com/p/bwapi/wiki/Competitions"&gt;Starcraft AI Competitions&lt;/a&gt; and many others.&lt;br /&gt;&lt;br /&gt;It would so be nice to be able to experiment with AI bots in online games without the fear of one's account being banned (and having to spend money on a new account).&lt;br /&gt;&lt;br /&gt;This blog post is partly aimed at Blizzard since they represent such a large part of the PC online games market with Starcraft 2, World of Warcraft and, in a few months, Diablo 3.</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/567556088139319209/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2012/04/open-letter-to-online-game-developers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/567556088139319209'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/567556088139319209'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2012/04/open-letter-to-online-game-developers.html' title='Open Letter to Online Game Developers: Allow Bots'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-5429974962351581732</id><published>2012-01-06T12:07:00.000+01:00</published><updated>2012-01-06T12:07:42.833+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='amazon aws dropbox ec2 shell ssh'/><title type='text'>Ghetto DNS</title><content type='html'>This is probably stupid, but…&lt;br /&gt;
&lt;br /&gt;
I start my &lt;a href="http://aws.amazon.com/ec2/"&gt;EC2&lt;/a&gt; instance only when I need it but a while ago it was
needed pretty often and figuring out the IP every time I wanted to SSH
to the machine got annoying quickly.&amp;nbsp; Using the &lt;a href="http://github.com/andreafabrizi/Dropbox-Uploader"&gt;Dropbox Uploader&lt;/a&gt; bash script it was easy to set up a poor
man's DNS since &lt;a href="http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html?r=8687"&gt;Amazon provides a way to figure out the public IP of an EC2 instance&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
So by doing:&lt;br /&gt;
&lt;pre class="src src-shell"&gt;curl -s http://169.254.169.254/latest/meta-data/public-hostname&lt;/pre&gt;
and using Dropbox Uploader one can put that result into a text file
(say &lt;code&gt;ec2-hostname.txt&lt;/code&gt;) in a Dropbox folder and use it in an SSH
command as follows:&lt;br /&gt;
&lt;pre class="src src-shell"&gt;ssh -i your-amazon.pem username@`cat ~Dropbox/ec2-hostname.txt`&lt;/pre&gt;
This solution had a certain gum and wire charm that I had to try it
out but it only suffices for one man in his attic.  If you want robust
and scalable solution you'll need to use real DNS or Amazon's Elastic
IP.&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/5429974962351581732/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2012/01/ghetto-dns.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/5429974962351581732'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/5429974962351581732'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2012/01/ghetto-dns.html' title='Ghetto DNS'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-1819015072784368460</id><published>2011-10-19T11:23:00.005+02:00</published><updated>2011-10-19T14:41:13.718+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><category scheme='http://www.blogger.com/atom/ns#' term='virtualbox'/><category scheme='http://www.blogger.com/atom/ns#' term='proxybot'/><category scheme='http://www.blogger.com/atom/ns#' term='google-ai-challenge'/><title type='text'>VirtualBox Common Lisp Environment for Google AI Ants Challenge</title><content type='html'>&lt;i&gt;(see the end of this post for remarks I've gotten about the vbox image)&lt;/i&gt; &lt;br /&gt;
&lt;br /&gt;
So, the next &lt;a href="http://aichallenge.org/"&gt;Google AI Challenge&lt;/a&gt; seems to be &lt;a href="http://groups.google.com/group/ai-contest-discuss/browse_thread/thread/1c072f12667b31a5#5ea70ef2ce95d6b5"&gt;almost ready to get going&lt;/a&gt;, albeit six months later than I expected.&lt;br /&gt;
&lt;br /&gt;
As blogged about earlier this year I have been worked on &lt;a href="http://github.com/aichallenge/aichallenge/tree/epsilon/ants/dist/starter_bots/common_lisp"&gt;the Common Lisp starter bot&lt;/a&gt; for the challenge, &lt;a href="http://github.com/aerique/google-ai-challenge-2011-1-ants"&gt;an alternative starter bot&lt;/a&gt; with a proxybot, &lt;a href="http://aerique.blogspot.com/2011/07/common-lisp-proxy-bot-videos-for-google.html"&gt;some YouTube videos&lt;/a&gt; and now &lt;a href="http://s3.amazonaws.com/google-ai-ants-common-lisp/Google+AI+Ants+Challenge+%28Common+Lisp%29.7z"&gt;a VirtualBox image&lt;/a&gt; with an Emacs+Slime environment ready to go.&lt;br /&gt;
&lt;br /&gt;
Due to the long delay for this challenge to get started some of these projects aren't quite up to date anymore but they should still be quite usable and at least get you started or help you along.&lt;br /&gt;
&lt;br /&gt;
The VirtualBox image is up to date as of writing this post and any comments on it would be welcomed.  I will not make a new image (although someone else is free to do so) but if possible I will provide a patch on the AI Challenge forums.&lt;br /&gt;
&lt;br /&gt;
On booting the image it will start up SBCL, Emacs and Slime (connected to SBCL) with some instructions in the scratch buffer.&amp;nbsp; Perhaps it is a good start for another Lisp-in-a-box project.&lt;br /&gt;
&lt;br /&gt;
I am not sure how much time I will be able to spend on the current challenge due to also participating in the online &lt;a href="http://www.ai-class.com/"&gt;Introduction to Artificial Intelligence&lt;/a&gt; and starting a three month sabbatical gig writing an iPad client for a startup November 1st.&lt;br /&gt;
&lt;h3&gt;
Specific Remarks about the VirtualBox Image &lt;/h3&gt;
&lt;blockquote&gt;
14:23 &amp;lt; Xach&amp;gt; the remapping of [] and () confused me though.&lt;/blockquote&gt;
Right, I've been computing like this for so many years that I totally forgot about this.&amp;nbsp; The parens have been swapped with the brackets otherwise Lisp programming becomes quite painful.&amp;nbsp; If you want to reset this check out keycodes 18, 19, 34 and 35 in ~/.xmodmaprc and reboot the image.&lt;br /&gt;
&lt;br /&gt;
Now that I think of it, Control and Caps Lock are probably swapped as well.&amp;nbsp; That's done in the ~/.xmodmaprc as well.</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/1819015072784368460/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2011/10/virtualbox-common-lisp-environment-for.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/1819015072784368460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/1819015072784368460'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2011/10/virtualbox-common-lisp-environment-for.html' title='VirtualBox Common Lisp Environment for Google AI Ants Challenge'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-1243442563932622162</id><published>2011-09-25T22:23:00.001+02:00</published><updated>2011-09-25T22:25:34.412+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='png'/><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='zpng'/><category scheme='http://www.blogger.com/atom/ns#' term='vecto'/><category scheme='http://www.blogger.com/atom/ns#' term='png-read'/><title type='text'>Adding Text to PNGs</title><content type='html'>&lt;p&gt;(I'm putting this out here since Google queries for this situation
didn't turn up anything useful for me.)
&lt;/p&gt;
&lt;p&gt;
Last night I had to add some text ± 5000 PNG files and I knew about
Zach Beane's &lt;a href="http://www.xach.com/lisp/zpng/"&gt;ZPNG&lt;/a&gt; package for reading PNGs but I didn't know of a
package that would read them.
&lt;/p&gt;
&lt;p&gt;
A quicklisp:system-apropos turned up &lt;a href="https://github.com/Ramarren/png-read#readme"&gt;png-read&lt;/a&gt; written by Ramarren
which looked simple enough to use so I went with that.  After
initially failing to get ZPNG to use png-read's image-data slot I gave
up and wrote a little loop to copy the values over to zpng:data-array.
This was succesful after one or two tries:
&lt;/p&gt;



&lt;pre class="src src-common-lisp"&gt;(asdf &lt;span style="color: #8b4789;"&gt;:png-read&lt;/span&gt;)
(asdf &lt;span style="color: #8b4789;"&gt;:zpng&lt;/span&gt;)

&lt;span style="color: #b22222;"&gt;;; &lt;/span&gt;&lt;span style="color: #b22222;"&gt;http://imgur.com/qtriH.png
&lt;/span&gt;(&lt;span style="color: #551a8b;"&gt;defparameter&lt;/span&gt; &lt;span style="color: #000000;"&gt;png&lt;/span&gt; (png-read:read-png-file &lt;span style="color: #8b4513;"&gt;"qtriH.png"&lt;/span&gt;))
(&lt;span style="color: #551a8b;"&gt;defparameter&lt;/span&gt; &lt;span style="color: #000000;"&gt;zpng&lt;/span&gt; (make-instance 'zpng:png &lt;span style="color: #8b4789;"&gt;:color-type&lt;/span&gt; &lt;span style="color: #8b4789;"&gt;:truecolor&lt;/span&gt;
                                  &lt;span style="color: #8b4789;"&gt;:width&lt;/span&gt; (png-read:width png)
                                  &lt;span style="color: #8b4789;"&gt;:height&lt;/span&gt; (png-read:height png)))

(&lt;span style="color: #551a8b;"&gt;loop&lt;/span&gt; for y from 0 below (zpng:height zpng)
      do (&lt;span style="color: #551a8b;"&gt;loop&lt;/span&gt; for x from 0 below (zpng:width zpng)
               do (&lt;span style="color: #551a8b;"&gt;loop&lt;/span&gt; for rgb from 0 below 3
                        do (setf (aref (zpng:data-array zpng) y x rgb)
                                 (aref (png-read:image-data png) x y rgb)))))

(zpng:write-png zpng &lt;span style="color: #8b4513;"&gt;"tmp.png"&lt;/span&gt;)
&lt;/pre&gt;



&lt;p&gt;
I'm sure Zach had a good reason to reverse the x and y in ZPNG but I
can't deduce it.
&lt;/p&gt;
&lt;p&gt;
So, reading and writing the files was working but now I realized ZPNG
didn't have any functionality for generating text.  (Why should it?
It shouldn't.)  I started thinking of &lt;a href="http://www.xach.com/lisp/vecto/"&gt;Vecto&lt;/a&gt; since I had used that
before and also recalled that it actually used ZPNG for saving PNGs.
Now all I needed to do was getting the original image into Vecto so
text could be written over it.
&lt;/p&gt;
&lt;p&gt;
Going through Vecto's source showed me I could get at the ZPNG object
through the (shadowed) *GRAPHICS-STATE* global.  It wasn't exported
from the Vecto package but since I was in hack mode anyway it didn't
really matter.  I used the (slightly adapted) code above, drew some
text, did a VECTO:SAVE-PNG and got an empty image.
&lt;/p&gt;
&lt;p&gt;
In Vecto's source I noticed the ZPNG object had four channels instead
of the three I was using so I set the fourth channel (alpha) to opaque
and got my input PNG back with the custom text generated by Vecto.
Done!
&lt;/p&gt;



&lt;pre class="src src-common-lisp"&gt;(asdf &lt;span style="color: #8b4789;"&gt;:png-read&lt;/span&gt;)
(asdf &lt;span style="color: #8b4789;"&gt;:vecto&lt;/span&gt;)

(use-package &lt;span style="color: #8b4789;"&gt;:vecto&lt;/span&gt;)

&lt;span style="color: #b22222;"&gt;;; &lt;/span&gt;&lt;span style="color: #b22222;"&gt;http://imgur.com/qtriH.png
&lt;/span&gt;(&lt;span style="color: #551a8b;"&gt;defparameter&lt;/span&gt; &lt;span style="color: #000000;"&gt;png&lt;/span&gt; (png-read:read-png-file &lt;span style="color: #8b4513;"&gt;"qtriH.png"&lt;/span&gt;))
(&lt;span style="color: #551a8b;"&gt;defparameter&lt;/span&gt; &lt;span style="color: #000000;"&gt;zpng&lt;/span&gt; (make-instance 'zpng:png &lt;span style="color: #8b4789;"&gt;:color-type&lt;/span&gt; &lt;span style="color: #8b4789;"&gt;:truecolor&lt;/span&gt;
                                  &lt;span style="color: #8b4789;"&gt;:width&lt;/span&gt; (png-read:width png)
                                  &lt;span style="color: #8b4789;"&gt;:height&lt;/span&gt; (png-read:height png)))

(&lt;span style="color: #551a8b;"&gt;with-canvas&lt;/span&gt; (&lt;span style="color: #8b4789;"&gt;:width&lt;/span&gt; (zpng:width zpng) &lt;span style="color: #8b4789;"&gt;:height&lt;/span&gt; (zpng:height zpng))
  (&lt;span style="color: #551a8b;"&gt;loop&lt;/span&gt; for y from 0 below (zpng:height zpng)
        do (&lt;span style="color: #551a8b;"&gt;loop&lt;/span&gt; for x from 0 below (zpng:width zpng)
                 do (&lt;span style="color: #551a8b;"&gt;loop&lt;/span&gt; for rgb from 0 below 4
                          do (&lt;span style="color: #551a8b;"&gt;if&lt;/span&gt; (&amp;lt; rgb 3)
                                 (setf (aref (zpng:data-array (vecto::image vecto::*graphics-state*)) y x rgb)
                                       (aref (png-read:image-data png) x y rgb))
                                 (setf (aref (zpng:data-array (vecto::image vecto::*graphics-state*)) y x rgb)
                                       255)))))
  (set-font (get-font &lt;span style="color: #8b4513;"&gt;"font.ttf"&lt;/span&gt;) 32)
  (draw-centered-string (floor (/ (zpng:width zpng) 2))
                        (- (zpng:height zpng) 80)
                        &lt;span style="color: #8b4513;"&gt;"Hello, World!"&lt;/span&gt;)
  (save-png &lt;span style="color: #8b4513;"&gt;"tmp.png"&lt;/span&gt;))
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/1243442563932622162/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2011/09/adding-text-to-pngs.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/1243442563932622162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/1243442563932622162'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2011/09/adding-text-to-pngs.html' title='Adding Text to PNGs'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-1143215429978352896</id><published>2011-07-31T11:22:00.003+02:00</published><updated>2011-08-02T14:53:52.089+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='dto'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><title type='text'>What has happened to David O'Toole?</title><content type='html'>&lt;b&gt;Update: he linked me to this restatement on #lisp: &lt;a href="http://cryptome.org/0005/dod-lisp-sol.htm"&gt;http://cryptome.org/0005/dod-lisp-sol.htm&lt;/a&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Does anyone know what has happened to David O'Toole?&amp;nbsp; He hasn't been heard of since a last curious post to the lisp-games-dev mailing list: &lt;a href="http://lists.common-lisp.net/pipermail/lisp-game-dev/2011-July/000158.html"&gt;http://lists.common-lisp.net/pipermail/lisp-game-dev/2011-July/000158.html&lt;/a&gt; (read the whole thread)&lt;br /&gt;
&lt;br /&gt;
His website, blog, twitter and github have all been either removed or cleared:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://lispgamesdev.blogspot.com/"&gt;http://lispgamesdev.blogspot.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://twitter.com/dto1138"&gt;http://twitter.com/dto1138&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/dto"&gt;http://github.com/dto&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/1143215429978352896/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2011/07/what-has-happened-to-david-otoole.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/1143215429978352896'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/1143215429978352896'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2011/07/what-has-happened-to-david-otoole.html' title='What has happened to David O&apos;Toole?'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-7185894865304547128</id><published>2011-07-23T20:54:00.001+02:00</published><updated>2011-07-23T20:57:42.900+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='proxybot'/><category scheme='http://www.blogger.com/atom/ns#' term='google-ai-challenge'/><title type='text'>Common Lisp Proxy Bot Videos for Google AI Ants Challenge</title><content type='html'>I have made two screencasts showing the setup and usage of the proxy bot for the upcoming Google AI Challenge. This was at the request of &lt;a href="https://github.com/mcleopold"&gt;McLeopold&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
For the Planet Wars challenge I've tried to explain the use case for a proxy bot on the forums. Please read &lt;a href="http://www.ai-contest.com/forum/viewtopic.php?f=19&amp;amp;t=468"&gt;that post&lt;/a&gt; if you have no idea what the proxy bot does, although I will try to sum it up now: the proxy bot allows one to develop your actual bot in the usual 'Lispy' way[1] while the game engine runs and kills the proxy bot.&lt;br /&gt;
&lt;br /&gt;
Since it uses sockets for communication it ought to work for other languages than Common Lisp but this hasn't been tested.&lt;br /&gt;
&lt;br /&gt;
[1] Running Lisp image and, for example, Emacs + Slime.&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen="" frameborder="0" height="349" src="http://www.youtube.com/embed/xNsaZSFCEPQ" width="425"&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen="" frameborder="0" height="349" src="http://www.youtube.com/embed/x999Y0xB6kU" width="425"&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/7185894865304547128/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2011/07/common-lisp-proxy-bot-videos-for-google.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/7185894865304547128'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/7185894865304547128'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2011/07/common-lisp-proxy-bot-videos-for-google.html' title='Common Lisp Proxy Bot Videos for Google AI Ants Challenge'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/xNsaZSFCEPQ/default.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-449791122153351290</id><published>2011-04-05T15:16:00.000+02:00</published><updated>2011-04-05T15:16:09.420+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='ogre'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='okra'/><title type='text'>Ogre3D / Okra Update</title><content type='html'>&lt;a href="https://github.com/aerique/okra#readme"&gt;Okra&lt;/a&gt; (Common Lisp bindings for the Ogre3D engine) hasn't seen a lot of work lately. It covers my current needs and I've mostly been off to other projects.  However, there's good news from the Ogre camp: there's now &lt;a href="http://www.ogre3d.org/forums/viewtopic.php?f=3&amp;amp;t=63153"&gt;a community effort&lt;/a&gt; to create a &lt;a href="http://code.google.com/p/llcoi/"&gt;C API&lt;/a&gt;!&lt;br /&gt;
&lt;br /&gt;
I can only hope the API will have settled down before I return to using Ogre.</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/449791122153351290/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2011/04/ogre3d-okra-update.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/449791122153351290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/449791122153351290'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2011/04/ogre3d-okra-update.html' title='Ogre3D / Okra Update'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-5842001728061452491</id><published>2011-03-31T10:57:00.001+02:00</published><updated>2011-03-31T10:58:21.657+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='google-ai-challenge'/><title type='text'>Preparing for the next Google AI Challenge</title><content type='html'>Work is in progress for the next &lt;a href="http://ai-contest.com/"&gt;Google AI Challenge&lt;/a&gt; and I've been working on the Common Lisp starter package.  &lt;a href="http://github.com/aichallenge/aichallenge/issues#issue/3/comment/934055"&gt;At the request of the organizers&lt;/a&gt; the starter package has been made very basic.&lt;br /&gt;
&lt;br /&gt;
A more extensive starter package with &lt;a href="http://ai-contest.com/forum/viewtopic.php?f=19&amp;amp;t=468"&gt;proxy-bot&lt;/a&gt; functionality is available at: &lt;a href="http://github.com/aerique/google-ai-challenge-2011-1-ants/"&gt;http://github.com/aerique/google-ai-challenge-2011-1-ants/&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Proxy-bot functionality is meant to allow for more Lisp-like development of your bot.  You can keep your actual bot running in, for example, a Slime session while the proxy-bot is started up and killed by the game server.  The proxy-bot connects to your actual bot in the Slime session to play the game, ie. it just passes on state and orders between the game server and your actual bot.</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/5842001728061452491/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2011/03/preparing-for-next-google-ai-challenge.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/5842001728061452491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/5842001728061452491'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2011/03/preparing-for-next-google-ai-challenge.html' title='Preparing for the next Google AI Challenge'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-8024950545070946198</id><published>2011-01-18T16:39:00.002+01:00</published><updated>2011-01-18T23:15:21.770+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='ai'/><category scheme='http://www.blogger.com/atom/ns#' term='artificial-intelligence'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='genetic-programming'/><category scheme='http://www.blogger.com/atom/ns#' term='machine-learning'/><title type='text'>Baby Steps into Genetic Programming</title><content type='html'>&lt;div id="table-of-contents"&gt;
&lt;h2&gt;Table of Contents&lt;/h2&gt;
&lt;div id="text-table-of-contents"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#sec-1"&gt;1 Introduction &lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#sec-1_1"&gt;1.1 Toy Project &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-1_2"&gt;1.2 Environment &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-2"&gt;2 Generating Random Code &lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#sec-2_1"&gt;2.1 Operators &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-2_2"&gt;2.2 RANDOM-ELT &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-2_3"&gt;2.3 Generating Random Function Forms &lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#sec-2_3_1"&gt;2.3.1 Limiting RANDOM-FORM &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-2_4"&gt;2.4 &lt;code&gt;=INPUT=&lt;/code&gt; &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-2_5"&gt;2.5 Testing RANDOM-ELT and RANDOM-FORM &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-3"&gt;3 Running Generated Code &lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#sec-3_1"&gt;3.1 SBCL note &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-4"&gt;4 Population &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-5"&gt;5 Fitness &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-6"&gt;6 Generation Functions &lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#sec-6_1"&gt;6.1 Traversing Nodes &lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#sec-6_1_1"&gt;6.1.1 N-NODES &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-6_1_2"&gt;6.1.2 Picking Random Nodes &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-6_1_3"&gt;6.1.3 Replacing Nodes &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-6_2"&gt;6.2 Cross-overs &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-6_3"&gt;6.3 Mutation &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-7"&gt;7 Advancing a Generation &lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#sec-7_1"&gt;7.1 Evaluating a Population &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-7_2"&gt;7.2 HEAD &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-7_3"&gt;7.3 Running the Advancement &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-7_4"&gt;7.4 Finding a Solution &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-8"&gt;8 Conclusion &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#sec-9"&gt;9 Thanks &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="outline-container-1" class="outline-2"&gt;
&lt;h2 id="sec-1"&gt;&lt;span class="section-number-2"&gt;1&lt;/span&gt; Introduction &lt;/h2&gt;
&lt;div class="outline-text-2" id="text-1"&gt;


&lt;p&gt;
While my final ranking in the Google AI Contest was disappointing
(&lt;a href="http://ai-contest.com/language_profile.php?lang=Lisp"&gt;280th&lt;/a&gt;), it was a very educational experience and was totally offset
by &lt;a href="http://quotenil.com/Planet-Wars-Post-Mortem.html"&gt;Gábor Melis' dominating win&lt;/a&gt; using Common Lisp as well.
&lt;/p&gt;
&lt;p&gt;
One of things that piqued my interest during the contest was &lt;a href="http://ai-contest.com/forum/viewtopic.php?f=17&amp;amp;t=1136"&gt;a post on the AI Challenge forums&lt;/a&gt; about a bot written using &lt;a href="http://en.wikipedia.org/wiki/Genetic_programming"&gt;genetic programming&lt;/a&gt;.
Genetic programming (GP) and &lt;a href="http://en.wikipedia.org/wiki/Genetic_algorithms"&gt;genetic algorithms&lt;/a&gt; have always held my
interest but &lt;a href="http://ai-contest.com/visualizer.php?game_id=9519434"&gt;seeing the bot in action&lt;/a&gt; really motivated me to dive into
the matter.
&lt;/p&gt;
&lt;p&gt;
Genetic programming is inspired by biological evolution and is a way
of solving problems by setting up an environment (tuned to the problem
at hand!) and allowing computer programs to evolve towards a possible
solution in that environment.
&lt;/p&gt;
&lt;p&gt;
This article shows my initial exploration into GP using Common Lisp
and should be an example of a typical &lt;a href="http://en.wikipedia.org/wiki/REPL"&gt;REPL&lt;/a&gt; session (my session was a
couple of hours divided over two evenings).  The code has been
reviewed, made a more readable and lispier but still looks very much
like what I wrote initially.  From the REPL session useful output has
been cut and pasted into this article.
&lt;/p&gt;
&lt;p&gt;
This is a &lt;i&gt;really&lt;/i&gt; basic introduction into GP and is meant for people
interested in GP and/or interested in (Common) Lisp.  It is heavy on
code and examples and light on theory.  My intention is for the reader
to play around with the functions on the REPL as they come by in the
article.
&lt;/p&gt;
&lt;p&gt;
The code in this article should be portable Common Lisp.  If you need
to know what a function or macro does please consult the &lt;a href="http://clhs.lisp.se/Front/X_Symbol.htm"&gt;Common Lisp HyperSpec&lt;/a&gt;.
&lt;/p&gt;

&lt;/div&gt;

&lt;div id="outline-container-1_1" class="outline-3"&gt;
&lt;h3 id="sec-1_1"&gt;&lt;span class="section-number-3"&gt;1.1&lt;/span&gt; Toy Project &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-1_1"&gt;


&lt;p&gt;
I found &lt;a href="http://www.gp-field-guide.org.uk/"&gt;A Field Guide to Genetic Programming&lt;/a&gt; on-line and decided to
duplicate &lt;a href="http://bc.tech.coop/blog/040619.html"&gt;Bill Clementson's toy project&lt;/a&gt; of discovering the formula for
calculating the area of a circle.  Except for educational purposes we
will be starting from scratch.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-1_2" class="outline-3"&gt;
&lt;h3 id="sec-1_2"&gt;&lt;span class="section-number-3"&gt;1.2&lt;/span&gt; Environment &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-1_2"&gt;


&lt;p&gt;
Many Common Lispers use Emacs, &lt;a href="http://common-lisp.net/project/slime/"&gt;Slime&lt;/a&gt; and usually Unix or OS X as
development environment.  However, do not get the impression this is
the only way to write Lisp.  The &lt;a href="http://www.cliki.net/development"&gt;development page on CLiki&lt;/a&gt; lists many
other alternatives in various states of usability.
&lt;/p&gt;
&lt;p&gt;
My recommendation is to use your favorite text editor and &lt;a href="http://www.clisp.org/"&gt;CLISP&lt;/a&gt; since
it comes with command line history and tab completion built in.  Write
or paste the code in your editor and save the file after every
addition as for example "&lt;code&gt;gp.lisp&lt;/code&gt;".  Then you only need to type:
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
(load "/path/to/gp.lisp")
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;
&lt;p&gt;
once and can use the command line history to reload it.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-2" class="outline-2"&gt;
&lt;h2 id="sec-2"&gt;&lt;span class="section-number-2"&gt;2&lt;/span&gt; Generating Random Code &lt;/h2&gt;
&lt;div class="outline-text-2" id="text-2"&gt;


&lt;p&gt;
As you might have read, the &lt;a href="http://ai-contest.com/profile.php?user_id=4038"&gt;space.invaders&lt;/a&gt; bot was written in PHP.
Our weapon of choice is Common Lisp and the first matter of business
is generating random code.
&lt;/p&gt;

&lt;/div&gt;

&lt;div id="outline-container-2_1" class="outline-3"&gt;
&lt;h3 id="sec-2_1"&gt;&lt;span class="section-number-3"&gt;2.1&lt;/span&gt; Operators &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-2_1"&gt;





&lt;pre class="src src-common-lisp"&gt;(&lt;span style="color: #551a8b;"&gt;defparameter&lt;/span&gt; &lt;span style="color: #000000;"&gt;*operators*&lt;/span&gt; '(+ - * /))
&lt;/pre&gt;



&lt;p&gt;
To keep things simple and already knowing our target function (πr²) we
opt for using four operators: addition, subtraction, multiplication
and division.  In the name of simplicity (again) they will have an
arity of 2, so they will all take two arguments.
&lt;/p&gt;
&lt;p&gt;
*OPERATORS* is the name of the  variable.  The *earmuffs* convention
is used to signify global variables.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-2_2" class="outline-3"&gt;
&lt;h3 id="sec-2_2"&gt;&lt;span class="section-number-3"&gt;2.2&lt;/span&gt; RANDOM-ELT &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-2_2"&gt;





&lt;pre class="src src-common-lisp"&gt;(&lt;span style="color: #551a8b;"&gt;defun&lt;/span&gt; &lt;span style="color: #000000;"&gt;random-elt&lt;/span&gt; (sequence)
  (&lt;span style="color: #551a8b;"&gt;let&lt;/span&gt; ((seq-length (length sequence)))
    (&lt;span style="color: #551a8b;"&gt;when&lt;/span&gt; (&amp;gt; seq-length 0)
      (elt sequence (random seq-length)))))
&lt;/pre&gt;



&lt;p&gt;
The function RANDOM-FORM in the next section uses RANDOM-ELT to select
a random element from the list of operators.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-2_3" class="outline-3"&gt;
&lt;h3 id="sec-2_3"&gt;&lt;span class="section-number-3"&gt;2.3&lt;/span&gt; Generating Random &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_f.htm#function_form"&gt;Function Forms&lt;/a&gt; &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-2_3"&gt;





&lt;pre class="src src-common-lisp"&gt;(&lt;span style="color: #551a8b;"&gt;defun&lt;/span&gt; &lt;span style="color: #000000;"&gt;random-form&lt;/span&gt; (operators)
  (append (list (random-elt operators))
          (&lt;span style="color: #551a8b;"&gt;loop&lt;/span&gt; repeat 2  &lt;span style="color: #b22222;"&gt;; &lt;/span&gt;&lt;span style="color: #b22222;"&gt;arity
&lt;/span&gt;                collect (&lt;span style="color: #551a8b;"&gt;let&lt;/span&gt; ((random-nr (random 100)))
                          (&lt;span style="color: #551a8b;"&gt;cond&lt;/span&gt; ((&amp;lt; random-nr 50) (random-form operators))
                                ((&amp;lt; random-nr 75) (random 10.0))
                                (t                '=input=))))))
&lt;/pre&gt;



&lt;p&gt;
The function works as follows: it creates a list of three items.  The
first item is a random operator and the second and third items are the
arguments to that operator:
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
(operator argument-1 argument-2)
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;
&lt;p&gt;
The arguments are either a random number between 0.0 and 10.0
(arbitrary limit), a variable called &lt;code&gt;=INPUT=&lt;/code&gt; (more about this later)
or, &lt;b&gt;and this is important&lt;/b&gt;, another list of three items.  For
example:
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
(* =INPUT= 2.345)
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;
&lt;p&gt;
or
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
(+ 6.789 (- =INPUT= 0.123))
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;
&lt;p&gt;
So the RANDOM-FORM function will call itself recursively if needed.
The (arbitrary) probabilities for the ARGUMENT-1 and ARGUMENT-2 are:
50% of the time another random form, 25% of the time a random number
and 25% of the time the &lt;code&gt;=INPUT=&lt;/code&gt; variable.
&lt;/p&gt;
&lt;p&gt;
The process of generating random forms described above is similar to
the "grow" method described in &lt;a href="http://cswww.essex.ac.uk/staff/rpoli/gp-field-guide/22InitialisingthePopulation.html"&gt;Chapter 2.2 of the Field Guide&lt;/a&gt;.
&lt;/p&gt;

&lt;/div&gt;

&lt;div id="outline-container-2_3_1" class="outline-4"&gt;
&lt;h4 id="sec-2_3_1"&gt;&lt;span class="section-number-4"&gt;2.3.1&lt;/span&gt; Limiting RANDOM-FORM &lt;/h4&gt;
&lt;div class="outline-text-4" id="text-2_3_1"&gt;





&lt;pre class="src src-common-lisp"&gt;(&lt;span style="color: #551a8b;"&gt;defun&lt;/span&gt; &lt;span style="color: #000000;"&gt;random-form&lt;/span&gt; (operators &lt;span style="color: #000000;"&gt;&amp;amp;optional&lt;/span&gt; (max-depth 4))
  (append (list (random-elt operators))
          (&lt;span style="color: #551a8b;"&gt;loop&lt;/span&gt; repeat 2  &lt;span style="color: #b22222;"&gt;; &lt;/span&gt;&lt;span style="color: #b22222;"&gt;arity
&lt;/span&gt;                collect (&lt;span style="color: #551a8b;"&gt;let&lt;/span&gt; ((random-nr (random 100)))
                          (&lt;span style="color: #551a8b;"&gt;if&lt;/span&gt; (&amp;gt; max-depth 0)
                              (&lt;span style="color: #551a8b;"&gt;cond&lt;/span&gt; ((&amp;lt; random-nr 50)
                                     (random-form operators (- max-depth 1)))
                                    ((&amp;lt; random-nr 75) (random 10.0))
                                    (t                '=input=))
                              (&lt;span style="color: #551a8b;"&gt;cond&lt;/span&gt; ((&amp;lt; random-nr 50) (random 10.0))
                                    (t                '=input=)))))))
&lt;/pre&gt;



&lt;p&gt;
Since RANDOM-FORM can call itself recursively it can potentially
create huge amounts of random code and even exhaust the stack of the
Lisp implementation.  Hence we need to place some limits on
RANDOM-FORM.  The addition of the MAX-DEPTH parameter and the
deduction of MAX-DEPTH when RANDOM-FORM is called again prevents nasty
things from happening.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-2_4" class="outline-3"&gt;
&lt;h3 id="sec-2_4"&gt;&lt;span class="section-number-3"&gt;2.4&lt;/span&gt; &lt;code&gt;=INPUT=&lt;/code&gt; &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-2_4"&gt;


&lt;p&gt;
Since we want our generated code to calculate the area of a circle
from an input value, the radius, we've added the possibility to
generate the &lt;code&gt;=INPUT=&lt;/code&gt; variable to RANDOM-FORM.  This variable is the
same as the input argument of the RUN-FORM function that is discussed
later.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-2_5" class="outline-3"&gt;
&lt;h3 id="sec-2_5"&gt;&lt;span class="section-number-3"&gt;2.5&lt;/span&gt; Testing RANDOM-ELT and RANDOM-FORM &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-2_5"&gt;


&lt;p&gt;
Pasting RANDOM-ELT and RANDOM-FORM into the REPL and running the
latter a couple of times will yield some randomly generated code:
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
CL-USER&amp;gt; (random-form *operators*)
(/ 2.8173013 5.378826)

CL-USER&amp;gt; (random-form *operators*)
(* =INPUT= =INPUT=)

CL-USER&amp;gt; (random-form *operators*)
(+ 7.9595613
 (- (- =INPUT= (* =INPUT= 0.57189345))
  (* (- (/ 6.9174767 9.723027) =INPUT=) (* =INPUT= =INPUT=))))

CL-USER&amp;gt; (random-form *operators*)
(- (- =INPUT= (- (/ 2.002045 (* =INPUT= 9.829036)) 4.531122)) =INPUT=)
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-3" class="outline-2"&gt;
&lt;h2 id="sec-3"&gt;&lt;span class="section-number-2"&gt;3&lt;/span&gt; Running Generated Code &lt;/h2&gt;
&lt;div class="outline-text-2" id="text-3"&gt;





&lt;pre class="src src-common-lisp"&gt;(&lt;span style="color: #551a8b;"&gt;defun&lt;/span&gt; &lt;span style="color: #000000;"&gt;run-form&lt;/span&gt; (form input)
  (funcall (eval `(&lt;span style="color: #551a8b;"&gt;lambda&lt;/span&gt; (=input=) ,form))  &lt;span style="color: #b22222;"&gt;; &lt;/span&gt;&lt;span style="color: #b22222;"&gt;note: backquote!
&lt;/span&gt;           input))
&lt;/pre&gt;



&lt;p&gt;
To run the generated forms we wrap them in a LAMBDA with an &lt;code&gt;=INPUT=&lt;/code&gt;
argument and funcall the evaluated lambda with an input value.  The
following REPL interaction shows line by line what happens in
RANDOM-FORM:
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
CL-USER&amp;gt; (defparameter random-form (random-form *operators*))
RANDOM-FORM

CL-USER&amp;gt; random-form
(* 6.341989 =INPUT=)

CL-USER&amp;gt; `(lambda (=input=) ,random-form)
(LAMBDA (=INPUT=) (* 6.341989 =INPUT=))

CL-USER&amp;gt; (eval `(lambda (=input=) ,random-form))
#&amp;lt;FUNCTION (LAMBDA (=INPUT=)) {AF2F08D}&amp;gt;

CL-USER&amp;gt; (funcall (eval `(lambda (=input=) ,random-form)) 2)
12.683978

CL-USER&amp;gt; (* 6.341989 2)
12.683978
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;
&lt;p&gt;
However, the generated code can be illegal and cause errors.  Since
we'll be running a great many pieces of generated code multiple times
we don't want to see error messages and drop into the debugger.  To
keep things simple we let illegal forms return NIL so we can kill them
off later.  Adding an error handler to RUN-FORM will do this:
&lt;/p&gt;



&lt;pre class="src src-common-lisp"&gt;(&lt;span style="color: #551a8b;"&gt;defun&lt;/span&gt; &lt;span style="color: #000000;"&gt;run-form&lt;/span&gt; (form input)
  (&lt;span style="color: #551a8b;"&gt;let&lt;/span&gt; ((*error-output* (make-broadcast-stream)))
    (&lt;span style="color: #551a8b;"&gt;handler-case&lt;/span&gt; (funcall (eval `(&lt;span style="color: #551a8b;"&gt;lambda&lt;/span&gt; (=input=) ,form))
                           input)
      (&lt;span style="color: #ff0000; font-weight: bold;"&gt;error&lt;/span&gt; () nil))))
&lt;/pre&gt;



&lt;p&gt;
&lt;code&gt;*ERROR-OUTPUT*&lt;/code&gt; is redirected so we won't be bothered by all kinds of
compilation notices.  They only serve to distract in this situation.
&lt;/p&gt;

&lt;/div&gt;

&lt;div id="outline-container-3_1" class="outline-3"&gt;
&lt;h3 id="sec-3_1"&gt;&lt;span class="section-number-3"&gt;3.1&lt;/span&gt; SBCL note &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-3_1"&gt;


&lt;p&gt;
SBCL is a very good, open-source CL implementation but it doesn't
compile code very fast.  The way we currently handle RUN-FORM by
recompiling the form every time causes the advancing of generations
later in the article to be very slow .  Compared to SBCL, which
compiles to native code, CLISP, which compiles to byte-code, does the
advancing of generations much faster.
&lt;/p&gt;
&lt;p&gt;
Since we're in exploration mode we will leave RUN-FORM as it is.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-4" class="outline-2"&gt;
&lt;h2 id="sec-4"&gt;&lt;span class="section-number-2"&gt;4&lt;/span&gt; Population &lt;/h2&gt;
&lt;div class="outline-text-2" id="text-4"&gt;





&lt;pre class="src src-common-lisp"&gt;(&lt;span style="color: #551a8b;"&gt;defun&lt;/span&gt; &lt;span style="color: #000000;"&gt;create-initial-population&lt;/span&gt; (operators &lt;span style="color: #000000;"&gt;&amp;amp;optional&lt;/span&gt; (size 100))
  (&lt;span style="color: #551a8b;"&gt;loop&lt;/span&gt; repeat size
        collect (random-form operators)))
&lt;/pre&gt;



&lt;p&gt;
If you're not familiar with CL: the COLLECT statement in LOOP
accumulates a random form on each iteration and returns them as a list
once iteration has finished.  For example:
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
CL-USER&amp;gt; (create-initial-population *operators* 10)
((* =INPUT= 6.8947406)
 (* (+ =INPUT= 2.1140647) 6.7930226)
 (+
  (/ (+ (* =INPUT= (/ 8.296512 =INPUT=)) 1.1989254)
   (- =INPUT= (/ =INPUT= (- 5.1625586 1.4763731))))
  =INPUT=)
 (- 1.5379852 2.1223724)
 (* =INPUT= (- 3.0632048 (* (+ (- 5.8116364 =INPUT=) 0.1915878) =INPUT=)))
 (/ 8.237898 =INPUT=)
 (* (/ (/ (- =INPUT= =INPUT=) 0.56726336) =INPUT=) =INPUT=)
 (+ (+ 7.147339 =INPUT=) =INPUT=)
 (- (- =INPUT= =INPUT=) =INPUT=)
 (+ (/ =INPUT= (- (* =INPUT= =INPUT=) (* (- =INPUT= =INPUT=) =INPUT=)))
  6.520609))
&lt;/pre&gt;

&lt;p&gt;&lt;/dd&gt;&lt;/dl&gt;
&lt;/p&gt;
&lt;p&gt;
The way we're creating the initial population is not ideal.  This is
because RANDOM-FORM only creates one type of syntax tree (using the
"grow" method mentioned earlier).  For a more diverse initial
population we'd need more code generation functions that would output
different kinds of syntax trees.
&lt;/p&gt;
&lt;p&gt;
The "full" method is easy to add and is left as an exercise to the
reader.  See the &lt;a href="http://cswww.essex.ac.uk/staff/rpoli/gp-field-guide/22InitialisingthePopulation.html"&gt;Field Guide&lt;/a&gt; for a description.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-5" class="outline-2"&gt;
&lt;h2 id="sec-5"&gt;&lt;span class="section-number-2"&gt;5&lt;/span&gt; Fitness &lt;/h2&gt;
&lt;div class="outline-text-2" id="text-5"&gt;





&lt;pre class="src src-common-lisp"&gt;(&lt;span style="color: #551a8b;"&gt;defun&lt;/span&gt; &lt;span style="color: #000000;"&gt;fitness&lt;/span&gt; (form fitness-fn test-input)
  (&lt;span style="color: #551a8b;"&gt;loop&lt;/span&gt; for input in test-input
        for output = (run-form form input)
        for target = (funcall fitness-fn input)
        for difference = (&lt;span style="color: #551a8b;"&gt;when&lt;/span&gt; output (abs (- target output)))
        for fitness = (&lt;span style="color: #551a8b;"&gt;when&lt;/span&gt; output (/ 1.0 (+ 1 difference)))
        when (null output) do (&lt;span style="color: #551a8b;"&gt;return-from&lt;/span&gt; fitness nil)
        collect fitness into fitness-values
        finally (&lt;span style="color: #551a8b;"&gt;return&lt;/span&gt; (reduce #'* fitness-values))))
&lt;/pre&gt;



&lt;p&gt;
We need a way to test the output of a generated function against our
desired outcome and represent this as a number: the fitness.  This is
commonly a number between 0.0 and 1.0.  The closer to 1.0 the better
the fitness.
&lt;/p&gt;
&lt;p&gt;
We also need to check whether the return value of RUN-FORM is NIL in
which case it executed illegal code.  FITNESS will return NIL in that
case as well.  (Poor man's exception handling but suffices for now.)
&lt;/p&gt;
&lt;p&gt;
So the function needs: 1) the form to check, 2) the fitness function
to check against and 3) test input.  We also want to check against
multiple input values.
&lt;/p&gt;
&lt;p&gt;
The TEST-INPUT argument is a list of input values so the most direct
approach will be to iterate over these values and running both the
form and the fitness functions against them.
&lt;/p&gt;
&lt;p&gt;
To get a fitness value between 0.0 and 1.0 we take the absolute
difference between the output of the generated form (OUTPUT) and the
output of the fitness function (TARGET).  We then add 1 to this
difference and use that to divide 1.0.  To illustrate:
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
CL-USER&amp;gt; (defun fit (x) (/ 1.0 (+ 1 x)))
FIT
CL-USER&amp;gt; (fit 0)  ; no difference so the desired output
1.0
CL-USER&amp;gt; (fit 0.1)
0.9090909
CL-USER&amp;gt; (fit 5)
0.16666667
CL-USER&amp;gt; (fit 500)
0.001996008
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;
&lt;p&gt;
We're not testing negative values since DIFFERENCE in FITNESS will never be
negative.
&lt;/p&gt;
&lt;p&gt;
REPL test of FITNESS:
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
CL-USER&amp;gt; (defparameter random-form (random-form *operators*))
RANDOM-FORM

CL-USER&amp;gt; random-form
(/ 8.552494 =INPUT=)
CL-USER&amp;gt; (fitness random-form (lambda (r) (* pi r r)) '(0 1 -2))
NIL  ; this is correct since we divided by zero

CL-USER&amp;gt; (setf random-form (random-form *operators*))
(- =INPUT= 5.246996)
CL-USER&amp;gt; (fitness random-form (lambda (r) (* pi r r)) '(0 1 -2))
9.168484389517398d-4

CL-USER&amp;gt; (setf random-form (random-form *operators*))
(* =INPUT= (+ (* =INPUT= 1.8322039) (- =INPUT= 6.812643)))
CL-USER&amp;gt; (fitness random-form (lambda (r) (* pi r r)) '(0 1 -2))
0.009196622001630076d0

CL-USER&amp;gt; (fitness '(* pi =input= =input=) (lambda (r) (* pi r r)) '(0 1 -2))
1.0d0
CL-USER&amp;gt; (fitness '(* (- pi 0.1) =input= =input=) (lambda (r) (* pi r r)) '(0 1 -2))
0.649350645706412d0
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-6" class="outline-2"&gt;
&lt;h2 id="sec-6"&gt;&lt;span class="section-number-2"&gt;6&lt;/span&gt; Generation Functions &lt;/h2&gt;
&lt;div class="outline-text-2" id="text-6"&gt;


&lt;p&gt;
Now everything is in place to start thinking about creating new
generations from the initial population.  Currently we will only
support &lt;a href="http://cswww.essex.ac.uk/staff/rpoli/gp-field-guide/53GPCrossover.html#11_3"&gt;cross-overs&lt;/a&gt; and &lt;a href="http://cswww.essex.ac.uk/staff/rpoli/gp-field-guide/52GPMutation.html#11_2"&gt;mutations&lt;/a&gt;.
&lt;/p&gt;

&lt;/div&gt;

&lt;div id="outline-container-6_1" class="outline-3"&gt;
&lt;h3 id="sec-6_1"&gt;&lt;span class="section-number-3"&gt;6.1&lt;/span&gt; Traversing Nodes &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-6_1"&gt;


&lt;p&gt;
Before we get to cross-overs and mutations we need to look at three
important functions: N-NODES, RANDOM-NODE and REPLACE-NODE.  They all
share a common, but for each slightly different, function:
TRAVERSE-NODES.
&lt;/p&gt;
&lt;p&gt;
It is a basic recursive function.  It iterates through each element of
the FORM list and if that element is a list as well it calls
TRAVERSE-NODES again with that list element as argument.
&lt;/p&gt;



&lt;pre class="src src-common-lisp"&gt;(&lt;span style="color: #551a8b;"&gt;defun&lt;/span&gt; &lt;span style="color: #000000;"&gt;traverse-nodes-example&lt;/span&gt; (form)
  (&lt;span style="color: #551a8b;"&gt;labels&lt;/span&gt; ((traverse-nodes (subform &lt;span style="color: #000000;"&gt;&amp;amp;optional&lt;/span&gt; (indent &lt;span style="color: #8b4513;"&gt;""&lt;/span&gt;))
             (&lt;span style="color: #551a8b;"&gt;loop&lt;/span&gt; for node in subform
                   do (format t &lt;span style="color: #8b4513;"&gt;"~D:~A ~S~%"&lt;/span&gt; (/ (length indent) 2) indent node)
                      (&lt;span style="color: #551a8b;"&gt;when&lt;/span&gt; (listp node)
                        (traverse-nodes node
                                        (concatenate 'string indent &lt;span style="color: #8b4513;"&gt;"  "&lt;/span&gt;))))))
    (traverse-nodes form)))
&lt;/pre&gt;



&lt;p&gt;
TRAVERSE-NODES-EXAMPLE goes through FORM exactly how TRAVERSE-NODES
does and for each node it prints its nesting level and the node
itself:
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
CL-USER&amp;gt; (traverse-nodes-example '(a (b c) (d (e f) g) h))
0: A
0: (B C)
1:   B
1:   C
0: (D (E F) G)
1:   D
1:   (E F)
2:     E
2:     F
1:   G
0: H
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;

&lt;/div&gt;

&lt;div id="outline-container-6_1_1" class="outline-4"&gt;
&lt;h4 id="sec-6_1_1"&gt;&lt;span class="section-number-4"&gt;6.1.1&lt;/span&gt; N-NODES &lt;/h4&gt;
&lt;div class="outline-text-4" id="text-6_1_1"&gt;





&lt;pre class="src src-common-lisp"&gt;(&lt;span style="color: #551a8b;"&gt;defun&lt;/span&gt; &lt;span style="color: #000000;"&gt;n-nodes&lt;/span&gt; (form)
  (&lt;span style="color: #551a8b;"&gt;let&lt;/span&gt; ((nodes 1))
    (&lt;span style="color: #551a8b;"&gt;labels&lt;/span&gt; ((traverse-nodes (subform)
               (&lt;span style="color: #551a8b;"&gt;loop&lt;/span&gt; for node in subform
                     do (incf nodes)
                        (&lt;span style="color: #551a8b;"&gt;when&lt;/span&gt; (listp node)
                          (traverse-nodes node)))))
      (traverse-nodes form))
    nodes))
&lt;/pre&gt;



&lt;p&gt;
Helper function for &lt;a href="#RANDOM-NODE"&gt;RANDOM-NODE&lt;/a&gt;.  Returns the number of nodes in FORM
including the root node.  Note that "&lt;code&gt;(B C)&lt;/code&gt;" as well as B and C are
counted as nodes:
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
CL-USER&amp;gt; (n-nodes '(b c))
3
CL-USER&amp;gt; (n-nodes '(a (b c) (d (e f) g) h))
12
CL-USER&amp;gt; (n-nodes '())
1
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-6_1_2" class="outline-4"&gt;
&lt;h4 id="sec-6_1_2"&gt;&lt;span class="section-number-4"&gt;6.1.2&lt;/span&gt; Picking Random Nodes &lt;/h4&gt;
&lt;div class="outline-text-4" id="text-6_1_2"&gt;


&lt;p&gt;
We want to be able to pick a random node from a form to perform
operations on.  &lt;a name="RANDOM-NODE" class="target"&gt;RANDOM-NODE&lt;/a&gt; does this:
&lt;/p&gt;



&lt;pre class="src src-common-lisp"&gt;(&lt;span style="color: #551a8b;"&gt;defun&lt;/span&gt; &lt;span style="color: #000000;"&gt;random-node&lt;/span&gt; (form)
  (&lt;span style="color: #551a8b;"&gt;let*&lt;/span&gt; ((index 1)
         (nodes-1 (- (n-nodes form) 1))
         (random-node-index (+ (random nodes-1) 1)))
    (&lt;span style="color: #551a8b;"&gt;labels&lt;/span&gt; ((traverse-nodes (subform)
               (&lt;span style="color: #551a8b;"&gt;loop&lt;/span&gt; for node in subform
                     do (&lt;span style="color: #551a8b;"&gt;when&lt;/span&gt; (= index random-node-index)
                          (&lt;span style="color: #551a8b;"&gt;return-from&lt;/span&gt; random-node
                                       (list &lt;span style="color: #8b4789;"&gt;:index&lt;/span&gt; index &lt;span style="color: #8b4789;"&gt;:node&lt;/span&gt; node)))
                        (incf index)
                        (&lt;span style="color: #551a8b;"&gt;when&lt;/span&gt; (listp node)
                          (traverse-nodes node)))))
      (traverse-nodes form))))
&lt;/pre&gt;



&lt;p&gt;
It picks a RANDOM-NODE-INDEX and starts traversing the nodes of FORM.
When it arrives at the index it returns both the node and the index as
a &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_p.htm#property_list"&gt;property list&lt;/a&gt;:
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
(:index random-node-index :node random-node)
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;
&lt;p&gt;
Will not return the root node at index 0.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-6_1_3" class="outline-4"&gt;
&lt;h4 id="sec-6_1_3"&gt;&lt;span class="section-number-4"&gt;6.1.3&lt;/span&gt; Replacing Nodes &lt;/h4&gt;
&lt;div class="outline-text-4" id="text-6_1_3"&gt;


&lt;p&gt;
We need to be able to replace a node in a form with another node.  The
avoid bugs and confusion we'll let REPLACE-NODE return this result as
a &lt;b&gt;new form&lt;/b&gt;.
&lt;/p&gt;



&lt;pre class="src src-common-lisp"&gt;(&lt;span style="color: #551a8b;"&gt;defun&lt;/span&gt; &lt;span style="color: #000000;"&gt;replace-node&lt;/span&gt; (form node-index new-node)
  (&lt;span style="color: #551a8b;"&gt;let&lt;/span&gt; ((index 0))
    (&lt;span style="color: #551a8b;"&gt;labels&lt;/span&gt; ((traverse-nodes (subform)
               (&lt;span style="color: #551a8b;"&gt;loop&lt;/span&gt; for node in subform
                     do (incf index)
                     when (= index node-index)
                       collect new-node
                     when (and (/= index node-index)
                               (not (listp node)))
                       collect node
                     when (and (/= index node-index)
                               (listp node))
                       collect (traverse-nodes node))))
      (traverse-nodes form))))
&lt;/pre&gt;



&lt;p&gt;
Traverses the nodes of FORM and collects them to return as a new form.
When its INDEX counter is equal to NODE-INDEX it collects NEW-NODE
instead.
&lt;/p&gt;
&lt;p&gt;
The function does not replace the root node (index 0).
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-6_2" class="outline-3"&gt;
&lt;h3 id="sec-6_2"&gt;&lt;span class="section-number-3"&gt;6.2&lt;/span&gt; Cross-overs &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-6_2"&gt;


&lt;p&gt;
There are &lt;a href="http://cswww.essex.ac.uk/staff/rpoli/gp-field-guide/53GPCrossover.html#11_3"&gt;different kinds of cross-overs&lt;/a&gt; but we will be doing the most
straight-forward one: replace a random node in form A with a random
node from form B.
&lt;/p&gt;
&lt;p&gt;
Cross-overs are the most used genetic operation in GP and some people
have even suggested to never use mutations.  They can be compared to
the procreation of humans in which attributes of the male and female
are represented in their offspring.
&lt;/p&gt;



&lt;pre class="src src-common-lisp"&gt;(&lt;span style="color: #551a8b;"&gt;defun&lt;/span&gt; &lt;span style="color: #000000;"&gt;cross-over&lt;/span&gt; (form1 form2 &lt;span style="color: #000000;"&gt;&amp;amp;key&lt;/span&gt; (debug nil))
  (&lt;span style="color: #551a8b;"&gt;let&lt;/span&gt; ((rnode1 (random-node form1))
        (rnode2 (random-node form2)))
    (&lt;span style="color: #551a8b;"&gt;when&lt;/span&gt; debug
      (format t &lt;span style="color: #8b4513;"&gt;"form1: ~S~%form2: ~S~%rnode1: ~S~%rnode2: ~S~%"&lt;/span&gt;
              form1 form2 rnode1 rnode2))
    (replace-node form1 (getf rnode1 &lt;span style="color: #8b4789;"&gt;:index&lt;/span&gt;) (getf rnode2 &lt;span style="color: #8b4789;"&gt;:node&lt;/span&gt;))))
&lt;/pre&gt;



&lt;p&gt;
CROSS-OVER takes two forms as arguments and returns a new form.  The
new form is largely similar to FORM1 but one random node is replaced
by a random node from FORM2.  The function RANDOM-NODE is used to pick
these random nodes.
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
CL-USER&amp;gt; (cross-over '(1 (2 3) (4 (5 6) 7) 8) '(a (b c) (d (e f) g) h) :debug t)
form1: (1 (2 3) (4 (5 6) 7) 8)
form2: (A (B C) (D (E F) G) H)
rnode1: (:INDEX 1 :NODE 1)
rnode2: (:INDEX 3 :NODE B)
(B (2 3) (4 (5 6) 7) 8)

CL-USER&amp;gt; (cross-over '(1 (2 3) (4 (5 6) 7) 8) '(a (b c) (d (e f) g) h) :debug t)
form1: (1 (2 3) (4 (5 6) 7) 8)
form2: (A (B C) (D (E F) G) H)
rnode1: (:INDEX 3 :NODE 2)
rnode2: (:INDEX 7 :NODE (E F))
(1 ((E F) 3) (4 (5 6) 7) 8)

CL-USER&amp;gt; (cross-over '(1 (2 3) (4 (5 6) 7) 8) '(a (b c) (d (e f) g) h) :debug t)
form1: (1 (2 3) (4 (5 6) 7) 8)
form2: (A (B C) (D (E F) G) H)
rnode1: (:INDEX 2 :NODE (2 3))
rnode2: (:INDEX 6 :NODE D)
(1 D (4 (5 6) 7) 8)

CL-USER&amp;gt; (cross-over '(1 (2 3) (4 (5 6) 7) 8) '(a (b c) (d (e f) g) h) :debug t)
form1: (1 (2 3) (4 (5 6) 7) 8)
form2: (A (B C) (D (E F) G) H)
rnode1: (:INDEX 5 :NODE (4 (5 6) 7))
rnode2: (:INDEX 5 :NODE (D (E F) G))
(1 (2 3) (D (E F) G) 8)
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-6_3" class="outline-3"&gt;
&lt;h3 id="sec-6_3"&gt;&lt;span class="section-number-3"&gt;6.3&lt;/span&gt; Mutation &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-6_3"&gt;


&lt;p&gt;
Mutations change a part of a form without needing another form for the
operation.  It is perhaps analogue to a cosmic ray changing a bit of
genetic information in a biological entity.
&lt;/p&gt;
&lt;p&gt;
We will be using &lt;a href="http://cswww.essex.ac.uk/staff/rpoli/gp-field-guide/52GPMutation.html"&gt;subtree mutation&lt;/a&gt; since it is straight-forward to
write and has a potentially large effect.
&lt;/p&gt;



&lt;pre class="src src-common-lisp"&gt;(&lt;span style="color: #551a8b;"&gt;defun&lt;/span&gt; &lt;span style="color: #000000;"&gt;mutate&lt;/span&gt; (form operators &lt;span style="color: #000000;"&gt;&amp;amp;key&lt;/span&gt; (debug nil))
  (&lt;span style="color: #551a8b;"&gt;let&lt;/span&gt; ((rform (random-form operators))
        (rnode (random-node form)))
    (&lt;span style="color: #551a8b;"&gt;when&lt;/span&gt; debug
      (format t &lt;span style="color: #8b4513;"&gt;"form: ~S~%rform: ~S~%rnode: ~S~%"&lt;/span&gt; form rform rnode))
    (replace-node form (getf rnode &lt;span style="color: #8b4789;"&gt;:index&lt;/span&gt;) rform)))
&lt;/pre&gt;



&lt;p&gt;
Mutation replaces a random node of FORM with a form created by
RANDOM-FORM.
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
CL-USER&amp;gt; (mutate '(a (b c) (d (e f) g) h) *operators* :debug t)
form: (A (B C) (D (E F) G) H)
rform: (+ =INPUT= (- 4.4699216 (+ 9.623513 =INPUT=)))
rnode: (:INDEX 3 :NODE B)
(A ((+ =INPUT= (- 4.4699216 (+ 9.623513 =INPUT=))) C) (D (E F) G) H)

CL-USER&amp;gt; (mutate '(a (b c) (d (e f) g) h) *operators* :debug t)
form: (A (B C) (D (E F) G) H)
rform: (+ 4.5209084 (- 8.943897 (+ 6.657296 =INPUT=)))
rnode: (:INDEX 2 :NODE (B C))
(A (+ 4.5209084 (- 8.943897 (+ 6.657296 =INPUT=))) (D (E F) G) H)
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-7" class="outline-2"&gt;
&lt;h2 id="sec-7"&gt;&lt;span class="section-number-2"&gt;7&lt;/span&gt; Advancing a Generation &lt;/h2&gt;
&lt;div class="outline-text-2" id="text-7"&gt;



&lt;/div&gt;

&lt;div id="outline-container-7_1" class="outline-3"&gt;
&lt;h3 id="sec-7_1"&gt;&lt;span class="section-number-3"&gt;7.1&lt;/span&gt; Evaluating a Population &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-7_1"&gt;





&lt;pre class="src src-common-lisp"&gt;(&lt;span style="color: #551a8b;"&gt;defun&lt;/span&gt; &lt;span style="color: #000000;"&gt;evaluate-population&lt;/span&gt; (population fitness-fn test-input)
  (&lt;span style="color: #551a8b;"&gt;loop&lt;/span&gt; for form in population
        for fitness = (fitness form fitness-fn test-input)
        when fitness collect (list &lt;span style="color: #8b4789;"&gt;:fitness&lt;/span&gt; fitness &lt;span style="color: #8b4789;"&gt;:form&lt;/span&gt; form) into result
        finally (&lt;span style="color: #551a8b;"&gt;return&lt;/span&gt; (sort result
                              (&lt;span style="color: #551a8b;"&gt;lambda&lt;/span&gt; (a b)
                                (&amp;gt; (getf a &lt;span style="color: #8b4789;"&gt;:fitness&lt;/span&gt;) (getf b &lt;span style="color: #8b4789;"&gt;:fitness&lt;/span&gt;)))))))
&lt;/pre&gt;



&lt;p&gt;
To advance a generation we need to do cross-overs and mutations to the
forms in the population.  The literature suggests we give forms with a
higher fitness more chance to be a candidate for a cross-over or
mutation.
&lt;/p&gt;
&lt;p&gt;
EVALUATE-POPULATION evaluates a population and returns a list of the
forms in that population and their fitness (minus any forms that gave
errors).  For ease of testing on the REPL and for use in our next
function the output is &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_sort_.htm#sort"&gt;sorted&lt;/a&gt; from best fitness to worst:
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
CL-USER&amp;gt; (defparameter population (create-initial-population *operators* 10))
POPULATION

CL-USER&amp;gt; (evaluate-population population (lambda (r) (* pi r r)) '(0 1 -2))
((:FITNESS 0.016815323605722716111d0 :FORM (- (- =INPUT= =INPUT=) =INPUT=))
 (:FITNESS 0.009437720627636827027d0 :FORM (- 1.5379852 2.1223724))
 (:FITNESS 0.007690745276452599039d0 :FORM (* =INPUT= 6.8947406))
 (:FITNESS 0.0031801166742824690382d0 :FORM
  (* =INPUT= (- 3.0632048 (* (+ (- 5.8116364 =INPUT=) 0.1915878) =INPUT=))))
 (:FITNESS 0.0016815216288940106286d0 :FORM (+ (+ 7.147339 =INPUT=) =INPUT=))
 (:FITNESS 2.6768631466526024146d-4 :FORM (* (+ =INPUT= 2.1140647) 6.7930226)))
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;
&lt;p&gt;
This is the same population as created in the &lt;a href="#sec-4"&gt;Population&lt;/a&gt; chapter.
Note that four of the ten forms have been eliminated since they
executed illegal code.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-7_2" class="outline-3"&gt;
&lt;h3 id="sec-7_2"&gt;&lt;span class="section-number-3"&gt;7.2&lt;/span&gt; HEAD &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-7_2"&gt;





&lt;pre class="src src-common-lisp"&gt;(&lt;span style="color: #551a8b;"&gt;defun&lt;/span&gt; &lt;span style="color: #000000;"&gt;head&lt;/span&gt; (sequence &lt;span style="color: #000000;"&gt;&amp;amp;optional&lt;/span&gt; (amount 1))
  (&lt;span style="color: #551a8b;"&gt;if&lt;/span&gt; (&amp;lt;= amount 0)
      nil
      (&lt;span style="color: #551a8b;"&gt;if&lt;/span&gt; (&amp;lt; (length sequence) amount)
          sequence
          (subseq sequence 0 amount))))
&lt;/pre&gt;



&lt;p&gt;
Utility function used by ADVANCE-GENERATION.  Returns AMOUNT
elements from the start of SEQUENCE.  If SEQUENCE is shorter than
AMOUNT it will return the whole SEQUENCE.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-7_3" class="outline-3"&gt;
&lt;h3 id="sec-7_3"&gt;&lt;span class="section-number-3"&gt;7.3&lt;/span&gt; Running the Advancement &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-7_3"&gt;





&lt;pre class="src src-common-lisp"&gt;(&lt;span style="color: #551a8b;"&gt;defun&lt;/span&gt; &lt;span style="color: #000000;"&gt;advance-generation&lt;/span&gt; (population fitness-fn operators test-input
                           &lt;span style="color: #000000;"&gt;&amp;amp;optional&lt;/span&gt; (max-population 100))
  (&lt;span style="color: #551a8b;"&gt;let&lt;/span&gt; ((epop (evaluate-population population fitness-fn test-input)))
    (format t &lt;span style="color: #8b4513;"&gt;"Best fitness of current population: ~S~%"&lt;/span&gt;
            (getf (first epop) &lt;span style="color: #8b4789;"&gt;:fitness&lt;/span&gt;))
    (&lt;span style="color: #551a8b;"&gt;loop&lt;/span&gt; for plist in (head epop max-population)
          for i from 0
          for fitness = (getf plist &lt;span style="color: #8b4789;"&gt;:fitness&lt;/span&gt;)
          for form = (getf plist &lt;span style="color: #8b4789;"&gt;:form&lt;/span&gt;)
          collect form
          when (&amp;lt;= (random 1.0d0) fitness)
            collect (&lt;span style="color: #551a8b;"&gt;if&lt;/span&gt; (&amp;lt;= (random 100) 90)
                        (cross-over form (getf (random-elt epop) &lt;span style="color: #8b4789;"&gt;:form&lt;/span&gt;))
                        (mutate form operators))
          &lt;span style="color: #b22222;"&gt;;; &lt;/span&gt;&lt;span style="color: #b22222;"&gt;Add a new random form to the population now and then.
&lt;/span&gt;          when (&amp;lt;= (random 100) 2) collect (random-form operators))))
&lt;/pre&gt;



&lt;p&gt;
Using the list of forms and their fitness from EVALUATE-POPULATION as
input we only loop over the first MAX-POPULATION items to keep the
population size in check.  We then check the form's fitness against a
random number between 0.0 and 1.0 and if the number is lower than the
fitness the form will be selected for either a cross-over (90% chance)
or a mutation (10% chance).
&lt;/p&gt;
&lt;p&gt;
So the form's fitness is its chance to be selected.  Since the fitness
of the forms in the initial population is usually very low it will
take quite a few generations before something starts happening.
&lt;/p&gt;
&lt;p&gt;
We collect the form and if it's been selected we also collect the
result from either CROSS-OVER or MUTATE.  These will all be
accumulated and eventually returned as the new generation.
&lt;/p&gt;
&lt;p&gt;
There's also a small chance a new random form will be added to the
population since the way we're currently handling things it is very
possible for a successful form to take over the entire population and
make it too homogeneous for good results.  This is a quick and easy
hack to introduce some chaos into populations.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-7_4" class="outline-3"&gt;
&lt;h3 id="sec-7_4"&gt;&lt;span class="section-number-3"&gt;7.4&lt;/span&gt; Finding a Solution &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-7_4"&gt;


&lt;p&gt;
Lets run ADVANCE-GENERATION a hundred times over a new population (we
also update the population on each iteration with SETF):
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
CL-USER&amp;gt; (defparameter population (create-initial-population *operators* 100))
POPULATION
CL-USER&amp;gt; (loop repeat 100
               for i from 0
               do (format t "[~S] " i)
                  (setf population
                        (advance-generation population
                                            (lambda (r) (* pi r r))
                                            *operators*
                                            '(0 1 -2))))
[0] Best fitness of current population: 0.08546627574466652d0
[...]
[43] Best fitness of current population: 0.08626213422506805d0
[...]
[66] Best fitness of current population: 0.10050107335294403d0
[...]
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;
&lt;p&gt;
And again:
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
CL-USER&amp;gt; (loop repeat 100 for i from 0 do (format t "[~S] " i) (setf population (advance-generation population (lambda (r) (* pi r r)) *operators* '(0 1 -2))))
[...]
[26] Best fitness of current population: 0.3865141184760903d0
[...]
[93] Best fitness of current population: 0.49884414719455095d0
[...]
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;
&lt;p&gt;
Lets do another 300 runs so we've done 500 in total and see what the
best form looks like in the end:
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
CL-USER&amp;gt; (loop repeat 300 for i from 0 do (format t "[~S] " i) (setf population (advance-generation population (lambda (r) (* pi r r)) *operators* '(0 1 -2))))
[...]
[35] Best fitness of current population: 0.5397727425319018d0
[...]
[62] Best fitness of current population: 0.559234953025742d0
[...]
[117] Best fitness of current population: 0.6436990901489741d0
[...]
[179] Best fitness of current population: 0.9657338407311192d0
[...]
[201] Best fitness of current population: 0.9705968409735506d0
[202] Best fitness of current population: 0.9755729636966523d0
[203] Best fitness of current population: 0.9994359703065686d0
[...]

CL-USER&amp;gt; (defparameter best-form (first (evaluate-population population (lambda (r) (* pi r r)) '(0 1 -2))))
BEST-FORM
CL-USER&amp;gt; best-form
(:FITNESS 0.9994359703065686d0 :FORM
 (* (+ (+ =INPUT= =INPUT=) (+ =INPUT= (/ =INPUT= (+ 3.5050452 3.5518444))))
    =INPUT=))

CL-USER&amp;gt; (run-form (getf best-form :form) 0)
0.0
CL-USER&amp;gt; (run-form (getf best-form :form) 1)
3.1417055
CL-USER&amp;gt; (run-form (getf best-form :form) 2)
12.566822
CL-USER&amp;gt; (run-form (getf best-form :form) 3)
28.275349
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;
&lt;p&gt;
Here's the output from the real function to calculate the area of a
circle for comparison:
&lt;/p&gt;
&lt;p&gt;
&lt;dl&gt;&lt;dd&gt;
&lt;/p&gt;&lt;pre class="example"&gt;
CL-USER&amp;gt; (run-form '(* pi =input= =input=) 0)
0.0d0
CL-USER&amp;gt; (run-form '(* pi =input= =input=) 1)
3.141592653589793d0
CL-USER&amp;gt; (run-form '(* pi =input= =input=) 2)
12.566370614359172d0
CL-USER&amp;gt; (run-form '(* pi =input= =input=) 3)
28.274333882308138d0
&lt;/pre&gt;

&lt;p&gt;&lt;/dl&gt;&lt;/dd&gt;
&lt;/p&gt;
&lt;p&gt;
Not quite the impressive result of Bill Clementson's attempt but not
half bad either!
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-8" class="outline-2"&gt;
&lt;h2 id="sec-8"&gt;&lt;span class="section-number-2"&gt;8&lt;/span&gt; Conclusion &lt;/h2&gt;
&lt;div class="outline-text-2" id="text-8"&gt;


&lt;p&gt;
I hope to have shown how one can start with a few simple functions
(RANDOM-FORM and its RANDOM-ELT helper) and explore a topic which
might interest you.
&lt;/p&gt;
&lt;p&gt;
If you read the literature you'll notice that there are a lot of
things still wrong with the current setup.  As you will find out if
you start experimenting with the code in this article &lt;a href="http://cswww.essex.ac.uk/staff/rpoli/gp-field-guide/113Bloat.html#17_3"&gt;bloat&lt;/a&gt; is a big
problem, as well as a successful form taking over the entire
population.
&lt;/p&gt;
&lt;p&gt;
If the topic of GP interests you I would suggest you read up and look
into:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
eliminating bloat
&lt;/li&gt;
&lt;li&gt;
improving the creation of the initial population
&lt;/li&gt;
&lt;li&gt;
improvements to the cross-over and mutation functions

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;for the code in this article.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-9" class="outline-2"&gt;
&lt;h2 id="sec-9"&gt;&lt;span class="section-number-2"&gt;9&lt;/span&gt; Thanks &lt;/h2&gt;
&lt;div class="outline-text-2" id="text-9"&gt;


&lt;p&gt;
Thanks to the denizens of #lisp at freenode for Common Lisp help in
general.
&lt;/p&gt;
&lt;p&gt;
Thanks to the following people for proofreading and comments: Marijn
Haverbeke, Gábor Melis, David O'Toole and Matthias of the space.invaders team.
&lt;/p&gt;
&lt;p&gt;
Keep in mind that any mistakes are mine.
&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/8024950545070946198/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2011/01/baby-steps-into-genetic-programming.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/8024950545070946198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/8024950545070946198'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2011/01/baby-steps-into-genetic-programming.html' title='Baby Steps into Genetic Programming'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-1097379694892087700</id><published>2010-10-11T08:36:00.000+02:00</published><updated>2010-10-11T08:36:30.968+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='google-ai-challenge'/><title type='text'>Planet Wars: You Can Still Participate</title><content type='html'>&lt;p&gt;The &lt;a href="http://ai-contest.com/"&gt;Planet Wars&lt;/a&gt; competition has been running for a month now and the deadline for submissions is Saturday the 27th of November 2010.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Don't let the fact that it has already been running for a month dissuade you from participating.  If you're an experienced programmer a weekend of solid work will get your bot in the top 500 (out of a little more than 3000 participants currently) and maybe even in the top 100.  If you're less experienced perhaps a week or two of work will get you the same (and if not, you will still learn a lot!).&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Some perspective: my bot briefly entered the top 25 this weekend (but it's on its way out of the top 50 currently) and I've been working on it in my spare time the last two or three weeks.  I'm not experienced in AI programming and I've got a full time job, a wife and two young kids to distract me.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;So, grab a &lt;a href="http://ai-contest.com/forum/viewtopic.php?f=18&amp;amp;t=421"&gt;Common Lisp starter pack&lt;/a&gt; and get hacking!&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;One tip: The map format is very simple (check the &lt;code&gt;maps&lt;/code&gt; directory in any starter pack).  Make simple maps to test your attack and defense routines on.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Some helpful links:&lt;br /&gt;
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.benzedrine.cx/planetwars/"&gt;dhartmei's TCP server&lt;/a&gt;: with this you can play games against others from your own machine (ie. without uploading) and it gives you more games in a shorter amount of time than the official server.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ai-contest.com/forums/viewtopic.php?f=18&amp;amp;t=751"&gt;JBotManager&lt;/a&gt;: I use this utility exclusively for replaying games.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ai-contest.com/forums/viewtopic.php?f=17&amp;amp;t=395"&gt;Test scripts&lt;/a&gt; for running your bot against the example bots on all the maps.  If you win against these bots 95% of the time you'll end up in the top 500 and if you win against them 100% of the time you'll probably end up in the top 100.&lt;/li&gt;
&lt;li&gt;A &lt;a href="http://ai-contest.com/forums/viewtopic.php?f=17&amp;amp;t=856"&gt;strategy guide&lt;/a&gt; with links to other strategy guides.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ai-contest.com/forums/viewtopic.php?f=17&amp;amp;t=628"&gt;Parsing the game output state&lt;/a&gt;: this will allow you to get a played game back from the official server in a way that can be fed back into your bot.  This has helped me find some bugs of games where my bot crashed on the official server which I missed when testing locally.&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/1097379694892087700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2010/10/planet-wars-you-can-still-participate.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/1097379694892087700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/1097379694892087700'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2010/10/planet-wars-you-can-still-participate.html' title='Planet Wars: You Can Still Participate'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-1092672185093812385</id><published>2010-09-21T15:40:00.000+02:00</published><updated>2010-09-21T15:40:40.734+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='google-ai-challenge'/><title type='text'>Planet Wars: Common Lisp Starter Package, part 2</title><content type='html'>It took a while but Common Lisp is finally supported on the official &lt;a href="http://ai-contest.com/"&gt;Planets Wars game server&lt;/a&gt; (Google AI Challenge)!  (In the meantime one could use &lt;a href="http://www.benzedrine.cx/planetwars/"&gt;dhartmei's server&lt;/a&gt; (and you still can since it offers some advantages like more games in a shorter time).)&lt;br /&gt;
&lt;br /&gt;
Both Gábor Melis and I updated our starter packages which can be found here:&lt;br /&gt;
&lt;ul&gt;  &lt;li&gt;&lt;a href="http://quotenil.com/Planet-Wars-Common-Lisp-Starter-Package-Actually-Works.html"&gt;http://quotenil.com/Planet-Wars-Common-Lisp-Starter-Package-Actually-Works.html&lt;/a&gt;&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://ai-contest.com/forum/viewtopic.php?f=18&amp;t=421&amp;p=4494#p4494"&gt;http://ai-contest.com/forum/viewtopic.php?f=18&amp;t=421&amp;p=4494#p4494&lt;/a&gt;&lt;br /&gt;
&lt;/ul&gt;
My starter package has been improved a little since earlier versions (most importantly no reliance on *features* anymore) and it comes with a silly bot that is currently slowly climbing the ranks: &lt;a href="http://ai-contest.com/profile.php?user_id=4055"&gt;http://ai-contest.com/profile.php?user_id=4055&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/1092672185093812385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2010/09/planet-wars-common-lisp-starter-package.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/1092672185093812385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/1092672185093812385'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2010/09/planet-wars-common-lisp-starter-package.html' title='Planet Wars: Common Lisp Starter Package, part 2'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-571823845231090236</id><published>2010-09-09T23:01:00.006+02:00</published><updated>2010-09-10T11:44:56.914+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='google-ai-challenge'/><title type='text'>Planet Wars: Common Lisp Starter Package (Google AI Challenge)</title><content type='html'>The &lt;a href="http://ai-contest.com/"&gt;Google AI Challenge&lt;/a&gt; should start any day now and I and "anwyn" have both made &lt;a href="http://ai-contest.com/forums/viewtopic.php?f=18&amp;t=421"&gt;Common Lisp starter packages&lt;/a&gt;.  anwyn's follows the API of the other starter packages more and is perhaps a little more lispier (I like LOOP a lot) and mine's a little more bare-bones: just the basic communication with the game server and a silly example and you have to do the rest.&lt;br /&gt;
&lt;br /&gt;
One little extra in my starter package is a "proxy bot".  Since the initial starter packages use conventional languages, developing and running the bot is also pretty conventional: a basic edit, compile, run (crash, coredump) loop.  The proxy bot takes it on himself to be the one that's started up and shut down every time[1] instead of your real bot, so you can keep the latter running in an, in my case, Emacs + Slime session.&lt;br /&gt;
&lt;br /&gt;
(I don't have to tell the advantages of this to this audience.)&lt;br /&gt;
&lt;br /&gt;
This proxy bot is perhaps useful to people writing their bots in Clojure and Scheme (and Haskell?) as well.  Although they will have to adapt their main loop a little to allow for socket communications besides the normal way of talking to the game server.&lt;br /&gt;
&lt;br /&gt;
Also, there's an unofficial server on which you can test your bot against others: &lt;a href="http://www.benzedrine.cx/planetwars/"&gt;http://www.benzedrine.cx/planetwars/&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
[1] You don't really have a choice with the Planet Wars game engine.</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/571823845231090236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2010/09/planet-wars-common-lisp-start-package.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/571823845231090236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/571823845231090236'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2010/09/planet-wars-common-lisp-start-package.html' title='Planet Wars: Common Lisp Starter Package (Google AI Challenge)'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-7316003767510261219</id><published>2010-09-06T10:28:00.000+02:00</published><updated>2010-09-06T10:28:33.477+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='google-ai-challenge'/><title type='text'>New Google AI Challenge: Planet Wars</title><content type='html'>There's a new Google AI Challenge: &lt;a href="http://ai-contest.com/"&gt;Planet Wars&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
It seems &lt;a href="http://jpcameron.com/blog/?p=128"&gt;they're also working on adding support for Common Lisp&lt;/a&gt; due to the number of people that used it in the last challenge.  Awesome!</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/7316003767510261219/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2010/09/new-google-ai-challenge-planet-wars.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/7316003767510261219'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/7316003767510261219'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2010/09/new-google-ai-challenge-planet-wars.html' title='New Google AI Challenge: Planet Wars'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-3103154186346574379</id><published>2010-08-09T13:41:00.000+02:00</published><updated>2010-08-09T13:41:25.962+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='ois'/><category scheme='http://www.blogger.com/atom/ns#' term='ecl'/><category scheme='http://www.blogger.com/atom/ns#' term='ogre'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='okra'/><category scheme='http://www.blogger.com/atom/ns#' term='ilge2010'/><title type='text'>ILGE 2010 Post-mortem: Engine Troubles over Tentacle Planet</title><content type='html'>&lt;h3&gt;Progress&lt;/h3&gt;&lt;p&gt;I have made very little progress since the last report, mainly due to the little time that was available to me.  Only two things were done:&lt;/p&gt;&lt;ol&gt;  &lt;li&gt;The source code was cleaned up a little.&lt;/li&gt;
  &lt;li&gt;A windows binary was made (OpenGL only).&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;In the short term I will not work on ETOTP anymore but perhaps for ILGE 2011 or another challenge or expo I'll continue where I left off.&lt;/p&gt;&lt;h3&gt;What Went Right&lt;/h3&gt;&lt;ul&gt;  &lt;li&gt;Making wrapper functions in C for Ogre's C++ methods and adding them to ECL from C using ECL's API.  I used this approach because the inverse (making the C wrapper code from Lisp) gave me segmentation faults and didn't get me very far about 2 years ago.  (Note: this was using ECL functionality, not CFFI for which there's &lt;a href="http://github.com/aerique/okra"&gt;Okra&lt;/a&gt;.)&lt;/li&gt;
  &lt;li&gt;Compiling a C program on both Linux and Windows that was (dynamically) linked to ECL, Ogre and OIS.  This C program can, for example, start a game right away and quit back to the OS but it can also provide a CL REPL (like ECL's &lt;code&gt;si:toplevel&lt;/code&gt;) so one can interactively play with a 3D scene.  Since it's just a plain CL one can load extra packages and perhaps start Slime.&lt;/li&gt;
&lt;/ul&gt;&lt;h3&gt;What Went Wrong&lt;/h3&gt;&lt;ul&gt;  &lt;li&gt;Compiling a statically linked binary on Linux.  This didn't go as easily as I had hoped and was starting to eat into my time budget.&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.ogre3d.org/docs/api/html/classOgre_1_1ManualObject.html"&gt;ManualObjects&lt;/a&gt; and shadows.  I had to resort to Ogre's &lt;a href="http://www.ogre3d.org/docs/api/html/classOgre_1_1SceneManager.html#a9d9c135f1e3fe85db6e1976f1df3fb35"&gt;prefab entities&lt;/a&gt; to get shadows working the way I wanted in the time that I had available.&lt;/li&gt;
&lt;/ul&gt;&lt;h3&gt;What I Learned&lt;/h3&gt;&lt;ul&gt;  &lt;li&gt;ECL is a really good option for embedding a CL implementation in C(++) programs.  Juanjo has been working on ECL for years now and he's still going strong.  Questions on the mailing-list are generally answered within hours.&lt;/li&gt;
  &lt;li&gt;One doesn't just add "-static" to a build rule and be done with it :-)&lt;/li&gt;
  &lt;li&gt;Perlin noise is usable to animate objects with.  Definitely for prototyping since it's so easy and quick to implement.&lt;/li&gt;
  &lt;li&gt;I should brush up on my maths.&lt;/li&gt;
&lt;/ul&gt;&lt;h3&gt;Source &amp;amp; Binary&lt;/h3&gt;&lt;p&gt;The source code and the Windows binary are available here&lt;br /&gt;
&lt;a href="http://www.aerique.net/software/etotp/"&gt;http://www.aerique.net/software/etotp/&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I have not given the source code its separate GitHub repository since it will be added to &lt;a href="http://github.com/aerique/okra"&gt;Okra&lt;/a&gt;.&lt;/p&gt;&lt;h4&gt;Linux Dependencies&lt;/h4&gt;&lt;p&gt;ECL (10.4.1) configured "&amp;ndash;with-cxx".  (Feel free to try without it, I haven't.)&lt;/p&gt;&lt;p&gt;Debian: libogre-dev libois-dev ogre-plugins-cgprogrammanager&lt;/p&gt;&lt;h4&gt;Windows Dependencies&lt;/h4&gt;&lt;p&gt;I develop on Linux but the build is checked and tested on Windows using &lt;a href="http://www.mingw.org/"&gt;MinGW&lt;/a&gt; and &lt;a href="http://www.mingw.org/wiki/MSYS"&gt;MSYS&lt;/a&gt;.  Either MSYS 1.10 or 1.11 was used, it doesn't really matter.  The MinGW release that was used is &lt;a href="http://tdm-gcc.tdragon.net/"&gt;TDM-GCC&lt;/a&gt; 4.4.1 but I see there's a 4.5.0 release out now.&lt;/p&gt;&lt;p&gt;&lt;a href="http://sourceforge.net/projects/ogre/files/ogre/1.6.1/OgreSDKSetup1.6.1_CBMingW.exe/download"&gt;Ogre SDK 1.6.1&lt;/a&gt; for MinGW (there's no later 1.6.x SDK for MinGW).  You can try the 1.7.x SDK for MinGW since the Ogre API is pretty stable, but I can make no guarantees that it will work.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/3103154186346574379/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2010/08/ilge-2010-post-mortem-engine-troubles.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/3103154186346574379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/3103154186346574379'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2010/08/ilge-2010-post-mortem-engine-troubles.html' title='ILGE 2010 Post-mortem: Engine Troubles over Tentacle Planet'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-9206035938656970560</id><published>2010-07-22T22:31:00.001+02:00</published><updated>2010-07-23T16:10:48.481+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='ois'/><category scheme='http://www.blogger.com/atom/ns#' term='ecl'/><category scheme='http://www.blogger.com/atom/ns#' term='ogre'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='okra'/><category scheme='http://www.blogger.com/atom/ns#' term='ilge2010'/><title type='text'>ILGE 2010: Engine Troubles over Tentacle Planet, part 2</title><content type='html'>&lt;h3&gt;1 Progress&lt;/h3&gt;&lt;p&gt;Since the last report I've added: a controllable spaceship, bullets, tentacles and I made an unsuccessful attempt at producing a Linux binary.&lt;/p&gt;&lt;p&gt;For the controls I use the &lt;a href="http://sourceforge.net/projects/wgoi/"&gt;OIS&lt;/a&gt; library. I was already familiar with this due to my &lt;a href="http://github.com/aerique/clois-lane"&gt;clois-lane&lt;/a&gt; library.  The controls work but don't feel quite right yet and need some minor adjustments.&lt;/p&gt;&lt;p&gt;Adding bullets was straightforward.  The most time was put into the tentacles and the attempt at making a statically linked Linux binary.&lt;/p&gt;&lt;p&gt;The tentacles are Ogre &lt;a href="http://www.ogre3d.org/docs/api/html/classOgre_1_1SceneManager.html#a9d9c135f1e3fe85db6e1976f1df3fb35"&gt;prefab cubes&lt;/a&gt; plot along a &lt;a href="http://en.wikipedia.org/wiki/B%C3%A9zier_curve"&gt;Bézier curve&lt;/a&gt;.  The P1 and P2 control points and the P3 end point are assigned a new x,y,z coordinate each frame.  This coordinate is picked by walking through 3D Perlin noise with a random movement vector for each point.  (The vector was created randomly at creation time, it's stays the same from frame to frame.)&lt;/p&gt;&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/RMwJXP8EOU4&amp;amp;hl=en_US&amp;amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/RMwJXP8EOU4&amp;amp;hl=en_US&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;
&lt;p&gt;The code is a huge mess by now and it is getting in the way.  Next priority should be a clean-up.&lt;/p&gt;&lt;h3&gt;2 To Do &lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;[X]&lt;/b&gt; rolling terrain &lt;i&gt;(high)&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[X]&lt;/b&gt; controllable spaceship &lt;i&gt;(high)&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; improve controls &lt;i&gt;(low)&lt;/i&gt;: The controls aren't quite there yet,especially moving left and right.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[X]&lt;/b&gt; bullets &lt;i&gt;(high)&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[X]&lt;/b&gt; cmake file &lt;i&gt;(low)&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[X]&lt;/b&gt; basic tentacles &lt;i&gt;(high)&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; shootable tentacles &lt;i&gt;(high)&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; collision detection: spaceship vs terrain &lt;i&gt;(high)&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; collision detection: spaceship vs all other entities &lt;i&gt;(high)&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; tentacles that shoot small spores &lt;i&gt;(medium)&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; roaming (bigger) spores that attack the player &lt;i&gt;(medium)&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; some minor GUI elements showing the score, highscore and FPS. &lt;i&gt;(high)&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; make binary release for Windows &lt;i&gt;(medium)&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; spaceship needs to cast a shadow in the terrain to judge heights&lt;i&gt;(high)&lt;/i&gt;: Solved this by using prefab entities instead of a manual object.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;canceled:&lt;/b&gt; make binary release for Linux &lt;i&gt;(high)&lt;/i&gt;: This is just too much of a hassle.  The Ogre package for Debian didn't come with static libraries and compiling it myself with "&amp;ndash;disable-shared &amp;ndash;enable-static" didn't produce them either so this is going to take too much time.&lt;br /&gt;
Eventually I managed to build static Ogre libraries but ran into other problems when compiling with "-static".  Statically compiling is something I have no experience with and this looks like it is going to take too much time for the ILGE 2010.&lt;br /&gt;
For Linux it seems distribution by deb and rpm packages will be the best solution.  (What a revelation!)&lt;/li&gt;
&lt;/ul&gt;&lt;h3&gt;3 Source&lt;/h3&gt;&lt;p&gt;The code for the latest version isn't available yet since it is a horrible mess.  Keep watching &lt;a href="http://www.aerique.net/software/etotp/"&gt;http://www.aerique.net/software/etotp/&lt;/a&gt; (not up yet) if you're interested.&lt;/p&gt;&lt;h4&gt;3.1 Linux Dependencies&lt;/h4&gt;&lt;p&gt;ECL (10.4.1) configured "&amp;ndash;with-cxx".  (Feel free to try without it, I haven't.)&lt;/p&gt;&lt;p&gt;Debian: libogre-dev libois-dev ogre-plugins-cgprogrammanager&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/9206035938656970560/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2010/07/ilge-2010-engine-troubles-over-tentacle_22.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/9206035938656970560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/9206035938656970560'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2010/07/ilge-2010-engine-troubles-over-tentacle_22.html' title='ILGE 2010: Engine Troubles over Tentacle Planet, part 2'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-4908063997124084500</id><published>2010-07-13T12:28:00.003+02:00</published><updated>2010-07-13T12:31:18.372+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='ois'/><category scheme='http://www.blogger.com/atom/ns#' term='ecl'/><category scheme='http://www.blogger.com/atom/ns#' term='ogre'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='okra'/><category scheme='http://www.blogger.com/atom/ns#' term='ilge2010'/><title type='text'>ILGE 2010: Engine Troubles over Tentacle Planet, part 1</title><content type='html'>&lt;h3&gt;Introduction&lt;/h3&gt;&lt;p&gt;I've finally managed to scramble together a good couple of hours to work on my &lt;a href="http://dto.github.com/notebook/2010expo.html"&gt;ILGE 2010&lt;/a&gt; entry.  At this rate it will be doubtful whether I'll have a minimal game by the end of this month :-(&lt;/p&gt;&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/4QljLf9OSi8&amp;amp;hl=en_US&amp;amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/4QljLf9OSi8&amp;amp;hl=en_US&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;
&lt;p&gt;The first item that can be checked off the to-do list: rolling terrain.  The video is low quality and stutters but this is due to me using sub-optimal software to capture my desktop.  The program actually runs very smoothly on both systems I've ran it on (a Samsung NC10 netbook and an Intel P4 2.8Ghz desktop).&lt;/p&gt;&lt;p&gt;The video shows the planet on which this game is played.  It is a standard heightfield created using &lt;a href="http://en.wikipedia.org/wiki/Perlin_noise"&gt;Perlin Noise&lt;/a&gt; (with the CL &lt;a href="http://github.com/aerique/black-tie"&gt;Black Tie&lt;/a&gt; library) which keeps scrolling down endlessly until the player dies.&lt;/p&gt;&lt;h3&gt;Goal&lt;/h3&gt;&lt;p&gt;Explore the usability of &lt;a href="http://www.ogre3d.org/"&gt;Ogre&lt;/a&gt; and C++ from &lt;a href="http://ecls.sourceforge.net/"&gt;Embeddable Common Lisp&lt;/a&gt; (ECL) using functionality specific to ECL as opposed to using the CFFI approach used by &lt;a href="http://github.com/aerique/okra"&gt;Okra&lt;/a&gt;.  (Since Okra's CFFI approach needs to compile a small C wrapper library to access Ogre's C++ functions anyway.)&lt;/p&gt;&lt;p&gt;I will be ignoring any licensing issues that might come with releasing a binary that's statically linked to ECL and Ogre for now.&lt;/p&gt;&lt;h3&gt;Development Environment&lt;/h3&gt;&lt;p&gt;My development environment is Debian Linux.  Testing will also be done on Windows (Vista unfortunately) in the future but that hasn't happened yet.&lt;/p&gt;&lt;h4&gt;Dependencies&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;ECL 10.4.1&lt;/li&gt;
&lt;li&gt;Ogre 1.6.4&lt;/li&gt;
&lt;li&gt;OIS 1.2.0 &lt;i&gt;(not used yet)&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;ECL has been compiled by myself but Ogre and OIS have been installed using Debian's package manager (you need libogre-dev and libois-dev).&lt;/p&gt;&lt;p&gt;I have not used Ogre 1.7.x yet but since Ogre's API has been pretty stable in the past it might just work without any changes.&lt;/p&gt;&lt;h3&gt;TO-DO&lt;/h3&gt;&lt;p&gt;In chronological order:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;[X]&lt;/b&gt; rolling terrain&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; controllable spaceship&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; basic tentacles&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; bullets&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; shootable tentacles&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; tentacles that shoot small spores&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; roaming (bigger) spores that attack the player&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; collision detection: spaceship vs terrain&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; collision detection: spaceship vs all other entities&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Don't know when:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;[&lt;span style="visibility:hidden;"&gt;X&lt;/span&gt;]&lt;/b&gt; some minor GUI elements showing the score, highscore and FPS.&lt;/li&gt;
&lt;/ul&gt;&lt;h3&gt;Source&lt;/h3&gt;&lt;p&gt;The code is not pretty but available here: &lt;a href="http://www.aerique.net/software/etotp/etotp-20100713.tar.gz"&gt;http://www.aerique.net/software/etotp/etotp-20100713.tar.gz&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I'm slowly moving from using global variables to stuffing everything into a scene-class instance so that will account for any duplication you might see.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/4908063997124084500/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2010/07/ilge-2010-engine-troubles-over-tentacle.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/4908063997124084500'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/4908063997124084500'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2010/07/ilge-2010-engine-troubles-over-tentacle.html' title='ILGE 2010: Engine Troubles over Tentacle Planet, part 1'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-4980299800770246137</id><published>2010-03-17T12:10:00.001+01:00</published><updated>2010-03-17T12:12:34.513+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='markdown'/><title type='text'>Common Lisp source to Markdown converter</title><content type='html'>&lt;a href="http://www.aerique.net/software/cl2md/"&gt;cl2md&lt;/a&gt; is a quick hack inspired by &lt;a href="http://discontinuity.info/%7Epkhuong/pbook.el"&gt;pbook.el&lt;/a&gt; (which you should check out if you've never heard of it and are an Emacs user since it marks up the source code much nicer).&lt;br /&gt;
&lt;br /&gt;
The page "cl2md" in the previous paragraph links to is the actual source code file which has been run through itself and a &lt;a href="http://daringfireball.net/projects/markdown/"&gt;Markdown&lt;/a&gt; converter.</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/4980299800770246137/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2010/03/common-lisp-source-to-markdown.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/4980299800770246137'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/4980299800770246137'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2010/03/common-lisp-source-to-markdown.html' title='Common Lisp source to Markdown converter'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-5321580916012181027</id><published>2010-03-10T14:12:00.000+01:00</published><updated>2010-03-10T14:12:12.645+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='unreal-tournament'/><category scheme='http://www.blogger.com/atom/ns#' term='gamebots'/><category scheme='http://www.blogger.com/atom/ns#' term='starcraft-ai-competition'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='proxybot'/><title type='text'>StarCraft ProxyBot Client for Common Lisp</title><content type='html'>Sorry for the CamelCase but I didn't come up with the names :-)&lt;br /&gt;
&lt;br /&gt;
For those bitten by the game AI bug since the &lt;a href="http://csclub.uwaterloo.ca/contest/rankings.php"&gt;Google AI Challenge&lt;/a&gt; (all eleven of us) I've started working on a Common Lisp (CL) client for the &lt;a href="http://en.wikipedia.org/wiki/Starcraft"&gt;StarCraft&lt;/a&gt; &lt;a href="http://code.google.com/p/bwapi-proxy/"&gt;ProxyBot&lt;/a&gt; with the &lt;a href="http://eis.ucsc.edu/StarCraftAICompetition"&gt;StarCraft AI competition&lt;/a&gt; in mind: &lt;a href="http://github.com/aerique/cl-starcraft-proxybot"&gt;http://github.com/aerique/cl-starcraft-proxybot&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
The project is still in its early stages but the important groundwork is done: commands can be send to in-game units.&lt;br /&gt;
&lt;br /&gt;
Before this project I started working on a CL client for &lt;a href="http://artemis.ms.mff.cuni.cz/pogamut/tiki-index.php?page=GameBots"&gt;GameBots 2004&lt;/a&gt; with which one can control an &lt;a href="http://en.wikipedia.org/wiki/Unreal_Tournament_2004"&gt;Unreal Tournament 2004&lt;/a&gt; avatar.&amp;nbsp; The project's stalled for now and hasn't come much farther than setting up the initial connection but for those interested it is here: &lt;a href="http://www.aerique.net/software/"&gt;http://www.aerique.net/software/&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Lastly for those interested in game AI: &lt;a href="http://taeb.sartak.org/"&gt;TAEB&lt;/a&gt; is on my radar.&amp;nbsp; See also this excellent blog post: &lt;a href="http://taeb-blog.sartak.org/2009/08/planar-taeb-ai.html"&gt;Planar - a TAEB AI&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/5321580916012181027/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2010/03/starcraft-proxybot-client-for-common.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/5321580916012181027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/5321580916012181027'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2010/03/starcraft-proxybot-client-for-common.html' title='StarCraft ProxyBot Client for Common Lisp'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-8137324532621230199</id><published>2010-02-10T15:10:00.002+01:00</published><updated>2010-02-10T15:21:44.906+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='google-ai-challenge'/><title type='text'>Google AI Challenge 2010 part 2</title><content type='html'>They've finally added &lt;a href="http://csclub.uwaterloo.ca/contest/starter_packages.php"&gt;Common Lisp as a supported language&lt;/a&gt; to the Google AI Challenge.&amp;nbsp; (Just before they stopped adding new languages, phew!)&lt;br /&gt;
&lt;br /&gt;
There were some issues getting my starter pack to work on their server since they're running an older SBCL (1.0.18 on Debian) and that didn't support the "--script" switch.&amp;nbsp; That combined with them being very busy meant it took a while.&amp;nbsp; We were passing error messages and solution back and forth only once every other day.&lt;br /&gt;
&lt;br /&gt;
So now the code is on the server side is compiled (#'save-lisp-and-die with :executable t) which means you can make good use of the two extra seconds you get for the first move (which some other languages need for starting up).&amp;nbsp; Anyway, check the Makefile and example.sh for details. &lt;br /&gt;
&lt;br /&gt;
There's still some issues with the starter pack if you're running locally and you don't want to run "make" for every other change (and ofcourse you don't want that!) so check the &lt;a href="http://csclub.uwaterloo.ca/contest/forums/viewtopic.php?f=10&amp;amp;t=28"&gt;"Common Lisp pack?" thread&lt;/a&gt; in their forums for discussion and solutions.</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/8137324532621230199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2010/02/google-ai-challenge-2010-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/8137324532621230199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/8137324532621230199'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2010/02/google-ai-challenge-2010-part-2.html' title='Google AI Challenge 2010 part 2'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-7013752191316475147</id><published>2010-02-05T16:43:00.003+01:00</published><updated>2010-02-10T15:11:06.488+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='google-ai-challenge'/><title type='text'>Google AI Challenge 2010</title><content type='html'>For those who've missed it: &lt;a href="http://csclub.uwaterloo.ca/contest/"&gt;Google AI Challenge 2010&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
There's no Common Lisp starter pack &lt;i&gt;(edit: since this is getting misinterpreted I meant a CL starter pack for the AI Challenge)&lt;/i&gt; but after a particular nasty adventure spelunking for days through an archaic database at work, fighting through the 20 years of cruft that has been build up inside of it and finally finding and fixing the problem I decided that I needed a break and wrote an initial version of a Common Lisp (SBCL) client.&lt;br /&gt;
&lt;br /&gt;
Perhaps someone with connections at the University of Waterloo and some work can finish it and make it an official starter pack?  I've got to go back to work ;-)&lt;br /&gt;
&lt;br /&gt;
Relevant links:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://csclub.uwaterloo.ca/contest/forums/download/file.php?id=16"&gt;Common Lisp starter pack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://csclub.uwaterloo.ca/contest/forums/viewtopic.php?f=10&amp;amp;t=28&amp;amp;p=184"&gt;Forum post&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/7013752191316475147/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2010/02/google-ai-challenge-2010.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/7013752191316475147'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/7013752191316475147'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2010/02/google-ai-challenge-2010.html' title='Google AI Challenge 2010'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-5749026789161663653</id><published>2010-02-01T10:41:00.003+01:00</published><updated>2010-02-01T10:43:56.317+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='gtk'/><category scheme='http://www.blogger.com/atom/ns#' term='clysma'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='okra'/><category scheme='http://www.blogger.com/atom/ns#' term='black-tie'/><title type='text'>A Black Tie and a Clysma</title><content type='html'>I've uploaded one-and-a-half project to GitHub that may or may not be useful to other people:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://github.com/aerique/black-tie#readme"&gt;Black Tie&lt;/a&gt; packages the noise functions that were previously in &lt;a href="http://github.com/aerique/okra#readme"&gt;Okra&lt;/a&gt; as a seperate library.  It is not very extensive yet and has only been optimized for SBCL.  At the moment it includes functions for generating Perlin noise, simplex noise and Voronoi diagrams.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://github.com/aerique/clysma#readme"&gt;Clysma&lt;/a&gt; is a toy project that at the moment mostly serves as an example of using &lt;a href="http://common-lisp.net/project/cl-gtk2/"&gt;CL-GTK2&lt;/a&gt;.  I don't really know where I want to go with it but for now it allows you to stroll through a running CL session and do some sightseeing.</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/5749026789161663653/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2010/02/black-tie-and-clysma.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/5749026789161663653'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/5749026789161663653'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2010/02/black-tie-and-clysma.html' title='A Black Tie and a Clysma'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-748929008271039429</id><published>2010-01-13T10:40:00.001+01:00</published><updated>2010-01-13T10:40:39.538+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='politiek'/><category scheme='http://www.blogger.com/atom/ns#' term='nl'/><title type='text'>De Nederlandse Politiek van Tegenwoordig</title><content type='html'>Vroeger trad er nog wel eens een minister af als deze over de scheef was gegaan, maar tegenwoordig trekken ze een Rita Verdonk-hoofd, doen alsof feiten meningen zijn, zeggen dat ze tóch gelijk hebben en gaan gewoon lekker verder.</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/748929008271039429/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2010/01/de-nederlandse-politiek-van.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/748929008271039429'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/748929008271039429'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2010/01/de-nederlandse-politiek-van.html' title='De Nederlandse Politiek van Tegenwoordig'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-6779072912070988818</id><published>2009-12-25T21:23:00.005+01:00</published><updated>2010-01-13T10:12:59.317+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='okra'/><title type='text'>Easy Okra on Debian</title><content type='html'>I was installing Debian (testing release) on a netbook since my main laptop is away for repairs and I noticed the Ogre packages in the distribution. So far I have always compiled Ogre and its dependencies myself so I was curious how much work it would take to get the Okra examples running.&lt;br /&gt;
&lt;br /&gt;
Not much work, but you do need to pull the latest master branch from GitHub since I had to make a few corrections.&lt;br /&gt;
&lt;br /&gt;
To run simple-okra.sh you'll need to install the following packages: cmake, g++, libogre-dev, libogremain-1.6.4 and ogre-plugins-cgprogrammanager. Go to Okra's root directory, turn BUILD_CEGUI off in CMakeLists.txt, run "cmake -G 'Unix Makefiles'" and finally run make. Then go to the examples-directory and run ./simple-okra.sh.&lt;br /&gt;
&lt;br /&gt;
To run flock.sh you'll need OIS and CEGUI as well. The latter pulls in a lot of extra dependencies (which is why I'll be switching to MyGUI). Install these additional packages: libcegui-mk2-1, libcegui-mk2-dev, libceguiogre-dev, libceguiogrerenderer-1.6.4, libois-1.2.0 and libois-dev. (You'll also need to get clois-lane from GitHub, run cmake and make for it and copy lib/libclois-lane.so to okra/lib.) Turn on BUILD_CEGUI again if you turned it off above, run cmake and make again and then run ./flock.sh in the examples directory.&lt;br /&gt;
&lt;br /&gt;
I didn't try running physics-and-input.sh since Bullet isn't available as a package in Debian/testing. It only needs OIS and not CEGUI if I remember correctly.</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/6779072912070988818/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2009/12/easy-okra-on-debian.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/6779072912070988818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/6779072912070988818'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2009/12/easy-okra-on-debian.html' title='Easy Okra on Debian'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-4796399259537116645</id><published>2009-12-05T00:22:00.009+01:00</published><updated>2010-01-13T10:12:48.889+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='gtk'/><category scheme='http://www.blogger.com/atom/ns#' term='common-lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='okra'/><title type='text'>Embedding an Ogre render window in GTK using Okra</title><content type='html'>&lt;img src="http://www.aerique.net/software/okra-gtk-demo/fractal-explorer-wireframe.png"&gt;&lt;br /&gt;
&lt;br /&gt;
Thanks to &lt;a href="http://common-lisp.net/project/cl-gtk2/"&gt;CL-GTK2&lt;/a&gt;'s author Dmitry Kalyanov for his help and patience and also thanks to several #lisp residents for testing some of my builds.&lt;br /&gt;
&lt;br /&gt;
Go to &lt;a href="http://www.aerique.net/software/okra-gtk-demo/"&gt;http://www.aerique.net/software/okra-gtk-demo/&lt;/a&gt; for the downloads.&lt;br /&gt;
&lt;br /&gt;
This post should be treated more as a work-in-progress report&lt;sup&gt;1&lt;/sup&gt; than as the blog I hoped I could publish, which would have had a title like: "Easy cross-platform executable delivery using CL-GTK2 and Okra".&lt;br /&gt;
&lt;br /&gt;
So this post should be considered as a first step and perhaps a helpful reference for people with the same intent as I did.  It should definitely not be treated as a completed project or as a reference on the proper way to build such things in Common Lisp (CL)!&lt;br /&gt;
&lt;br /&gt;
I set out to write a little demo that would have an Ogre window embedded in a GUI application and that could distributed as an executable on both Linux and Windows.  (I have neither access to nor experience with OS X.)&lt;br /&gt;
&lt;br /&gt;
I settled on CL-GTK2 for the GUI&lt;sup&gt;2&lt;/sup&gt;.  I also wanted it to work on SBCL for Windows so that ruled out using threads.  Not a smart decision on my part since it would have been better to use a separate thread for the GUI.  Eventually I didn't use SBCL on Windows anyway since it didn't work out how I initially used CL-GTK2.  (It might work using #'GTK:GTK-MAIN but I never tried.)&lt;br /&gt;
&lt;br /&gt;
Keep in mind I used Glade to construct my GUI.  CL-GTK2 comes with many examples if you want to construct your GUI programmatically.&lt;br /&gt;
&lt;h2&gt;Things to be aware of when embedding an Ogre window in GTK&lt;/h2&gt;&lt;br /&gt;
&lt;li&gt;Let CL-GTK2 run in its separate background thread, this will avoid many awkward constructs and unresponsiveness in the GUI.&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;Use a GTKEventBox for embedding the Ogre window if you need to catch events.  It also needs to be declared "can focus" and of course you'll need to enable all the events you want to catch.&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;Ogre: You'll need to use Ogre::WindowEventUtilities.messagePump() in configure_event or the GUI will hang when it is being realized.&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;Linux: I had better success using the downloadable 0.1 release than the latest from the Git repository.  Especially with signals the GUI just hung.  I'll still advice you to use the latest version from the repository but if you're running into these kind of problems you'll know what to try. When using the 0.1 release gtk/gtk.widget.lisp will need to be patched: &lt;a href="http://github.com/dmitryvk/cl-gtk2/commit/804b4c8f24b3725eb90f29d7e6910b2598b68771"&gt;http://github.com/dmitryvk/cl-gtk2/commit/804b4c8f24b3725eb90f29d7e6910b2598b68771&lt;/a&gt; (%gtk-widget:state and -:saved-state need to become :uint8).&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;Windows: I couldn't restart a Clozure CL (CCL) saved application when using the CL-GTK2 0.1 release.  However the latest from Git HEAD also had issues which were resolved by commenting out (:file "gdk.threads") in gdk/cl-gtk2-gdk.asd.  See: &lt;a href="http://github.com/dmitryvk/cl-gtk2/commit/061cf59f4abaa71f92182ee8db56e023208718d0"&gt;http://github.com/dmitryvk/cl-gtk2/commit/061cf59f4abaa71f92182ee8db56e023208718d0&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;Windows: I had to declare the event box as "above child" for the mouse events to be caught.&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;Windows: The Ogre render window needs to be repositioned to 0,0.  At the start it will be offset by a couple of hundred pixels.&lt;br /&gt;
&lt;h2&gt;Unresolved issues&lt;/h2&gt;&lt;br /&gt;
&lt;li&gt;CCL: To be fair I didn't put in the time to figure this out but I'm not sure what the top-level function given as argument to SAVE-APPLICATION needs to work like.  I wasn't able to reload the foreign libraries using this function and I needed to use the :INIT-FILE argument.&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;SBCL: It doesn't seem to be possible to set cffi:*foreign-library-directories* before the saved image starts looking for them.  Because of this I still need a start-up script.&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;CCL vs SBCL: On CCL (at least on Windows) you'll need to manually reload the foreign libraries when starting up the saved image.  SBCL does this automatically.&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;Resizing doesn't really work well yet.  Ogre::RenderWindow: update vs windowMovedOrResized vs renderOneFrame?&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;I wasn't able to get a configure_event to fire for the GTKEventBox nor was I able to make it available from Glade for the top level window.&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;I also was not able to make the destroy event for the top level window available from Glade.&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;How do I neatly align the text in the camera, mouse and statistics frames using Glade?  I've been fooling around using different approaches but didn't succeed.&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;What's the easiest way to distribute an executable on Linux? :-) &lt;i&gt;(don't answer this)&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;Ogre: When to use messagePump?&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;Linux: BadDrawables, I get these now and then and I've tried and tried to debug them but since they come only sporadically it's hard.  What causes them?  My guess would be Ogre trying to use an invalid GDK window but several different approaches to fix this were all unsuccessful.&lt;br /&gt;
&lt;h2&gt;Notes on the source-code&lt;/h2&gt;&lt;br /&gt;
The source-code is in a "Hey it compiles, ship it!" state, albeit a little cleaned up.  Still I think it is more useful to no source-code at all.  The intention was to provide a single package that would work on both Linux and Windows, hence the init.lisp script.&lt;br /&gt;
&lt;br /&gt;
I got familiar with CL-GTK2 and GTK throughout this project which explains several awkward constructs in the source-code.&lt;br /&gt;
&lt;br /&gt;
The demo uses keyboard scan-codes.  I know this is hopeless.&lt;br /&gt;
&lt;br /&gt;
I'm depending on the keyboard repeat for continuous movement instead of the key press and release events like one should for nice control and feedback.  Check the Okra demos for how that should be done.&lt;br /&gt;
&lt;br /&gt;
This project was developed on Linux using SBCL 1.0.31.debian and GTK 2.18.x and on both Windows XP and Vista using Clozure CL and GTK 2.16.x.&lt;br /&gt;
&lt;h2&gt;Footnotes&lt;/h2&gt;&lt;br /&gt;
&lt;sup&gt;1&lt;/sup&gt; On which I won't be spending any more work in the near future.&lt;br /&gt;
&lt;br /&gt;
&lt;sup&gt;2&lt;/sup&gt; I tried out several GTK and QT bindings for CL and CL-GTK2 was the easiest to get working on both Linux and Windows of the active projects.</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/4796399259537116645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2009/12/embedding-ogre-render-window-in-gtk.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/4796399259537116645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/4796399259537116645'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2009/12/embedding-ogre-render-window-in-gtk.html' title='Embedding an Ogre render window in GTK using Okra'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14701151.post-2543172907539150264</id><published>2009-10-28T14:22:00.003+01:00</published><updated>2010-01-13T10:12:12.996+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='okra'/><title type='text'>Torchlight Released</title><content type='html'>&lt;a href="http://www.torchlightgame.com/"&gt;Torchlight&lt;/a&gt; has been released by &lt;a href="http://www.runicgames.com/"&gt;Runic Games&lt;/a&gt;.  It's is a hack &amp; slash game in the grand tradition of Rogue, Diablo and Diablo 2.  Key people that worked on the last two titles have also worked on Torchlight.&lt;br /&gt;
&lt;br /&gt;
The reason I blog about this is because it uses &lt;a href="http://www.ogre3d.org/"&gt;Ogre&lt;/a&gt; for its graphics engine which is the same library Okra uses.&lt;br /&gt;
&lt;br /&gt;
I played it for a couple hours last night and it is really enjoyable.  So go check it out it's only $20 and can be bought from their site, Steam or any of the other online distributors.</content><link rel='replies' type='application/atom+xml' href='http://aerique.blogspot.com/feeds/2543172907539150264/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://aerique.blogspot.com/2009/10/torchlight-released.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/2543172907539150264'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14701151/posts/default/2543172907539150264'/><link rel='alternate' type='text/html' href='http://aerique.blogspot.com/2009/10/torchlight-released.html' title='Torchlight Released'/><author><name>aerique</name><uri>http://www.blogger.com/profile/00198490678736556031</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://3.bp.blogspot.com/_SRPxILDpGSU/Sqlbaiu5yoI/AAAAAAAAAL8/POT9dcr-sbI/S220/look-at-me.png'/></author><thr:total>0</thr:total></entry></feed>