Monthly Archive for April, 2010

Referrers, Webmails and Competition

When you visit a web site, that web site remembers your request, along with some information about that request. Here’s some data that the Apache web server remembers:

  • 217.111.148.194 : your IP address
  • [26/Apr/2010:13:02:15 +0200] : when you visited
  • GET /ladies/naughty.avi : what you asked for.
  • https://www.facebook.com : the page where you found the link to the current page
  • Mozilla/5.0 : your browser
  • Windows NT 6.0 : your operating system

It is of course possible to eliminate most of that information (only the first three are required). It is the fourth, however, that can cause havoc: people know where you come from.

Consider now what would happen if your corporation uses some kind of webmail. Something like http://mail.google.com/a/myCompany or http://intranet.myCompany.com/zimbra. Suppose that one of your co-workers send you an e-mail about a new feature from your competitor that you absolutely have to see. In that e-mail is a link. You click on the link.

Since the e-mail was displayed as a web page in your web browser, its address will be sent to your competitor’s server. Now your competitor knows that your company is exchanging mails about their latest feature.

Some web mailers protect you against this. Check it out.

MySQL (Un)Maintenance Trick

Not so long ago, I discussed the puzzling fact that in JavaScript, if(x) is not equivalent to if(x == true). Today, I stumbled upon a similar occurence in MySQL.

The Problem

Consider the following table, containing arbitrary text with an «alive» boolean flag:

CREATE TABLE tested (
  txt CHAR(32) NOT NULL,
  alive BOOLEAN NOT NULL,
  PRIMARY KEY(txt),
  KEY(alive)
);

INSERT INTO tested (txt,alive) VALUES
( MD5(1), FALSE ),
( MD5(2), FALSE ),
( MD5(3), FALSE ),
( MD5(4), TRUE ),
( MD5(5), TRUE );

I want to display all the lines that are marked as alive, sorted by their text field. What is the difference between these two requests?

SELECT txt FROM tested WHERE alive ORDER BY txt;
SELECT txt FROM tested WHERE alive = TRUE ORDER BY txt;

And the answer is… both queries will return the same result set! But let’s EXPLAIN them, just in case.

type possible keys key rows
WHERE alive ALL 5
WHERE alive = TRUE ref alive alive 2

The first query will scan through the entire table, whereas the second query will use the index to only run through lines that are still alive. If your table consists of 99% dead elements, the first query will be a hundred times slower than the second one!

The Reason

The fundamental reason for this behavior can be found in the MySQL documentation:

These types are synonyms for TINYINT(1). A value of zero is considered false. Nonzero values are considered true:

However, the values TRUE and FALSE are merely aliases for 1 and 0, respectively, as shown here:

In short, that boolean column is not actually a boolean value, but actually an integer. This means it can contain values that are neither TRUE nor FALSE, such as 2. Such a value would be returned by the first query, but not the second, so the query optimizer is not allowed to turn the first one into the second one. And «this column evaluates to true in a boolean context» is not easily expressed as a key constraint, whereas «this column equals one» is the textbook definition of a key constraint. This explains why the second query is faster.

It also means that the second query might start behaving incorrectly if a non-TRUE, non-FALSE value finds its way into that column.

The Solution

The good news is that NOT foo is mathematically equivalent to foo = FALSE, so that the constraint can be easily rewritten by turning the «alive» property into a «dead» property. Both queries become equivalent, so the second query is a faster yet functionally identical alternative:

CREATE TABLE tested (
  txt CHAR(32) NOT NULL,
  dead BOOLEAN NOT NULL,
  PRIMARY KEY(txt),
  KEY(dead)
);

INSERT INTO tested (txt,dead) VALUES
( MD5(1), TRUE ),
( MD5(2), TRUE ),
( MD5(3), TRUE ),
( MD5(4), FALSE ),
( MD5(5), FALSE );

SELECT txt FROM tested WHERE dead = FALSE ORDER BY txt;

Back/Refresh/Bookmark

A feature shared by almost any web search engine in existence is the ability to return to the list of results if the result you check out wasn’t what you hoped it would be. Even better, you actually return to the same page in the search results that you were on in the first place, so you can just resume your search.

Sounds obvious?

