<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>Vito Van</title>
        <link>https://vitovan.com/</link>
        <description>The chips will fall where they may.</description>
        <generator>xml-emitter</generator>
        <language>en-us</language>
        <image>
            <title>Vito&apos;s avatar</title>
            <url>https://vitovan.com/favicon.png</url>
            <link>https://vitovan.com/</link>
        </image>
        <item>
            <title>Porting Lisp Game to the Web</title>
            <link>https://vitovan.com/porting.html</link>
            <description>&lt;p&gt;2023/06&lt;/p&gt;
&lt;h2&gt;&lt;a name=&quot;tldr&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#tldr&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;Here is a game written in Common Lisp and ported to the web:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/VitoVan/pelusica/#readme&quot;&gt;Pel&#xFA;sica: Survive and make melodies&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/VitoVan/pelusica/#readme&quot;&gt;&lt;img src=&quot;porting.assets/pelusica.png&quot; alt=&quot;pelusica&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It&apos;s an action game in which you can control the blue dot with your keyboard to create music and avoid colliding with other dots.&lt;/p&gt;
&lt;p&gt;You can play it in your browser:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://vitovan.com/pelusica/0.0.6/calm.html&quot; rel=&quot;nofollow&quot;&gt;&lt;img src=&quot;https://camo.githubusercontent.com/31e3a7e8e1d3bc65a63c82ce83a0fb7e1db381b57be3917a220baa46ccaa4e52/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6f70656e2d696e25323074686525323062726f777365722d627269676874677265656e3f6c6f676f3d776562617373656d626c79266c6f676f436f6c6f723d7768697465&quot; alt=&quot;open in the browser&quot; data-canonical-src=&quot;https://img.shields.io/badge/open-in%20the%20browser-brightgreen?logo=webassembly&amp;amp;logoColor=white&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;or download it for &lt;a href=&quot;https://github.com/VitoVan/pelusica/releases/latest/download/Pelusica.AppImage&quot;&gt;Linux&lt;/a&gt;, &lt;a href=&quot;https://github.com/VitoVan/pelusica/releases/latest/download/Pelusica.macos-13.dmg&quot;&gt;macOS&lt;/a&gt;, and &lt;a href=&quot;https://github.com/VitoVan/pelusica/releases/latest/download/Pelusica.exe&quot;&gt;Windows&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a name=&quot;motivation&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#motivation&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;Motivation&lt;/h2&gt;
&lt;p&gt;I made a game, and I sent it to &lt;a href=&quot;https://vitovan.com/jack.html&quot; rel=&quot;nofollow&quot;&gt;Jack&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Jack asked: &quot;How to run it?&quot;&lt;/p&gt;
&lt;p&gt;I thought Jack was stupid, so I ignored him and sent it to Emma.&lt;/p&gt;
&lt;p&gt;Emma said: &quot;It cannot be opened.&quot;&lt;/p&gt;
&lt;p&gt;I was like: &quot;Really?&quot;&lt;/p&gt;
&lt;p&gt;It turns out Microsoft and Apple were sitting between me and my friends, saying:&lt;/p&gt;
&lt;p&gt;&quot;No, you are not opening this, because Vito didn&apos;t pay.&quot;&lt;/p&gt;
&lt;p&gt;Like this:&lt;/p&gt;
&lt;p&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;porting.assets/windows-smart-screen.png&quot;&gt;&lt;img src=&quot;porting.assets/windows-smart-screen.png&quot; alt=&quot;Windows protected your PC&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;or this:&lt;/p&gt;
&lt;p&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;porting.assets/macos-cannot-open.png&quot;&gt;&lt;img src=&quot;porting.assets/macos-cannot-open.png&quot; alt=&quot;&amp;quot;Pelusica.app&amp;quot; cannot be opened because the developer cannot be verified.&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I hate this.&lt;/p&gt;
&lt;p&gt;&quot;Who watches the watchmen?&quot; I don&apos;t know.&lt;/p&gt;
&lt;p&gt;I just want to share my game without making deal with the OS police. Since I don&apos;t have the resources to fight them, I have to find a workaround. So I tried porting this game to the web.&lt;/p&gt;
&lt;p&gt;Hopefully, we won&apos;t encounter the web police too soon.&lt;/p&gt;
&lt;h2&gt;&lt;a name=&quot;exploration&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#exploration&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;Exploration&lt;/h2&gt;
&lt;h3&gt;&lt;a name=&quot;to-lisp&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#to-lisp&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;to Lisp&lt;/h3&gt;
&lt;p&gt;The first step should be running Lisp in the browser.&lt;/p&gt;
&lt;p&gt;Today we can run &lt;a href=&quot;https://bellard.org/jslinux/&quot; rel=&quot;nofollow&quot;&gt;Linux&lt;/a&gt; and &lt;a href=&quot;https://copy.sh/v86/&quot; rel=&quot;nofollow&quot;&gt;Windows&lt;/a&gt; inside a browser, running a Lisp system is just a piece of cake, compared to an operating system.&lt;/p&gt;
&lt;p&gt;I found the following two approaches:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;via WebAssembly
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://news.ycombinator.com/item?id=31590819&quot; rel=&quot;nofollow&quot;&gt;Common Lisp running over WebAssembly for the first time&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gitlab.com/embeddable-common-lisp/ecl/-/merge_requests/277/commits&quot; rel=&quot;nofollow&quot;&gt;ECL targetting WASM via Emscripten - preliminary support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://weitz.de/chaitin/&quot; rel=&quot;nofollow&quot;&gt;A WebAssembly Version of Chaitin&apos;s Lisp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.fermyon.com/wasm-languages/lisp&quot; rel=&quot;nofollow&quot;&gt;Wisp - Lisp in WebAssembly&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;via JavaScript
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://lisperator.net/slip/&quot; rel=&quot;nofollow&quot;&gt;SLip — a Lisp system in JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tailrecursion.com/JACL/&quot; rel=&quot;nofollow&quot;&gt;JACL: JavaScript Assisted Common Lisp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/cxxxr/valtan&quot;&gt;Valtan: Common Lisp to JavaScript Compiler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jscl-project/jscl/&quot;&gt;JSCL - A Lisp-to-JavaScript compiler&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I didn&apos;t list everything here, you could find more. I also didn&apos;t list the approach of (Lisp (inside an emulated x86 (inside a browser))), because it sounds too aggressive.&lt;/p&gt;
&lt;p&gt;The point is the work could be done or has already been done.&lt;/p&gt;
&lt;p&gt;So, what now?&lt;/p&gt;
&lt;h3&gt;&lt;a name=&quot;to-game&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#to-game&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;to Game&lt;/h3&gt;
&lt;p&gt;We need to be able to provide an interactive multimedia experience to the players, that is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;to respond to the user inputs&lt;/li&gt;
&lt;li&gt;to present dynamic graphics&lt;/li&gt;
&lt;li&gt;to play music and sounds&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lisp the great and powerful itself won&apos;t do any good to that, unless you cut the graphic and sound parts, and decide to make a text-based game.&lt;/p&gt;
&lt;h4&gt;&lt;a name=&quot;compiling-sdl2-and-cairo&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#compiling-sdl2-and-cairo&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;Compiling SDL2 and Cairo&lt;/h4&gt;
&lt;p&gt;I was using &lt;a href=&quot;https://libsdl.org/&quot; rel=&quot;nofollow&quot;&gt;SDL2&lt;/a&gt; and &lt;a href=&quot;https://www.cairographics.org/&quot; rel=&quot;nofollow&quot;&gt;Cairo&lt;/a&gt; to provide the interactive multimedia experience on the desktop, with the assistance of &lt;a href=&quot;https://github.com/lispgames/cl-sdl2&quot;&gt;cl-sdl2&lt;/a&gt; and &lt;a href=&quot;https://github.com/rpav/cl-cairo2&quot;&gt;cl-cairo2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;How do I use them in the browser?&lt;/p&gt;
&lt;p&gt;Maybe we could try WebAssembly.&lt;/p&gt;
&lt;p&gt;SDL2 is WebAssembly-ready since &lt;a href=&quot;https://github.com/emscripten-core/emscripten/pull/15452&quot;&gt;the last year&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And I spent some time on Cairo and &lt;a href=&quot;https://github.com/VitoVan/pango-cairo-wasm/&quot;&gt;compiled Cairo into WebAssembly&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;&lt;a name=&quot;try-to-use-sdl2-and-cairo-with-lisp&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#try-to-use-sdl2-and-cairo-with-lisp&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;Try to Use SDL2 and Cairo With Lisp&lt;/h4&gt;
&lt;p&gt;Now we know that we can use SDL2 and Cairo in the browser, but how?&lt;/p&gt;
&lt;p&gt;On the desktop, we use &lt;a href=&quot;https://github.com/lispgames/cl-sdl2&quot;&gt;cl-sdl2&lt;/a&gt; and &lt;a href=&quot;https://github.com/rpav/cl-cairo2&quot;&gt;cl-cairo2&lt;/a&gt;, which is &lt;a href=&quot;https://cffi.common-lisp.dev/&quot; rel=&quot;nofollow&quot;&gt;CFFI&lt;/a&gt; → &lt;code&gt;load-shared-object&lt;/code&gt; →  &lt;code&gt;dlopen&lt;/code&gt; under the hood.&lt;/p&gt;
&lt;p&gt;How do we do it in WebAssembly?  Or, is it possible?&lt;/p&gt;
&lt;p&gt;It is possible.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://emscripten.org/docs/compiling/Dynamic-Linking.html&quot; rel=&quot;nofollow&quot;&gt;Dynamic Linking&lt;/a&gt; and &lt;a href=&quot;https://emscripten.org/docs/compiling/Dynamic-Linking.html#practical-details&quot; rel=&quot;nofollow&quot;&gt;dlopen&lt;/a&gt; in WebAssembly is &lt;a href=&quot;https://github.com/emscripten-core/emscripten/blob/9eff02bc816c50ab0e3b70a3bd5b72a8dc2893a2/test/other/test_dlopen_blocking.c#LL7C18-L7C24&quot;&gt;not&lt;/a&gt; a &lt;a href=&quot;https://github.com/emscripten-core/emscripten/blob/9eff02bc816c50ab0e3b70a3bd5b72a8dc2893a2/test/other/test_dlopen_async.c#L25&quot;&gt;problem&lt;/a&gt;, the problem is to make CFFI work with it.&lt;/p&gt;
&lt;p&gt;No, not with &lt;em&gt;it&lt;/em&gt;, with the Lisp implementation we chose.&lt;/p&gt;
&lt;p&gt;CFFI depends on &lt;a href=&quot;https://asdf.common-lisp.dev/&quot; rel=&quot;nofollow&quot;&gt;ASDF&lt;/a&gt; and &lt;a href=&quot;https://sourceware.org/libffi/&quot; rel=&quot;nofollow&quot;&gt;libffi&lt;/a&gt;. libffi had its WebAssembly support &lt;a href=&quot;https://github.com/libffi/libffi/pull/763&quot;&gt;earlier this year&lt;/a&gt;, so we only need to focus on ASDF.&lt;/p&gt;
&lt;p&gt;Only one of the above Lisps was officially supported by ASDF, which is &lt;a href=&quot;https://ecl.common-lisp.dev/&quot; rel=&quot;nofollow&quot;&gt;ECL&lt;/a&gt;. So, to save time, we should stick to ECL and see if we can make any progress.&lt;/p&gt;
&lt;br&gt;
&lt;p&gt;I paused.&lt;/p&gt;
&lt;br&gt;
&lt;p&gt;I was intimidated by ECL when I was young and fragile.&lt;/p&gt;
&lt;p&gt;It was a long long time ago, one day morning, I loaded my project into ECL and tried to generate a standalone application. It took a thousand years to compile and end up with some &lt;a href=&quot;https://stackoverflow.com/questions/46520876/building-an-executable-with-ecl-missing-dependency-or-can-not-find-make-build-i&quot; rel=&quot;nofollow&quot;&gt;weird&lt;/a&gt; ASDF-related &lt;a href=&quot;https://old.reddit.com/r/Common_Lisp/comments/hicmyt/error_with_uiop_running_ecl_application_built_by/&quot; rel=&quot;nofollow&quot;&gt;error&lt;/a&gt; that I still can&apos;t solve today. I also failed to upgrade &lt;a href=&quot;https://gitlab.common-lisp.net/ecl/ecl/-/blob/develop/contrib/asdf/README.ECL&quot; rel=&quot;nofollow&quot;&gt;ASDF for ECL&lt;/a&gt; after many hours of scrambling. I must say this was solely because of my stupidity, ECL is great, I am just too dumb.&lt;/p&gt;
&lt;br&gt;
&lt;p&gt;And I paused.&lt;/p&gt;
&lt;br&gt;
&lt;p&gt;I was so frightened by this task, so I asked Daniel, whose name will be printed out along with the word &quot;Copyright&quot; when you were starting ECL, like this:&lt;/p&gt;
&lt;div class=&quot;highlight highlight-source-lisp&quot;&gt;&lt;pre&gt;ECL (Embeddable Common-Lisp) &lt;span class=&quot;pl-c1&quot;&gt;21.2.1&lt;/span&gt; (git:6af4b3e51f80d569d88f0e8a4782b21c8b04970e)
Copyright (C) &lt;span class=&quot;pl-c1&quot;&gt;1984&lt;/span&gt; Taiichi Yuasa &lt;span class=&quot;pl-k&quot;&gt;and&lt;/span&gt; Masami Hagiya
Copyright (C) &lt;span class=&quot;pl-c1&quot;&gt;1993&lt;/span&gt; Giuseppe Attardi
Copyright (C) &lt;span class=&quot;pl-c1&quot;&gt;2013&lt;/span&gt; Juan J. Garcia-Ripoll
Copyright (C) &lt;span class=&quot;pl-c1&quot;&gt;2018&lt;/span&gt; Daniel Kochmanski &lt;span class=&quot;pl-c&quot;&gt;&lt;span class=&quot;pl-c&quot;&gt;;&lt;/span&gt;; &amp;lt;---- this Daniel&lt;/span&gt;
Copyright (C) &lt;span class=&quot;pl-c1&quot;&gt;2021&lt;/span&gt; Daniel Kochmanski &lt;span class=&quot;pl-k&quot;&gt;and&lt;/span&gt; Marius Gerbershagen
ECL is free software, &lt;span class=&quot;pl-k&quot;&gt;and&lt;/span&gt; you are welcome to redistribute it
under certain conditions&lt;span class=&quot;pl-c&quot;&gt;&lt;span class=&quot;pl-c&quot;&gt;;&lt;/span&gt; see file &apos;Copyright&apos; for details.&lt;/span&gt;
Type :h for Help.
Top level.
&amp;gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And Daniel &lt;a href=&quot;https://www.reddit.com/r/lisp/comments/ys7jpl/ecl_targetting_wasm_via_emscripten_preliminary/jjz39oh/&quot; rel=&quot;nofollow&quot;&gt;said&lt;/a&gt;: &quot;go for it!&quot;&lt;/p&gt;
&lt;p&gt;Then I went for it.&lt;/p&gt;
&lt;p&gt;That&apos;s when the nightmare began. It turns out that making ASDF work with ECL in the browser is way more difficult than on the desktop.&lt;/p&gt;
&lt;p&gt;I was drowned in the sea of ECL source code; suffocated on the mountain of Emscripten reference; and lost in the forest of 13987 lines of asdf.lisp.&lt;/p&gt;
&lt;p&gt;Although &lt;a href=&quot;https://gitlab.com/spaghettisalat&quot; rel=&quot;nofollow&quot;&gt;Marius Gerbershagen&lt;/a&gt; (another ECL maintainer, also listed in the ECL copyright notice) pointed out &lt;a href=&quot;https://gitlab.com/embeddable-common-lisp/ecl/-/merge_requests/277#note_1398797537&quot; rel=&quot;nofollow&quot;&gt;another path&lt;/a&gt; (static linking) for me to achieve the goal, I still haven&apos;t made it.&lt;/p&gt;
&lt;p&gt;My intelligence was heavily questioned.&lt;/p&gt;
&lt;br&gt;
&lt;p&gt;I felt sad and paused again.&lt;/p&gt;
&lt;p&gt;Until one day.&lt;/p&gt;
&lt;br&gt;
&lt;p&gt;I was talking with Jack on the phone:&lt;/p&gt;
&lt;p&gt;&quot;Now, press the &lt;kbd&gt;return&lt;/kbd&gt; key.&quot;&lt;/p&gt;
&lt;p&gt;&quot;Where is the &lt;kbd&gt;return&lt;/kbd&gt; key?&quot;&lt;/p&gt;
&lt;p&gt;&quot;It&apos;s on your keyboard, damn! The one above &lt;kbd&gt;shift&lt;/kbd&gt;!&quot;&lt;/p&gt;
&lt;p&gt;&quot;Oh, you mean &lt;kbd&gt;Enter&lt;/kbd&gt;?&quot;&lt;/p&gt;
&lt;p&gt;&quot;......&quot;&lt;/p&gt;
&lt;p&gt;Jack was using a Windows PC, and the letter on his keycap is &quot;Enter&quot;.&lt;/p&gt;
&lt;p&gt;I was using a MacBook, it is &quot;return&quot;.&lt;/p&gt;
&lt;p&gt;So: If my game were running in the browser one day, how do I know the player&apos;s operating system?&lt;/p&gt;
&lt;p&gt;Did you just say &lt;code&gt;navigator.userAgent&lt;/code&gt;? &lt;code&gt;navigator.platform&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Yeah, that&apos;s it!&lt;/p&gt;
&lt;p&gt;Wait, what language is that? JavaScript?&lt;/p&gt;
&lt;p&gt;No, shit.&lt;/p&gt;
&lt;h4&gt;&lt;a name=&quot;if-using-javascript-were-inevitable&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#if-using-javascript-were-inevitable&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;If Using JavaScript Were Inevitable&lt;/h4&gt;
&lt;p&gt;It seems to be it.&lt;/p&gt;
&lt;p&gt;Running in the browser, you have to deal with the browser.&lt;/p&gt;
&lt;p&gt;Not only to detect the operating system but also:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;to &lt;a href=&quot;https://github.com/emscripten-core/emscripten/issues/3985&quot;&gt;detect&lt;/a&gt; the browser&apos;s preferred sampleRate of &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/AudioContext&quot; rel=&quot;nofollow&quot;&gt;AudioContext&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;to get the parameter of the URL, like: &lt;code&gt;?name=Jack&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;to get the current window size&lt;/li&gt;
&lt;li&gt;to redirect the page to my cool web blog&lt;/li&gt;
&lt;li&gt;to show an evil alert&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With C, we can &lt;a href=&quot;https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#calling-javascript-from-c-c&quot; rel=&quot;nofollow&quot;&gt;call JavaScript&lt;/a&gt; like this:&lt;/p&gt;
&lt;div class=&quot;highlight highlight-source-c&quot;&gt;&lt;pre&gt;#&lt;span class=&quot;pl-k&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;pl-s&quot;&gt;&lt;span class=&quot;pl-pds&quot;&gt;&amp;lt;&lt;/span&gt;emscripten.h&lt;span class=&quot;pl-pds&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;pl-en&quot;&gt;EM_JS&lt;/span&gt;(&lt;span class=&quot;pl-k&quot;&gt;void&lt;/span&gt;, call_alert, (), {
  &lt;span class=&quot;pl-c1&quot;&gt;alert&lt;/span&gt;(&lt;span class=&quot;pl-s&quot;&gt;&lt;span class=&quot;pl-pds&quot;&gt;&apos;&lt;/span&gt;hello world!&lt;span class=&quot;pl-pds&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;);
  throw &lt;span class=&quot;pl-s&quot;&gt;&lt;span class=&quot;pl-pds&quot;&gt;&apos;&lt;/span&gt;all done&lt;span class=&quot;pl-pds&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;;
});

