<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en"><title type="text">The Stoneship Journal</title><link rel="alternate" type="text/html" href="http://stoneship.org" /><author><name>Denis Defreyne</name><uri>http://stoneship.org/</uri></author><updated>2009-10-14T13:00:00+00:00</updated><id>http://stoneship.org/</id><link rel="self" href="http://feeds.feedburner.com/stoneship_blog" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry><title type="html">How nanoc's Rules DSL Works</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/stoneship_blog/~3/bjAUuDUBxVM/" /><updated>2009-10-14T07:19:11-07:00</updated><id>tag:stoneship.org,2009-10-14:/journal/2009/how-nanocs-rules-dsl-works/</id><summary type="html">nanoc has recently gained an entirely new way of specifying how pages should be processed. Instead of describing processing instructions in YAML, they are now described using pure Ruby. This blog article explains how these rules are implemented so that you can use the same idea in your projects.</summary><content type="html">&lt;p&gt;nanoc has recently gained an entirely new way of specifying how pages should be processed. Instead of describing processing instructions in YAML, they are now described using pure Ruby, like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;compile '/articles/*/' do
  filter :erb
  filter :markdown

  layout 'article'

  filter :rubypants
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These rules are located in a file called &lt;em&gt;Rules&lt;/em&gt;, which is loaded by nanoc on startup. This blog article explains how these rules are implemented so that you can use the same idea in your projects.&lt;/p&gt;

&lt;p&gt;There are two slightly different ways of implementing such a DSL, and I'll describe them both in this post. The first iteration of nanoc used a DSL based on method #1, but in the second iteration I switched to the cleaner, prettier method #2.&lt;/p&gt;

&lt;p&gt;For demonstration purposes, this blog post will not use nanoc's domain-specific language, but instead use a much more minimal language that uses a &lt;code&gt;#process&lt;/code&gt; method to define rules. The Rules file in the example will look like this:

&lt;pre&gt;&lt;code&gt;process /oo/ do
  puts "I am rule /oo/ and I am processing #{item.inspect}!"
end&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Method #1&lt;/h2&gt;

&lt;p&gt;This method uses a DSL that looks slightly different: it has an explicit &lt;code&gt;item&lt;/code&gt; parameter, and all methods are called explicitly on this item. A Rules file written using method #1 looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;process /oo/ do |item|
  puts "I am rule /oo/ and I am processing #{item.inspect}!"
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;#process&lt;/code&gt; function creates a &lt;em&gt;rule&lt;/em&gt; (I'll show you how in a bit) which can be applied to an item. The first function argument is a pattern that specifies which items this rule can be applied to. When nanoc loads the Rules file, it creates a &lt;code&gt;Rule&lt;/code&gt; instance containing this pattern as well as a block containing the actual code. Something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Rule

  def initialize(pattern, block)
    @pattern = pattern
    @block   = block
  end

  def applicable_to?(item)
    item.identifier =~ @pattern
  end

  def apply_to(item)
    @block.call(item)
  end

end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;#applicable_to?&lt;/code&gt; method is used for determining whether the rule is able to process a given item, and the &lt;code&gt;#apply_to&lt;/code&gt; method performs the actual processing by calling the block and giving the item as a parameter.&lt;/p&gt;

&lt;p&gt;The Item class is, in this case, rather simple: it only contains an &lt;code&gt;identifier&lt;/code&gt; attribute. It is implemented like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Item

  attr_reader :identifier

  def initialize(identifier)
    @identifier = identifier
  end

end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here's how the rules file is loaded and parsed:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class App

  def initialize
    @rules = []
  end

  def load_rules
    rules_content = File.read('Rules')
    dsl = DSL.new(@rules)
    dsl.instance_eval(rules_content)
  end

end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;#instance_eval&lt;/code&gt; method takes a block or a string and evaluates it in the content of the object on which the method is called. The last line of the code example above evaluates the string, which contains the content of the rules file, in the context of a &lt;code&gt;DSL&lt;/code&gt; instance.&lt;/p&gt;

&lt;p&gt;The idea is to have the &lt;code&gt;#process&lt;/code&gt; method implemented in this &lt;code&gt;DSL&lt;/code&gt; instance. This method then generates a &lt;code&gt;Rule&lt;/code&gt; instance using the pattern and the block given to the &lt;code&gt;#process&lt;/code&gt; call, like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class DSL

  def initialize(rules)
    @rules = rules
  end

  def process(pattern, &amp;amp;block)
    @rules &amp;lt;&amp;lt; Rule.new(pattern, block)
  end