It is, when you’re using a technology straight out of the 90′s such as plain vanilla HTTP. The original problem that led to the design of HTTP was that you had many resources publicly available on the web, but there was no simple way to tell your friends where the latest naughty lady bitmaps important accounting files were. Thus were born the Uniform Resource Locators, known nowadays as URLs, which obviously helped locate resources in a way that was uniform across servers. Of course, for this to work, reaching out for the same URL twice should bring back the same piece of data both times (or, at the very least, a piece of data that is similar within reasonable expectations, such as being the “latest version” of the same data).

This is what HTTP GET does: locate and fetch a resource from the tubes, bringing back the same resource every single time.

The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI.

This is why your web browser can implement back, refresh and bookmark but your SSH client can’t. And this is also why HTTP POST does not play nice with back, refresh and bookmark (it involves posting data, which may have an impact if done more than once, such as double-posting on a forum).

The Good

Google et alii play into this game: every search result page is a resource, which can be located through an URL that contains all the information about that page. Of course, the resource is generated on the fly on the server, but to the user (and the browser) it looks as if a static resource was present on the internet, so pressing the back button brings you back to the same URL, and this yields the expected data.

Note that many web browsers will also remember some other things about the visited page, such as the scroll position and any text you entered in the fields. This is important, because this lets you refresh a page without losing the data you entered.

The Bad

Of course, it’s hard to think in terms of resources-each-bound-to-locators when you’re not dealing with resources. And besides, the “user gets form, user posts form, user is redirected to new page” mechanism can be quite limiting when you’re trying to be clever. And it all looks so different from how desktop applications work!

I am regularly brought on the brink of intellectual suicide when faced with “web applications” that maul the very spirit of HTTP with spiked baseball bats covered in hot pepper oil. No back, no refresh, no bookmark… These designers hope (and in this, they are quite correct) that as long as their application looks and feels like an application, there will be no affordances that would cause the user to use these forbidden buttons.

A list of elements is the most ubiquitous example in modern computing: clicking on an element opens a detailed view of that element. The “application” way of doing this is opening a new window to display the details, so that the user may close the window or cancel their way out of it to go back to the list. No sane user will try to use the back feature to return to the list, because that’s not how the desktop taught us to behave.

This can be imitated on the web with a new browser window, or with a modal window using javascript and (possibly) AJAX.

On the other hand, if the application replaces the list with the detailed view, then it’s using the “web” way of doing things, and the “show me the previous screen” reflex of pressing back will kick in really soon. Too bad pressing back breaks the application. And pressing forward again to return to a reasonable state won’t work either.

I will not delve into the sheer stupidity of moving against affordances that are so deeply ingrained in the average internet user for design reasons (and even doing so for technical reasons is pretty bad).

The Ugly

And then, there’s the matter of AJAX. The good thing about AJAX is that it lets you dynamically update only a part of your page, without having to refresh the rest. The bad thing about AJAX is that it lets you dynamically update only a part of your page, without having to refresh the rest.

That’s because every single thing you did on your AJAX page will be lost the moment your user presses back or refresh. If your lists are managed through AJAX, then the user will navigate to page 3, then click on the link, which will bring them to another page, then press back, which will (as expected) bring them back to the page with the list… that was reset to page 1, because there’s no way for the browser to know that the complex javascript state that kept your list on page 3 had to be remembered in the history.

For a real-life example, try this link (from the ExtJS library), click around a bit, and then refresh — you’re back to step zero. Since everything happens on a single page in a new tab/window, there’s no back button to be used.

The good news is that there are tricks available for handling back/refresh/bookmark in JavaScript. Another example would be this one, from ExtJS again, which handles the back part almost correctly (still no luck on refresh/bookmark), or this example based on the excellent jQuery Address plugin, which manages to do all three properly.

The hash : a hack on top of a hack

Back in the days where documents could be quite large in order to be handled offline as a single file, people had to come up with a way of navigating though them. The adopted solution was to use anchors. Somewhere in your file, you would add a named anchor, such as <a name="myAnchor">. Then, appending #myAnchor to the URL of the document would scroll the anchor into view (well, the anchor was invisible, but you get my meaning).

So, you could link to a part of a document from the document itself by using the URL-with-hash as the target of a link. And you could link to it from other pages, which let you send your readers to the appropriate location on the referenced document.

