Desdemona 0.4.1

October 9, 2007

I’ve released a new version of Desdemona, my Reversi game. From the release note:

Fixed a nasty bug in the AI which could lead it to make strange (and terrible) moves near the end of the game. Also fixed an error in the search optimisation code that caused the AI to perform much weaker than it should be.

Given the latter fix I also took the opportunity to overhaul the difficulty levels. There was too little difference between them. The same range of levels from 1-10 is available, but they now represent a wider range of ability in the AI.

Difficulty level 1 is about the same as it was before. However, at level 10 it will now take about 22 seconds to search for a move, up from about 10 seconds previously. (Because of the bugfixes, however, the prior version would have to use about 5 minutes or more to perform as well!)

You can now produce human-readable JSON! There is a new method that takes options to control the formatting.

The public methods were renamed to jive better with existing Cocoa conventions. The affected methods are as follows:

  • -JSONString was renamed -JSONRepresentation
  • -JSONStringFragment was renamed -JSONFragment
  • -objectFromJSON was renamed -JSONValue
  • -objectFromJSONFragment was renamed -JSONFragmentValue

See the website for up-to-date documentation.

I released version 1 a little while ago.

Cocoa JSON Framework v0.1

September 23, 2007

I’m proud to release version 0.1 of my JSON framework for Cocoa! Other people have released code to work with JSON in Cocoa, but this would appear to be the first project to provide an stand-alone framework (an embedded one at that).

From the website:

This framework contains a collection of categories on existing Cocoa classes that together provide full JSON support. Importing the <JSON/JSON.h> header provides the following main methods:

-[NSArray JSONString];
-[NSDictionary JSONString];
-[NSString objectFromJSON];

Strictly speaking JSON has to have at least one top-level container (array or object/dictionary). Nulls, numbers, booleans and strings cannot be represented in strict JSON on their own. It can be quite convenient to pretend that such JSON fragments are valid JSON and the following methods will let you do so:

-[NSNull JSONStringFragment];
-[NSNumber JSONStringFragment];
-[NSString JSONStringFragment];
-[NSString objectFromJSONFragment];

Edited for clarity after original posting.

Updated: I’ve released version 0.2 now.

I released version 1 a little while ago.

Embedding Cocoa Frameworks

September 22, 2007

Cocoa has a really neat feature that allows you to embed a framework inside your application bundle. Why would you want to do this? Not all frameworks are available everywhere. Instead of forcing your users to install lots of frameworks before they can start using your app, simply bundle them inside your app.

You cannot simply embed any framework; it has to be built specifically for embedding. A framework is a dynamically linked library. These have the path they are installed at hardcoded inside them. (For security reasons, or some such; it’s damn inconvenient at any rate.) Normally these paths are of the form `/Library/Frameworks/`. For an embedded framework, however, we have to use something else. The special path `@executable_path` refers to the path of the executable inside your application bundle. You can then refer to the `Frameworks` directory in your application bundle by setting the installation path of your framework to be `@executable_path/../Frameworks`.

install_path.png

If you want to embed a framework inside another framework you’ll need the even more special `@loader_path`, which is only available in OS X 10.4 Tiger and later. I find this useful, so that’s what I used in the example above. Now add the framework to your application the way you’d add any other existing framework:

add_existing_framework.png

Add a “copy files” build phase and chose destination `Frameworks`. Drag the embedded framework you added into it.

copy_files_build_phase.png

Voilá!

Jonathan “Wolf” Rentzsch has a screencast that shows you in more detail how to embed frameworks. It is for a rather older version of Xcode than what is available now, but it is still good. The Cocoa developer guide to embedding a framework is also good.

Objective-C JSON again

September 13, 2007

As I mentioned in my previous post I’m currently writing an Objective-C JSON framework. Now, I’ve run into an issue that I’m not sure how to handle: JSON only supports strings as dictionary keys, but Objective-C supports other types as well, for example numbers. The bit I’m stuck on is this:

When encoding a dictionary, should I throw an error as soon as I encounter a non-string dictionary key? Or should I try to mangle it into a string?