end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;rules&lt;/code&gt; array contains all rules. To actually use these rules, i.e. find a rule for an item and apply it, you'd use something like this (no error checking implemented):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class App

  def process(item)
    rule = rules.find { |r| r.applicable_to?(item) }
    rule.apply_to(item)
  end

end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that's how the DSL is implemented using method #1.&lt;/p&gt;

&lt;h2&gt;Method #2&lt;/h2&gt;

&lt;p&gt;The second method gets rid of the extra block parameter to the &lt;code&gt;#process&lt;/code&gt; call. Using method #2, the Rules file looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;process /oo/ do
  puts "I am rule /oo/ and I am processing #{item.inspect}!"
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To get rid of the extra &lt;code&gt;item&lt;/code&gt; parameter, the block will have to be evaluated in the context of an object that provides access to the item in a different way. One way of doing this is to provide an &lt;code&gt;@item&lt;/code&gt; variable in a &lt;code&gt;RuleContext&lt;/code&gt; object, which looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class RuleContext

  def initialize(item)
    @item = item
  end

end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Applying a rule to an item no longer involves calling the block and giving the item as a parameter. Instead, a &lt;code&gt;RuleContext&lt;/code&gt; is created with a given item, and then the block is evaluated in the context of this rule context, like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Rule

  def apply_to(item)
    rule_context = RuleContext.new(item)
    rule_context.instance_eval(&amp;amp;@block)
  end

end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Accessing the item is now done using &lt;code&gt;@item&lt;/code&gt;. If you want to be able to use &lt;code&gt;item&lt;/code&gt; without that &lt;code&gt;@&lt;/code&gt; sigil, define an accessor:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class RuleContext

  attr_reader :item

end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that's how method #2 works.&lt;/p&gt;