It became fairly standard for web browsers to implement this system so that:

  • Clicking on an anchor (or changing the anchor part of the URL) would not reload the document if it was already being displayed.
  • The anchor was taken into account by back/refresh/bookmark.
  • JavaScript would have read-write access to the anchor part of the URL (usually as window.location.hash).

This, in turn, provides several ways of solving the back/refresh/bookmark in heavy JavaScript situations.

The first one, used by the ExtJS example above, is to alter the hash every single time you change the application state in a relevant way (what is relevant is left for the developer to decide), and simultaneously push information about the state in some kind of storage.

Then, as the user presses forward and back, the hash-changing will keep the user on the same page and let the JavaScript read from the storage whatever state needs to be applied to elements and restores that state accordingly. The problem is that, when the page is refreshed (or bookmarked and loaded later), everything but the hash will disappear in a puff of garbage-collected smoke, so that no memory of the stored states will remain.

The second solution is to store those states in the hash, so that they will be available even if you refresh, or bookmark the link, or give it to someone else.  This is what the jQuery Address example does, by storing the name of the selected tab in the hash, and then reading that name from the hash to activate the relevant tab whenever back or refresh happen.

Deep Linking

Quick note: this solution is sometimes referred to as deep linking. In fact, deep linking represents the very ability to open any page in a web site by entering its URL (so, if you find this article in a Google search, then Google is by definition deep linking into my site so you can access the article directly). As explained above, deep linking is a natural consequence of how HTTP works:

The conclusion is that any attempt to forbid the practice of “Deep Linking” is based on a misunderstanding of the technology [...]

The entire point of those hash-based tricks is to enable (or restore) deep linking in heavy JavaScript web sites. Quite ironic, given that not so long ago we were trying to forbid it.

The Middle Path : a hash behind the hash

Of course, between those two solutions, there’s the middle way: store some fundamental information in the hash, and keep the rest in a separate storage area. This way, back will be fully functional, refresh will still manage to keep enough relevant information around to be useful, and the hash will be small enough so that it remains below allowed size limits.

This third strategy is quite simple to manage by starting from the second approach, keeping a global hash table to store the detailed state, and adding the key of the current detailed state to the summarized state.

This is basically saying, store the current (detailed) state of components A and B in the hash table with key 0x3ffc, then store 0x3ffc in the hash along with the current (summarized) state of component C. When that hash is reactivated because of back, the detailed state will be available based on the key, and when reactivated because of refresh, the summarized state will be replaced and the unavailable detailed state will be replaced by defaults.

Model Zero : Keep Stuff Around

The simplest situation for this kind of thing is when developers absolutely need to keep some part of the page on the user’s computer. It could be, for instance, a media player that has to remain present on the page even as the user browses the web site. Refreshing the page would drop the media player, which would cause the music to stop, so the page must stay, and content must be updated on the fly.

Of course, you don’t want to have AJAX-related link problems: Google does not follow JavaScript links, so if the entire link tree of your website is implemented in JavaScript, only your home page will be known to Google.

A classic design technique found on Deezer is to keep two URLs for every page. One URL contains the hash, the other doesn’t. By default, links use the non-hash URL, and as such can be followed by Google. If JavaScript is enabled, links automatically start using the hash URL instead.

For example, the non-hash URL for a search for “nicollet” on Deezer is:

http://www.deezer.com/en/music/result/all/nicollet

The hash URL for that same search is:

http://www.deezer.com/en/#music/result/all/nicollet

Both display the same page, so the algorithm for displaying the hash URL is basically, “load all the data for the non-hash URL and use it, while keeping the few elements that have to stay around, such as the music player”. Quite simple, and it does not detract a lot from the typical way of designing web pages in a non-AJAX world.

Sure, Deezer is flash-based, but equivalent JavaScript techniques are used by Facebook when they need to keep a chat box around, and (if you need a public JS-based example anyone can visit) by Jukebo.fr.

This is actually what the jQuery Address plugin was designed to do: run through all the links on a given page and turn their no-hash URL targets into hash-based URL targets, then provide the user with a “hash was changed” event that they can respond to by doing whatever they feel should be done (such a loading bits of data from the server for the new URL).

As a whole, Model Zero is fairly simple to implement and use, and requires only minimal support from the server, such as controllers that display partial views instead of complete views if called with a certain parameter.

Model One : Components on a Page