&lt;span class=&quot;pl-k&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;pl-en&quot;&gt;main&lt;/span&gt;() {
  &lt;span class=&quot;pl-c1&quot;&gt;call_alert&lt;/span&gt;();
  &lt;span class=&quot;pl-k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;0&lt;/span&gt;;
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With Lisp, how?&lt;/p&gt;
&lt;p&gt;We can:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;write JavaScript in a C function&lt;/li&gt;
&lt;li&gt;expose that the C function&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;defcfun&lt;/code&gt; in Lisp with CFFI to use it&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If the above feels too complicated, we can also use &lt;a href=&quot;https://ecl.common-lisp.dev/static/manual/Foreign-Function-Interface.html#SFFI-Reference&quot; rel=&quot;nofollow&quot;&gt;SFFI&lt;/a&gt; from ECL, to (write JavaScript code (inside C code (inside Lisp code))), &lt;em&gt;maybe&lt;/em&gt; like this:&lt;/p&gt;
&lt;div class=&quot;highlight highlight-source-lisp&quot;&gt;&lt;pre&gt;(&lt;span class=&quot;pl-k&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;pl-en&quot;&gt;alert&lt;/span&gt; (x)
  (ffi:clines &lt;span class=&quot;pl-s&quot;&gt;&lt;span class=&quot;pl-pds&quot;&gt;&quot;&lt;/span&gt;#include &amp;lt;emscripten.h&amp;gt;&lt;span class=&quot;pl-pds&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;)
  (ffi:c-inline (x) (:cstring) :void &lt;span class=&quot;pl-s&quot;&gt;&lt;span class=&quot;pl-pds&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;pl-s&quot;&gt;        EM_JS(void, call_alert, (), {&lt;/span&gt;
&lt;span class=&quot;pl-s&quot;&gt;          alert(&apos;hello world!&apos;);&lt;/span&gt;
&lt;span class=&quot;pl-s&quot;&gt;          throw &apos;all done&apos;;&lt;/span&gt;
&lt;span class=&quot;pl-s&quot;&gt;        });&lt;/span&gt;
&lt;span class=&quot;pl-s&quot;&gt;        call_alert(#0);&lt;/span&gt;
&lt;span class=&quot;pl-s&quot;&gt;&lt;span class=&quot;pl-pds&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;))&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Beautiful, right? I wouldn&apos;t dare to touch things like that, it&apos;s holy and sacred, and it should be reserved for sainthood.&lt;/p&gt;
&lt;p&gt;Now let&apos;s forget the SFFI approach and sort out our tasks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;make WASM Dynamic Linking, ASDF, CFFI, and ECL work,&lt;/p&gt;
&lt;p&gt;or make ASDF, CFFI, WASM ECL statically linked with Cairo working&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;write an unknown amount of JavaScript in C and wrap them in CFFI&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;compile all those pieces of spaghetti code into WebAssembly&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;press our palms together and pray&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I am only good at the last one.&lt;/p&gt;
&lt;h4&gt;&lt;a name=&quot;using-sdl2-and-cairo-with-lisp-in-jscl&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#using-sdl2-and-cairo-with-lisp-in-jscl&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;Using SDL2 and Cairo With Lisp in JSCL&lt;/h4&gt;
&lt;p&gt;If&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;using JavaScript were inevitable&lt;/li&gt;
&lt;li&gt;using SDL2 and Cairo with WASM Lisp were hard to achieve&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;then, why don&apos;t we&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;use a JavaScript-powered Lisp to interact with JavaScript, then&lt;/li&gt;
&lt;li&gt;use SDL2, Cairo WASM exported functions within JavaScript, then&lt;/li&gt;
&lt;li&gt;wrap the JavaScript call with some Lisp code?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&apos;s try &lt;a href=&quot;https://jscl-project.github.io/&quot; rel=&quot;nofollow&quot;&gt;JSCL&lt;/a&gt;, to call JavaScript within Lisp:&lt;/p&gt;
&lt;div class=&quot;highlight highlight-source-lisp&quot;&gt;&lt;pre&gt;(&lt;span class=&quot;pl-c1&quot;&gt;#j:alert&lt;/span&gt; &lt;span class=&quot;pl-s&quot;&gt;&lt;span class=&quot;pl-pds&quot;&gt;&quot;&lt;/span&gt;this is an alert&lt;span class=&quot;pl-pds&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;)&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we exported &lt;a href=&quot;https://wiki.libsdl.org/SDL2/SDL_GetTicks&quot; rel=&quot;nofollow&quot;&gt;SDL_GetTicks&lt;/a&gt; via &lt;a href=&quot;https://emscripten.org/&quot; rel=&quot;nofollow&quot;&gt;emscripten&lt;/a&gt;, we could call it in Lisp, like:&lt;/p&gt;
&lt;div class=&quot;highlight highlight-source-lisp&quot;&gt;&lt;pre&gt;(&lt;span class=&quot;pl-c1&quot;&gt;#j:_SDL_GetTicks&lt;/span&gt;)&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Convenient, right?&lt;/p&gt;
&lt;p&gt;Now, let&apos;s sort out our tasks again:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;export all the needed functions via emscripten&lt;/li&gt;
&lt;li&gt;wrap them a little for ease of use&lt;/li&gt;
&lt;li&gt;done&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Oh, really?&lt;/p&gt;
&lt;p&gt;Yes, really.&lt;/p&gt;
&lt;p&gt;I &lt;a href=&quot;https://github.com/VitoVan/calm/blob/b683b2a8e983ff508069ad95aa7c9ab6415b8080/s/usr/web/wasm.lisp#L46&quot;&gt;exported&lt;/a&gt; all the frequently used SDL2 and Cairo functions, then wrapped them with &lt;a href=&quot;https://github.com/VitoVan/calm/blob/main/src/web/cairo.lisp#L268&quot;&gt;some Lisp code&lt;/a&gt;, and then I can call them as if I were on the desktop operating system:&lt;/p&gt;
&lt;div class=&quot;highlight highlight-source-lisp&quot;&gt;&lt;pre&gt;(&lt;span class=&quot;pl-k&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;pl-en&quot;&gt;draw-blade&lt;/span&gt; (&amp;amp;optional (degree &lt;span class=&quot;pl-c1&quot;&gt;0&lt;/span&gt;))
  (c:save)
  (c:translate &lt;span class=&quot;pl-c1&quot;&gt;300&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;170&lt;/span&gt;)
  (c:rotate (* degree (/ pi &lt;span class=&quot;pl-c1&quot;&gt;180&lt;/span&gt;)))
  (c:move-to &lt;span class=&quot;pl-c1&quot;&gt;0&lt;/span&gt; -&lt;span class=&quot;pl-c1&quot;&gt;15&lt;/span&gt;)
  (c:line-to &lt;span class=&quot;pl-c1&quot;&gt;0&lt;/span&gt; -&lt;span class=&quot;pl-c1&quot;&gt;100&lt;/span&gt;)
  (c:curve-to &lt;span class=&quot;pl-c1&quot;&gt;0&lt;/span&gt; -&lt;span class=&quot;pl-c1&quot;&gt;110&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;100&lt;/span&gt; -&lt;span class=&quot;pl-c1&quot;&gt;65&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;0&lt;/span&gt;)
  (c:stroke-preserve)

  (c:set-source-rgba (/ &lt;span class=&quot;pl-c1&quot;&gt;12&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;255&lt;/span&gt;) (/ &lt;span class=&quot;pl-c1&quot;&gt;55&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;255&lt;/span&gt;) (/ &lt;span class=&quot;pl-c1&quot;&gt;132&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;255&lt;/span&gt;) &lt;span class=&quot;pl-c1&quot;&gt;0.1&lt;/span&gt;)
  (c:fill-path)
  (c:restore))&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;porting.assets/calm-fan.png&quot;&gt;&lt;img src=&quot;porting.assets/calm-fan.png&quot; alt=&quot;Calm Example Fan&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can try it yourself &lt;a href=&quot;https://vitovan.com/calm/examples-0.1.1/fan/calm.html&quot; rel=&quot;nofollow&quot;&gt;with this link&lt;/a&gt;, the source code is &lt;a href=&quot;https://github.com/VitoVan/calm/tree/examples-0.1.1/docs/examples/fan&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As I clicked on the blue circle in the upper right corner, a gentle  breeze carrying the scent of freshly cut grass wafted out of the screen. It was then that I knew it was time to call it a day.&lt;/p&gt;
&lt;h2&gt;&lt;a name=&quot;what-now&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#what-now&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;What Now?&lt;/h2&gt;
&lt;p&gt;With the availability of Lisp in the browser, along with SDL2 and Cairo, the possibilities for interesting projects are endless.&lt;/p&gt;
&lt;p&gt;The day-to-day development could happen on the desktop with &lt;a href=&quot;https://www.sbcl.org/&quot; rel=&quot;nofollow&quot;&gt;SBCL&lt;/a&gt; + &lt;a href=&quot;https://slime.common-lisp.dev/&quot; rel=&quot;nofollow&quot;&gt;SLIME&lt;/a&gt; enabled to get an interactive programming experience. When done, compile everything to WebAssembly + JavaScript, and publish the result online, then you have an application that supports Linux, macOS, Windows, and the web browser!&lt;/p&gt;
&lt;p&gt;But, JSCL is &lt;a href=&quot;https://github.com/jscl-project/jscl/#status&quot;&gt;far from complete&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the perfect new world, we should expect:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;JSCL (or any other &lt;em&gt;JavaScript&lt;/em&gt; Lisp) is complete, like &lt;a href=&quot;https://webstore.ansi.org/standards/incits/incits2261994s2008&quot; rel=&quot;nofollow&quot;&gt;ANSI complete&lt;/a&gt;, or&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ECL (or any other &lt;em&gt;complete&lt;/em&gt; Lisp) and the surrounding ecosystem function seamlessly in the browser&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you&apos;re interested, then go for it!&lt;/p&gt;
&lt;p&gt;And we don&apos;t need a complete Lisp to have fun, right?&lt;/p&gt;
&lt;p&gt;I can&apos;t wait to see what you are going to make.&lt;/p&gt;
&lt;p&gt;;-)&lt;/p&gt;</description>
            <author>Vito Van</author>
            <pubDate>Mon, 05 Jun 2023 15:28:05 +0000</pubDate>
        </item>
        <item>
            <title>Jack&apos;s Ass</title>
            <link>https://vitovan.com/jack.html</link>
            <description>&lt;p&gt;2023/02&lt;/p&gt;
&lt;p&gt;Jack is my friend, he had hemorrhoids.&lt;/p&gt;
&lt;p&gt;Hemorrhoid is one of the experiences which could be legitimately called: &quot;the pain in the ass&quot;. Something grows in the ass and causes pain.&lt;/p&gt;
&lt;h2&gt;&lt;a name=&quot;1&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#1&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;1&lt;/h2&gt;
&lt;p&gt;One day in a coffee shop, Jack and I were chattering.&lt;/p&gt;
&lt;p&gt;I said: &quot;Damn! Lisp is so cool! I wish I could have known it earlier!&quot;&lt;/p&gt;
&lt;p&gt;Then Jack said: &quot;Is it cool enough to solve my ass problem?&quot;&lt;/p&gt;
&lt;p&gt;That was a medical problem, and I ain&apos;t no medic. Although I deeply know that Lisp is cool enough to solve it, I choose to hold my impulse and asked:&lt;/p&gt;
&lt;p&gt;&quot;What did your doctor say?&quot;&lt;/p&gt;
&lt;p&gt;&quot;He said this is not curable by any known medicine. Once it is there, it is there. The only way to solve this problem is to cut it out. I said no.&quot;&lt;/p&gt;
&lt;p&gt;&quot;And?&quot;&lt;/p&gt;
&lt;p&gt;&quot;And I&apos;m in pain! I can&apos;t sit for too long, otherwise, my ass will blow up.&quot;&lt;/p&gt;
&lt;p&gt;&quot;Can&apos;t you just keep standing?&quot;&lt;/p&gt;
&lt;p&gt;&quot;That will hurt my knees! I have tried to set a bunch of timers, but they were a mess.&quot;&lt;/p&gt;
&lt;p&gt;&quot;OK, that&apos;s easy, Lisp can do it, I assure you,&quot; I said.&lt;/p&gt;
&lt;p&gt;Then Jack paid for the coffee, and I sent him the software to cure his ass by the end of the day. It&apos;s just a &lt;a href=&quot;https://en.wikipedia.org/wiki/Pomodoro_Technique&quot; rel=&quot;nofollow&quot;&gt;Pomodoro&lt;/a&gt; timer that reminds him to stand up every 25 minutes, written in Lisp with SDL2 and Cairo Graphics.&lt;/p&gt;
&lt;p&gt;I also have written a detailed manual to explain how to install the software with SBCL, SDL2, Cairo Graphics, and some other dependencies. Anyone with some basic computer knowledge could manage to install it.&lt;/p&gt;
&lt;h2&gt;&lt;a name=&quot;2&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#2&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;2&lt;/h2&gt;
&lt;p&gt;A month later, I met Jack in the same coffee shop.&lt;/p&gt;
&lt;p&gt;&quot;How&apos;s your ass?&quot; I asked.&lt;/p&gt;
&lt;p&gt;&quot;The hemorrhoids were gone.&quot;&lt;/p&gt;
&lt;p&gt;&quot;See? I told you, Lisp is cool!&quot;&lt;/p&gt;
&lt;p&gt;&quot;No, I let the doctor cut my ass.&quot;&lt;/p&gt;
&lt;p&gt;&quot;Oh, Why&apos;s that?&quot;&lt;/p&gt;
&lt;p&gt;&quot;I spent a whole day sitting in front of the computer to install SDL2, SDL_Mixer, SDL_Image, Cairo, SBCL, Quicklisp, and many other shits to get your shitty software working. Suddenly, a huge pain came from my ass. When I stood up, blood was all over the chair. Then I called the ambulance.&quot;&lt;/p&gt;
&lt;p&gt;&quot;No! Uh...&quot;&lt;/p&gt;
&lt;h2&gt;&lt;a name=&quot;3&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#3&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;3&lt;/h2&gt;
&lt;p&gt;That night, I couldn&apos;t sleep.&lt;/p&gt;
&lt;p&gt;Jack&apos;s wounded ass is all my fault.&lt;/p&gt;
&lt;p&gt;So I decided to never ask non-wizard users to install any dependencies again.&lt;/p&gt;
&lt;p&gt;After uncountable days and nights sitting in front of the computer, I made it.&lt;/p&gt;
&lt;p&gt;Suddenly, a huge pain came from my ass.&lt;/p&gt;
&lt;h2&gt;&lt;a name=&quot;4&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#4&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;4&lt;/h2&gt;
&lt;p&gt;If you have any interest, here is the ass-curing software: &lt;a href=&quot;https://vitovan.com/focalizzare/&quot; rel=&quot;nofollow&quot;&gt;Focolizzare&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And here is the framework used to build it: &lt;a href=&quot;https://github.com/VitoVan/calm/&quot;&gt;CALM&lt;/a&gt;.&lt;/p&gt;</description>
            <author>Vito Van</author>
            <pubDate>Sun, 19 Feb 2023 09:38:19 +0000</pubDate>
        </item>
        <item>
            <title>ख़िंलेर्मोर्ना - xinlermorna</title>
            <link>https://vitovan.com/xinlermorna.html</link>
            <description>&lt;p&gt;2019/09, revision: 2019/10&lt;/p&gt;
&lt;p&gt;By: la vitno, Version: &lt;strong&gt;ख़िं 0.6&lt;/strong&gt; , PDF: &lt;a href=&quot;xinlermorna/xinlermorna-V0.6.pdf&quot;&gt;xinlermorna-V0.6.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Devanagari Orthography for &lt;a href=&quot;https://mw.lojban.org/papri/Lojban&quot; rel=&quot;nofollow&quot;&gt;Lojban&lt;/a&gt; based on Hindi pronunciation&lt;/p&gt;
&lt;p&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;xinlermorna/xinlermorna.png&quot;&gt;&lt;img src=&quot;xinlermorna/xinlermorna.png&quot; alt=&quot;xinlermorna&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a name=&quot;tables&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#tables&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;Tables&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Consonants&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Note: all the inherent vowels &lt;strong&gt;/ə/&lt;/strong&gt; are reserved as &lt;strong&gt;y&lt;/strong&gt; in Lojban, suppressing is not allowed without being explicitly marked as such (with ्) or being the last letter of word.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Latin&lt;/th&gt;
&lt;th&gt;देवनागरी&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;c&lt;/td&gt;
&lt;td&gt;श&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;j&lt;/td&gt;
&lt;td&gt;झ़&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;td&gt;स&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;z&lt;/td&gt;
&lt;td&gt;ष़ *&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;f&lt;/td&gt;
&lt;td&gt;फ़&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v&lt;/td&gt;
&lt;td&gt;व&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;ख़&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&apos;&lt;/td&gt;
&lt;td&gt;ह&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;r&lt;/td&gt;
&lt;td&gt;र&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;l&lt;/td&gt;
&lt;td&gt;ल&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;n&lt;/td&gt;
&lt;td&gt;न&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;m&lt;/td&gt;
&lt;td&gt;म&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;b&lt;/td&gt;
&lt;td&gt;ब&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;d&lt;/td&gt;
&lt;td&gt;द&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;g&lt;/td&gt;
&lt;td&gt;ग&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;k&lt;/td&gt;
&lt;td&gt;क&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;p&lt;/td&gt;
&lt;td&gt;प&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;t&lt;/td&gt;
&lt;td&gt;त&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dj&lt;/td&gt;
&lt;td&gt;ज&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tc&lt;/td&gt;
&lt;td&gt;च&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dz&lt;/td&gt;
&lt;td&gt;ज़ *&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ts&lt;/td&gt;
&lt;td&gt;च़&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;* letter &lt;strong&gt;ष़&lt;/strong&gt; /ɭə/ is assigned the value &lt;strong&gt;/zə/&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;* letter &lt;strong&gt;ज़&lt;/strong&gt; /zə/ is assigned the value &lt;strong&gt;/ʣə/&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vowels&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Latin&lt;/th&gt;
&lt;th&gt;देवनागरी (Indepdt. Form)&lt;/th&gt;
&lt;th&gt;देवनागरी (Diacritic Form)&lt;/th&gt;
&lt;th&gt;देवनागरी (Diacritic Form with &apos;k/क&apos;)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;a&lt;/td&gt;
&lt;td&gt;आ&lt;/td&gt;
&lt;td&gt;ा&lt;/td&gt;
&lt;td&gt;का&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;e&lt;/td&gt;
&lt;td&gt;ए&lt;/td&gt;
&lt;td&gt;े&lt;/td&gt;
&lt;td&gt;के&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;i&lt;/td&gt;
&lt;td&gt;इ&lt;/td&gt;
&lt;td&gt;ि&lt;/td&gt;
&lt;td&gt;कि&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;o&lt;/td&gt;
&lt;td&gt;ओ&lt;/td&gt;
&lt;td&gt;ो&lt;/td&gt;
&lt;td&gt;को&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;u&lt;/td&gt;
&lt;td&gt;उ&lt;/td&gt;
&lt;td&gt;ु&lt;/td&gt;
&lt;td&gt;कु&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;y&lt;/td&gt;
&lt;td&gt;अ&lt;/td&gt;
&lt;td&gt;(inherent)&lt;/td&gt;
&lt;td&gt;क&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Diphthongs&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When used alone, diphthongs can be written as Vowel Independent Form or Diphthong Independent Form, they are &lt;strong&gt;All Accepted&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When &lt;strong&gt;i (इ)&lt;/strong&gt; is written as first letter in diphthongs, the following vowel should always be written as the Independent Form (e.g. आ instead of the Diacritic Form  ा). By this way, we are able to seperate words start with &lt;strong&gt;kai... (काि...)&lt;/strong&gt; the ones start with &lt;strong&gt;kia... (किआ...)&lt;/strong&gt;. If not, we will get &lt;strong&gt;kai... (काि...)&lt;/strong&gt; and &lt;strong&gt;kia... (किा...)&lt;/strong&gt;, which is hard to tell the differences by a normal human.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Latin&lt;/th&gt;
&lt;th&gt;देवनागरी (Vowel Indepdt. Form)&lt;/th&gt;
&lt;th&gt;देवनागरी (Diphthong Indepdt. Form)&lt;/th&gt;
&lt;th&gt;देवनागरी (Diacritic Form)&lt;/th&gt;
&lt;th&gt;देवनागरी (Diacritic Form with &apos;k/क&apos;)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ai&lt;/td&gt;
&lt;td&gt;आइ&lt;/td&gt;
&lt;td&gt;आि&lt;/td&gt;
&lt;td&gt;ाि&lt;/td&gt;
&lt;td&gt;काि&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ei&lt;/td&gt;
&lt;td&gt;एइ&lt;/td&gt;
&lt;td&gt;एि&lt;/td&gt;
&lt;td&gt;ेि&lt;/td&gt;
&lt;td&gt;केि *&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;oi&lt;/td&gt;
&lt;td&gt;ओइ&lt;/td&gt;
&lt;td&gt;ओि&lt;/td&gt;
&lt;td&gt;ोि&lt;/td&gt;
&lt;td&gt;कोि&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;au&lt;/td&gt;
&lt;td&gt;आउ&lt;/td&gt;
&lt;td&gt;आु&lt;/td&gt;
&lt;td&gt;ाु&lt;/td&gt;
&lt;td&gt;काु&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ia&lt;/td&gt;
&lt;td&gt;इआ&lt;/td&gt;
&lt;td&gt;इा&lt;/td&gt;
&lt;td&gt;िआ&lt;/td&gt;
&lt;td&gt;किआ&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ie&lt;/td&gt;
&lt;td&gt;इए&lt;/td&gt;
&lt;td&gt;इे&lt;/td&gt;
&lt;td&gt;िए&lt;/td&gt;
&lt;td&gt;किए&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ii&lt;/td&gt;
&lt;td&gt;इइ&lt;/td&gt;
&lt;td&gt;ई&lt;/td&gt;
&lt;td&gt;ी&lt;/td&gt;
&lt;td&gt;की&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;io&lt;/td&gt;
&lt;td&gt;इओ&lt;/td&gt;
&lt;td&gt;इो&lt;/td&gt;
&lt;td&gt;िओ&lt;/td&gt;
&lt;td&gt;किओ&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iu&lt;/td&gt;
&lt;td&gt;इउ&lt;/td&gt;
&lt;td&gt;इु&lt;/td&gt;
&lt;td&gt;िउ&lt;/td&gt;
&lt;td&gt;किउ&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ua&lt;/td&gt;
&lt;td&gt;उआ&lt;/td&gt;
&lt;td&gt;उा&lt;/td&gt;
&lt;td&gt;ुा&lt;/td&gt;
&lt;td&gt;कुा&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ue&lt;/td&gt;
&lt;td&gt;उए&lt;/td&gt;
&lt;td&gt;उे&lt;/td&gt;
&lt;td&gt;ुे&lt;/td&gt;
&lt;td&gt;कुे&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ui&lt;/td&gt;
&lt;td&gt;उइ&lt;/td&gt;
&lt;td&gt;उि&lt;/td&gt;
&lt;td&gt;ुि&lt;/td&gt;
&lt;td&gt;कुि&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;uo&lt;/td&gt;
&lt;td&gt;उओ&lt;/td&gt;
&lt;td&gt;उो&lt;/td&gt;
&lt;td&gt;ुो&lt;/td&gt;
&lt;td&gt;कुो&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;uu&lt;/td&gt;
&lt;td&gt;उउ&lt;/td&gt;
&lt;td&gt;ऊ&lt;/td&gt;
&lt;td&gt;ू&lt;/td&gt;
&lt;td&gt;कू&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iy&lt;/td&gt;
&lt;td&gt;इअ&lt;/td&gt;
&lt;td&gt;इअ&lt;/td&gt;
&lt;td&gt;िअ&lt;/td&gt;
&lt;td&gt;किअ&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;uy&lt;/td&gt;
&lt;td&gt;उअ&lt;/td&gt;
&lt;td&gt;उअ&lt;/td&gt;
&lt;td&gt;ुअ&lt;/td&gt;
&lt;td&gt;कुअ&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;* When &lt;strong&gt;kei&lt;/strong&gt; is written in as &lt;strong&gt;केि&lt;/strong&gt;, it may not be rendered properly by every font. Hence, Devanagari Vowel &lt;strong&gt;ai (ऐ / ै)&lt;/strong&gt; is also acceptable to be used as &lt;strong&gt;ei&lt;/strong&gt;, so &lt;strong&gt;kei&lt;/strong&gt; can also be written as &lt;strong&gt;कै&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;&lt;a name=&quot;conjunct-consonants&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#conjunct-consonants&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;Conjunct Consonants&lt;/h3&gt;
&lt;p&gt;Consonants lacking a vowel in between them &lt;strong&gt;MUST&lt;/strong&gt; physically join together as a conjunct consonant.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Latin&lt;/th&gt;
&lt;th&gt;देवनागरी (GOOD)&lt;/th&gt;
&lt;th&gt;देवनागरी (BAD)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;lojban&lt;/td&gt;
&lt;td&gt;लोझ़्बान&lt;/td&gt;
&lt;td&gt;लोझ़बान = lojyban&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;kanla&lt;/td&gt;
&lt;td&gt;कान्ला&lt;/td&gt;
&lt;td&gt;कानला = kanyla&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ckaji&lt;/td&gt;
&lt;td&gt;श्काझ़ि&lt;/td&gt;
&lt;td&gt;शकाझ़ि = cykaji&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;klama&lt;/td&gt;
&lt;td&gt;क्लामा&lt;/td&gt;
&lt;td&gt;कलामा = kylama&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bajra&lt;/td&gt;
&lt;td&gt;बाझ़्रा&lt;/td&gt;
&lt;td&gt;बाझ़रा = bajyra&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;&lt;a name=&quot;anusvara&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#anusvara&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;Anusvara&lt;/h3&gt;
&lt;p&gt;When consonant &lt;strong&gt;n&lt;/strong&gt; is preceded with a vowel and followed with a consonant (e.g. ka&lt;strong&gt;n&lt;/strong&gt;la), you can use a diacritic dot (which is called Anusvara: ं) to mark it instead of the independent form &lt;strong&gt;n&lt;/strong&gt; (न), write with Anusvara or Independent Form are &lt;strong&gt;Both Accepted&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;latin&lt;/th&gt;
&lt;th&gt;देवनागरी (Indepdt. Form)&lt;/th&gt;
&lt;th&gt;देवनागरी (Anusvara)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;kanla&lt;/td&gt;
&lt;td&gt;कान्ला&lt;/td&gt;
&lt;td&gt;कांला&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;condi&lt;/td&gt;
&lt;td&gt;शोन्दि&lt;/td&gt;
&lt;td&gt;शोंदि&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;panci&lt;/td&gt;
&lt;td&gt;पान्शि&lt;/td&gt;
&lt;td&gt;पांशि&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;&lt;a name=&quot;text-examples&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#text-examples&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;Text Examples&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Text Sample&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Standard Orthography&lt;/td&gt;
&lt;td&gt;pu ze&apos;u se djuno lei ze&apos;u renvi gi&apos;e se jijnu ca le temci be le nu le dzena ca jmive vau fa le du&apos;u le bradi be le la tlunranan. ba klama ri&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xinlermorna&lt;/td&gt;
&lt;td&gt;पु ष़ेहु से जुनो लै ष़ेहु रेंवि गिहे से झ़िझ़्नु शा ले तेम्शि बे ले नु ले ज़ेना शा झ़्मिवे वाु फ़ा ले दुहु ले ब्रादि बे ले ला त्लुंरानां&#xB7; बा क्लामा रि&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;* Text Sample Source comes from &quot;How the enemy came to Thlunrana&quot;: &lt;a href=&quot;https://jbotcan.org/lojban/en/how-the-enemy-came-to-thlunrana/&quot; rel=&quot;nofollow&quot;&gt;https://jbotcan.org/lojban/en/how-the-enemy-came-to-thlunrana/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pictures with Different Fonts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;* Jaldi &lt;a href=&quot;https://fonts.google.com/specimen/Jaldi&quot; rel=&quot;nofollow&quot;&gt;https://fonts.google.com/specimen/Jaldi&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;xinlermorna/Jaldi.png&quot;&gt;&lt;img src=&quot;xinlermorna/Jaldi.png&quot; alt=&quot;Jaldi&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;* Hind &lt;a href=&quot;https://fonts.google.com/specimen/Hind&quot; rel=&quot;nofollow&quot;&gt;https://fonts.google.com/specimen/Hind&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;xinlermorna/Hind.png&quot;&gt;&lt;img src=&quot;xinlermorna/Hind.png&quot; alt=&quot;Hind&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;* Martel &lt;a href=&quot;https://fonts.google.com/specimen/Martel&quot; rel=&quot;nofollow&quot;&gt;https://fonts.google.com/specimen/Martel&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;xinlermorna/Martel.png&quot;&gt;&lt;img src=&quot;xinlermorna/Martel.png&quot; alt=&quot;Martel&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;You can try it with the &lt;a href=&quot;https://vitovan.com/xinlermorna-transliteration/&quot; rel=&quot;nofollow&quot;&gt;xinlermorna transliteration tool&lt;/a&gt;.&lt;/p&gt;</description>
            <author>Vito Van</author>
            <pubDate>Sat, 28 Sep 2019 00:53:58 +0000</pubDate>
        </item>
        <item>
            <title>Dinosaur and Lisp</title>
            <link>https://vitovan.com/dino.html</link>
            <description>&lt;p&gt;2016/08&lt;/p&gt;
&lt;p&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;dino/high-score.png&quot;&gt;&lt;img src=&quot;dino/high-score.png&quot; alt=&quot;High Score&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Dinosaur is old enough, as well as Lisp, they may like each other. When I am talking about dinosaur here, I mean the dinosaur hiding in Google Chrome, it shows up when &quot;There is no Internet connection&quot;.&lt;/p&gt;
&lt;h3&gt;&lt;a name=&quot;whats-this-all-about&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#whats-this-all-about&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;What&apos;s This All about?&lt;/h3&gt;
&lt;p&gt;This is about writing some code in Common Lisp, which is capable of playing the Chrome Dinosaur Game itself (no &lt;a href=&quot;https://en.wikipedia.org/wiki/Deep_learning&quot; rel=&quot;nofollow&quot;&gt;Deep Learning&lt;/a&gt; involved).&lt;/p&gt;
&lt;h3&gt;&lt;a name=&quot;what-do-we-have-in-hand&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#what-do-we-have-in-hand&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;What Do We Have in Hand?&lt;/h3&gt;
&lt;p&gt;When I&apos;m trying to do this, I&apos;m sitting in front of a computer with Linux installed, and of course it has a screen monitor. So, it is easy to set up a Common Lisp environment, here is my list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Linux Machine (with screen monitor connected, to watch the dinosaur jump)&lt;/li&gt;
&lt;li&gt;
&lt;a href=&quot;http://www.sbcl.org/&quot; rel=&quot;nofollow&quot;&gt;SBCL&lt;/a&gt; (I&apos;m using 1.3.4 now, higher may be better)&lt;/li&gt;
&lt;li&gt;
&lt;a href=&quot;https://download-chromium.appspot.com/&quot; rel=&quot;nofollow&quot;&gt;Chromium&lt;/a&gt; or &lt;a href=&quot;https://www.google.com/chrome/browser/desktop/index.html&quot; rel=&quot;nofollow&quot;&gt;Google Chrome&lt;/a&gt; (I&apos;m using Chromium 52.0.2743.116 now)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also installed &lt;a href=&quot;https://www.gnu.org/software/emacs/&quot; rel=&quot;nofollow&quot;&gt;Emacs&lt;/a&gt; with &lt;a href=&quot;https://common-lisp.net/project/slime/&quot; rel=&quot;nofollow&quot;&gt;SLIME&lt;/a&gt; to play around with Lisp, you can have any other editor instead of this.&lt;/p&gt;
&lt;p&gt;Well, all set, let&apos;s start.&lt;/p&gt;
&lt;h3&gt;&lt;a name=&quot;the-eyes&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#the-eyes&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;the Eyes&lt;/h3&gt;
&lt;p&gt;It&apos;s easy for us to recognize the dinosaur, a tiny cute creature with two short legs running on our screen, but it&apos;s not easy for Lisp. We can see the screen with our eyes, Lisp can&apos;t, so we gonna write some code to read the screen, and find the dinosaur.&lt;/p&gt;
&lt;h5&gt;&lt;a name=&quot;read-the-screen&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#read-the-screen&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;Read the Screen&lt;/h5&gt;
&lt;p&gt;After searching the web, I found that there&apos;s no concept of Screen in Common Lisp. Actually, I found this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;... There are only rudimentary libraries for manipulating strings, and &lt;strong&gt;almost none&lt;/strong&gt; for talking to the operating system. For historical reasons, Common Lisp tries to pretend that &lt;strong&gt;the OS doesn&apos;t exist&lt;/strong&gt; ...&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;- &lt;a href=&quot;http://www.paulgraham.com/popular.html&quot; rel=&quot;nofollow&quot;&gt;Being Popular (Section 6)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&quot;the OS doesn&apos;t exist&quot;, what the ... , I must be lost my mind to choose Common Lisp.&lt;/p&gt;
&lt;p&gt;But since that article is written in May 2001, it&apos;s been 15 years later, things must have been changed a lot. After digging around again, I found something very useful:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href=&quot;http://www.cliki.net/CFFI&quot; rel=&quot;nofollow&quot;&gt;CFFI&lt;/a&gt;, the Common Foreign Function Interface, and this means we can call any C (and not only) library from Lisp.&lt;/li&gt;
&lt;li&gt;
&lt;a href=&quot;http://www.cliki.net/CLX&quot; rel=&quot;nofollow&quot;&gt;CLX&lt;/a&gt;, an implementation of the X Window System protocol to Lisp, and this means we can take control of the whole X Window System, of course we can read the screen! (if you are using &lt;a href=&quot;https://support.apple.com/en-us/HT201341&quot; rel=&quot;nofollow&quot;&gt;OS X&lt;/a&gt; or &lt;a href=&quot;http://x.cygwin.com/&quot; rel=&quot;nofollow&quot;&gt;Windows&lt;/a&gt;, this may be a little tricky)&lt;/li&gt;
&lt;li&gt;
&lt;a href=&quot;http://www.cliki.net/burgled-batteries&quot; rel=&quot;nofollow&quot;&gt;burgled-batteries&lt;/a&gt;, a Python-Lisp bridge, and this means we can call any Python functions seamlessly in Common Lisp.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Actually, there&apos;s &lt;a href=&quot;http://www.cliki.net/current%20recommended%20libraries&quot; rel=&quot;nofollow&quot;&gt;plenty of libraries&lt;/a&gt; out there today, you can basically do anything you want in Common Lisp, &lt;strong&gt;the OS does exist!&lt;/strong&gt; Hooray~&lt;/p&gt;
&lt;h5&gt;&lt;a name=&quot;finding-dinosaur&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#finding-dinosaur&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;Finding Dinosaur&lt;/h5&gt;
&lt;p&gt;After reading the &lt;a href=&quot;https://common-lisp.net/project/cmucl/doc/clx/&quot; rel=&quot;nofollow&quot;&gt;CLX Manual&lt;/a&gt;, we found that we can use function &lt;code&gt;get-raw-image&lt;/code&gt; to directly &lt;a href=&quot;https://common-lisp.net/project/cmucl/doc/clx/7_5_Direct_Image_Transfer.html&quot; rel=&quot;nofollow&quot;&gt;get the image data from the specific region&lt;/a&gt;. Then what? Let&apos;s find out what we need to find the dinosaur:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What&apos;s in my mind now? well, the dinosaur is keep running and running, we need to keep read the screen and find it&apos;s position. Yah, let&apos;s do it.&lt;/li&gt;
&lt;li&gt;OK, I am reading the screen every 0.1 seconds, and now I need to write some code to match the shape pattern of the dinosaur.&lt;/li&gt;
&lt;li&gt;Shape Matching, sounds thrilling, I&apos;ve never been there before, then after another round of searching, I found some papers:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://graphics.stanford.edu/courses/cs468-08-fall/pdf/belongie-pami02.pdf&quot; rel=&quot;nofollow&quot;&gt;Shape Matching and Object Recognition Using Shape Contexts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.cs.utexas.edu/~grauman/courses/spring2008/slides/ShapeMatching.pdf&quot; rel=&quot;nofollow&quot;&gt;Shape Matching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://i.stanford.edu/pub/cstr/reports/cs/tr/99/1620/CS-TR-99-1620.pdf&quot; rel=&quot;nofollow&quot;&gt;FINDING COLOR AND SHAPE PATTERNS IN IMAGES&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I started to read, the papers are obscure, Mm... they are talking about math, Mm... I don&apos;t recognize this mathematical formula, Mm...&lt;/li&gt;
&lt;li&gt;I have to take a break, let&apos;s play the Dinosaur Game.&lt;/li&gt;
&lt;li&gt;Oh, my! The dinosaur never moved! It is just keep dangling it&apos;s tiny legs and pretending: &quot;Yah, I am running, I am running&quot;.&lt;/li&gt;
&lt;li&gt;This is the ultimate humiliation to my extraordinary human intelligence.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But I&apos;ve been over it almost immediately, cause I have no need to read those obscure papers anymore, phew~&lt;/p&gt;
&lt;p&gt;Then, what&apos;s left?&lt;/p&gt;
&lt;p&gt;All we have to do about this dinosaur now, is to determine the current state of our dinosaur: &lt;strong&gt;STAND&lt;/strong&gt;ing / &lt;strong&gt;JUMP&lt;/strong&gt;ing / &lt;strong&gt;BEND&lt;/strong&gt;ing (yah, it can bend, try the down key).&lt;/p&gt;
&lt;p&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;dino/state.png&quot;&gt;&lt;img src=&quot;dino/state.png&quot; alt=&quot;Three State of Dinosaur&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Since the dinosaur never really moved forward or back, we can take screenshots of the different postures of our dinosaur, then open them in &lt;a href=&quot;https://www.gimp.org/&quot; rel=&quot;nofollow&quot;&gt;GIMP&lt;/a&gt; to get the corresponding position points, we can do this in our code:&lt;/p&gt;
&lt;div class=&quot;highlight highlight-source-lisp&quot;&gt;&lt;pre&gt;(&lt;span class=&quot;pl-k&quot;&gt;defvar&lt;/span&gt; &lt;span class=&quot;pl-smi&quot;&gt;*dino-standing-points*&lt;/span&gt; &apos;((&lt;span class=&quot;pl-c1&quot;&gt;207&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;238&lt;/span&gt;) (&lt;span class=&quot;pl-c1&quot;&gt;242&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;223&lt;/span&gt;)))
(&lt;span class=&quot;pl-k&quot;&gt;defvar&lt;/span&gt; &lt;span class=&quot;pl-smi&quot;&gt;*dino-bending-points*&lt;/span&gt; &apos;((&lt;span class=&quot;pl-c1&quot;&gt;209&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;240&lt;/span&gt;) (&lt;span class=&quot;pl-c1&quot;&gt;262&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;243&lt;/span&gt;)))&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After we have these points, we can capture the image data of current screen, then get the colors of those specific dots, and determine if the color equals to the color of dinosaur, if all &lt;code&gt;*dino-standing-points*&lt;/code&gt; matched, then it is standing, as well as &lt;code&gt;*dino-bending-points*&lt;/code&gt;, otherwise it is jumping.&lt;/p&gt;
&lt;p&gt;But after playing a while, we know that the color of dinosaur is changing between day and night, so we should have a function to get the changing color of the dinosaur. Since the dinosaur is jumping or bending, it&apos;s much easier to locate the color picking point of background, then we can determine the state of the dinosaur by using the background color: If all the color of &lt;code&gt;*dino-standing-points*&lt;/code&gt; &lt;em&gt;does not match&lt;/em&gt; the background color, then it is standing.&lt;/p&gt;
&lt;p&gt;Dinosaur Finding Problem solved.&lt;/p&gt;
&lt;h5&gt;&lt;a name=&quot;cactuses-and-birds&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#cactuses-and-birds&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;Cactuses and Birds&lt;/h5&gt;
&lt;p&gt;These front cactuses and birds could kill our dinosaur. So we have to detect them and take an action of &lt;strong&gt;JUMP&lt;/strong&gt; / &lt;strong&gt;BEND&lt;/strong&gt; or just &lt;strong&gt;STAND&lt;/strong&gt; still (the time of action also matters). We can get the image data in front of the dinosaur, and check if there is a cactus or bird:&lt;/p&gt;
&lt;p&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;dino/search-square.png&quot;&gt;&lt;img src=&quot;dino/search-square.png&quot; alt=&quot;Search Square&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The search area could be narrowed down to a 500x35 square, and the position of this square is fixed, we can easily get it from a full screenshot with &lt;a href=&quot;https://www.gimp.org/&quot; rel=&quot;nofollow&quot;&gt;GIMP&lt;/a&gt;. Then we can write something like this:&lt;/p&gt;
&lt;div class=&quot;highlight highlight-source-lisp&quot;&gt;&lt;pre&gt;&lt;span class=&quot;pl-c&quot;&gt;&lt;span class=&quot;pl-c&quot;&gt;;&lt;/span&gt;; the block search square (x y weight height)&lt;/span&gt;
(&lt;span class=&quot;pl-k&quot;&gt;defvar&lt;/span&gt; &lt;span class=&quot;pl-smi&quot;&gt;*block-search-square*&lt;/span&gt; &apos;(&lt;span class=&quot;pl-c1&quot;&gt;265&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;220&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;500&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;35&lt;/span&gt;))&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And when we get the image data of this area, then compare the background color with each pixel, if it does not match, then the cactus or bird is found!&lt;/p&gt;
&lt;p&gt;When we comparing the pixels, we choose to scan the image from left/top to right/bottom, then we will get the top/left position of the front cactus or bird.&lt;/p&gt;
&lt;p&gt;Here are the cactuses and birds I collected (some kind of cactuses may be missed):&lt;/p&gt;
&lt;p&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;dino/cactuses-and-birds.png&quot;&gt;&lt;img src=&quot;dino/cactuses-and-birds.png&quot; alt=&quot;Cactuses and Birds&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Actually, the types of cactus make nothing different, no matter it is tall or short, wide or narrow, it will be successfully passed if we jump at the appropriate time. But for the birds, we should separate them out by LOW / MIDDLE / HIGH, when it is LOW type bird, we JUMP; when it is MIDDLE type bird, we BEND, when it is HIGH type bird, we do nothing.&lt;/p&gt;
&lt;p&gt;From the image above, we can see that those birds in different types have unique y-coordinates among themselves and cactuses, we can just tell which kind of bird it is by the value of it&apos;s y-coordinate.&lt;/p&gt;
&lt;p&gt;Actually, all we need is the unique y-coordinate of the MIDDLE type bird, cause we can treat the LOW type bird the same as cactuses, and the HIGH type bird, we just pretend they never exist (cause we gonna ignore them). So, all we need is:&lt;/p&gt;
&lt;div class=&quot;highlight highlight-source-lisp&quot;&gt;&lt;pre&gt;&lt;span class=&quot;pl-c&quot;&gt;&lt;span class=&quot;pl-c&quot;&gt;;&lt;/span&gt;; the y of middle flying bird&lt;/span&gt;
(&lt;span class=&quot;pl-k&quot;&gt;defvar&lt;/span&gt; &lt;span class=&quot;pl-smi&quot;&gt;*middle-bird-y*&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;220&lt;/span&gt;)&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Cactuses and Birds Detecting Problem solved.&lt;/p&gt;
&lt;p&gt;Now, here&apos;s what we got:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We know the state of our dinosaur: STANDing / BENDing / JUMPing.&lt;/li&gt;
&lt;li&gt;We know the position of the front cactus or bird.&lt;/li&gt;
&lt;li&gt;We know what action we should take: JUMP / BEND or NOTHING.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What&apos;s left?&lt;/p&gt;
&lt;p&gt;It&apos;s &lt;strong&gt;HOW&lt;/strong&gt; and &lt;strong&gt;WHEN&lt;/strong&gt;, how to perform the JUMP or BEND action, and when to perform that action. Let&apos;s discuss them next.&lt;/p&gt;
&lt;h3&gt;&lt;a name=&quot;dancing-around&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#dancing-around&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;Dancing Around&lt;/h3&gt;
&lt;h5&gt;&lt;a name=&quot;how&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#how&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;HOW?&lt;/h5&gt;
&lt;p&gt;To jump or bend our dinosaur, we need to simulate the key press event of &lt;kbd&gt;SPACE&lt;/kbd&gt; (or &lt;kbd&gt;UP&lt;/kbd&gt;) and &lt;kbd&gt;DOWN&lt;/kbd&gt;.&lt;/p&gt;
&lt;p&gt;The X Window System must have a way to simulate key press event, and also &lt;a href=&quot;http://www.cliki.net/CLX&quot; rel=&quot;nofollow&quot;&gt;CLX&lt;/a&gt; is an implementation of the X Window System protocol to Lisp, it means we have a way to simulate key press event as well. Once we figure out how, we&apos;ll be able to control the dinosaur.&lt;/p&gt;
&lt;p&gt;After reading the &lt;a href=&quot;https://common-lisp.net/project/cmucl/doc/clx/&quot; rel=&quot;nofollow&quot;&gt;CLX Manual&lt;/a&gt;, we found a section called: &lt;a href=&quot;https://common-lisp.net/project/cmucl/doc/clx/12_Events_and_Input.html&quot; rel=&quot;nofollow&quot;&gt;Event and Input&lt;/a&gt;, it&apos;s all about events manipulating, we may use them. But after talking with some awesome fellas on IRC, I learned that there&apos;s an extension of X Window System called &lt;a href=&quot;https://www.x.org/docs/Xext/xtest.pdf&quot; rel=&quot;nofollow&quot;&gt;XTEST&lt;/a&gt;, which is &quot;a minimal set of client and server extensions required to completely test the X11 server with no user intervention&quot;, and it has an operation called  &lt;code&gt;XTestFakeInput&lt;/code&gt; which can be used to perform a fake key/mouse input as it is said by it&apos;s name.&lt;/p&gt;
&lt;p&gt;And more luckily, this extension is already &lt;a href=&quot;https://github.com/sharplispers/clx/blob/master/extensions/xtest.lisp&quot;&gt;implemented in CLX&lt;/a&gt;, so we can directly call the function &lt;code&gt;fake-key-event&lt;/code&gt; or &lt;code&gt;fake-button-event&lt;/code&gt;, they should just work! What a good day~ Now we can call something like this in the &lt;a href=&quot;https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop&quot; rel=&quot;nofollow&quot;&gt;REPL&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight highlight-source-lisp&quot;&gt;&lt;pre&gt;(xtest:fake-key-event display &lt;span class=&quot;pl-smi&quot;&gt;*space-keycode*&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;pl-c&quot;&gt;&lt;span class=&quot;pl-c&quot;&gt;;&lt;/span&gt; key down&lt;/span&gt;
(xtest:fake-key-event display &lt;span class=&quot;pl-smi&quot;&gt;*space-keycode*&lt;/span&gt; &lt;span class=&quot;pl-c1&quot;&gt;nil&lt;/span&gt;) &lt;span class=&quot;pl-c&quot;&gt;&lt;span class=&quot;pl-c&quot;&gt;;&lt;/span&gt; key up&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then the dinosaur jumped, :-D&lt;/p&gt;
&lt;h5&gt;&lt;a name=&quot;when&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#when&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;WHEN?&lt;/h5&gt;
&lt;p&gt;We should start to jump when we getting close to the cactus or bird, but how close? 100px? or 200px? should we test all these values and find the best one? No, there&apos;s no one. We can&apos;t say &quot;Hey tiny dino, you should jump when the distance between you and the cactus in front is less than 100px&quot;, because the speed is accelerating. Maybe 100px works pretty well when it is slow, but when the game speed up, the value should be far more than 100px.&lt;/p&gt;
&lt;p&gt;So, it is speed related, huh~ Since we can get the coordinates of the front cactus, calculate the speed will be done by dividing the change of x-coordinate by time passed, we can collect all the speed value each time we read the screen, then get the average value. Then we should figure out something like this:&lt;/p&gt;
&lt;div class=&quot;highlight highlight-source-lisp&quot;&gt;&lt;pre&gt;(&lt;span class=&quot;pl-k&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;pl-en&quot;&gt;jump?&lt;/span&gt; (distance speed)
    (&amp;lt;= (/ distance speed) &lt;span class=&quot;pl-c1&quot;&gt;0.15&lt;/span&gt;))&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This function &lt;code&gt;jump?&lt;/code&gt; take two parameters: &lt;code&gt;distance&lt;/code&gt;, which represent the distance between the dinosaur and the front cactus; &lt;code&gt;speed&lt;/code&gt; , which represent the speed of the cactus. Then, &lt;code&gt;(/ distance speed)&lt;/code&gt; will be the time left before cactus hit our dinosaur, &lt;code&gt;0.15&lt;/code&gt; is the time we preserved for our dinosaur to take it&apos;s feet off the ground. So, this function means: If we the cactus will hit our dinosaur in 0.15 seconds, we jump, then at the time cactus comes, our dinosaur will be right up in the sky, cactus passed!&lt;/p&gt;
&lt;p&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;dino/jumping.png&quot;&gt;&lt;img src=&quot;dino/jumping.png&quot; alt=&quot;Jumping Dinosaur&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Then, we can read the screen 60 times per second, and call &lt;code&gt;jump?&lt;/code&gt; in every screen reading action, to check if we should jump.&lt;/p&gt;
&lt;h3&gt;&lt;a name=&quot;at-last&quot; class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#at-last&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;octicon octicon-link&quot;&gt;&lt;/span&gt;&lt;/a&gt;At Last&lt;/h3&gt;
&lt;p&gt;After playing around with all the code snippets in SLIME-REPL, seems all systems go:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Screen Reading, powered by &lt;a href=&quot;https://common-lisp.net/project/cmucl/doc/clx/7_5_Direct_Image_Transfer.html&quot; rel=&quot;nofollow&quot;&gt;get-raw-image&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Dinosaur State Checking (stand or bend or in the sky?)&lt;/li&gt;
&lt;li&gt;Game State Checking (game over or not)&lt;/li&gt;
&lt;li&gt;Cactuses and Birds Detection&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Keyboard/Mouse Simulation, powered by &lt;a href=&quot;https://github.com/sharplispers/clx/blob/master/extensions/xtest.lisp#L130&quot;&gt;fake-key-event&lt;/a&gt; and &lt;a href=&quot;https://github.com/sharplispers/clx/blob/master/extensions/xtest.lisp#L117&quot;&gt;fake-button-event&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Dinosaur Controller (&lt;kbd&gt;SPACE&lt;/kbd&gt; and &lt;kbd&gt;DOWN&lt;/kbd&gt; key)&lt;/li&gt;
&lt;li&gt;Game Activation (click to active the game window)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Just do a little more clean up, we&apos;ll have a Common Lisp-powered Super Dinosaur~&lt;/p&gt;
&lt;p&gt;Now, we won&apos;t go through the details of the code implementation, you can find them at the end of this page.&lt;/p&gt;
&lt;p&gt;Before we go, I wanna say: Lisp is not the old fragile useless academic language, also, it&apos;s not any alien super power. It&apos;s a language, it works if you really touched it, and works great.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Video on YouTube:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://youtu.be/PkzlJcKR4TI&quot; rel=&quot;nofollow&quot;&gt;https://youtu.be/PkzlJcKR4TI&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;dino/such-dino.gif&quot;&gt;&lt;img src=&quot;dino/such-dino.gif&quot; alt=&quot;WOW! SUCH DINO!&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code on GitHub:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/VitoVan/cl-dino&quot;&gt;https://github.com/VitoVan/cl-dino&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I am pretty new to Common Lisp, the code may be a little messy (although I tried not to be like that), it will be great if you can point out something inelegant for me, thanks!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;License: GNU GPL v2.0&lt;/p&gt;
&lt;p&gt;Discuss on HN: &lt;a href=&quot;https://news.ycombinator.com/item?id=12351187&quot; rel=&quot;nofollow&quot;&gt;https://news.ycombinator.com/item?id=12351187&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Related:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://postd.cc/dinosaur-and-lisp/&quot; rel=&quot;nofollow&quot;&gt;Japanese Translation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
            <author>Vito Van</author>
            <pubDate>Mon, 10 Jun 2019 05:58:35 +0000</pubDate>
        </item>
    </channel>
</rss>