&lt;p&gt;You can get the source of the example implementation &lt;a href="http://stoneship.org/pub/software/how-nanocs-rules-dsl-works.tar.bz2"&gt;over here&lt;/a&gt;. It contains two directories; one for each method. Each directory contains a dsl.rb file which contains the library code, a test.rb file which can be executed, and of course a Rules file which contains the rules.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/stoneship_blog/~4/bjAUuDUBxVM" height="1" width="1"/&gt;</content><feedburner:origLink>http://stoneship.org/journal/2009/how-nanocs-rules-dsl-works/</feedburner:origLink></entry><entry><title type="html">Comments on Comments on Zeldman's XHTML WTF</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/stoneship_blog/~3/ED32tVmW08U/" /><updated>2009-10-14T03:27:50-07:00</updated><id>tag:stoneship.org,2009-07-03:/journal/2009/comments-on-comments-on-zeldmans-xhtml-wtf/</id><summary type="html">In which I comment on a number of interesting, accurate and highly useful comments on Jeffrey Zeldman's XHTML WTF article.</summary><content type="html">&lt;p&gt;Here are a few interesting comments on &lt;a href="http://www.zeldman.com/2009/07/02/xhtml-wtf/"&gt;Jeffrey Zeldman's XHTML WTF article&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I don’t understand why this is happening. Didn’t XHTML fix all the inconsistencies in HTML? HTML5 seems to bring back a lot of those inconsistencies from what I’ve seen so far. WTF indeed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because XHTML 1.0 is so much more consistent than HTML 4.01! &lt;a href="http://www.zeldman.com/2009/07/02/xhtml-wtf/#comment-43868"&gt;#&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;So what happens now? Leave tags open? Validate code to what standard? Sigh, Googling HTML 5 resources..&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because HTML 5 is not, and never will be, a standard! &lt;a href="http://www.zeldman.com/2009/07/02/xhtml-wtf/#comment-43875"&gt;#&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;There’s a long time to debate this, IE6 doesn’t support HTML5. IE8/FF/Safari have partial support. So we’re back to that again. We can’t actually use HTML 5 yet because we want to provide a good experience accross the range of browsers our visitors have. XHTML will remain the best way to do this for many years to come.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because Internet Explorer totally supports XHTML! &lt;a href="http://www.zeldman.com/2009/07/02/xhtml-wtf/#comment-43953"&gt;#&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I just scratched the surface with my xhtml reading and im in love with it. HTML 5… not so much. Haven’t we been working to move away from pages filled with crap defining colors and towards pages containing useful info and tags to define who is what? This is moving backwards. Its a bad move.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because in HTML 5 you &lt;em&gt;have&lt;/em&gt; to use &lt;code&gt;&amp;lt;FONT&amp;gt;&lt;/code&gt; for colors and &lt;code&gt;&amp;lt;TABLE&amp;gt;&lt;/code&gt; for layout! &lt;a href="http://www.zeldman.com/2009/07/02/xhtml-wtf/#comment-43896"&gt;#&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Also, for the sake of chronicle, whenever I tried to parse XHTML as XML through ruby I failed miserably, falling back to hpricot, which treats everything as HTML, and works very well, so maybe some looseness isn’t that bad.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because parsing XHTML as HTML is the way to go! &lt;a href="http://www.zeldman.com/2009/07/02/xhtml-wtf/#comment-43952"&gt;#&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And so on, and so on, and so on. Browse through &lt;a href="http://www.zeldman.com/2009/07/02/xhtml-wtf/#comments"&gt;the comments&lt;/a&gt; and see for yourself. I seriously had no idea that the number of ignorant web developers is so huge. People need to be educated, &lt;em&gt;fast&lt;/em&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/stoneship_blog/~4/ED32tVmW08U" height="1" width="1"/&gt;</content><feedburner:origLink>http://stoneship.org/journal/2009/comments-on-comments-on-zeldmans-xhtml-wtf/</feedburner:origLink></entry><entry><title type="html">Game Review: Braid&amp;nbsp;(2008)</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/stoneship_blog/~3/5muQkxv9bBY/" /><updated>2009-10-14T03:27:50-07:00</updated><id>tag:stoneship.org,2009-06-02:/journal/2009/game-review-braid/</id><summary type="html">Braid is a stunningly pretty puzzle platformer with a serious twist. Anyone who enjoys puzzle games should definitely play this game.</summary><content type="html">&lt;div class="hreview"&gt;
	&lt;div class="item description"&gt;
		&lt;p&gt;&lt;i&gt;&lt;a href="http://braid-game.com/"&gt;Braid&lt;/a&gt;&lt;/i&gt; is a stunningly pretty platform game with a serious twist.&lt;/p&gt;

		&lt;p&gt;Scratch that&amp;mdash;Braid &lt;em&gt;looks like&lt;/em&gt; a platform game, but it's not. Sure, the references to &lt;i&gt;Super Mario Bros.&lt;/i&gt; and &lt;i&gt;Donkey Kong&lt;/i&gt; are immediately apparent, but Braid is a whole different genre. Describing it as a puzzle game would be much more appropriate.&lt;/p&gt;

		&lt;p&gt;Tim, the protagonist in Braid, has the power to rewind time. Therefore, if Tim falls into a pit filled with spikes and dies, he can simply rewind time and avoid permanent death. Nothing too special&amp;hellip; until he stumbles on items and enemies that are immune to rewinding time. And that's just the beginning&amp;hellip;&lt;/p&gt;

		&lt;div class="banner banner-wide"&gt;&lt;img src="http://stoneship.org/assets/images/journal/game-review-braid/1.jpg" alt="Braid"&gt;&lt;/div&gt;

		&lt;p&gt;Every puzzle in Braid is unique. Sometimes it'll take hours to find the solution&amp;mdash;but the game never gets frustratingly hard. All puzzles, no matter how clever, still make sense and in the end you always get this warm feeling of accomplishment. Even if you can't solve a puzzle, you can always skip it and come back later.&lt;/p&gt;

		&lt;p&gt;Braid is not just good for its puzzles, though. The artwork is amazingly pretty&amp;mdash;I don't know of any games with such high-quality 2D graphics. This, along with its haunting soundtrack, makes Braid into one of the highest-quality indie games out there.&lt;/p&gt;

		&lt;p&gt;The storyline doesn't disappoint either. A casual gamer likely won't pay much attention and see it as a simple "boy rescues princess"-story, but there's more to it. Throughout the game, Tim finds various books which each give fragments of a story that is much deeper than it would appear at first sight.&lt;/p&gt;

		&lt;div class="banner banner-wide"&gt;&lt;img src="http://stoneship.org/assets/images/journal/game-review-braid/2.jpg" alt="Braid"&gt;&lt;/div&gt;

		&lt;p&gt;In short, Braid is a game that excels in every aspect. While not everyone will enjoy it as much as I did, anyone who enjoys puzzle games should definitely &lt;a href="http://braid-game.com/"&gt;grab a copy&lt;/a&gt; and play.&lt;/p&gt;

		&lt;p&gt;&lt;strong&gt;Rating&lt;/strong&gt;: &lt;abbr class="rating" title="5"&gt;&amp;#9733;&amp;#9733;&amp;#9733;&amp;#9733;&amp;#9733;&lt;/abbr&gt;&lt;/p&gt;
	&lt;/div&gt;