… starring Samuel L. Jackson. This is the simplest model that does not involve simply mirroring server-side pages on the client, and it usually happens when a normal page contains some kind of JavaScript component, such as jQuery UI tabs that are expected to be refreshed appropriately, or an ExtJS grid with complex state.

The assumption here is that you don’t care about Google following the links in your grid (jQuery UI tabs decay to a nice HTML markup when JS is disabled, so they would create no problems), but you do care about your user using back/refresh/bookmark on the page.

The basic idea is that every single component on the page has to be connected to the history handler (be it Ext.History, $.address or anything else) so that they notify it of their state changes, and are notified in return of external address changes.

Depending on which component you are trying to connect to which history handler, things will be more or less difficult. In the rather common situation where you wrote your own component, it will have to provide a “my state changed” event (triggered by your component whenever user interaction causes a change of state) and a “give me a new state” function (called by the history handler whenever the state changes). Somewhere along the way (probably in your component) you will need a serialization-deserialization utility to turn the complex state of your component into a hash-storable string and back.

For additional safety, make sure that setting a state that is already the current state does not trigger the state change callback: depending on your history handler implementation, it might cause an infinite loop, and it ain’t pretty.

A quick-and-dirty example to connect jQuery UI tabs to the jQuery address plugin (this should not work as is, and is intended merely as an illustration):

$(function(){

  $.address.externalChange(function(){
    var i = $.address.value().substr(1) || 0;
    $('#tabs').tabs('select', i);
  });

  $('#tabs').tabs({
    select : function(event){
      $.address.value(
        $('#tabs').tabs('option','selected');
      );
    }
  });
});

The first part extracts the state from the hash and selects a tab, the second part reads the currently selected tab and activates it. It relies on the tabs not firing a “select” event if the selected tab was already active, and on externalChange not being triggered by setting the value from the code.

Note that the second part does not compute the new hash value from the event itself, but rather from global data: this is because, if you had two components on the same page, changing any of the two would have to store the new state of both components in the URL. In that situation, you would have a single “compute the hash based on the state of both components” function triggered by the on-change events of both components.

Model One-Dot-Five : what if I use both of the above?

What happens if you load your pages using model zero, and then you have components on these pages that use model one?

This is not very difficult, but it requires some cooperation on the part of model zero, which “owns” the hash for practical reasons. The first possibility is to have model zero use only one channel of your history management tool—for instance, if your tool allows you to specify query strings, you can store your state as ZERO?COMPONENT=STATE&COMPONENT=STATE without difficulties.

The second possibility is to have model zero provide an interface that lets components from the loaded pages register and control parts of what model zero will save to the hash through a modification to its serialization process (again, the query string seems like an obvious choice).

The problem is that the first possibility will not work…

First: since you always remain on the same page, components that disappear from the page do not remove the events you registered with the history manager to handle them. It is the responsibility of model zero (which knows when a page content change happens) to eliminate any callbacks registered by components from model one. Otherwise, on every URL change, all callbacks will be processed, which reduces performance, causes memory leaks and might, in really nasty situations, cause a component on a page you visited five minutes ago to maul the URL of the page you’re visiting right now.

Also remember that the hash-was-changed event will trigger an AJAX reload of the page contents, so the new components will by definition not be present on the page when the event is triggered!

So, model zero reloading takes a little more effort now:

  1. Detect that a reload is required.
  2. Unregister all hash change event handlers registered from child components.
  3. Query the content, insert it into the page. It may contain components, which will then register themselves with the hash change event.
  4. Propagate the hash change event to the newly created components.

Since it now needs to unregister child handlers and propagate the hash change after loading is done, model zero needs tighter control over how children are connected to the history handler. I believe the only clean solution here is to make model zero a global object that wraps around the history handler, so that child components only need to interact with the global object.

An interesting interface for this part of the global object would be:

zero.onChange(callback)
Registers a callback to be called whenever the state of the child components needs to be modified (because of an URL change). Child components, when they initialize themselves, register themselves this way to listen to URL changes. All callbacks registered this way are discarded when the contents of the page change.

zero.setState(dictionary)
Changes the query string part of the URL to take into account changes that happened to child components. This does not trigger the change event.

Being global means components initialized in <script> tags in the incoming, server-sent HTML can still reach out for it and register themselves.

Model Two : recursive boxing