Mangling numbers into strings will probably work reasonably well. Converting back from JSON will give you an NSString instead of an NSNumber instance back, but given that you can often treat strings as numbers this will probably work reasonably well. However. However. In Objective-C you can use nulls, dictionaries, or arrays as dictionary keys. (It might not necessarily be a good idea, however.) You simply cannot encode such structures into JSON and get something meaningful back.

Teddy-bear debugging strikes again. By taking time to formulate my predicament as a plea for help to the metaphorical teddy-bear that is the interweb things have become clearer in my mind and I have managed to reach a decision all on my own. I shall make my JSON library throw a hissy fit if it encounters a non-string dictionary key.

I’ve been playing around trying to parse and generate JSON from Objective-C the last few days. The core of the parser takes the form of a category on NSScanner, and I’m really chuffed with how neat and clear the code turned out. A tip of the hat to the designers of Objective-C and NSScanner!

A category—though originally conceived as a way to split large classes into multiple files (at least this is my understanding)—can be used to extend classes at run-time. This is a feature that is most commonly associated with interpreted languages. Used soberly it can be used to great effect to add functionality to a class without having to subclass it. You can add methods, and even override existing ones, but not add any instance variables.

The JSON Framework I’m working on provides no public classes on its own. Instead it adds a method to NSString that returns an object structure representing the JSON string. To emit JSON for a complex structure I’ve added a method to NSObject that will do the right thing for nulls, booleans, numbers, arrays, dictionaries and strings.

Please be aware that the code at point is the result of just one night and 2 days of coding. There are no docs. There are no options. There are no limits, so if you feed it carefully crafted JSON you can make my parser run out of C stack space. There is working proof-of-concept code, copyright statements, and tests.

Update 24/9/07: I’ve released version 0.1 of my JSON framework now.

I’ve updated my Connect-4 game for Mac OS X. In addition to a rename from “Puck” to “Auberon” it has the following changes (they should now sound familiar):

  • Cleaned up the interface somewhat and put some of the existing clutter in a preferences pane.
  • Added a progress indicator for things that go on in the background.
  • Added a “Check for updates” menu item to check if new versions are available, using the wonderful Sparkle framework. You also have the option to automatically check for new versions on startup.

Download Auberon 0.3 (0.25 MB disk image). Visit the homepage.

Phage 0.2.1

April 30, 2007

I just fixed a bug that caused Phage to be confused about whether you or the AI had won the game. This would sometimes cause Phage to declare that the AI won the game, when in fact you had. Pesky cheating AIs. At least I get to test whether auto-updating with Sparkle works then, which I introduced in the last release.

Download Phage 0.2.1 (0.5 MB disk image). Visit the homepage.

Phage 0.2

April 26, 2007

There’s not a lot of changes in here, but one of them should make incremental releases much more manageable. I also gave the website a little face lift, so hopefully it shouldn’t scare off people now.

The changes in this release are:

  • Added a progress indicator for things that go on in the background.
  • Added a “Move hint” menu item. Selecting this makes the AI give
    you a hint for a move.
  • Added a “Check for updates” menu item to check if new versions
    are available, using the wonderful Sparkle framework.
    You also have the option to automatically check for new
    versions on startup.

Download Phage (0.5 MB disk image). Visit the homepage.

Introducing Phage

March 27, 2007

Phage is a strategy game for 2 players, where you play against an AI (built using my game-tree search framework). The interface is a bit crude—click origin, then click target instead of drag and drop—and the featureset is somewhat limited, but it’s got the basics (making moves, undo) and I’d like it out there for people to play with.

phage.png

Previously I’ve just been re-implementing old classics (like Reversi & Connect-4), but this is completely original. After seeing some of my game-tree search work online Steve Gardner, Phage’s inventor, contacted me about creating a computer version of his game. So I did, after stalling mulling it over for about a year.

I created the core of the game logic at a hack day four weeks ago and a first stab at an interface the following weekend. A new hack day is coming up, and assuming I get the chance to hack more on Phage then, what do you think I should focus on next? A more challenging AI? Drag-n-drop of pieces? Highlight possible moves? Answers in the comments please!