&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/stoneship_blog/~4/5muQkxv9bBY" height="1" width="1"/&gt;</content><feedburner:origLink>http://stoneship.org/journal/2009/game-review-braid/</feedburner:origLink></entry><entry><title type="html">adsf</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/stoneship_blog/~3/wYe5jZBXm5M/" /><updated>2009-10-14T03:27:50-07:00</updated><id>tag:stoneship.org,2009-05-29:/journal/2009/adsf/</id><summary type="html">I've grown terribly tired of using heel. So I've written a replacement called adsf that works mostly like heel but isn't as annoying to use.</summary><content type="html">&lt;p&gt;I've grown terribly tired of using &lt;a href="http://copiousfreetime.rubyforge.org/heel/"&gt;heel&lt;/a&gt;; it has grown bloated and now it's impossible to run it due to incompatibilities with recent libraries…&lt;/p&gt;

&lt;p&gt;So I've written a replacement called &lt;a href="/software/adsf/"&gt;adsf - A Dead Simple Fileserver&lt;/a&gt;. It works mostly like heel, but does not have that (sometimes annoying) browser-launching feature, (never really useful) directory listing support, and (always frustrating) syntax highlighting.&lt;/p&gt;

&lt;div class="banner banner-wide"&gt;&lt;a href="/software/adsf/"&gt;&lt;img src="/assets/images/banners/adsf.png" alt="adsf"&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;You can install adsf using RubyGems, like this:&lt;/p&gt;

&lt;pre&gt;&lt;kbd&gt;&gt; sudo gem install adsf&lt;/kbd&gt;&lt;/pre&gt;

&lt;p&gt;And using it is simple, too:&lt;/p&gt;

&lt;pre&gt;&lt;kbd&gt;&gt; adsf           # launches with . as web root at port 3000
&gt; adsf -r output # launches with ./output as web root
&gt; adsf -H thin   # launches with the Thin handler
&gt; adsf -p 8080   # launches at port 8080 instead of 3000&lt;/kbd&gt;&lt;/pre&gt;

&lt;p&gt;It goes without saying that it is perfect in combination with &lt;a href="http://nanoc.stoneship.org/"&gt;nanoc&lt;/a&gt;. Enjoy!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/stoneship_blog/~4/wYe5jZBXm5M" height="1" width="1"/&gt;</content><feedburner:origLink>http://stoneship.org/journal/2009/adsf/</feedburner:origLink></entry><entry><title type="html">Movie Review: Blue&amp;nbsp;Velvet (1986)</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/stoneship_blog/~3/9WOdbcWhRIw/" /><updated>2009-10-14T03:27:50-07:00</updated><id>tag:stoneship.org,2008-12-22:/journal/2008/movie-review-blue-velvet/</id><summary type="html">&lt;i&gt;David Lynch&lt;/i&gt;'s &lt;i&gt;Blue Velvet&lt;/i&gt; has been slowly climbing up to be one of my all-time favourite movies. Its simple story and stunning imagery will keep on the edge of your seat. A must-see for everyone who likes psychological thrillers.</summary><content type="html">&lt;div class="hreview"&gt;
	&lt;div class="item description"&gt;
		&lt;p&gt;&lt;i&gt;David Lynch&lt;/i&gt;'s &lt;i&gt;Blue Velvet&lt;/i&gt; has been slowly climbing up to be one of my all-time favourite movies. Its simple story and stunning imagery will keep on the edge of your seat.&lt;/p&gt;

		&lt;p&gt;&lt;i&gt;Jeffrey Beaumont&lt;/i&gt; (&lt;i&gt;Kyle MacLachlan&lt;/i&gt;) is a young man living in an idyllic little town. One day, after discovering a severed human ear in a field, Jeffrey invokes the police, but they remain idle. He decides to investigate the case on his own, with the help of detective William's daughter &lt;i&gt;Sandy&lt;/i&gt; (&lt;i&gt;Laura Dern&lt;/i&gt;), only to be thrown into a dark underworld beneath their small village.&lt;/p&gt;

		&lt;div class="banner banner-wide"&gt;&lt;img src="http://stoneship.org/assets/images/journal/movie-review-blue-velvet/1.jpg" alt="Blue Velvet"&gt;&lt;/div&gt;

		&lt;p&gt;&lt;i&gt;Blue Velvet&lt;/i&gt;'s story is, in essence, quite straightforward. There are no supernatural demons, no dream worlds, and time linearly flows forward. The real beauty of this film is the strong imagery: colorful roses against an immaculate white fence, darkly lit corridors, unsettlingly tidy apartment rooms.&lt;/p&gt;

		&lt;p&gt;The actors' performances are all simply great. For example, &lt;i&gt;MacLachlan&lt;/i&gt;'s character is convincingly innocent—or maybe exactly the opposite. However, every single character is blown out of the water by &lt;i&gt;Dennis Hopper&lt;/i&gt;, who plays a disturbingly psychotic and evil character—probably &lt;i&gt;Hopper&lt;/i&gt;'s all-time best role.&lt;/p&gt;

		&lt;div class="banner banner-wide"&gt;&lt;img src="http://stoneship.org/assets/images/journal/movie-review-blue-velvet/2.jpg" alt="Blue Velvet"&gt;&lt;/div&gt;

		&lt;p&gt;&lt;i&gt;Blue Velvet&lt;/i&gt; contains quite a bit of music. Most noticeable is &lt;i&gt;Bobby Vinton&lt;/i&gt;'s song after which the film is named, but there is also &lt;i&gt;Roy Orbison&lt;/i&gt;'s &lt;i&gt;In Dreams&lt;/i&gt;, used in a scene that won't get out of your head once you've seen it.&lt;/p&gt;

		&lt;p&gt;It is striking that some scenes have no music at all, leaving them open to interpretation. In scenes with music, the score, composed by &lt;i&gt;Angelo Badalamenti&lt;/i&gt;, greatly contributes to the film's atmosphere. In other words, music is used carefully but effectively.&lt;/p&gt;

		&lt;div class="banner banner-wide"&gt;&lt;img src="http://stoneship.org/assets/images/journal/movie-review-blue-velvet/3.jpg" alt="Blue Velvet"&gt;&lt;/div&gt;

		&lt;p&gt;&lt;i&gt;Blue Velvet&lt;/i&gt; is probably Lynch's masterpiece. This film will slowly drag you down, and won't release its grip until long after you've finished watching this movie. A must-see for everyone who likes psychological thrillers.&lt;/p&gt;

		&lt;p&gt;&lt;strong&gt;Rating&lt;/strong&gt;: &lt;abbr class="rating" title="5"&gt;&amp;#9733;&amp;#9733;&amp;#9733;&amp;#9733;&amp;#9733;&lt;/abbr&gt;&lt;/p&gt;
	&lt;/div&gt;