When you look at the previous model, you notice that model one components inside a model zero page is a flat structure only waiting to be made recursive. The key to this is to create a component that acts like a model zero page by loading its content from the server and passing down some information to its own child components.

Model Three : client controllers

This model gives up any kind of non-javascript usage of the web site. A classic example is gmail (and, just like gmail, you can provide an alternate static HTML version of the web site with greatly reduced features). This approach basically leaves everything in the hands of the JavaScript programmer by letting him define the application as a stateful component, with the hash in the URL being a serialized version of the component state (or the relevant parts thereof). It’s also the hardest to work with, since there’s basically no high-level architecture, though you may implement a domain-specific one like gmail did.

Fast Learners

Slow learners need weeks of training and years of practice to become skilled in their area of expertise. Fast learners «get it» within days, and become fully operational within weeks. Intelligence is certainly a factor, but it does not matter as much as one would expect.

How fast is a given person going to relate new concepts to her experience? Is she going to sift through all the feedback she gets, positive or negative, for lessons or ideas? Faced with new responsibilities, is she going to try something, anything at all, or freeze in fear because of the possible consequences? Does she think about the issue at all between 6pm and 9am? Is she going to repeat the same mistakes twice? Does she think everything is fine when everything is not fine?

But being a fast learner is a skill that is hard to demonstrate. You can demonstrate great skill with a programming language by single-handedly writing an open source program, you can demonstrate great leadership or management skills by successfully leading several teams and managing several projects, and you can demonstrate great artistic skills with a well-stocked portfolio, because these skills work on the basis of «if you did it ten times, you can do it eleven times»

By definition, you cannot learn the same thing ten times in a row, and saying that you will learn how to manage a team in two weeks because you learned how to code in PHP in two weeks is a bit of a stretch. It’s very hard to determine in a single job interview how fast someone can learn about new subjects. Once you hire someone and get the chance to work with them for a short while, though, you should be able determine this.

Otherwise, there’s no telling where that person will be a few months from now. And that would be bad management.

Building Hammer Factories

I recently acted as a technical advisor to a small start-up company that was having difficulties getting their product out the door. The situation there reminded me of this “Hammer Factory” post by BenjiSmith:

“So this week, we’re introducing a general-purpose tool-building factory factory factory, so that all of your different tool factory factories can be produced by a single, unified factory. The factory factory factory will produce only the tool factory factories that you actually need, and each of those factory factories will produce a single factory based on your custom tool specifications. The final set of tools that emerge from this process will be the ideal tools for your particular project. You’ll have *exactly* the hammer you need, and exactly the right tape measure for your task, all at the press of a button (though you may also have to deploy a few *configuration files* to make it all work according to your expectations).”

That start-up company wanted to provide various groups of customers with online services. Those customers would have similar high-level needs (buying and keeping track of sports accessories*), but different segments would have different specific needs (football teams need to keep track of numbered shirts with appropriate sizes and only buy a dozen each year, while rock climbing groups need to purchase rope and chalk on a weekly basis*). The business plan called for starting with the basic functionality, and being able to quickly provide each segment with a specifically tailored version of the online service within months of the initial launch.

(*: the business plan has been anonymized to protect the innocent.)

Obviously, if you write the basic application without paying attention to what the tailored versions will need to provide, you will end up in trouble for the quickly part. The smart people at that start-up realized that and went all the way to the other extreme: the basic version would actually be a fully configurable application, so that the development of segment-specific versions would be as simple as ticking a few checkboxes.

Needless to say, this kind of decision increases by a large factor the cost of initial development:

Even writing your own reusable code is orders of magnitude harder than just jotting down a quick one-shot solution to whatever problem you have. An excessive tendency to build generic code from the very beginning makes your development process look like Dragon Ball Z : you have to power up for fifteen episodes before you can show a splash screen.

The long road from «everything must be done by writing new code» to «everything can be done by ticking checkboxes» is a form of optimization that tries to reduce the time and skill required to perform certain tasks. Like any other optimization process:

  • Doing it ahead of time without access to profiling data can often result in unnecessary or insufficient modifications. While humans are better at estimating their own time than they can estimate computer processing time, they’re not perfect, and it’s not easy to determine how often a given task will have to be performed.
  • If a given task represents only 1% of the time spent by humans using the application, then even a 1000% improvement will not improve the application by more than 1%.

