<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>I R Cubic</title>
    <link rel="alternate" type="text/html" href="http://ircubic.net/" />
    <link rel="self" type="application/atom+xml" href="http://ircubic.net/atom.xml" />
    <id>tag:ircubic.net,2010-02-10://2</id>
    <updated>2012-01-12T22:02:08Z</updated>
    
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 5.01</generator>

<entry>
    <title>The holidays are over, the game refactored.</title>
    <link rel="alternate" type="text/html" href="http://ircubic.net/2012/01/holidays-over-game-refactored.html" />
    <id>tag:ircubic.net,2012://2.11</id>

    <published>2012-01-12T20:08:21Z</published>
    <updated>2012-01-12T22:02:08Z</updated>

    <summary>A lot of time since has passed since my last post, and it&apos;s late too. The main reason for the silence is the holidays, very little actually work transpired in respects to my thesis during that time, and this is...</summary>
    <author>
        <name>Daniel E. Bruce</name>
        <uri>http://ircubic.net/</uri>
    </author>
    
    <category term="adate" label="adate" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ai" label="AI" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="deadend" label="dead end" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="python" label="python" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="thesis" label="thesis" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="tips" label="tips" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="worklog" label="work log" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://ircubic.net/">
        <![CDATA[<p>A lot of time since has passed since my last post, and it's late too. The main reason for the silence is the holidays, very little actually work transpired in respects to my thesis during that time, and this is the first week with significant progress since then, and the post is late as I had to finish up the final touches on them today. There has been a great deal of changes, and some interesting considerations, so this post is going to be a long one. It's the first one where I actually felt the need to use the feature in this blog to have a "read more" link on the front page. :)</p>

<p>Since the last post the entire game has been refactored, so before going into detail about changes, I'll sum up the main changes. Before the refactoring, the game was structured like your basic game, with every game character located on the pixel grid of the screen and moving every frame (so, 30 times per second), with movements being in pixels per frame and collisions being based on the actual character sprites. Now it has been split into two parts, one "game" part that handles the screen and keyboard input, and one simulation part that handles the position of the characters, the AI and the logic of the game (collisions and such). The simulation part (or at least its logic) will be shared with the ADATE system and will be translated into ADATE-ML to be used with it, so it made sense to split the code into two bits like this.</p>
]]>
        <![CDATA[<h2>A story of two worlds</h2>

<p><a href="http://ircubic.net/assets_c/2012/01/GameDiagram-9.html" onclick="window.open('http://ircubic.net/assets_c/2012/01/GameDiagram-9.html','popup','width=1003,height=594,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="http://ircubic.net/assets_c/2012/01/GameDiagram-thumb-212x125-9.png" width="212" height="125" alt="GameDiagram.png" class="mt-image-left" style="float: left; margin: 0 20px 20px 0;" /></a> To facilitate splitting the game in two, I created a flowchart diagram of sorts to help brainstorm how to separate the game into two parts, which is included in this post for your perusal. It doesn't exactly represent the final product as some modifications needed to be done while coding, but it's close enough for government work. In addition the code is <a href="https://github.com/ircubic/Master-Thesis/tree/master/src/testbed">available on github</a> for the specially interested.</p>

<p>The main idea of the split was to drastically minimize the amount of information shared between the two parts, as you see by the two "interface methods" on the border between them, which represent the only points of information exchange. There is the simtick method, which tells the simulation to run a new simulation cycle and returns the new state of the world (represented only by a collection of positions, whether the game is over, and whether it was won or lost), and there is the setCatMove method which is a bit of hack to allow passing in the current direction to move based on the keyboard input if the current cat AI is the one that allows keyboard control. This minimal interaction surface and the simplicity of the data that is passed through, means that it's almost trivial to exchange the current simulation world with, say, one implemented in SML/ADATE-ML.</p>

<p>Another big benefit of this split is that it allows you to have two different representations of the world. In the current implementation there exists the "simulation world", where the characters are represented as squares 1.5 units in size positioned in a small field that is 16 by 16 units in size, and they can only move in four directions (up, down, left, right, naturally). In addition, there is the "game world" where the characters are positioned on the screen scaled by (currently) 30 pixels per simulation units, giving you a 480 by 480 pixels screen size, and they might be positioned between two simulation world positions to allow for more fluid animation.</p>

<p>The two worlds also runs at different speeds. The simulation world runs, currently, at 5 cycles (or ticks) per second, and the game world runs 6 times faster, to give you the standard 30 frames per second of games. To prevent jerky motion from the fact that characters only update their position once every six frames, we try to animate the characters in the game world. This is done by interpolating between the previous and current position of the character in the simulation over the span of six frames, making them look like they're moving between them.</p>

<h2>Entering the simulation world</h2>

<p>The simulation world is a simple place, with very few moving bits. The bits that do move are separated into their own method called updateState (as shown in the diagram by the dashed arrows pointing towards the simulation state, representing write access). The flow is simple (again, refer to diagram for 200% of your daily allotment of arrows pointing to shapes), the characters each get a chance to run their AI code, which decides which direction they move in next out of the four possible, the state of the simulation is updated with these movements, making sure that everything stays within the world, and everything is checked for collisions. After this, either the game is declared over (a collision occured between the cat and anything else in the world) and it's marked as either win or loss (depending on what the collision was with), or nothing really happens. Either way, the simulation returns the new state of the world to whatever called it.</p>

<p>To facilitate this localized protection of the state, the characters themselves, along with their AI code, are not allowed to alter the state of the simulation, and the state is only updated after <em>every</em> character has made their decision. This makes sure that every character receives the same information, and that no AI code can "cheat" by moving others around, even by accident. If the state was updated each time a character had made an AI decision, the characters that come later would have an unfair advantage of knowing where the character is at in the "future", so any evasive action becomes useless. And not allowing AI code to cheat prevents ADATE from generating code that is a bit TOO human like, resorting to cheats to win. :)</p>

<h2>Retreat to the game world</h2>

<p>The game world is a bit different. The first, and most obvious, difference is that it has to deal with "the real world", not a made up virtual world, so it has to deal with pixels and keyboards, and most scary of all, people. The diagram makes it seem like this part is very simple, and for the most part it is, but dealing with the difference between the game speed and the simulation speed introduces a bit of gnarly code in the game's updateState method.</p>

<p>It has to deal with the game in terms of "rounds" of ticks, where there currently are 6 game ticks per simulation tick, and for each game tick that is not also a simulation tick, the game has to interpolate between the previous position of a character and the target of the character (as given by the simulation state). It also has to deal with the very last simulation tick specially, where the game is over, so that it finishes the last round of ticks (moves the characters to their final locations), and <em>then</em> stops animating.</p>

<p>Handling the keyboard intelligently is another tricky point, you can't just make the key handling code transmit a movement direction to the simulated cat on every keydown. It has to handle multiple keypresses in an intelligent fashion. The way I solved this was that every time a key is pressed down, it is added to the front of a buffer (a sort of stack, if you will), pushing any other keys currently there backwards. Now, whenever a key is released, that buffer is searched, and that key is removed from the buffer. This means that if the currently active key (the last key pressed) is released, it will mark the previously pressed key active, but if you release an inactive key, no appreciable changes happen. This means that if you're holding down the right key, then press the up key to start moving upwards, that works fine and you can then release the up key to return to moving right, but if you release the right key, nothing happens and you keep moving up, and further releasing the up button returns you to a standstill. This is, I believe, the best way to handle key presses when you're only allowed one movement direction.</p>

<p>Other than these points there is scant little difference in flow from the simulation world. The game is initialized with an instance of the simulation, set up with the right cat and dog AIs, and enters the game loop. Within, the game polls for events, such as keyboard presses, and handles this by sending the information to the simulation world. Then the game runs the logic by running a simulation tick if necessary, and updating the position of every character in the game (interpolating between positions if needed). The game state is then drawn to the screen and the game goes to sleep until the next frame is needed, to make sure we only draw 30 frames per second. Rinse and repeat, easy peasy.</p>

<h2>Conclusion</h2>

<p>This is where I'd usually showcase the game again to show how much it's changed, but the truth is, it looks pretty much exactly the same. It plays a bit differently, due to it now being constrained by the simulation world where everything only moves in four directions and can only change directions five times a second, so it is no longer possible to move diagonally, and your character will not respond "instantly" like it did with the previous version.</p>

<p>And this is as it should be, a refactoring should leave the product the same, mostly, and I'm pretty pleased with the result. Next up is starting on my ADATE specification and the ML translation, and getting into the <em>actual</em> research bits of it. :)</p>
]]>
    </content>