&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/stoneship_blog/~4/9WOdbcWhRIw" height="1" width="1"/&gt;</content><feedburner:origLink>http://stoneship.org/journal/2008/movie-review-blue-velvet/</feedburner:origLink></entry><entry><title type="html">Game Review: Portal:&amp;nbsp;Prelude</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/stoneship_blog/~3/D6T9OX4gFgI/" /><updated>2009-10-14T03:27:50-07:00</updated><id>tag:stoneship.org,2008-10-11:/journal/2008/game-review-portal-prelude/</id><summary type="html">&lt;i&gt;Portal: Prelude&lt;/i&gt; is an unofficial, fan-made prequel to &lt;i&gt;Valve&lt;/i&gt;'s popular &lt;i&gt;Portal&lt;/i&gt; game. The mod is quite disappointing, however. Weak dialogue, below-average voice acting, and &lt;em&gt;hellishly&lt;/em&gt; frustrating levels make this game barely worth playing.</summary><content type="html">&lt;div class="hreview"&gt;
	&lt;div class="item description"&gt;
		&lt;div class="banner banner-wide"&gt;&lt;img src="http://stoneship.org/assets/images/journal/review-portal-prelude/1.jpg" alt="Portal: Prelude test chamber 00"&gt;&lt;/div&gt;

		&lt;p&gt;&lt;a href="http://www.portalprelude.com/"&gt;Portal: Prelude&lt;/a&gt; is an unofficial fan-made prequel to &lt;i&gt;Valve&lt;/i&gt;'s awesome &lt;a href="http://orange.half-life2.com/portal.html"&gt;Portal&lt;/a&gt; game. Like many others, I've been eagerly awaiting the release of this mod. Yesterday, I got the opportunity to download and play it.&lt;/p&gt;

		&lt;p&gt;Unfortunately, excitement was quickly replaced by disappointment immediately after the start of the game. For starters, the game's dialogues are riddled with grammar errors. &lt;q&gt;That was close, doesn't it?&lt;/q&gt; is just one of many mistakes. Recruiting a native English speaker would not have been just a luxury. The dialogues are extremely awkward, which pretty much ruins any attempt at an in-dialogue joke.&lt;/p&gt;

		&lt;p&gt;The test chambers in the original &lt;i&gt;Portal&lt;/i&gt; were fun and entertaining. &lt;i&gt;Portal: Prelude&lt;/i&gt;'s puzzles, on the other hand, are &lt;em&gt;hellishly frustrating&lt;/em&gt;. For many puzzles you need &lt;em&gt;exact&lt;/em&gt; timing, you need to be able to aim at &lt;em&gt;exactly&lt;/em&gt; the right spot, and on top of all that, you need a &lt;em&gt;huge&lt;/em&gt; load of luck and a &lt;em&gt;lot&lt;/em&gt; of patience.&lt;/p&gt;

		&lt;p&gt;Figuring out &lt;em&gt;how&lt;/em&gt; to find the exit of a given test chamber is not too hard. Actually &lt;em&gt;getting there&lt;/em&gt; is a whole other story. In short, &lt;i&gt;Portal: Prelude&lt;/i&gt;'s gameplay is purely sadistic.&lt;/p&gt;

		&lt;p&gt;The game relies on crouching while jumping. According to the developers, crouching affects momentum. Huh? Momentum is the product of mass and velocity; crouching changes neither factor. Drag? Hardly relevant. Get your physics right, please.&lt;/p&gt;

		&lt;p&gt;Nicolas, &lt;i&gt;Portal: Prelude&lt;/i&gt;'s lead developer, regularly mentions that the game has been play-tested. Considering I couldn't finish the first part of the second test chamber for more than half an hour, even after getting numerous hints from the forums, I can hardly believe there really was any play-testing at all.&lt;/p&gt;

		&lt;p&gt;I was expecting a mod with maps that resembled the original &lt;i&gt;Portal&lt;/i&gt;'s advanced levels: difficult, challenging, but well-balanced. Instead, I got a bunch of maps that rely on quirks in the game's physics.&lt;/p&gt;

		&lt;p&gt;I'm tempted to say &lt;q&gt;I'm making a note here, great failure&lt;/q&gt; but that would probably be too harsh. &lt;i&gt;Portal: Prelude&lt;/i&gt; is not a bad attempt, but it nonetheless falls short in many aspects. It's probably a better idea to (re)play the original &lt;i&gt;Portal&lt;/i&gt;'s advanced or challenge levels instead of this mod.&lt;/p&gt;

		&lt;p&gt;&lt;strong&gt;Rating&lt;/strong&gt;: &lt;abbr class="rating" title="2"&gt;&lt;span class="full"&gt;&amp;#9733;&amp;#9733;&lt;/span&gt;&lt;span class="empty"&gt;&amp;#9734;&amp;#9734;&amp;#9734;&lt;/span&gt;&lt;/abbr&gt;&lt;/p&gt;
	&lt;/div&gt;