Back when I worked as a freelancer, I worked with a client that wanted a poll system for their website. I offered them a choice between a complete poll system (to be designed and implemented in around four days)  that would let them create new polls at will, or a simple system (designed and implemented in half a day) that would require a couple of hours for a moderately skilled developer every time a new poll was needed.

They asked me for the four-day package.

In six years, they have changed the poll three times. Every time, the change was performed by their in-house developer. One of these times actually required the developer to add support for a new feature.

Was it worth it?

Readability Improvement

Updated the stylesheet for the blog today to increase readability:

  • Decreased the size of the header, which used valuable screen real estate, from 220 pixels to 70 pixels. In terms of screen size, it decreased from 1/3rd of the screen height down to 1/9th.
  • Increased the width from 750 to 960 pixels (all of that increase went into making the content column wider).
  • Increased the font size by a few percent, and reduced the line height a bit.
  • Restored sane colors for the links (blue by default, orange when visited).
  • Corrected some silly rules (such as strong text using a different font, code being larger than the rest of the line, and the extreme line height in pre blocks).

Hopefully, it should be easier to read.

Harbringer of Spring postmortem

Yesterday was the seventh installment of the Three Hour Game Development Contest, hosted on GameDev.Net by capn_midnight. The premise is that a theme is provided and contestants have three hours to design, implement and deliver a complete video game using art, libraries and technology of their choice, that is somehow related to that theme. The contest results will be revealed today.

harbringer-of-spring

My entry is called Harbringer of Spring, a game where you have to step on dirt tiles to make grass grow there, and step on the stone tile when there’s grass everywhere. To increase difficulty, water tiles cannot be traversed, and bridge tiles turn into water tiles once they are stepped over. It’s written in HTML-CSS-jQuery, sou can play it online. The original intent is vaguely inspired from the Bridges of Königsberg mathematical problem where you have to cross all bridges exactly once.

The technical details:

  • 233 lines of JavaScript code, divided into 100 lines of level data and 133 lines of actual gameplay code.
  • 53 lines of HTML
  • 174 lines of CSS, divided into 103 lines for the general UI (title, links) and 71 lines for the map and tileset.
  • Uses jQuery 1.4.2 to interact with the document.
  • Uses the PlanetCute tileset, because I couldn’t be bothered with graphics.

Here’s the step-by-step rundown of how I developed this entry (the given time is actually a countdown to the time the game must be delivered).

3:15 (that’s 15 minutes before the contest begins): I’ve already decided that the game shall be written in HTML-CSS-jQuery, so I set up my work environment accordingly. Desktop 1 will be my development environment, with a browser on the left monitor containing documentation for jQuery and an xterm on the right monitor connected to the nicollet.net server through SSH, running an emacs with two vertically split buffers. Desktop 2 will be my testing environment, with a browser containing the game on the left monitor and a maximized Firebug on the right monitor.

I also create the index.html, style.css and game.js files, download (with wget) the latest minified version of jQuery, and create an img directory for my images. I’m a bit bored, so I decide to add the “© 2010 Victor Nicollet” footer to the document.

3:00 : apparently, the theme has already been given out a little earlier. Time to start brainstorming. A few ideas I get right off the bat: a game like Sim City where you have to build spring factories in a world covered by winter. The Silk icon set from FamFamFam contains some weather icons, but they’re really small. Perhaps I could instead build a Risk-like game by placing absolutely positioned stacks of units on a world map image? I start browsing the web for acceptable tile sets, just in case.

2:45 : I stumble upon the PlanetCute tileset (courtesy of the GameDev.Net thread on art resources). The concept seems simple enough to implement a 2D tile map quickly, and I like the grass/dirt contrast. I download (with wget) the file and unzip it into img. The water tiles are quite cute, so I’m starting to think about “Spring” in terms of “Hot Spring” or something. Anyway, I need to be drawing tiles, I might as well get that out of the way while letting my right brain think about the theme.

2:30 : through a clever combination of float:left, position:absolute and background-image CSS trickery (with some help from Firebug for empirically guessing the pixel offsets I need) I manage to render the tile map, with the possibility of a “selection” golden light overlayed on top. It’s all controlled by classes on the root tile elements, so controlling it from jQuery will be easy.