</entry>

<entry>
    <title>Game is feature complete</title>
    <link rel="alternate" type="text/html" href="http://ircubic.net/2011/12/game-is-feature-complete.html" />
    <id>tag:ircubic.net,2011://2.10</id>

    <published>2011-12-16T04:00:54Z</published>
    <updated>2011-12-16T04:32:08Z</updated>

    <summary> This work log post is a day late, because I figured I might as well finish up my coding before posting. My game has now achieved what could be called beta status (feature completeness). It has collision with the...</summary>
    <author>
        <name>Daniel E. Bruce</name>
        <uri>http://ircubic.net/</uri>
    </author>
    
    <category term="deadend" label="dead end" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="python" label="python" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="thesis" label="thesis" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="worklog" label="work log" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://ircubic.net/">
        <![CDATA[<p><a href="http://ircubic.net/Screenshot%20at%202011-12-16%2005%3A03%3A43.png"><img alt="Dead End Win Screen" src="http://ircubic.net/assets_c/2011/12/Screenshot at 2011-12-16 05:03:43-thumb-212x167-7.png" width="212" height="167" class="mt-image-left" style="float: left; margin: 0 20px 20px 0;" /></a> This work log post is a day late, because I figured I might as well finish up my coding before posting. My game has now achieved what could be called beta status (feature completeness). It has collision with the dogs (so you can lose the game), it has a goal (and the ability to WIN the game) and it has a win/lose screen. My master thesis repo has also been put up on <a href="https://github.com/ircubic/Master-Thesis">github</a>, so if you want to take a look at the actual code, it's in the src/testbed/ folder there. :)</p>

<p>Although it is feature complete according to my thesis spec, the game isn't really playable yet. This is because there is no actual AI for the opponents, but the hooks are there to input one when needed. Technically the dogs HAVE an AI, it just does nothing and is overrideable, and this counts as feature complete since evolving the AI is the goal of the thesis. :)</p>

<p>ANYWAY, have another screenshot of the game which shows the immensely awesome win screen in my game. There's still some tweaking left to make it finished, I need to play around with the relative speeds of the cats and dogs, and see if I need to change the sizes of the characters to make it more fair, and other such minor details, but for now it's actually usable. :)</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Beginnings of a game -- Work log, Dec. 8.</title>
    <link rel="alternate" type="text/html" href="http://ircubic.net/2011/12/master-thesis-work-log-8-dec.html" />
    <id>tag:ircubic.net,2011://2.9</id>

    <published>2011-12-08T02:52:19Z</published>
    <updated>2011-12-08T03:15:35Z</updated>

    <summary>This is going to be a short log, as I haven&#8217;t done much related to the thesis that is actually visible, most of it&#8217;s been discussions regarding implementation, and the rest of my time has been spent on other projects....</summary>
    <author>
        <name>Daniel E. Bruce</name>
        <uri>http://ircubic.net/</uri>
    </author>
    
    <category term="deadend" label="dead end" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="python" label="python" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="sml" label="sml" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="thesis" label="thesis" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="worklog" label="work log" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://ircubic.net/">
        <![CDATA[<p>This is going to be a short log, as I haven&#8217;t done much related to the thesis that is actually visible, most of it&#8217;s been discussions regarding implementation, and the rest of my time has been spent on other projects. I have made some progress on the game, though. It&#8217;s a very simple game, but still has enough complexity to serve as a boiled down simulation environment.</p>

<p><a href="http://ircubic.net/assets_c/2011/12/deadend-prototype-2.html" onclick="window.open('http://ircubic.net/assets_c/2011/12/deadend-prototype-2.html','popup','width=642,height=514,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="http://ircubic.net/assets_c/2011/12/deadend-prototype-thumb-212x169-2.png" width="212" height="169" alt="Dead End Prototype" class="mt-image-left" style="float: left; margin: 0 20px 20px 0;" /></a> The game, shown on the left, is named &#8220;Dead End&#8221; and is written in Python. In it, the player controls a cat that needs to reach the exit (which, as I notice now, is not depicted in the picture, but it&#8217;s supposed to be an area in the top of the screen) to win. The opponents are a pack of dogs, which attempt to capture the cat, at which point the game ends. This, of course, is just a prototype intended to demonstrate how the game would work if it were really played, it is not intended to be fully robust or playable, but the aim is to make it &#8220;good enough&#8221; so that one can test it out with some real users at the end as a final dataset.</p>

<p>The game needs to exist both as a playable game and a simulation in the ADATE system, preferrably without having to rewrite any code. This would require a game &#8220;core&#8221; written in Standard ML, which is then called from the python code that handles the graphics and input system for the playable game. This would, ideally, make the game logic completely consistent between game and simulation, as anything related to how the characters move and behave is controlled by the shared Standard ML code. To me, this seems like the best way to go, unless it turns out that the game logic is sufficiently simple that writing the code to interface between python and Standard ML would actually end up being more work than maintaining two copies.</p>

<p>For the next week, my focus is going to be finishing up the game completely in Python, and start work on translating the core to Standard ML for the simulation.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Beginning a work log for my Master&apos;s Thesis</title>
    <link rel="alternate" type="text/html" href="http://ircubic.net/2011/12/beginning-a-work-log-for-my-masters-thesis.html" />
    <id>tag:ircubic.net,2011://2.8</id>

    <published>2011-12-01T18:53:09Z</published>
    <updated>2011-12-01T20:25:51Z</updated>

    <summary>The last half year I&apos;ve been doing working on a Master&apos;s Thesis, mostly preliminary research work, but it never occurred to me to use this as an excuse to start using my blog more actively again. I&apos;ve now decided to...</summary>
    <author>
        <name>Daniel E. Bruce</name>
        <uri>http://ircubic.net/</uri>
    </author>
    
    <category term="adate" label="adate" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ai" label="AI" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="artificialevolution" label="artificial evolution" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="sml" label="sml" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="thesis" label="thesis" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://ircubic.net/">
        <![CDATA[<p>The last half year I've been doing working on a Master's Thesis, mostly preliminary research work, but it never occurred to me to use this as an excuse to start using my blog more actively again. I've now decided to start holding a sort of work log here, as a place to collect my thoughts about the progress of the thesis, maybe get some feedback or discussion and maybe even teach someone something. This might also help structure my work in the same way the "review" structures the GTD process.</p>

<p>This first blog post is <em>not</em> going to be a work log for my project, but rather an introduction to the project (as it is currently formulated, which may change) that I am working on and the tech that is used. I intend to create my work log posts on Wednesdays, to coincide with my GTD review, so the first work log post is going to be next Wednesday.</p>

<h1>Introduction</h1>

<p>The tentative title of my thesis is "Evolving entertaining game adversaries using ADATE" which probably tells you very little. In more descriptive terms the aim of the thesis to use artificial evolution to create the artificial intelligence for a game's opponents, with the aim of creating a more entertaining game. This will be accomplished using a system for doing such artificial evolution named ADATE created by one of my supervisors, <a href="http://www-ia.hiof.no/~rolando/">Dr. J. Roland Olsson</a>.</p>

<p>The hypothesis I'm working from is that variation in game adversaries would create a more entertaining game than if all the adversaries behaved in a similar way, and that using artificial evolution makes it easy to create diverse AI for opponents that fulfill the criteria set for them, in this case entertainment value.</p>

<h1>The game</h1>

<p>At this point you might wonder which game I will be using. Sadly this part is perhaps not as fancy as others, I won't be making new opponent behaviors for a game like Skyrim or anything of that complexity. The game I will be using will be a very simple "predator-prey" game akin to Pacman or other games where the aim is basically to avoid a small amount of enemies that are chasing you and fulfill a goal.</p>

<p>I don't have any more specific details about the game I will be using, but this is the focus of my current work, and will most likely be the topic of next week's work log, where I will cover how to integrate the game into ADATE, and other such fancy things.</p>

<h1>Artificial evolution and ADATE</h1>

<p>Of course, most people will not know what this mysterious ADATE system is or what artificial evolution is all about, so I'm going to take some time to describe. I'm going to treat artificial evolution in the context of the ADATE system, which might gloss over certain parts of the more general description, but these are easily looked up if one is more interested.</p>

<p>First off, ADATE's name is actually a decently good description of what it actually does. The name stands for Automatic Design of Algorithms Through Evolution, which is exactly what it does. More specifically, it uses artificial evolution to automatically create program code in the language SML (more specifically, a subset of this named ADATE-ML), based on some input data and a function which is used to rate the performance of the evolved algorithms.</p>

<h2>General description of artificial evolution</h2>

<p>Artificial evolution is a technique that takes what we know about the process of biological evolution and applies it to programming. In this process, the "species" are pieces of program code, data or any other artificial thing, often termed <em>individuals</em>, and "genes" are usually small pieces of each individual that are considered to be the smallest division, in program code this could be a single instruction, in a picture this could be a pixel, etc.</p>

<p>This population of individuals are run through a "cycle of life" where the individuals are reproduced to create new individuals which are slightly different from their parent(s), through genetic recombination, mutation or other techniques which are inspired by biological reproduction. The new individuals are then ranked according to what is called a <em>fitness function</em>, which is a function that takes the individual and anything else it needs (such as input to the system), and gives it a rating.</p>

<p>After enough reproduction, the population is trimmed to a certain size by removing the worst performing individuals, and the process starts over, and is run over and over until the system is stopped, either because good enough individuals have been created, a time limit has been exceeded, or any other reason, really.</p>

<h2>How ADATE works</h2>

<p>ADATE takes this process and specializes it. As mentioned before, the individuals are pieces of SML code, and the genes are individual instructions of this code. In ADATE new individuals are created only through a form of mutation, there is no genetic recombination. The mutation process works as such: the parent individual has one or more alterations applied to it, picked from a predefined set of possible alterations. (things such as changing one variable/value to another random one, adding a new function call, adding an if-else, and so on)</p>

<p>ADATE starts this process from a specification which defines a set of input values, a fitness function that rates the performance of individuals over the input values, a function that serves as the starting point for creating the individuals (often just an empty function for maximum randomness), and various pieces of support code that the individuals and fitness function might need.</p>

<p>Other than all of this, ADATE's cycle of is very similar, it uses some more specialized ways of managing its population, and decides when to stop creating new individuals based on the time expired and how "complex" the individuals were, but these are all minor details which aren't worth going into here.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Conditional search and replace with regexps in python</title>
    <link rel="alternate" type="text/html" href="http://ircubic.net/2011/07/conditional-search-and-replace-with-regexps-in-python.html" />
    <id>tag:ircubic.net,2011://2.7</id>

    <published>2011-07-17T17:20:13Z</published>
    <updated>2011-07-17T19:33:06Z</updated>

    <summary>Sometimes you have a text manipulation job ahead of you that&apos;s a bit too complex to just handle with a single sed command, but too much work to do by hand. Recently I had to deal with this at my...</summary>
    <author>
        <name>Daniel E. Bruce</name>
        <uri>http://ircubic.net/</uri>
    </author>
    
    <category term="git" label="git" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="hack" label="hack" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="python" label="python" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="regexp" label="regexp" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="snippet" label="snippet" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://ircubic.net/">
        <![CDATA[<p>Sometimes you have a text manipulation job ahead of you that's a bit too complex to just handle with a single <code>sed</code> command, but too much work to do by hand. Recently I had to deal with this at my intern position, when I had to update from an old set of deprecated API to a new one, across a decently sized code base (~900 changes).</p>

<p>The APIs I had to update were in ruby code, and they looked as follows:</p>

<pre class="brush: ruby" title="The old API">b.key "a"
b.key "Enter"
b.key_up "Ctrl"
b.key_down "Ctrl"
</pre>

<pre class="brush: ruby" title="The new API">b.keys.send "a"
b.keys.send :Enter
b.keys.up :Ctrl
b.keys.down :Ctrl
</pre>

<p>So not only do you need to change three different function calls, but you also need to change any special keys to Ruby symbols, and this doesn't even take into account that Ruby supports two different ways of calling functions (both with and without parentheses), and the code base used both, with varying spacing. In the end you should be left with more consistent code, that doesn't throw a gazillion deprecation warning. :)</p>

<p>What is an intern to do? You hatch a master plan, of course! One including a single regexp matching all the cases, and use python's ability to replace with the result from a function call to make everything magically happening. So, without further ado, here's my code:</p>

<pre class="brush: python" title="The master plan!">import os
import os.path
import re
import sys
import tempfile

tmp = tempfile.NamedTemporaryFile(delete=False)
f = open(sys.argv[1])
print tmp.name, os.path.abspath(f.name)
called = False

def key_upgrade(key):
    if len(key) == 1:
        return '"%s"' % key
    else:
        return ':%s' % key.capitalize()

def replacement(match):
    global called
    called = True
    func = match.group(1)
    if func:
        func = func[1:]
    else:
        func = 'send'

    key = key_upgrade(match.group(2))

    trail = ''
    if match.group(3):
        trail = match.group(3).replace(')', '')

    return '.keys.%s %s%s' % (func, key, trail)

for line in f:
    tmp.write(re.sub(r'\.key(_down|_up|)[ (]\s*["\'](.+?)["\'](\s*[ )]?\s*[}#]?)?',
                    replacement, line, 0))

tmp.close()
f.close();

#Minor security thing
if called:
    os.rename(tmp.name, os.path.abspath(f.name))
else:
    os.unlink(tmp.name)
</pre>

<p>As you can see, it uses a simple (probably too simple for "real" code, so be warned) file handling routine that creates a new temporary file, rips through the code file line by line, running the regexp against it, and writing the result to the temporary file.</p>

<p>The regexp substitution calls the function <code>replacement</code> whenever it matches, sending in a match object containing either two or three groups (depending on if the last group of the regexp matches). This is then used to do the necessary manipulation on the key names, generate the right function call, and do some munging on the trailing parts of the call.</p>

<p>The last group (<code>(\s*[ )]?\s*[}#]?)?</code>) is probably the most bewildering. It's used to filter out closing parentheses in calls that use them, even if they are followed by a comment or a brace, in a way that retains spacing. Purely aesthetic, but it leaves things looking neat and consistent, which was a design goal.</p>

<p>When all the lines have been processed, it does some magic to put the new and improved file into place. It'll check if any replacements have been done. If none, just delete the temporary file, otherwise you rename the temporary file to the same name as the old one to replace it, this should avoid a few of the problems inherent in doing this sort of thing, and be reasonably fast, without thrashing the old file if anyone is trying to run it while we're working.</p>

<p>After running this, I was left with a pretty massive diff, which I actually went through and controlled every single change in to make absolutely sure my quickly hacked up code didn't break anything. This was made pretty easy by the use of git's interactive commit functionality (<code>git commit --interactive</code>), which may just be one of my favourite git features.</p>

<p>In summary, it was a very effective way to make my work more fun, and probably more efficient. Of course, since it's a quick hack, there are flaws in the code (it doesn't handle multiline calls, for example), but as noted it worked perfectly fine on the codebase I had, and I made sure to control the result (<em>!!!</em>), so everything went better than expected. :D</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Installing Windows 7 on the Eee PC 1000H - The Epic Struggle</title>
    <link rel="alternate" type="text/html" href="http://ircubic.net/2009/12/installing-windows-7-on-the-eee-pc-1000h---the-epic-struggle.html" />
    <id>tag:ircubic.net,2009://2.5</id>

    <published>2009-12-15T20:51:30Z</published>
    <updated>2010-02-10T00:49:11Z</updated>

    <summary>So I finally decided to convert my Eee 1000H from XP to Win7, which looked like a seemingly easy task now that it even has Win7 compatible drivers. Oh, how mistaken I was. Installing went fairly easy (except for errors...</summary>
    <author>
        <name>Daniel E. Bruce</name>
        <uri>http://ircubic.net/</uri>
    </author>
    
    <category term="eee" label="eee" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="fubar" label="fubar" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="win7" label="win7" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://ircubic.net/">
        <![CDATA[<p>So I finally decided to convert my Eee 1000H from XP to Win7, which looked like a seemingly easy task now that it even has Win7 compatible drivers. Oh, how mistaken I was.</p>

<p>Installing went fairly easy (except for errors completely of my own, but those are outside the scope of this post). I mounted the ISO I got from MSDNAA (yes, it's legit), went through the installer, five reboots later and I was in a shiny new Win7 world, complete with sound and partial hotkey functionality.</p>

<p>Then I went to get my fancy new drivers, to get all the functionality working. I started with the my usual driver install order: chipset, VGA, ACPI (called hotkeys on the Asus page), reboot. This is when the problems started. Up flashed a few dialog boxes on bootup, "Can't get WMI AsusManagement object" among others. A little googling later and I find out this means the ACPI driver doesn't recognize the BIOS, and I remember that I saw a BIOS update that said "supports Windows 7", so I thought "Oh, just have to update the BIOS."</p>

<p>Asus has a tool called Asus Update, that allows you to update the BIOS from Windows, so I went to install that, only to find that it didn't recognize my machine as an Eee PC, because the ACPI driver wasn't installed (or, in this case, not working properly). Uh, wait a minute, so you're telling me <strong>I can't update my BIOS because the ACPI isn't working, but the ACPI won't work before I update my BIOS</strong>? Oh dear...</p>

<p>Usually at this point you find a boot floppy and use a DOS-based BIOS updater, and indeed Asus has one called AfuDOS, but as you well know the Eee has no floppy, and Windows refuses to make an USB Pen an MS-DOS boot disk.</p>

<p>The rescue comes in the form of a very poorly documented feature of the Eee PC BIOS. If you press Alt+F2 at the grey screen when booting, it will go into a mode called EZ-Flash, and look for a BIOS ROM file from an USB device, named after your model ("1000H.ROM" in my case)!</p>

<p>Now, it is <strong>VERY important</strong> that you format the USB device as FAT16, otherwise it will not work. It will detect the file, but freeze while trying to read it. I have also seen the recommendation that the BIOS file be the only file on the device, but I don't think that should matter too much. However, as you most likely will have to reformat it to make it FAT16 anyway, that is most likely going to be the case.</p>

<p>So, to summarize, if you're getting the "Can't get WMI AsusManagement object" error, do the following:<br />
<ul><li>Download the newest BIOS update, rename it "1000H.ROM" (or whatever model your Eee is)</li><li>Find an USB Device, format it to FAT16 (if it isn't already), and copy the BIOS file to the device</li><li>Reboot your machine with the device plugged in, and hold Alt+F2 on bootup.</li><li>If all went well, it should beep a little, and show some messages indicating it's installing the new BIOS, and when you're done, it should tell you to power down. Do so, and when you start back up into Win7, the error should be gone!</li></ul></p>

<p>And if you're just planning on installing Win7 over XP, but haven't done so yet, <strong>update the BIOS before you start the install</strong>! You'll save yourself a load of trouble, and be able to install drivers with no problems.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Robots, Image Recognition and Path-finding, oh my!</title>
    <link rel="alternate" type="text/html" href="http://ircubic.net/2009/11/robots-image-recognition-and-path-finding-oh-my.html" />
    <id>tag:ircubic.net,2009://2.4</id>

    <published>2009-11-30T17:34:02Z</published>
    <updated>2010-02-10T00:49:11Z</updated>

    <summary>The last few months, I&apos;ve been doing a school project together with two other students in the course &quot;Image processing and pattern recognition,&quot; which had as its goal to control a small micro robot through an obstacle course using nothing...</summary>
    <author>
        <name>Daniel E. Bruce</name>
        <uri>http://ircubic.net/</uri>
    </author>
    
    <category term="a" label="A*" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="imagerecognition" label="image recognition" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="pathfinding" label="path finding" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="robot" label="robot" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://ircubic.net/">
        <![CDATA[<p>The last few months, I've been doing a school project together with two other students in the course "Image processing and pattern recognition," which had as its goal to control a small micro robot through an obstacle course using nothing but the images taken by a camera in the roof.</p>

<p>The project was done entirely in MATLAB, with some code supplied by the school to control the robot, and some proof-of-concept code written by me in Python. Now, the project is over, and I thought I'd go through the solution we came up with here.</p>

<p><strong>Detecting the robots and obstacles</strong><br />
To find the robot and the obstacles on the field, we decided to use a "base" image of the field when it's empty as a way to discern what's supposed to be there and what isn't. We then take a picture of the field with the robot in the starting position, move the robot forward a little bit, then take another picture.</p>

<p>These two pictures are then subtracted from the base picture and converted to binary images where every pixel value above 2 becomes white, and the rest becomes black. Then we apply a filtering algorithm (morphological opening-then-closing for the ones in the know) that removes whatever noise particles is left and connects certain disconnected pieces of the obstacles. Now we have sufficient grounds to discern what is an obstacle and what is the robot, as well as which direction the robot is facing.</p>

<p><img alt="filter-bw.png" src="http://ircubic.net/2009/11/30/filter-bw.png" width="500" height="359" class="mt-image-center" style="" /><br />
Binary image</p>

<p><img alt="filter-morph.png" src="http://ircubic.net/2009/11/30/filter-morph.png" width="500" height="359" class="mt-image-center" style="" /><br />
Morphologically filtered image</p>

<p>To find the obstacles, we just look at which pixels in the pictures stay the same (a simple AND operation between the two images), and the object that has moved is then the robot. To find the angle and position of the robot, all you need to do is see how far the moving objects' centers have moved.</p>

<p><strong>Path-finding</strong><br />
Now, the remaining part of the task to be done before we can even start moving the robot towards the goal is to figure out which way it should go, so as to reach the goal AND avoid the obstacles. To do this, we decided to lean on the juggernaut of path-finding known as <a href="http://en.wikipedia.org/wiki/A*">A*</a>, favourite of game devs.</p>

<p>Before we could apply this, though, we have to convert the field image to a more game-like "tile-set". So we basically go over the image with only the obstacles, split it into tiles of a given size, and check how many white pixels each tile contains. If it crosses a threshold (we got it down so nicely we could use a threshold of 1 pixel), then it is marked as uncrossable (a "wall") in the resulting tile matrix, otherwise it's walkable.</p>

<p><img alt="tiles.png" src="http://ircubic.net/2009/11/30/tiles.png" class="mt-image-center" style="" /><br />
Resulting tile matrix</p>

<p>We then run the A* algorithm over the image, with the current robot position, and the goal position, to get the goal path as a set of nodes per tile to cross. As this isn't exactly the best path to follow (way too many stops and turns), we then apply a further algorithm to smooth the path</p>

<p><strong>Path-smoothing</strong><br />
To do this, we chose to use a method we call "ray-casting" to weed out unnecessary path nodes. Imagine we have a path as detailed in this picture, with the start and end nodes marked as "valid" (green):<br />
<img alt="path.png" src="http://ircubic.net/2009/11/30/path.png" width="300" height="300" class="mt-image-center" style="" /></p>

<p>We start with the first node, draw a line (ray) to the next node in the path, then draw two more lines parallel to that at a distance representing the robot's width, as so:<br />
<img alt="raycasting1.png" src="http://ircubic.net/2009/11/30/raycasting1.png" width="300" height="300" class="mt-image-center" style="" /></p>

<p>We keep doing this for every node of the path, until any of these lines collide. When this happens we know that this node cannot be reached directly from the node we're checking for, and as such we need to mark the <strong>previous</strong> node as valid.<br />
<img alt="raycasting3.png" src="http://ircubic.net/2009/11/30/raycasting3.png" width="300" height="300" class="mt-image-center" style="" /></p>

<p>After we have done this for all the nodes, and reached the end node, we are left with a path that has significantly less nodes, as well as more direct paths where there was a stepladder effect previously.<br />
<img alt="finished_path.png" src="http://ircubic.net/2009/11/30/finished_path.png" width="300" height="300" class="mt-image-center" style="" /></p>

<p><strong>The last mile</strong><br />
Now, finally, we can move the robot through the path we have created. This is done by sending commands to the robot to rotate, and move a certain distance towards the next node in the path. As the robot isn't entirely precise, we decided to not let it move too far per movement command, so it wouldn't veer off course too much, and would be given a chance to "compensate" as it moves towards the goal.</p>

<p>The movement is tracked by taking a new picture with the camera, and doing the same filtering operations as before to find the new robot position and angle, so that we can guide it closer to the node as it approaches. If all goes as planned, it should eventually reach the goal position, without colliding into any of the obstacles!</p>]]>
        
    </content>
</entry>

<entry>
    <title>How to (re)enable Django&apos;s admin docs</title>
    <link rel="alternate" type="text/html" href="http://ircubic.net/2009/11/how-to-reenable-djangos-admin-docs.html" />
    <id>tag:ircubic.net,2009://2.3</id>

    <published>2009-11-27T17:43:13Z</published>
    <updated>2010-02-10T00:49:10Z</updated>

    <summary>If you&apos;ve used Django before, you may have remembered that Django&apos;s admin pages had a Documentation link in the top right corner. This lead to a site which provided documentation for all Models, Views, Tags and Filters that exist in...</summary>
    <author>
        <name>Daniel E. Bruce</name>
        <uri>http://ircubic.net/</uri>
    </author>
    
    <category term="django" label="django" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="tips" label="tips" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://ircubic.net/">
        <![CDATA[If you've used Django before, you may have remembered that Django's admin pages had a Documentation link in the top right corner. This lead to a site which provided documentation for all Models, Views, Tags and Filters that exist in your project, which is immensely useful for devs and designers alike.<br /><br />In the newer versions of Django this has seemingly disappeared, and the official documentation makes very little mention of it, as it has been split into its own (as of yet undocumented) app. So, you have to enable it yourself by adding the admindocs app and setting up an url pattern for it.<br /><br />So, to accomplish this, first open up your settings.py and add <code>'django.contrib.admindocs'</code> to your <code>INSTALLED_APPS</code>, set a SITE_ID if you haven't done so already, then do the following with your urls.py:<br /><br /><pre class="brush: python">urlpatterns = patterns(
    '',
    (r'^admin/doc/', include('django.contrib.admindocs.urls')),
    (r'^admin/(.*)', admin.site.root), # Standard admin url pattern
    # Other URL patterns go here
)</pre>Note that the admindocs pattern has to go before the standard admin pattern, because Django gives you the first view from the top that matches, and the admin pattern is very hungry. :)<br /><br />Now when you go into the admin section, you should have a shiny new Documentation link that leads to Django's automatic documentation for your project. Enjoy!<br />]]>
        
    </content>
</entry>

<entry>
    <title>Portable Django project with Buildout</title>
    <link rel="alternate" type="text/html" href="http://ircubic.net/2009/11/portable-django-project-with-buildout.html" />
    <id>tag:ircubic.net,2009://2.2</id>

    <published>2009-11-18T19:53:49Z</published>
    <updated>2010-02-10T00:49:10Z</updated>

    <summary>The last few days I&apos;ve been working on a project using Django, and to set up my Django projects, I find the best solution is using Buildout. I think messing around with virtual environments is annoying, makes it harder to...</summary>
    <author>
        <name>Daniel E. Bruce</name>
        <uri>http://ircubic.net/</uri>
    </author>
    
    <category term="buildout" label="buildout" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="django" label="django" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="python" label="python" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://ircubic.net/">
        <![CDATA[The last few days I've been working on a project using <a href="http://www.djangoproject.com/">Django</a>, and to set up my Django projects, I find the best solution is using <a href="http://www.buildout.org/">Buildout</a>. I think messing around with virtual environments is annoying, makes it harder to deploy the project later, and frankly just wastes my time more than it saves it. (It also happens to be the way I learned to do it while working at Opera, but that's besides the point ;) )<br /><br /><font style="font-size: 1.25em;"><b>The basics</b></font><br /><br />Getting started with Django and Buildout essentially requires two files, the Zope bootstrap.py (available <a href="http://svn.zope.org/*checkout*/zc.buildout/trunk/bootstrap/bootstrap.py">here</a>) and a buildout.cfg for configuring your environment.<br /><br />A basic buildout.cfg file, utilizing <a href="http://pypi.python.org/pypi/djangorecipe">Djangorecipe</a> to install Django, would look something like this:<br /><br />
<pre class="brush: plain">[buildout]
parts = django

[django]
recipe = djangorecipe
version = 1.1.1
eggs =
	mock
	django-notification
	django-messages
project = my-django-project</pre>This is the configuration for a simple Django project called "my-django-project", which depends on the mock, django-notification and django-messages modules. To build and set up this, you simply enter the following commands:<br /><br />
<pre>python bootstrap.py
python bin/buildout</pre>
This first runs the bootstrap file, which fetches the necessary modules for running buildout and gives you a buildout binary in the bin/ folder. Then you run the buildout command, which parses the buildout.cfg file, automatically fetching the necessary dependencies, the given Django version (in this case 1.1.1, but you could set it to "trunk" to get the newest development version), and create a version of the Django manager script at bin/django.<br /><br />This script does exactly what the manage.py script does in a regular django setup, to sync the db you run <code>bin/django syncdb</code>, to start the server you type <code>bin/django runserver</code>, and so on and so forth.<br /><br />If this is the first time you run the buildout, djangorecipe will also check for the presence of a directory called "my-django-project", and if that doesn't exist, it will create a skeleton Django project with that name, which serves as a great starting point.<br /><br />All of this <b>greatly</b> simplifies the amount of work needed to start a new django project, you just mock up a tiny buildout config and run buildout, and you have what you need to start easily set up for you.<br /><br /><b><font style="font-size: 1.25em;">Taking it further</font><br /></b><br />Now, for me, this still isn't simple enough. It requires the presence of the bootstrap.py file (which isn't strictly a part of the project, and IMO shouldn't be in source control), and two commands. So I made myself a little Makefile to automate the task of running buildout, and it looks a little something like this:<br /><br />
<pre class="brush: plain">.DEFAULT_GOAL = development
.PHONY = development clean

bootstrap.py :
	wget http://svn.zope.org/*checkout*/zc.buildout/trunk/bootstrap/bootstrap.py

bin/buildout : bootstrap.py
	python bootstrap.py

development : bin/buildout
	python bin/buildout

clean :
	rm -rf bin develop-eggs eggs parts .installed.cfg downloads bootstrap.py</pre>
This allows me to simply type in "make" in the directory with the buildout config, and everything will be done automatically, and subsequently type "make clean" if I need to clean out the environment again.<br /><br />Together with this, I've added a .gitignore file (since I use Git for most of my source control needs), that filters out all the buildout cruft, as well as .pyc files and the SQLite db, if you're using one:<br /><br />
<pre class="brush: plain">*.egg-info
*.egg
*.pyc
*.db
.installed.cfg
bin/
develop-eggs/
downloads/
eggs/
parts/</pre>
These two relatively minor additions allow me to more or less forget about everything that has to do with python virtual environments or even that you need to do special things to make it work. Updating the environment is just a simple "make" away, and the resultant environment stays out of my way in git.<br />]]>
        
    </content>
</entry>

<entry>
    <title>Rebirth of the blog + RenrakuOS</title>
    <link rel="alternate" type="text/html" href="http://ircubic.net/2009/08/rebirth-of-the-blog-renrakuos.html" />
    <id>tag:ircubic.net,2009://2.1</id>

    <published>2009-08-24T20:52:01Z</published>
    <updated>2010-02-10T00:49:10Z</updated>

    <summary>Yeah, my VPS got nuked due to the VAServ hack. I didn&apos;t really care too much, I didn&apos;t have much of importance on the server, so I&apos;m just going to restart my blog. Trying with Movable Type this time, as...</summary>
    <author>
        <name>Daniel E. Bruce</name>
        <uri>http://ircubic.net/</uri>
    </author>
    
    <category term="boo" label="boo" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="osdev" label="osdev" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="renraku" label="renraku" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://ircubic.net/">
        <![CDATA[Yeah, my VPS got nuked due to the VAServ hack. I didn't really care too much, I didn't have much of importance on the server, so I'm just going to restart my blog. Trying with Movable Type this time, as Wordpress gave me a real headache with its hugeness, maybe I'll actually like this one. =p<br /><br />Lately I have been mostly involved in developing RenrakuOS, which is an experimental managed OS programmed entirely in .NET (using the python-like language <a href="http://boo.codehaus.org/">Boo</a>, to be exact). There are a few relevant places to check for RenrakuOS info:<br /><ul><li>My github fork of the project, for code: <a href="http://github.com/ircubic/RenrakuOS">http://github.com/ircubic/RenrakuOS</a></li><li>The github repos of the owner (daeken): <a href="http://github.com/daeken/RenrakuOS">http://github.com/daeken/RenrakuOS</a></li><li>Daeken's blog, which has posts on Renraku: <a href="http://daeken.com">http://daeken.com/</a> and in particular the initial post: <a href="http://daeken.com/renraku-future-os">http://daeken.com/renraku-future-os</a></li></ul>At the current I'm the designated maintainer for Apps and BCL code, as well as the de facto owner of the input subsystem (I make the keyboard actually work). <br /><br />In addition, my priority for the foreseeable future is to create an initial set of docs describing the design of the OS, as well as what makes it special and different from contemporary OSes. This will be released as a set of blog posts.<br />]]>
        
    </content>
</entry>

</feed>