&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/stoneship_blog/~4/D6T9OX4gFgI" height="1" width="1"/&gt;</content><feedburner:origLink>http://stoneship.org/journal/2008/game-review-portal-prelude/</feedburner:origLink></entry><entry><title type="html">Monet</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/stoneship_blog/~3/1OhNbrvMRAw/" /><updated>2009-10-14T03:27:50-07:00</updated><id>tag:stoneship.org,2008-08-31:/journal/2008/monet/</id><summary type="html">&lt;em&gt;Monet&lt;/em&gt; is a Ruby library on top of Gosu, providing functionality such as better event handling and views. And it's open-source, of course.</summary><content type="html">&lt;p&gt;A week ago, I had the idea of creating a game in Ruby. After evaluating a few gaming frameworks, I settled on &lt;a href="http://code.google.com/p/gosu/"&gt;Gosu&lt;/a&gt;. Gosu is a simple and  minimalistic library, and I like minimalism a lot, so we started a loving relationship.&lt;/p&gt;

&lt;p&gt;I wrote a small library named &lt;em&gt;Monet&lt;/em&gt; on top of Gosu, providing functionality such as better event handling, views and subviews, buttons, and more. &lt;em&gt;Monet&lt;/em&gt; is named after Claude Monet, an impressionist painter. This library also does a bit of painting, but that's where the similarity ends---Claude Monet has nothing to do with event handling, really.&lt;/p&gt;

&lt;p&gt;The Gosu romance unfortunately didn't last long. For real-time games, Ruby is simply &lt;em&gt;way&lt;/em&gt; too slow (Gosu isn't slow; Ruby makes it slow). Gosu and I broke up, and now I've moved on to a much faster language.&lt;/p&gt;