I do have a problem, however: even though the root tile elements match the flat area on top of the tile graphics, the actual tile graphics are taller, and the CSS hover property seems to detect hovering even though I’m not above the root tile per se. I have no idea about how to resolve this quickly, so I’ll give up on selecting tiles with the mouse (there are plenty of things you can do with keyboard controls, and given the time I have at my disposal, trying to fix the issue might take much too long.

In the mean time, I thought about a simple “step over tiles to paint them” gameplay similar to Q*bert. The trouble is that the existing graphical framework does not support animations, so adding enemies to the fray might be a bad idea. Yet, “paint the nodes” reminds me of graph theory, which in turn reminds me of the Bridges of Königsberg problem. I quickly decide to add non-traversable areas (I did like those water tiles) with bridges that may only be crossed once. Being able to only use a resource once means having to decide when to use it and what for, and these kinds of decisions provide a nice puzzle game design. So be it. Time to implement!

2:00 : the first half hour is the hardest, because I have to set up the general layout of the game code before I can see anything move on the screen. I go for a simple architecture in jQuery-powered JavaScript : an initialization function sets up the DOM and places references to individual DOM tiles in a 2D array. Everything related to the game will be a member of the global «g» object. The code looks like this so far:

var $world   = $('#lyt-world');
g.$t = [];
for (var y = 0; y < 6; ++y ) {
  var r = [];
  for (var x = 0; x < 9; ++x) {
    r.push($('<div class="tile"><div class="tile-img"/><div class="tile-sel"/></div>').appendTo($world));
  }
  g.$t.push(r);
}

If you’ve already done tile-based rendering, you will probably recognize the YX way of doing things: tile x,y can be found at g.$t[y][x]. I’ve also decided that a level array named «l» will hold the levels, in an array-of-strings fashion (space is dirt, tilde is water, plus is bridge and hash is stone). This is what the first level looks like:

{
  name : '1. The beginning...',
  tile : [
    "   ~~~~~ ",
    "    ~#+  ",
    "~~~+~~~  ",
    "~   ~~~ ~",
    "~~+~~~~+~",
    "~        "
  ],
  init : [1,1]
}

Another major architectural decision was how to represent tiles that had been walked on. One possibility was to implement “on step” rules which altered the map whenever the player moved (but that would involve making a copy of the map present in the level definition). The other possibility was to store the list of all positions that had been stepped on in a way that’s easy to query for “has the player stepped there yet?”. JavaScript has dictionaries so I went with the latter, so the rendering code looked like this:

render : function() {
  for (var y = 0; y < 6; ++y) {
    for (var x = 0; x < 9; ++x) {
      var t = this.map[y].charAt(x),
         $t = g.$t[y][x];

      var xy = [x,y].join();

      $t.attr('class',[
        'tile',
        [x,y].join() == this.pos.join() ? 'show' : '',
        t == ' ' && xy in this.stepped ? 'grass' : '',
        t == ' ' && !(xy in this.stepped) ? 'dirt' : '',
        t == '~' || t == '+' && xy in this.stepped ? 'water' : '',
        t == '+' && !(xy in this.stepped) ? 'wood' : ''
      ].join(' '));
    }
  }
},

This made the “step onto tile” code exceedingly simple:

step : function(xy) {
 this.stepped[xy.join()] = true;
 this.pos = xy;
},

Using Firebug, it was fairly easy to test this by manually calling the step and rendering functions.

1:45 : implementing controls meant, mostly, catching keydown events on the document, detecting arrow key presses, and calling a “try step” function with the appropriate movement vector (that function would check if the movement was possible, then call the actual step function, and finally rendering the entire thing). What took me the longest was finding out what the key values were (I eventually found out by logging the key values to the Firebug console).

The game is now officially playable. I pour myself some hot Earl Grey Tea, eat a warm pancake, and give the first level a few test runs.

1:40 : it was pretty obvious that refreshing the entire page to restart the level was not very nice. In the name of polish, I add a “try again” button.

1:35 : turning a bridge into water as soon as it is stepped on feels weird. I split the “stepped” dictionary into “steppedOn” and “steppedOff” dictionaries that are filled independently, and adjust the rendering code accordingly.

1:30 : the game is quite simple. Maybe I could make it more complex if I forced the player to finish on a specific tile? I add stone tiles to the mix.

1:25 : I implement a “all tiles painted green” function and add a test in the “step” function to check the win condition (all tiles painted green and sitting on a stone tile). Winning starts the next level. The game is now officially in Alpha! Knowing that I can now deliver this simple game as is, I decide to move on to level design and design as many levels as possible.

Also, my fiancée just fell asleep. I guess I’ll plug in my headphones before I resume listening to Rammstein.

1:15 : after a bit of testing, it appears necessary to add a level selector, if only for level design purposes (I don’t want to have to solve seven levels just to test the eight). I now have two playable levels. I guess I should start designing more: aside from the game finished screen, everything’s implemented. In fact, there’s no instructions manual or tutorial yet, and the “step on the stone tile when you’re done” idea is not really that obvious.

1:00 : I write a few short text bubble to explain the game logic, place them in a layer that is only visible on the first level, and position them in Firebug. Now, the level design can start!

0:55 : level 3 (Chess) is over. It’s pretty easy to solve.

0:50 : I search for the actual Bridges of Königsberg on Wikipedia, and implement it as a (rather simple) level 4.

0:40 : I reuse the chessboard from  level 3, add another stone tile to confuse players, solve it while stepping on as few bridges as possible, then turn the unused bridges into water tiles. Seems obvious to me, but apparently this ended up being the most difficult level in the game.

0:30 : Out of ideas. I’ll try a random layout and work from there. This ends up as level 6 (Detour).

0:25 : Still out of ideas. Let’s draw a happy face: level 7 (Happy).

0:15 : Still out of ideas. I randomly draw something up, test it, and that’s it. I would have liked to draw more levels, but there was some polishing left to do (namely, the game finished screen).

0:10 : Game finished screen is over. Let’s start packaging the stuff.

0:05 : Last minute bug fix: apparently the overflow:hidden on the tile map behaved badly when the try again and select level elements were floated to the right and were past a certain height (on certain browsers). I add a clear:both to the tile map.

0:00 : as expected, I don’t have zip on my server, my aptitude cache is not up to date, and I don’t want to risk spending 10 minutes updating it. I should have fixed that before the contest! Still. I tar-gzip the stuff, download it on a Windows computer, extract it then turn it into a zip file, and upload it back to the server. There’s no time hunting for capn_midnight’s mail address, so I just post the links in the thread.

-0:05 : I manage to locate the captain’s address, so I mail the file there.

-0:10 : ?????

-0:15 : Profit.

http://en.wikipedia.org/wiki/Q*bert

Handwriting – Apple’s new License Agreement

The latest development in the fight against 1984 is the latest License Agreement for Apple’s iPhone developer platform, which includes a new constraint on allowed applications:

3.3.1 — Applications may only use Documented APIs in the manner prescribed by Apple and must not use or call any private APIs. Applications must be originally written in Objective-C, C, C++, or JavaScript as executed by the iPhone OS WebKit engine, and only code written in C, C++, and Objective-C may compile and directly link against the Documented APIs (e.g., Applications that link to Documented APIs through an intermediary translation or compatibility layer or tool are prohibited).

There should be no problem if you play by the rules and write your software in the specified languages. Conversely, you can expect to have problems if you write your application in a different language (say, ActionScript 3) and use a program to compile and link that against the iPhone API.

There’s a grey area in-between. Suppose for a moment that you originally wrote your software in a different language (say, a Java application on Android).

Can you rewrite that software in Objective C?

Can you outsource the project to a software sweatshop in India to have it rewritten it in Objective C?

Can you have that sweatshop define an API that your Java application has to use, to help them translate instructions in the iPhone API setting?

Can that sweatshop use automatic translation routines that work on 5% of the code (such as changing source file extensions, turning “private” into “@private”…), and finish the remaining 95% by hand?

What if the tools translate 95% of the original Java into clean and readable Objective C, and there’s only 5% left to do by hand?

What if the tools handle 99,99% of the translation work, and the remaining 0,01% is mostly typing in the project’s name and a few configuration elements such as indentation style or source and destination folders?

And, if you manage to find automatic translation routines that work so well and efficiently 99,99% of the work is done by the click of a button, is it really important if the resulting code isn’t easy to read or modify?

Where is the line drawn? And is Apple going to require the application source code, in order to check?

Can Apple require that all your source code listings be handwritten?



1150 feed subscribers
(readers who polled a feed this week)