&lt;p&gt;Monet is now &lt;a href="http://github.com/ddfreyne/monet/tree/master"&gt;available on github&lt;/a&gt; under a liberal MIT licence. It is very small and not feature-complete, but it should be fairly easy to extend it. I won't be developing Monet any longer, but I believe anyone who has used Gosu or is still using Gosu should check it out anyway. Fork and enjoy.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/stoneship_blog/~4/1OhNbrvMRAw" height="1" width="1"/&gt;</content><feedburner:origLink>http://stoneship.org/journal/2008/monet/</feedburner:origLink></entry><entry><title type="html">Exciting Times for nanoc</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/stoneship_blog/~3/hzq8Fx_D_FU/" /><updated>2009-10-14T03:27:50-07:00</updated><id>tag:stoneship.org,2008-05-22:/journal/2008/exciting-times-for-nanoc/</id><summary type="html">In the past 12 months, nanoc has grown from a hacky little script to a full-grown, powerful and flexible Ruby application. So, what are the next steps for nanoc?</summary><content type="html">&lt;p&gt;&lt;a href="http://nanoc.stoneship.org/"&gt;nanoc&lt;/a&gt; turned one year a few weeks ago. I completely missed its birthday, so happy belated birthday to you, nanoc.&lt;/p&gt;

&lt;p&gt;In the past 12 months, nanoc has grown from a hacky little script to a full-grown, powerful and flexible Ruby application. Quite a few people are using nanoc now, as proven by the small but growing community of active users out there (hi!).&lt;/p&gt;

&lt;p&gt;So, what are the next steps?&lt;/p&gt;

&lt;p&gt;There have been two distinct moments where I thought: "okay, nanoc is complete now, and there is nothing I can improve." Ah, I was so wrong. There are so many ways nanoc can be enhanced. I'm only limited by the time I have!&lt;/p&gt;

&lt;p&gt;Here are some features and ideas I've been working on lately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Including more plugins.&lt;/strong&gt; nanoc is quite bare-bones. There are some really cool plugins floating around, but few people know about them. Bundling all the cool stuff in the standard nanoc distribution would make sense.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Asset management.&lt;/strong&gt; A question that regularly pops up is how to manage assets such as images and stylesheets. The answer is an embarrassing "nanoc can't, so do it yourself." This'll change soon, as nanoc will get asset management.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A clean API.&lt;/strong&gt; nanoc has been too much of a black box, so I'm opening it up. This'll make it possible to tell nanoc to generate pages for each of your tags, for example.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This stuff will all be in nanoc 2.1, which, because it's going to be a big release, will take a while before it's complete. It'll be worth the wait, though.&lt;/p&gt;

&lt;p&gt;So, I definitely didn't get bored working on nanoc (but I should probably quit working on it for now---exams are coming up).&lt;/p&gt;

&lt;p&gt;Exciting times for nanoc indeed!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/stoneship_blog/~4/hzq8Fx_D_FU" height="1" width="1"/&gt;</content><feedburner:origLink>http://stoneship.org/journal/2008/exciting-times-for-nanoc/</feedburner:origLink></entry><entry><title type="html">CSS's Relative Units: Redundant</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/stoneship_blog/~3/3ehBxKf2cOk/" /><updated>2009-10-14T03:27:50-07:00</updated><id>tag:stoneship.org,2008-04-17:/journal/2008/css-s-relative-units-suck/</id><summary type="html">These days, the recommended approach for setting all widths, heights and sizes in CSS is using relative units instead of absolute units. With the recent redesign, however, Stoneship has—deliberately—gone the other way.</summary><content type="html">&lt;p&gt;These days, the recommended approach for setting all widths, heights and sizes in CSS is using relative units (e.g. &lt;code&gt;em&lt;/code&gt; and &lt;code&gt;%&lt;/code&gt;) instead of absolute units (e.g &lt;code&gt;pt&lt;/code&gt; and &lt;code&gt;px&lt;/code&gt;). Doing so has the advantage that the entire page "zooms" when the font size is changed, meaning that the proportions of all elements on the page are preserved.&lt;/p&gt;

&lt;p&gt;With the recent &lt;a href="/journal/2008/minimal-earth/"&gt;redesign&lt;/a&gt;, however, Stoneship has—deliberately—gone from a layout set in &lt;em&gt;relative&lt;/em&gt; units to a layout set in &lt;em&gt;absolute&lt;/em&gt; units.&lt;/p&gt;

&lt;p&gt;The reason why is because there is almost no point in using relative units anymore, as all browsers have or are getting full page zoom. Full page zoom, for those that don't know, gives browsers the ability to zoom pages as if you were using &lt;code&gt;em&lt;/code&gt;'s, except you're not using &lt;code&gt;em&lt;/code&gt;'s at all. Opera and Internet Explorer (!) already have it; Firefox and Safari are getting it soon.&lt;/p&gt;

&lt;p&gt;So, why still bother?&lt;/p&gt;

&lt;p&gt;The only real reason for still using &lt;code&gt;em&lt;/code&gt;'s or &lt;code&gt;%&lt;/code&gt;'s is backward compatibility. People with older browsers may still want to have that full page zoom effect after all. However, if you really want full page zoom everywhere, why not ditch your old browser and upgrade? Also, it's not like you are preventing people with older browsers from viewing your site—the content is still there, but without full page zoom… so what?&lt;/p&gt;

&lt;p&gt;I admit it's a bit early to completely banish &lt;code&gt;em&lt;/code&gt;'s everywhere, but once full page zoom is incorporated in all modern browsers, there's no need to bother anymore. Be lazy and use absolute units, like I did.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/stoneship_blog/~4/3ehBxKf2cOk" height="1" width="1"/&gt;</content><feedburner:origLink>http://stoneship.org/journal/2008/css-s-relative-units-suck/</feedburner:origLink></entry><entry><title type="html">Movie Review: Délicatessen (1991)</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/stoneship_blog/~3/sEICEE2XUpI/" /><updated>2009-10-14T03:27:50-07:00</updated><id>tag:stoneship.org,2008-04-12:/journal/2008/movie-review-delicatessen/</id><summary type="html">France, some time after the second world war. The country is in ruins, and there is not enough food around for everyone. The landlord of an apartment in a rural part of the country solves this by continuing his job as a butcher, regularly hiring new employees, eventually slaughtering them and serving them to his customers.</summary><content type="html">&lt;div class="hreview"&gt;
	&lt;div class="item description"&gt;
		&lt;div class="banner banner-wide"&gt;&lt;img src="http://stoneship.org/assets/images/journal/review-delicatessen/1.jpg" alt="Délicatessen"&gt;&lt;/div&gt;

		&lt;p&gt;France, some time after the second world war. The country is in ruins, and there is not enough food around for everyone. The landlord of an apartment in a rural part of the country solves this by continuing his job as a butcher, regularly hiring new employees, eventually slaughtering them and serving them to his customers.&lt;/p&gt;

		&lt;p&gt;When Louison, a new hired handyman, falls in love with butcher Clapet's beautiful daughter Julie, the wheel starts to turn in the other direction.&lt;/p&gt;

		&lt;div class="banner banner-wide"&gt;&lt;img src="http://stoneship.org/assets/images/journal/review-delicatessen/2.jpg" alt="Délicatessen"&gt;&lt;/div&gt;

		&lt;p&gt;&lt;span class="fn"&gt;Délicatessen&lt;/span&gt; is, however, not a horror movie. The story may sound quite macabre, but the setting actually has a surprisingly cozy mood. Maybe it's because the building's tenants are surprisingly happy given the situation they're in, or maybe it's the fact that the dominant color in the film is a warm brown.&lt;/p&gt;

		&lt;p&gt;The movie develops in a quite unpredictable way, and there's not a single boring moment. Every single tenant has its own, very eccentric personality: a cannibalistic butcher, an ex-circus clown and an old fellow living in a basement filled with snails and frogs are just three examples.&lt;/p&gt;

		&lt;div class="banner banner-wide"&gt;&lt;img src="http://stoneship.org/assets/images/journal/review-delicatessen/3.jpg" alt="Délicatessen"&gt;&lt;/div&gt;

		&lt;p&gt;The movie does not feel dated even though it was originally released in 1991. Its style is not unlike one of Jean-Pierre Jeunet's other movies, &lt;i&gt;Le Fabuleux destin d'Amélie Poulain&lt;/i&gt;. Even though Délicatessen could be seen as a stylistic study that led to Jeunet's later movies, it is an excellent movie in its own right.&lt;/p&gt;

		&lt;p&gt;Délicatessen is definitely a must-see for everyone who enjoys French films, dark comedies or surrealistic post-apocalyptic movies.&lt;/p&gt;

		&lt;p&gt;&lt;strong&gt;Rating&lt;/strong&gt;: &lt;abbr class="rating" title="5"&gt;&amp;#9733;&amp;#9733;&amp;#9733;&amp;#9733;&amp;#9733;&lt;/abbr&gt;&lt;/p&gt;
	&lt;/div&gt;
&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/stoneship_blog/~4/sEICEE2XUpI" height="1" width="1"/&gt;</content><feedburner:origLink>http://stoneship.org/journal/2008/movie-review-delicatessen/</feedburner:origLink></entry></feed>
