Previous 20

Dec. 1st, 2009

Categories 0.2

Categories 0.2 is released. You can download a snapshot from here, or you can clone it from its public git repository:

git://codebasehq.com/bywicket/xg/categories.git

Categories 0.2 includes implementations of the object system in R5RS Scheme, in Gambit-C-specific Scheme, and in Clojure. There are minor differences of syntax among the implementations, and the major difference that the Scheme implementations don't protect against mutation as assiduously as the Clojure version does.

The -flat- and -c3- domains are included in this release, along with a couple of pages of simple examples using each. You should know going in that this implementation of C3 is inefficient. Strike that; it's prodigal. Strike that; it's SPECTACULARLY wasteful. I chose to implement the semantics and leave porting the caching code for afterward, so every method dispatch on a C3 function wastes colossal amounts of time and memory unnecessarily recomputing precedence lists. There are other inefficiencies to fix, too, but that's the one that's likely to make your eyes bug out.

Categories is in the public XG repository now. You can find a few notes about that repository here. The XG repository provides access to various code and other things that are part of the ongoing Explorers' Guild gaming project. I'm reorganizing it a bit to move older things into archive locations, and make for smoother access to newer pieces of code that will be added to the public repo as I get them ready. Besides Categories, a few other pieces of infrastructure software will be packaged for separate release there soon. Mostly, these are pieces of the XG project or related commercial products. Several of these can conveniently be packaged for separate open-source release, and they'll be there as soon as I have a chance to do that.

Eduardo Cavazos reports that he has Categories 0.1 running on several R6RS Schemes. One thing I plan to do for 0.3 is provide an R6RS version in the release.

Have fun, and report bugs.

Nov. 23rd, 2009

Flat Cat in a C3 Vat

I'm getting close to a 0.2 release of Categories. Changes include:

  • A Clojure version
  • A version that targets Gambit-C
  • The -c3- domain is implemented, and -c3- examples are included
  • Several bugs are fixed
It's worth noting that the initial implementation of -c3- is spectacularly inefficient. It doesn't have to be that way, but it was easiest to concentrate first on getting the domain to work right, and worry about caching and other obvious optimizations afterward.

Another interesting point is that Eduardo Cavazos got the 0.1 release working in Ikarus and Ypsilon, which are both R6RS Schemes. I already planned to include an R6Rs version in a forthcoming release; Eduardo's kind efforts will likely make that happen faster.

The rest of this post walks through a little of the test code I've been using, as examples of working with the -flat- and -c3- domains.

First, let's define a few types.
  (define <user> (structure () username password))
  (define <admin> (structure (<user>) roles))
  (define <trial> (structure () start-date))
  (define <trial-user> (structure (<user> <trial>)))


If you're used to Java or C# or C++, you might be tempted to think
that <trial-user> inherits from <user> and
<trial>. It doesn't. In Categories, types don't have
inheritance. The definition of <trial-user> includes
<user> and <trial>, which means that it has all the fields
that are defined in those types. We haven't defined any inheritance
yet, though. Inheritance is possible, as we'll see shortly, but it
belongs to domains, not types.


Now let's define a function:

(define print-user (function -flat-))

This function belongs to the -flat- domain. -flat- is a very simple
domain that supports polymorphic functions, but not inheritance. That
means that if you define a method on <number>, then it will run
only if you pass an argument of type <number>. Passing an
argument of type <integer> won't select that method, because
<integer> is not <number>. -flat- does not support
inheritance. The disadvantage is that you can't automatically inherit
behavior in -flat-. The advantage is that it's simple and fast--and
you don't automatically inherit behavior. Hey, sometimes you don't
want to inherit.


So far, the function print-user doesn't have any methods. Let's add
some:
(add-method! print-user
            (flat:method ((u <user>))
                         (newline)
                         (display "User: ")
                         (display (get-key u 'username))
                         (newline)))

(add-method! print-user
            (flat:method ((u <admin>))
                         (newline)
                         (display "Administrator: ")
                         (display (get-key u 'username))
                         (newline)
                         (display "  Roles: ")
                         (display (get-key u 'roles))
                         (newline)))

(add-method! print-user
            (flat:method ((u <trial-user>))
                         (newline)
                         (display "Trial user: ")
                         (display (get-key u 'username))
                         (newline)
                         (display "  Start date: ")
                         (display (get-key u 'start-date))
                         (newline)))

The macro flat:method is a convenience provided by the -flat- domain
that creates a method suitable for use with -flat- functions. Now the
function print-user has three methods that work on three different
types. Let's try them out.


First we need some values to use as inputs:
(define $user (make <user> 'username "fred" 'password "dino"))
(define $admin (make <admin> 'username "joe" 'password "f23Zb!" 'roles '(gm dev)))
(define $trial (make <trial-user> 'username "noob" 'password "noob" 'start-date "2009-11-11"))

Now we can call print-user on them:
(print-user $user)

User: fred

(print-user $admin)

Administrator: joe
 Roles: (gm dev)

(print-user $trial)

Trial user: noob
 Start date: 2009-11-11

Categories dispatches on more than one argument. Let's define a
two-argument function and see how that works:

(define times (function -flat-))

(add-method! times
            (flat:method ((n <integer>)(x <integer>))
                         (* n x)))

(add-method! times
            (flat:method ((x <integer>)(y <integer>)(z <integer>))
                         (* x y z)))

(add-method! times
            (flat:method ((n <integer>)(s <string>))
                         (apply string-append (vector->list (make-vector n s)))))

(add-method! times
            (flat:method ((n <integer>)(s <symbol>))
                         (make-vector n s)))

(times 2 3) ; => 6
(times 2 3 4) ; => 24
(times 2 "Foo") ; => "FooFoo"
(times 2 'bob) ; => #(bob bob)

Notice that (times 2 3) calls a different method from (times 2 "Foo")
or (times 2 'bob). The difference is the second argument: in the first
example it's an integer; in the second, it's a string; in the third,
it's a symbol.

Okay, what if you want inheritance? Well, you use a different
domain. The domain I just added, -c3-, supports multiple
inheritance. We can write the same examples for -c3- with just a few
changes. First of all, let's tell -c3- about the new types we created:

(c3-dom:derive-type! -c3- <user> (list <anything>))
(c3-dom:derive-type! -c3- <admin> (list <user>))
(c3-dom:derive-type! -c3- <trial> (list <anything>))
(c3-dom:derive-type! -c3- <trial-user> (list <user> <trial>))

The type <anything> is the root of the -c3- type graph;
everything inherits from it one way or another. c3:derive-type! is a
convenience provided by -c3- for telling the domain about new
types. All you have to do is tell -c3- what supertypes you want a new
type to have; it figures out the rest.

Notice that in -c3-, <trial-user> inherits from <trial>
and <user>, just as you would expect. There's an important
subtlety here, though. The definition of the <trial-user> type
gave it the same fields as <trial> and <user>. The
c3-dom:derive-type! function made it inherit from those two types. The
important point is that it doesn't have to inherit from the
same types that it includes. Sometimes you want to say that a new type
is a subtype of some other type, but you don't want to inherit all
fields of the parent types. Representation and taxonomy are two
different things, and Categories doesn't force you to combine them,
though you can if you want.

Okay, now how do we write a polymorphic function in -c3-? The same way
we did it in -flat-, except that we make a -c3- function instead of a
-flat- function, like so:

(define print-user (function -c3-))

This definition replaces the old one, so print-user is no longer a
-flat- function. You can have both -c3- functions and -flat-
functions; they just can't have the same names.

Now let's add some methods again:
(add-method! print-user
            (c3:method ((u <user>))
                       (newline)
                       (display "User: ")
                       (display (get-key u 'username))
                       (newline)))

(add-method! print-user
            (c3:method ((u <admin>))
                         (next-method u)
                         (display "Admin roles: ")
                         (display (get-key u 'roles))
                         (newline)))

(add-method! print-user
            (c3:method ((u <trial-user>))
                         (next-method u)
                         (display "[Trial]  Start date: ")
                         (display (get-key u 'start-date))
                         (newline)))

This time we use c3:method instead of flat:method. c3:method is a
convenience that, you guessed it, creates a method suitable for use
with -c3-. (Actually, at this point there is no significant difference
between the two kinds of method, but the important point is that there
could be. A user-defined domain is free to represent type
relationships and method signatures any way it wants).

Notice that the -c3- methods are a little bit shorter. That's because
they take advantage of inheritance to reuse the code defined for
supertypes. The methods for <admin> and <trial-user> call
next-method to reuse the code defined for <user>.

Here's the output:
(print-user $user) ; =>

User: fred

(print-user $admin) ; =>

User: barney
Admin roles: (gm editor)

(print-user $trial)

User: noob
[Trial]  Start date: 2009-11-11

Notice that I didn't redefine any of the types, and I didn't recreate
any of the instances. Changing domains affects only the taxonomy. The
types and their instances don't have to change at all. you can reuse
the same types and values in several different domains at the same
time.

The two-argument functions work similarly, but again we can leverage
the fact that -c3- supports inheritance:

(define times (function -c3-))

(add-method! times
            (c3:method ((n <number>)(x <number>))
                         (* n x)))

(add-method! times
            (c3:method ((x <number>)(y <number>)(z <number>))
                         (* x y z)))

(add-method! times
            (c3:method ((n <number>)(s <string>))
                         (apply string-append (vector->list (make-vector n s)))))

(add-method! times
            (c3:method ((n <number>)(s <symbol>))
                         (make-vector n s)))

(times 2 3) ; => 6
(times 2 3.0 4.0) ; => 24.0
(times 2 "Foo") ; => "FooFoo"
(times 2 'bob) ; => #(bob bob)

We don't have to define methods specifically for <integer> and
<float> in -c3-; the <number> method works on values of those
types just fine, because -c3- defines <float> and
<integer> as subtypes of <number>. Otherwise, the behavior
of this function is the same as in the -flat- domain.

Nov. 22nd, 2009

Categories Bugs

There are some. I thought I'd warn people, because a few people seem to be using it.

Probably the worst is that method tables are unintentionally shared. That;s fixed in 0.2, which will be out after I get the -c3- domain done.

Category types use the wrong predicate. Oops. Also fixed in 0.2.

The current draft of 0.2 has working versions in Clojure, and in Gambit-specific Scheme. The port of the -c3- domain from earlier implementations of Categories is about half done, so expect 0.2 to contain that domain as well. It acts pretty much exactly like CLOS, so it's a way to have CLOS in Scheme or in Clojure, if you want it (that's what I initially wanted out of this exercise).

Eduardo Cavazos reports that my naming convention for domains (like -flat-) is not going to work in r6rs. Rats. I'll have to think of something else.

You Got Chocolate On My Peanut Butter

Eliot Lefevre writes, "what systems would you like to see combined?" Just yesterday, one of my game-playing buddies and I were talking about this very subject, perhaps because I've been playing WoW again lately. I already posted on the subject of things Blizzard could take form other games, but we got more specific in our conversation of lunch.

So let's build the ultimate MMORPG in our imaginations, by grabbing all the best features and cramming them together. Let's start with Champions, because we always start by creating characters, and they've got the best character creator. We can keep their Power Sets idea, too. To heck with classes. Give me a giant buffet menu of all the abilities and let me mix and match. The results are way more fun and varied than in WoW, and sometimes players discover totally unanticipated combinations. Who expected Power Armor to combine so well with Sorcery?

The Champions engine has some nice improvements over Blizzard's, too, including its collision-handling and much better use of line-of-sight. The destructible, throwable objects are good, too; let's have those.

Forget the Champions world, though. B-O-R-I-N-G. Instead, how about we round up Blizzard's world-designers and have them come up with a huge, varied world with zillions of completely different places in it, and all sorts of eye-popping scenery. We won't have them build it, though. Instead, let's get the Guild Wars scenery folks to do that, so that it all looks totally breathtaking, and then bring in the Lord of the Rings Online scenery folks to go over everything and give it all the incredible polish and detail that they give to everything. Then we should have them stick around and keep on doing what they do. We'll have them continue to make changes and improvements all the time, continuously. Instead of staying the same as it was when you first went through it, each zone will gradually change, little-by-little, with new NPCs, new buildings (and old ones tumbling down), new quests, and new destinations, so there's always a reason to go back and visit places you've already seen.

While we're building the world, let's pop over to Darkfall and scoop up the goblins. Darkfalls' goblins don't just spawn and stand around waiting to be killed. They have their own business, and they work together. If you outnumber them, they run and get help, or kite you into an ambush. Let's have some of that. Instead of utterly brainless wolves and bandits standing around sucking their thumbs, waiting to be killed and respawn, let's have herds of elk that move as a herd, that move defensively and try to avoid becoming food. Let's have wolves that hunt in packs. Let's have bandits who are actually trying to mug somebody, and villagers who try to defend their villages. In short, let's have some mobs with actual behavior.

But when the Blizzard world designers start segmenting the world up into level-specific zones, we need to step in and make them stop. We don't want our world to turn into nine deserted ghost towns for every one bustling community. We've got those excellent Turbine guys putting touches of inspiration on every little feature of the world; we want people to see their work. So let's arrange things so that people have a reason to go everywhere.

The Warhammer guys did a good job of weaving the Order and Destruction sides together, tracing their paths over and under and alongside one another. Their world map was crazy, and their travel system didn't help things hang together, but they did a terrific job of arranging things so that the two side were in their own worlds, and yet were brought together at intervals to duke it out. Let's have some of that, and we'll use that technique to thread different levels of challenge through every zone, so that there are good reasons for characters at every level to go everywhere, instead of sucking all the juice out of a zone and them leaving it forever.

Speaking of levels, let's ditch them. At any rate, let's toss out "experience levels". Instead, let's turn "experience" into skill in the power sets. We'll swipe another page from Darkfall and EVE, and have using your abilities earn skill that can be used to buy new, related abilities. User your abilities and your skill in them goes up; neglect them and it goes down. We'll add to that a Deeds and Traits system like the one in Lord of the Rings Online, so that, not only do you earn skill by using your abilities, but achieving certain milestones in the use of your abilities opens up new lines of enhancements. As in LOTRO, we can scatter these all over the game for players to discover. Some will come naturally from your playstyle. Others will be easter eggs hidden about the landscape, a great reason for people to explore the whole world.

We already ditched classes in favor of Power Sets; let's hide new Power Sets around the landscape, too. Achieve certain Deeds, and you discover new Power Sets opening up. Some Power Sets can come from NPCs; earn enough reputation from certain factions and special NPCs begin to offer you abilities from previously-hidden Power Sets.

That brings me to factions and things related. Blizzard's use of factions is all well and good. It's nice that each new expansion brings in a new rivalry between new sets of factions. It's nice that earning reputation with a faction earns you the opportunity to acquire new enhancements and customizations. But why stop there? Let's give players the opportunity to create their own factions, and add their own enhancements and customizations. Let's just grab the player towns and player fortresses from Darkfall and Age of Conan, and plop them into the game. We won't stop at being able to build a town, though. You can fortify your town, make it a fortress with all sorts of booby traps, suitable for guild-on-guild battles, as in Guild Wars. But you can also populate your town with vendors, and take a cut of their sales. You can associate a faction with your town, and offer reputation rewards to other players. You can put questgivers in your town and have them hand out quests that you design. If you design crappy quests, of course, you won't get much traffic. So let's reward you if you create great ones. When a player completes one of your quests, he can cheer or boo it to the questgiver, and if you get lots of cheers, you earn the opportunity to expand your faction's NPCs, buildings, rewards, and so on.

Yeah, people will abuse that system, no doubt. We'll have to playtest it for a while to see how to work in controls reward curves and and deterrents, so that reputation-trading doesn't get out of hand. The goal is to create an incentive for players to help us build and change the landscape. We don't want the world to be static; we want it to be alive and growing, and changing all the time, so there's always something new to see.

Speaking of potential for abuse, let's steal a bunch of ideas from the Sim games. Remember SimAnt and SimLife and SimEarth? Or how about Spore? Yeah, I know; Spore was disappointing. But you can make new critters! And in SimLife and SimEarth, your critters ran around eating and pooping and having babies, and the world changed and grew! Let's have that. In Champions, you also use their character creator to create an archenemy for yourself. In Star Trek Online, you'll be able to use it to create new alien races. Let's have some of that, too. We'll have our designers continually introduce new lifeforms and new civilizations, and we'll let players earn opportunities to do it, too.

Naturally, that means we'll have to have someone on staff to delete all the giant walking penises and boobs. Oh, well. C'est la vie.

Since we're adding new critters, let's snag some ideas from Eskil Steenberg's LOVE and make it possible to add and change the landscape, too. Let's start with the layout of the map. Let's say the world isn't a planet, first of all. It's a big flat expanse, and when you come to the edge, you don't fall off; you discover new places. Yeah, we'll have to set a limit on how fast you can do that, but discovery at limited speed is still way better than just bumping your head against an invisible wall. In fact, we can steal another page from EVE and relax the rules a little as you get out away from the center of the world. We can make it pretty hard to make big changes in the center, where the canonical game content is, but easier out on the fringes. It's sort of like the center of the world is also the realm of Order, and the far-distant edges are the realm of Chaos, where anything goes. Well, maybe not anything; but more things. That makes a handy arrangement for world PVP, too. As in EVE, you can be safe from predation if you stick to the realm of Order, but if you relish the danger, you can head out into the lands of Chaos. That also has the nice effect of automatically creating a sense of danger and adventure when you venture outside the safe areas because, well, you're likely to be killed.

Another things I want to swipe from Guild Wars is its system of NPC party members. Let's grab that, and combine it with WoW's pet controls. How many character can you effectively control at once? Well, Myth had some pretty cool group control for pretty large groups, back in the day. We could experiment some with that. Guild Wars is great in that nothing prevents a solo player from tackling group quests. you just have to be able to control a party of pets effectively. With that design, you can plop challenges for all different team sizes all over the map, and they're open to everyone. You can get together a group of friends to tackle a team challenge, or you can put together a big group of pets. Cryptic says they'll be borrowing that idea for Star Trek Online. Good plan.

All around the realm of Order, out away from the center, but not as far as the realms of Chaos, we can sprinkle rich resources and defensible lansdscapes. We can put abandoned castles and fortress all around. Let players seize the forts and try to hold them. A successful team that holds onto a fort and the region it guards can accumulate NPC serfs to enrich them and supply conscripts for their armies. An ambitious team might embark on a war of conquest and try to build an empire. Two or three such empires might go to war over the resources. Their epic battles might attract more player recruits, as in Darkfall. These Border Kingdoms will be dangerous for travelers, but exciting for the adventure-minded, and profitable for traders willing to brave the danger.

I guess I'd better stop, because I don't seem to be running out of things to describe, and this post is getting mighty long.

Nov. 19th, 2009

Different Categories of Categories

Before adding -c3- and -pred- to the Scheme version of Categories, I thought I'd see how long it would take to do the port back to Clojure. Turns out not very long at all. It's done (at least, to the same point as the Scheme version).

I wondered how to two versions would compare. The Clojure version is about 800 lines of code; the Scheme version is about 900. Pretty close. One important difference is that Clojure provides some amenities that R5RS Scheme doesn't--mainly, it provides a handy built-in associative array type, and a (slightly non-obvious) way to define your own appliable function-like objects. Those are definitely conveniences. So how come the size advantage of Clojure wasn't greater? Well, that's Scheme for you, I guess. Even when you write your own implementation of record types, it's not that much code.

So can you get the Clojure version yet? No. I want to add in -c3- and -pred- first, and fix a bug I found in the 0.1 release (the bowels of the Category code uses the wrong predicate function in once place). n good news, Categories 0.2 should be available soon, and it'll include the Clojure version. I'm speculatively eyeing R6RS now, wondering how much work it would be to make a version for that Scheme standard. Actually, it's more like I'm curious what the new features in R6RS might buy me. And I'm also idly wondering what the results would be like if I did a version in Common Lisp.

Stay tuned.

More WoW

I've been playing World of Warcraft again lately.

After more than four years of playing it, I gradually lost interest and stopped playing. Finally, last August I cancelled my account, because I hadn't really done anything in the game for months. I had sucked all the juice out of it.

I didn't stop playing MMORPGs. For years now, I've had multiple MMORPG subscriptions. I watch new releases closely, and I periodically drop some subscriptions in order to pick up others and try them out. I'm fiercely interested in the design of MMORPGs, in the variety of possibilities and the limitations of the genre. I have my own wishes and ideas, and whenever a game tries something similar to what I want, I'm really interested to see how it plays out. So I've continued to play MMORPGs; I had just lost all interest in WoW.

What drew me back again was my friends. As I've said to them many times, playing with friends is more interesting to me than anything else about these games. If we have a group of good friends playing on a regular basis, I'll enjoy a game immensely, even if it would bore me silly to play it alone. So when a few regular companions expressed an interest in a WoW project, I wasted no time in reactivating my subscription.

It's interesting to come back to what has become the gold standard of MMORPGs, after the better part of a year spent with its competitors. Returning to WoW, it's clear why it remains the 800-pound gorilla in the market. No other game can match its combination of breadth, variety, polish, fun, and performance. Other games exist that beat WoW in each of these areas, but none that can compete with it in all of them at once.

Still, WoW isn't perfect. The things that drove me away are still there, and if it weren't for the projects with friends, I wouldn't be playing it. Maybe Cataclysm will change that; we'll see.

In the meantime, this seems like a good opportunity to make a few observations about things WoW could do to make itself a better game. It's very good now; don't get me wrong. I didn't leave because it was bad, but because I was tired of certain things, and wanted to see what I could find elsewhere. Well now I'm coming back, and I have to say, I found some pretty cool things while I was away. I;d like to see WoW adopt some of them.

Everything Old Is New Again

Blizzard is already planning to do some of what I want, and I couldn't be happier. One thing that I found in Lord of the Rings Online is a developer that constantly revisits the entire landscape of the game, making little changes and improvements everywhere, across the board. If you start a character in LOTRO today, the quests you pursue and the path you take will be quite different from what it was the first time I played. This constant reworking keeps making the game world better, richer, and more appealing. The questlines get deeper, smoother, and more interesting. The changes draw players back again and again to create new characters and experience the world all over again, but not in exactly the same way.

Now Blizzard, of course, has their own way of going about this, but they are, in fact, planning to rework their world and the starting areas. Where Turbine does it a little bit all the time, continuously, Blizzard is of course planning a big bang release that dramatically remakes the familiar old world all at once, in one go. I like Turbine's approach better, I have to say, but still, I have no doubt that Cataclysm's huge makeover of WoW will be fun. Bravo, Blizzard. I only wish you had taken the lesson from Turbine sooner, and more faithfully. It wouldn't hurt WoW for you to put a team on reworking the whole world a little at a time, all the time, as they do. It would help keep every part of the world fresher and more intriguing, and would give you many chances to strengthen weak questlines and movement patterns. Not to mention that just sprinkling simple changes around the world all the time would help counteract the feeling of stagnation and stasis that sets in after a zone has been around for a while. Give players a reason to explore old areas, and maybe they won't be such ghost towns anymore.

There might be some hope in this area. Blizzard does learn from the successes of its competitors. It adopted an achievements system that bears a striking resemblance to the Deeds system in LOTRO (though the one in WoW is pure fluff, unlike the LOTRO version). It recently introduced legendary items like the ones pioneered by LOTRO, as well; another good move.

Talent Show

Any experienced WoW player can talk your ear off about "talent trees". Like most MMORPGs, WoW divides its characters up into classes, each of which has an exactly-specified set of abilities, and a set of group roles it is designed to play. Each class can be customized to some extent by using "talent points", acquired through leveling, to buy customizations called "talents". For each class, the talents are arranged into three sets in which later, more desirable talents require you to acquire earlier, less desirable talents, before they become available.

This is all fine, as far as it goes, and Blizzard's execution is certainly stellar in this area. They go to great lengths to play-balance all the classes and abilities to ensure, to the extent that it's possible to do so, a level playing field for all players. I'll acknowledge how tough this is, and certainly Blizzard's competitors have a pretty mixed track record in play-balancing, and in designing classes and customizations that play well together. Still, WoW's ten classes with three talent trees each feel pretty constricted to me, coming back from the wide world of other possibilities.

Consider Warhammer Online, with its twenty-four different classes, all distinctly different from one another. Dont' bother to remind me of the play-balance issues; I'm well aware of them. I acknowledge that they're a problem. But the variety, oh, the variety! Some of those classes are really interesting ideas; consider the Disciple of Khaine, a melee healer! Some are just buckets of fun in their very concept, like the Witch Hunter, or the Magus of Tzeench. (I'll also take Warhammer's vile, idiotic, and hilarious Greenskins over WoW's noble--and boring--Klingons in green paint any day of the week, but that's another conversation).

Champions Online takes it farther. Their eighteen classes are not really classes; they're just bundles of abilities that are designed to have a common theme and to work together smoothly. You can stick to one of these "Power Sets" if you want to. If you don't you're free to treat the Power Sets as a buffet lunch, and take a little from this and a little from that, as you like. Players can compose completely original combinations and invent entirely new playstyles. It's the most fun I've had in character-creation since...well, ever. Again, I'm well aware of the problems and disadvantages, and, on balance, I still think their approach is a good one.

So what would I like to see from WoW in this area? How about letting us buy abilities from a range of classes, rather than just one? How about opening up the talent trees, and letting us mix and match from those, too? It doesn't have to be a total free-for-all. I think the principle of making later customizations depend on earlier ones is a good one. But I think you could take the class abilities and talents out of their locked boxes and redesign them to support a style more like that of Champions. I think you could open the framework up a little, and let players in effect design their own classes by combining elements from two or more of the standard ones. I think if you did that, you would also open up the possibility that, instead of introducing some new hero class, you could instead introduce a new set of abilities and a new line of talents, and watch what players make of it.

Would it introduce new play-balance problems? Sure. Would some combinations be overpowered and require rebalancing, while others would be unusable? Sure. But you would also see players inventing completely unheard-of new playstyles, some of which would be great fun, and would inspire new feats of creativity in the developers. I think Blizzard could make it work, and could make it a ton of fun.

Ghettoes and Ghost Towns

WoW shepherds players pretty relentlessly through its zones. You start in one of the starting areas and within five levels you move on. You move on because you have to. If you don't, the quests dry up. There's nothing left for you to do. That dynamic continues through the game. If you're not questing somewhere, you have no reason to be there at all, so WoW players are, perforce, nomadic. There isn't anything like the Orc Fort on Ultima Online, and there can't be. You can't have a home in WoW because you always have to move. The inevitable result is that three quarters of that lovingly-crafted world is deserted at any given time, because no one has any reason to be in most of the zones.

But what if zone boundaries and level boundaries weren't so much the same? The way WoW's world is laid out now, the map is segmented into several dozen big chunks, each of which is dedicated to a particular level range. It's easy to understand why: that arrangement makes it easy to collect all the quest lines for a particular level range into a space that is easy to conceive, easy to design, and easy for players to navigate. But it doesn't have to be that way. What if instead a zone was just a geographic region with a common theme, and the questing paths for various levels were a completely separate thing? What if all the zones in WoW had questing paths for a wide variety of levels? What if subzones of mobs and destinations for low levels were woven through the landscape side-by-side with mobs and destinations for high-levels? In short, what if it were possible for lower levels to move productively through more the world? And what if there were reasons for higher levels to be in zones that are now deserted?

Low levels would then have a sense of exploring an even larger and more diverse world, one that is not so much closed off to them. Higher levels would have reasons to be in most of the world's zones, instead of only a select few. All that lovingly-crafted landscape wouldn't go to waste, sitting empty with tumbleweeds blowing through them ninety percent of the time.

Sure, there are logistical and design problems to solve, but I think it's worth it. Champions shows that the basic idea is workable. Their maps have other problems--too little variety, for one thing--but they do a fine job of intermingling high- and low-level content in a way that keeps characters of all levels moving through the whole landscape.

What We Fight For

I always enjoyed large-scale PVP battles in WoW, but I've always had problems with them, too. I began in WoW PVP before the introduction of the Honor System. The only reason for PVP battles was that they were fun. The Alliance and the Horde would fight for hours over the few hundred yards that separate Tarren Mill from Southshore. We weren't fighting for any objective; we were just fighting because it was fun.

Eventually, though, Blizzard introduced the Honor System, and rewards that required rank earned through PVP. Then it introduced Battlegrounds, and more rewards, and new ways to earn them in PVP games, and Arenas, and so on. PVP became a grind. Everything in WoW becomes a grind, by design.

A member of the venerable Shadowclan guild, which has been around since the dawn of MMORPGs, put it this way: if you can't loot other players, then the game will become a grind for gear. If you can loot other players, then it becomes a community. That's sounds wacky at first. What's the reasoning?

Well, think about it. In WoW, if you die in PVP, what are the consequences? You get up, dust yourself off, and run back into battle. That's it. In Ultima or Darkfall, if you die, the other side takes all your stuff, unless your friends are on the ball, drive them back, and grab it for you. Sounds terrible, right? But what does it mean for gameplay?

If you can't lose your stuff, there aren't really any consequences to losing. And if you can't take loot from the foes you defeat, there's not much incentive to beat them. It just doesn't matter very much. So how, as a game designer, do you get people into your lovingly-crafted battlegrounds? You give them rewards! What kind of rewards? Well, what's the one thing MMORPG players want more of? RIght! Better gear! So you churn out better and better gear, and you award it to players for playing longer and longer hours in your battlegrounds. And they clamor for more and better gear, because, heck, that;s what they're playing for. So you up the quality of gear some more, and make them play longer hours for it, and the whole thing inevitably becomes an endless grind. And, inevitably, because people are there to "earn" gear upgrades, and not to have fun fighting in a battle, the battles are stacked full of whiners and slackers who contribute little or nothing to the team effort. You start to need mechanisms to punish all the free riders who join a battle but don't do anything, because they aren't interested in the battle, just in the gear they can get by being in it.

What if you can take lot from other players? Well, one thing that happens is that they really don't want to lose. Another thing that happens is that if someone brings some epic weapon or armor to the battlefield, all his enemies want to kill him and take it away from him. So pretty soon, nobody wants to bring epic gear to the battlefield. SO gear isn't very important anymore, because nobody wants it anymore.

So what is important? What makes it worth fighting?

It turns out that there are a lot of different answers to this question, and a bunch of different games have demonstrated them. One thing that makes it worthwhile is the same thing that makes bowling leagues or bridge clubs worthwhile: you can get together with some friends and have some competitive fun. There will be winners and losers. You can root for your friends and help them try to win. Guild Wars maintains tournament ladders for a variety of different types of PVP games. For a lot of people, placing on those tournament ladders is a good enough reason to enter the competition.

Another reason to play is to pitch your flag at the top of the hill and keep it there when other people are trying to knock it off. Several games offer variations on this kind of play. Warhammer Online, for example, enables a guild to capture a keep and claim it. When they do, the keep flies the guild's flag. Vendors appear who owe their allegiance to the guild. Taking the keep away from them is tough (hey; they're forts!), but it's also a lot of fun, and awards some nice rewards in the form of experience, money, and other in-game goodies. It turns out that it's fun to fight for a collective objective, rather than to just grind away hours in battlegrounds because eventually that will "earn" you some gear.

Another reason to fight is because you've built something at the cost of some time, effort, and money, and you don't want someone else to take it away from you. Age of Conan and Darkfall both have ways for guilds to build towns or forts. It's not cheap or easy to do, but once you have one, it's a relatively safe haven where you can visit vendors, rest between adventures and battles, and enjoy the company of your friends. But once the town is built, your enemies know where to find it, and sooner or later, they'l attack it. If you want to keep it, you'll have to mount a defense.

Al of these PVP mechanics have challenges and problems. Some developers have solved them better than others. Guild Wars, in particular, has a stellar reputation for the quality of its PVP games. All of them, though, offer alternative possibilities that don't necessarily involve and endless, colossally repetitive grind for slightly better gear.

You Can't Go Home Again

I've barely scratched the surface of things that Blizzard could learn from its competitors. And maybe it will; Blizzard remains one of the best game companies on the planet. They clearly aren't standing still. They've already adopted many practices pioneered by other games, and sometimes they improve on them in the process (and sometimes they don't).I hope Blizzard continues to learn from the best that other games have to offer.

Am I back to stay? We'll see. Certainly I'll play WoW as long as a group of my friends has a project going. I still have trouble staying interested in solo play, though. If I'm not working toward a goal set by my play group, I lose interest quickly. Maybe Cataclysm will turn that around for a while. At the least, it will be interesting to see the revamped world. The playable Worgen and Goblins will be good for at least some fun, too. And who knows? Maybe Cataclysm will bring with it enough of what;s good in other games to make we want to play WoW again for its own sake.

Nov. 18th, 2009

Up pops a reasonable facsimile thereof

A preliminary release of Categories is available for those who want to play with it. There are various pros and cons.

Pro:

- it's written in R5RS Scheme, per a reader's request, so it should be possible for many people to grab it and poke at it.

- it's brief. The README describes the entire API. You should be able to see how everything works by reading just categories.scm and flat-domain.scm. You can read the rest of the code if you want to know what the guts are doing.

- it includes an example domain in flat-domain.scm, and some examples of using it in flat-domain-examples.scm. The -flat- domain is implemented in 65 lines of code.

- it's free, as in, under the Apache 2.0 license. If you find that you like it, you can use it.

Con:

- It's written in R5Rs Scheme. It's probably slow. There are some obvious things to do to make it faster, but not really any obvious way to do them portably in R5RS Scheme.

- It's brief. The -flat- domain is all you get for now. Implementations of -c3- and -pred- are coming, though.

- it's probably buggy; it's brand new.

You can get it from this page.

Feel free to send bug reports to mevins at me dot com.

Nov. 11th, 2009

No Kings in Rome

Google recently announced a new system programming language called Go. I've said before that I'm a Lisp hacker at heart, and I always end up liking Lisp better than anything else. I don't mean Common Lisp; I mean any Lisp. I call the Lisp family of languages home. I'm always messing around with Lisp to try to increase the Joy.

I remain interested in other languages, though, and new ones always catch my eye. I'm extra interested--and extra skeptical--when someone goes after C's niche with a new language, which is what Google is doing with Go. So I popped over to the Go site and right away noticed two names among the designers of the language: Rob Pike and Ken Thompson. Okay, that makes it extra interesting. (If you don't know why, go Google those guys.)

Then, while reading about their design decisions, I noticed something else really interesting.

Let me back up a minute.

I've been making steady, if slow, progress preparing Categories for a general release. If you're one of the couple of people champing at the bit for me to release it, have patience. It's coming along. I have to put most of my effort into things that will pay bills, so Categories development happens in small chunks, in between other things. Almost the entire surface syntax from A Peek at Categories is now implemented, with a few small changes. The main new feature is the syntax for explicitly specifying a domain in a function definition, which looks like this:

Without explicit domain:


(define-method add ((x <integer>)(y <integer>))
(+ x y))


With explicit domain:


(define-method add ((x <integer>)(y <integer>)) :: -c3-
(+ x y))



The one missing piece now is the syntax for renaming structure keys in includes.

Oh, and to the Concerned Reader who requested an implementation using define-syntax, I've done that, and it's working fine.

Why did I start talking about Go, then switch to Categories? Well, I found something in the design discussion of Go that I had already found in working with Categories. As I mentioned in A Peek at Categories, the default domain is -c3-, a domain that implements method dispatching in a fashion very similar to the way that CLOS and Dylan do it. That's just one domain of potentially many, though, and the Categories implementation includes two other example domains: the -pred- domain and the -flat- domain. The thing is, in experimenting with domains, and with category types, I was liking the -flat- domain more and more.

A quick refresher: the -flat- domain implements polymorphic dispatch, but without inheritance. There's no support in -flat- for supertypes. A function either has a method that matches the exact types of its passed arguments, or it doesn't. If it doesn't, there's no looking up supertypes to match, because there are no supertypes. This decision makes method dispatch very simple and efficient.

But how do I write generic, extensible APIs, then? you may ask. How do I use Categories to reuse code? Okay, first of all, my experience has been that code reuse sounds better in theory than it tends to be in practice, but don't despair; I'm not killing it off in Categories. First, you can add methods for new types to extend your APIs. Second, your method is free to reuse another method by passing arguments of the appropriate types. Third, category types provide an easy way to write methods meant to apply to a collection of types. Finally, if you really can't live without a type hierarchy, you are free to use -c3-, or write your own domain.

I initially designed -flat- just to serve as a limiting case. It was meant to be an example of the simplest kind of dispatch that actually does some dispatching, and nothing more. In using it, though, I've begun to actually like it more and more. Besides being efficient, it eliminates pretty much all of the complexity of multiple inheritance, without losing much. Category types make it easy to compose methods that are generic across arbitrary sets of types. You can add a new category any time you need one, and you need not concern yourself at all with the effects of any existing type hierarchies, because there aren't any.

What does this have to do with Google's new system programming language? Well, the Go designers seem to have come to the same conclusion about type hierarchies. In Go, types don't support inheritance. There are no subtypes or supertypes. To quote from the Language-design FAQ:

"Rather than requiring the programmer to declare ahead of time that two types are related, in Go a type automatically satisfies any interface that specifies a subset of its methods. Besides reducing the bookkeeping, this approach has real advantages. Types can satisfy many interfaces at once, without the complexities of traditional multiple inheritance. Interfaces can be very lightweight—having one or even zero methods in an interface can express useful concepts. Interfaces can be added after the fact if a new idea comes along or for testing—without annotating the original types. Because there are no explicit relationships between types and interfaces, there is no type hierarchy to manage or discuss."
 
Yeah. That's what I've been liking about the -flat- domain, too.

I'm thinking of making -flat- the default domain.

Oct. 31st, 2009

I'm a Busy Bee

Apis 1.0 is now ready to go. You can get it here.

Apis 1.0 is essentially the same application as Atta 1.0, but written in Common Lisp, using Clozure Common Lisp, instead of being written in Scheme using Gambit-C. The structure, appearance, and behavior of the two applications is nearly identical, so they may provide useful illustrations of the differences between Cocoa development using CCL versus using Gambit.

There are various superficial differences that you might notice right away. One is that Atta.app is about 7.5MB, while Apis.app is about 34MB. The size difference basically reflects the difference in features built into Common Lisp versus those of Scheme. Scheme is a much more compact language, which has its pluses an minuses. On the one hand, the Scheme application is much smaller. On the other hand, a developer will wind up reinventing more wheels (or hunting the net for someone else's version of a wheel).

Another obvious difference is that there are no Objective-C source files in the Apis distribution. It doesn't need them, because CCL's Objective-C bridge provides everything you need to define Cocoa classes and methods. That's an important point to some people; they want to be able to write a Cocoa app without having to see C code. CCL offers you that option, at the cost of having to learn the Objective-C-in-Lisp language of CCL's bridge. With Gambit, you must write your Objective-C code in C, but Gambit makes that easy to do. With CCL, on the other hand, you can write your Objective-C code in Lisp--but don't fool yourself; it's still basically Objective-C code, and you still have to learn Cocoa. Not that I'm complaining, mind you; if you're going to write Cocoa apps, you're going to have to learn Cocoa, no matter what language you use.

A fussier detail is that the build process of the two projects is a little different. Both use Makefiles, and I;ve packaged them to be about as similar in structure as is reasonable, but Atta uses Gambit and, through it, Apple's C compiler. Apis, on the other hand, uses CCL to compile, and Apple's C compiler is never involved. (Don't take that to mean you can build Apis without Apple's developer tools. Even if you replaced the Makefile with a Lisp program, you'd need Apple's ibtool to compile the resources for the bundle.)

The Atta source code is in three Scheme files and four Objective-C files. The Apis code is in five Lisp files. Ata is 260 lines of code total. Apis is 247. Apis launches in about a quarter of a second on my iMac; Atta launches in a bout a third of a second. Atta builds in about six seconds. Apis takes about nine.

For Apis, you'll need a recent install of Apple's developer tools, and a recent release of Clozure Common Lisp. I tested with XCode 3.2 and CCL 1.4.

Enjoy!

Atta, Boy!

Last week a reader expressed a hope that I'll release Apis soon, and I intend to. That reader, though, hoped that Apis was written in Gambit Scheme, and it isn't. It's written in Common Lisp, and uses Clozure Common Lisp's very good Cocoa support.

Do not despair, however, Faithful Reader! I've packaged a Gambit Scheme variant of Apis, called Atta, which you can download here.

Atta is an ultra-simple text editor, the kind that you can build by following along with Apple's tutorial example, "Building a Text Editor in 15 Minutes." Instead of using XCode and pure Objective-C code to implement the text editor, though, Atta uses a mix of Objective-C and Scheme, using Gambit-C's spiffy C interface to make that easy.

The net being what it is, I expect to hear complaints that Atta is trivial. Yes, it is; that's the point. It's a nearly-minimal Cocoa application whose main program and parts of the application logic are written in Scheme.

I also expect to hear complaints that there's hardly any Scheme code--not even as much as the Objective-C code (and there's precious little of that). That's also true, but it's because the application is so trivial. There is just barely enough code to do anything at all, and, what with Scheme code tending to be so compact and all, there's hardly anything to see.

Finally, I'm pretty sure that someone is going to read through the code and complain that the implementations of saving and loading text files are unnecessarily complicated. That's also true, but if they weren't, then there really wouldn't be any scheme code at all. Well, apart from the call to "(begin (cocoa:application-main))".

Atta is intentionally minimal, so that it's easy to read through all the code and see what it's doing. It's not completely minimal, because there needs to be enough code that you can see something being done, and in order to serve that purpose, I implemented parts of the save and load methods in Scheme, though it certainly would have been simpler just to write a line of Objective-C code in each place.

The point of doing it the way I did is that you can trace through the program's logic and see how an NSAttributedString value begins in a Cocoa window, is extracted and passed to Scheme, which then passes it back to Objective-C to convert it to an NSData value, then gets the NSData back and hands it to the original Objective-C context, which writes it to a file. A similar process occurs when opening a file, so you can follow the progress of the data all the way from Cocoa window to disk and back again, passing through Scheme's heap on the way.

In this initial version, the Scheme code doesn't actually do anything with the data, except pass it around. It would probably be useful to think of some transformation to do on it as it whizzes by, in order to better illustrate how Gambit can convert C data to Scheme data and vice versa. I don't want to wait around for inspiration to strike on that point, though, so I've gone ahead and packed up Atta 1.0 and made it available.

Apis should be along as well in pretty short order. It's not any more complicated or difficult to package up than is Atta.

Oh, and somebody's sure to wonder what's up with the names "Atta" and "Apis". They're genus names of insects; specifically, "Atta" is the leafcutter ant, and "Apis" is the honeybee. When I first wrote Apis it was part of an experiment in writing a minimal Cocoa application that could serve as the front-end of a system of cooperating processes. Lots of cooperating processes; a swarm that makes something appealing or useful; honeybees; you get the idea. When I decided to port the basic application framework over to Gambit, I debated using the same name, but I thought, "I still want to release the Common Lisp version, and it would be nice if were easy to distinguish them. It would also be nice if it could have a similarly brief and easy-to-remember name, and if it stuck to the eusocial organism theme established by Apis." There are several eusocial organisms to choose from. "Naked Mole Rat" has its own kind of aesthetic, but just didn't seem quite right. After some consideration, I chose "Atta', the leafcutter ants, because they're eusocial, and I admire their invention of agriculture.

So that's it; the clamoring throng of one or two people who want a simple example of how to build a Cocoa app in Gambit can grab Atta 1.0, and Apis will be along shortly. Bear in mind that for Atta to be of any use, you'll need to have a recent version of Apple's Developer Tools , and also a recent version of Gambit-C.

Have fun!

Oct. 23rd, 2009

A peek at Categories

I've begun preparations to package Categories for release. The first thing I'm doing is going over the surface syntax. In previous iterations I've built Categories from the bottom up, which confirmed that the concepts and mechanisms worked, but left a few warts in the surface syntax. This time, I figured I'd start at the surface syntax and work the other way, in hopes that the result will be more congenial.

This rather long post describes the current state of the Categories surface syntax. Those who are interested in such things are invited to tell me what's wrong with it.

Categories has three logical parts: datatypes (representation), functions (behavior), and domains (taxonomy). Following Larry Tesler's maxim that "simple things should be simple; complex things should be possible," I'll start by describing just the simplest and most common use-cases, and then make another pass through all three parts of the system to add in the more complicated options.

Datatypes

Representation is the province of Datatypes. Types are first-class objects in Categories. They can be created by evaluating expressions, passed to and returned from functions, and bound to variables.

Categories defines a set of primitive type objects that represent built-in types of the underlying platform. For example, the Scheme version defines primitive types like <pair> and <symbol>, and it arranges for its reflective operations to return appropriate values. For example:

  ? (type 'foo)
  <symbol>

  ? (type? 'foo <symbol>)
  #t


Type synonyms

The simplest possible way to define a type is to say that it's the same as some existing type. Of course, even simpler than that is to just go ahead and use the existing type. But sometimes you want a different name for the type, to better communicate its intended use. Sometimes you want to use an existing type for now, but may want to represent the data differently in the future. To make these uses easier, Categories provides type synonyms:

  (define <name> (type-synonym <string>))


By defining <name> as a synonym for <string> you can use <string> objects to represent names, while calling them <name>s in your code to clearly communicate their purpose. Later, if you find that you need to represent names in some other way--say as some structured object that takes into account various different kinds of names that people use--you can replace the definition of <name>. You'll then have to change the implementations of functions that operate on <name>s, of course, but if you structure your APIs appropriately, that's all you'll have to change.

Structures

More commonly, we want to create structured types by grouping several simpler types into named fields. In Categories, that kind of type is called a structure:

  (define <cartesian-point> (structure () x y))


Like other types, structures are first class objects. The above code binds a new structure to the variable <cartesian-point>. The new structure has two keys: x and y. Instances of <cartesian-point> will contain two values, one stored on the key x, and the other stored on the key y.

You can create an instance of a structure by applying the function make to it:

  (make <cartesian-point>)


You can get the value associated with a key by applying the function get-key:

  ? (get-key (make <cartesian-point>) 'x)
Error: Unbound key x


Unfortunately, we didn't specify any value for x when we created the instance. You can do that by passing in an initializer for the key:

  ? (get-key (make <cartesian-point> x: 101) 'x)
101


You can also specify a default value for a key in the definition of the type:

(define <cartesian-point> 
    (structure () 
        (x default: 7)
        y))

  ? (get-key (make <cartesian-point>) 'x)
7


Before I go any farther, I had better explain why there's an empty list after the symbol "structure" in:

(define <cartesian-point> (structure () x y))


When you create a new structure, you can specify zero or more existing structures to include in its definition. So if I wanted to define a new type of 3D point that is just like a cartesian point, but with an extra coordinate, I could define it like so:

(define <3d-point> (structure (<cartesian-point>) z))


"Okay," you're thinking, "that's nothing new. The new type inherits from the old one." Not so fast: there's no such thing as inheritance in types. Including a type just means you don't have to retype all its field definitions when you want to reuse them. Categories does support inheritance, but that belongs to domains, not to datatypes. Remember: datatypes are representation. Inheritance belongs to taxonomy, and that's the province of domains, not of datatypes.

Structure amenities

The structure constructor provides a few more conveniences. You can say that you want Categories to automatically construct getter functions for the new type's keys:

(define <cartesian-point> 
  (structure () 
             (x get: get-x)
             (y get: get-y)))


Now you can fetch the x value from a cartesian point like this:

  ? (get-x (make <cartesian-point> x: 101))
101


If you leave off the get: argument for a key, then you have to use get-key and the key's name to fetch the value.

You can also specify a setter:

(define <cartesian-point> 
  (structure () 
             (x get: get-x set: set-x!)
             (y get: get-y set: set-y!)))


Categories then constructs a function for setting the value associated with the key:

  ? (define p (make <cartesian-point> x: 101))
#<<cartesian-point> x: 101 y: #<unbound>>

  ? (get-x p)
101

  ? (set-x! p 1001)
  ? (get-x p)
1001


If you omit the set: argument then Categories makes the key read-only. Categories is generally biased in favor of immutable data.

Functions

Now that we know how to define datatypes, what do we do with them? We apply functions to them.

Functions are objects that can be applied to zero or more parameters and return zero or more results. Functions as defined in Categories are polymoprphic. In other words, the same function can have several different definitions. The one that applies to a particular set of inputs depends on the inputs.

This practice of making the particular implementation of a function depend on its inputs is called polymorphism, and is one of the foundations of object-oriented programming. Choosing a specific implementation to run is called dispatching. Categories provides polymorphic functions with programmable dispatching.

We'll look at how you can create your own dispatching schemes below. First, though, let's look at what it's like to define and use functions in the simplest way.

The Default domain

The simplest way to define and use functions in Categories is with the default domain. Categories assumes you are using the default domain unless you tell it otherwise. The features of the default domain generally resemble those of CLOS.

Like types, functions are first-class objects. You can create one and bind it to a variable, like this:

(define serialize
  (function ((s <store>))
     (vector 'store
             (version s)
             (map serialize (columns s))
             (column-order s)
             (sort-column s)
             (sort-reversed? s)
             (map serialize (rows s))
             (notes s))))


The function object that is bound to the variable named "serialize" is created with a single implementation, corresponding to the type <store>. If we want to add another implementation, we can use add-method!:

(add-method! serialize ((d <document>))
    ...)


Why do the parameter lists have double parentheses? Because each parameter may be type-qualified:

(add-method! serialize ((d <document>)(outs <stream>))
    ...)


You can define a method to execute when no match is found for the inputs by omitting the type qualifiers:

(add-method! serialize (something somewhere)
    ...)


It can be an inconvenience to keep track of where the definition of the function first appears, and to make sure that all the add-method! calls appear after it. If you instead use the define-function macro, that bookkeeping is handled for you automatically:

(define-function serialize ((s <store>))
    ...)

(define-function serialize ((d <document>))
    ...)


In that case, it doesn't matter which comes first.

Domains

So how exactly does dispatching work in Categories? Well, that depends on what domain you use. By default, you use the default domain. The default domain, which is named -c3-, uses a dispatching algorithm very similar to that of CLOS. It's not identical to CLOS; it uses a scheme first described in

http://192.220.96.201/dylan/linearization-oopsla96.html

That scheme, which is generally called "C3", yields dispatching behavior that is very similar to that of CLOS, but which in a few complicated corner cases produces less surprising results. It's the default in Categories because I like it, and because it has served the general programming community well. It was designed for the Dylan programming language, but has been adopted by implementors outside the Dylan community, including the Python implementors and the designers of the Class::C3 object system for Perl.

Although C3 is the default dispatching scheme, it's not the only dispatching scheme supported by Categories. Two other dispatching schemes are provided with Categories, and by defining your own Domains, you can make your own.

Before we get to that, though, let's just look at how to use something other than the default domain.

When you write:

(define-function serialize ((s <store>))
    ...)


that expression is really shorthand. It leaves out a reference to the domain you're using. If we wrote it out in full, it would look like this:

(define-function -c3- serialize ((s <store>))
    ...)


You can see that here we've said explicitly that we're defining a function that operates in the -c3- domain. We could instead use one of the other domains supplied with Categories, the Flat domain:

(define-function -flat- serialize ((s <store>))
    ...)


The difference between -c3- and -flat- is that -c3- defines supertype relations among types, and -flat- doesn't. Suppose you make an instance of <repository> and call serialize on it.

  (define $r (make <repository>))
  (serialize $r)


What happens? That depends on whether serialize is defined on the -c3- or on the -flat- domain. It's the domain that defines how dispatching is done. If it's defined on -flat- then the answer is simple: serialize finds no match for $r. Unless a default method is defined as in the example above, an error is signaled.

The -c3- domain defines a more complicated--and more familiar--dispatching scheme. It will try to match $r against serialize methods that are defined on <repository>. When it fails to find one, it then tries to find serialize methods defined on supertypes of <repository>.

Didn't I say above that datatypes don't define supertype or inheritance relations? Yes, because domains do. The -c3- domain defines supertype relations with multiple inheritance. It tries to find an inherited method that matches, using the C3 algorithm to determine which matching method is most specific. Once again, if no such method is found then either the default method is called or, if there is no default method, an error is signaled.

More options

That's a first pass across the simplest and most commonly-used features of Categories. Let's go over the parts of the system one more time, and look at a few more options that it provides.

Categories

First of all, I left out an important group of types, because it's hard to explain what they're for until you've seen how Categories works with domains. A constructor named "category" creates a kind of type that is different from the others. For example:

(define <vehicle> (category <car> <truck>))


The expression above binds a new type to <vehicle>. The new type, which is called a category, represents any of the types passed as inputs to the "category" constructor. Once <vehicle> is defined, any method matching <vehicle> will also match <car> or <truck>. You can therefore define functions that accept <vehicle> values, and those functions will work on <car> or <truck> values, even if the functions are defined on the flat domain. In other words, even without inheritance, it is possible to define functions that operate the same way on a variety of different types.

Supertypes and subtypes

Okay, but suppose you actually want types that have supertypes and subtypes? Well, then, you can use -c3-,or any domain that supports supertype relations, and you can add your own types to it. For example,

  (add-type! -c3- <truck> 
      supertypes: (list <transportation> <four-wheeled-objects>))



...adds to -c3- a type named <truck>, with supertypes <transportation> and <four-wheeled-objects>.

You can, of course, also add types to the -flat- domain:

  (add-type! -flat- <truck>)


You can't specify any supertypes for it, though, because -flat- doesn't support supertype relations. If you try to, then add-type! will signal an error.

Name collisions

What happens if I define a type that includes two other types that have different definitions for the same key?

For example, suppose I have these two definitions:

(define <monument> 
  (structure () 
       (age type: <historical-epoch>))

(define <property> 
  (structure () 
       (age type: <count-of-years>))


Now suppose I want to define <historical-property> like this:

(define <historical-property> 
    (structure (<monument> <property>)
        (square-footage asking-price))


Well, I can't. The definition of age in <monument> conflicts with the definition of age in <property>. What I can do, though, is rename one or both of the included keys:

(define <historical-property>
  (structure ((<monument> (age as: period))
                     (<property> (age as: how-old)))
    (square-footage asking-price)))


The Predicate domain

Besides the default C3 domain and the flat domain, Categories includes a third domain that works very differently from either. The -pred- domain matches input function arguments with a user-defined predicate function. For example:

(define-function -pred- ((x y z) all-odd?)
    ...)


The example above shows a function that will match any three inputs, as long as calling the function all-odd? on the sequence of three inputs returns true. You can define functions that match on any predicate you like. You just have to ensure that when the function passes the inputs to your predicate, the predicate correctly returns either true or false.

The -pred- domain also uses the C3 algorithm to support supertype relations among predicates. Using the -pred- domain you can construct whatever relations among predicate functions you like, and Categories will dispatch appropriately. For example, you define all-integers? to be a supertype of all-odd?, and then anything that matches all-odd? will also match all-integers?.

I should probably mention here that -pred- may not be all that useful to anyone. It exists mainly because I wanted to make sure that it was workable to build a dispatching scheme in Categories that was quite a bit different from the usual thing.

One mystery remains with the -pred- domain, though: the syntax for defining a function is different from the syntax used with the -c3- and -flat- domains. How does that work?

Defining domains

The unique define-function syntax of the -pred- domain is provided by the domain itself. It turns out that the operators "function" and "define-function" don't define the syntax of parameter lists; the domain does. The -c3- and -flat- domains both define a syntax that is familiar to users of CLOS and similar object systems. You write define-function forms like this:

(define-function -c3- add ((x <integer>)(y <integer>))
  ...)


The forms (x <integer>) and (y <integer>) mean that the formal parameters x and y match inputs only if those inputs can be matched with the <integer> type, according to the domain.

A domain like -pred- works quite differently, and requires a different syntax for parameter lists. Instead of piecewise matching input values against types, -pred- matches the parameter list as a whole against predicates applied to it. That makes it possible to dispatch on conditions that -c3- and -flat- can;t check. For example, -pred- can match a sequence of five integers that are monotonically increasing, or a sequence of characters that forms a palindrome.

But if some domains require unique parameter-list syntax, that means Categories must have a way to define that syntax; and it does.

When you define a domain, you are defining three things:

1. a format for function parameter lists

2. a function that determines whether a particular method matches a given sequence of input values

3. a function that can tell you which of two methods better matches a given set of inputs

Here's what a domain definition looks like:

(define -my-domain-
  (domain catalog: some-catalog-data-structure
          parser: (lambda (domain formals) ...)
          matcher: (lambda (domain signature values) ...)
          comparator: (lambda (domain signature1 signature2 values) ...)))


Right away you'll notice that, although I said you have to define three things, there are four inputs to the domain constructor. Categories provides each domain with a data structure called a catalog. The catalog can be anything you like. It can be a false value, or an integer, or a table, or a more complex data structure. It's up to you. Its purpose is to provide storage for any auxiliary data that your domain might need to perform its tasks correctly and efficiently. You can use it to store method caches, or arrangements of supertypes designed to make lookup fast, or whatever you wish. You can also ignore it completely, if you wish.

The other inputs to the domain constructor are essential, though. Each of them is a function that defines one aspect of how the domain works. Because your domain may have crucial data stored in its catalog, all three of the functions accept the domain itself as the first argument. Its up to you what you do with that argument; it's available in case you need it.

Besides the domain parameter, the functions that define a domain deal with three other items: formal parameters, method signatures, and input values.

A formal parameter is an object that represents the formal arguments in a function definition. Categories doesn't define the format of argument lists; that's up to the domain. When it processes a function definition, it extracts the formal parameter from the function or define-function expression, and passes it to the domain's parser. The parser must accept the formal parameter and return a method signature. It's the parser that determines what the argument list of a function definition looks like.

The parser doesn't have to be complicated. Consider a -c3- function definition again:

(define-function -c3- add ((x <integer>)(y <integer>))
  ...)


All the parser needs to do is collect the type qualifiers from the formal parameter, which is ((x <integer>)(y <integer>)), and make a method signature that matches two inputs that are both of type <integer>.

That brings us to method signatures, and to the matcher. Once again, the method signature can be any data structure you like, as long as it stores the information that the matcher needs. Categories passes to the matcher a method signature and a collection of input values. The matcher must return true if the signature matches the inputs, and false otherwise. For -c3-, a method signature can simply be a sequence of types. For example, the method signature for the add function defined above is just (<integer> <integer>). The -c3- domain will say that any sequence of two values matches that signature, as long as both are of type <integer>, or of some type that, according to -c3-, is a subtype of <integer>.

What if more than one signature matches a set of inputs? How does the domain know what to do?

That's what the comparator is for. After a function determines all the signatures that match a set of inputs, it sorts them. The comparator is the function it uses to determine their order. The comparator must accept two signatures and a sequence of input values. If the first signature is a better match than the second for the inputs, then the comparator returns -1. If the second signature is a better match, it returns 1. If neither is better, it returns 0. It's best to try to arrange for the comparator not to return zero, if that makes sense for the domain you;re designing, because returning zero means you can't tell which method to apply. Categories has to signal a dispatch error when that happens.

Customizing the default domain

It may happen that you want to make your own domain, but you don't really want to totally rewrite how everything works. Maybe, for example, you want to use something other than C3 to order methods, but everything else about how Categories works suits you fine. In order to make it easier to customize just the part you want to customize, Categories provides functions that implement the behavior of the default domain. You can make your own domains using them, and you can replace just one of them, or two of them, or you can use all of the standard functions, but change their inputs or outputs a little using your own code.

As an example, you can make a domain that duplicates the behavior of the default domain like this:

(define -my-c3-domain-
  (domain catalog: (make-c3-catalog)
          parser: (c3-signature-parser)
          matcher: (c3-signature-matcher)
          comparator: (c3-signature-comparator)))


What next?

All of the features described in this overview have been implemented, but the working code doesn't provide this surface syntax. The syntax of the working versions is not too different in most places, but it's a little more complicated and not quite so tidy. I'll be fixing that as part of getting the code ready for release.

The prototype I've most recently been working on is implemented on top of Gambit Scheme 4.5.2. I've tried to avoid making it particularly Gambit-specific, but the surface syntax I chose does use DSSSL keywords, which not all Schemes support. In addition, some of the syntax needs to be defined as macros. For reasons of convenience, those will be defined using Gambit's define-macro form, rather than something more portable. It may turn out that someone wants Categories on some Scheme that lacks DSSSL keywords, or where a different means of defining macros is needed. I'll cross that bridge when I come to it.

I plan to port it back to Clojure, as well. The first few versions of Categories were written in Clojure, but I wanted to move it elsewhere, mainly to gain the perspective of looking at it as something independent of a particular language, rather than as an extension specifically to Clojure. I'm planning a sizeable project in Clojure shortly, though, and I know for sure that I'll want what Categories offers me for it.

It may be that the design of Categories has serious flaws. If so, feel free to enlighten me about them. If they can be repaired, I'll do my best to fix them. If not, I'll have to look for alternatives. I could always port Sheeple to Clojure, or maybe implement PLOT's object system.

Oct. 18th, 2009

Gambit considered helpful

I've just packed up Delectus(tm) 1.0 Alpha 2 and shipped it off to my testers. Delectus is an application for keeping track of collections of things. The inspriation for it was an ancient and hoary program my mother used to keep track of her movies. She has around a thousand movies, the majority of them still on videocassettes. Each cassette has a catalog number on it, and she uses a database program to associate those numbers with information like the title, star, genre, and so forth, so that she can quickly find a particular movie in her stacks of shelves. Recently the software, which is over twenty years old, finally became obsolete. As we were looking for a replacement, I decided I'd just write one, and that became the genesis of Delectus.

The basic design of Delectus is very simple. A Delectus document stores a list of rows and a list of columns. Each column has a text label. Each row contains a list of text fields. The number of fields is the same in every row, and it's also the same as the number of columns. So you can create a document with the columns "Title", "Genre", and "Star", and every row will then have three fields. You can make a new row and put the title of a movie into the "Title" field, the star into the "Star" field, and the genre into the "Genre" field.

Delectus doesn't decide for you how many columns to create or what the names will be. Instead, a new Delectus document has no rows and no columns. You can add new rows and new columns at any time, and you can delete them at any time, too. This flexibility makes it easy to set up your databases any way that is convenient for you. You can sort a document's entries, forward or backward, by clicking the heading of a column. If every entry in a column is a number, Delectus detects that automatically, and sorts by number instead of lexicographically.

Delectus uses a trash can, like OS X's trash can. When you delete a row or column, it's not really gone, but tossed into the trash. Click a trash button, and Delectus shows the trash to you, integrated in the document, but displayed in a different color, so you can easily tell which items are deleted. Empty the trash, of course, and the deleted items are gone forever.

Delectus is mainly written in Scheme. The Scheme compiler I'm using is Gambit-C. A few weeks ago, I wrote a post about the happy discovery that Gambit-C made it easy to work with Mac OS X's Cocoa frameworks. I said Gambit was a great platform for Cocoa development. That opinion drew some fire, but I haven't changed it. To the contrary, I've grown happier with Gambit as I've developed Delectus.

Some people grumbled that I'm not allowed to call it a great platform if I still have to deal with C code. Now, that's silly. You know, I actually had a Lisp system once in which I never had to deal with C code. It was called a Symbolics Lisp Machine, Every other Lisp I've used--and I've used a lot of them in twenty one years of programming--has had to deal with C in one way or another, at one time or another. Heck, even when I was writing Lisp code for an operating system written in Lisp (an unshipped version of Apple's Newton), we had to deal with C code. If your eyes are damaged by the sight of semicolons, a hard road awaits you. C code is in the underpinnings of every system you are ever likely to use. At least Gambit makes it easy to wrap our beloved parentheses around it, so that the hothouse flowers in our midst are protected from the hot exhaust bits spewing forth from the C code beneath our feet.

The other common complaint seems to be that I made a grammatical error in using the adjective "great" to modify a set of development tools that does not include an IDE. To paraphrase Yoda, "IDEs not make one great." Sure, there have been great IDEs. Smalltalk-80 was a great IDE. Xerox Interlisp was a great IDE. Most IDEs are not great. Most IDEs are going to be great, someday. That is, they're going to be great, right up to the point where the weight of the implementation collapses the envelope of optimism providing their buoyancy, and they crumple into a heap of random features, slowly and inexorably sinking under their combined mass.

IDEs are large, complicated systems that require serious design and engineering. They are major cost centers to anyone who is not in the business of selling IDEs, and the market for them is small. It should not be surprising that they're mostly not all that good.

What's more, the benefit of even a great IDE is, let's face it, marginal, as long as the basic tools are comprehensive and good. So yeah, I'd like to have a great IDE. I'm not holding my breath. Maybe I'll like the Factor IDE. It looks pretty good. But I'm working in Scheme, right now.

So, yeah, folks who never want to see a line of C code, you're not going to like the tools I'm using. Ditto for anyone who must have his projects managed by a digital valet in an impeccably-tailored suit of color-coordinated windows. There's nothing for you guys to see here; move along.

For me, though, Gambit has definitely been great. In the development of Delectus, I've ditched XCode (but not Interface Builder). In Alpha 2, 83% of the application code by linecount is Scheme code. The remaining 17% is Objective-C. Basically, there's just enough Objective-C to load the nibfiles that define the app's windows and menus, and hook their event-handlers to the Scheme code that does all the real work.

After some experimentation, I partitioned the application into the following parts:

1. The back-end: this is pure Scheme code that handles all the data structures, as well as sorting, filtering, and updating. It also handles serializing and deserializing data as CSV and a native binary format, and writing to and reading from disk files.

2. The UI: this is Objective-C code that loads the nibfiles, sets up calls into the back-end, responds to notifications that originate in the back-end, and provides the minor customizations I needed to make Apple's UI elements look just the way I wanted. This part is less than 700 lines of code, total.

3. The bridge. This is a small amount of Scheme code, and an even smaller amount of Objective-C code, in a couple of files. It provides simple utilities like a means of converting Scheme strings to NSString objects when the UI needs to fetch a string from the back-end, without being prodigal about allocation of strings. It provides a mechanism for notifying the Objective-C code from Scheme code, so that the pure-Scheme back-end can post error messages, update requests, and other notifications, without any code that is actually aware that an Objective-C component exists.

The last point is maybe interesting. There is a very small amount of mixed Scheme/C code that enables the Objective-C UI to interact productively with the Scheme back-end. I could easily have put that code into the main body of the back-end proper, and at first, that's what I did. After all, there's only a little of it; what's the harm?

Before long though, I refactored the code to completely separate all that code into a bridge layer. The reason, basically, is that I like to have a fairly comprehensive set of unit tests around my major application functionality. With such a set of tests in place, it's very easy to detect when a change in the code makes an application feature fail, and it's easy to find what broke it. By factoring all of the mixed code out into its own small layer, I was able to make the back-end pure Scheme code, with no reference anywhere to any foreign functions. That means that I can load the entire back-end into an interactive repl and exercise it. I can run all the unit tests at once, or run particular ones interactively. If one breaks, I can use the interactive debugger to crawl around inside the back-end's runtime and figure out what's wrong.

Furthermore, by factoring things this way, I create a circumscribed and coherent API for calling into the back-end and getting data from it. That makes it very easy to hook up the Cocoa UI, simply by having event-handlers call the appropriate API functions. UI calls into the back-end are almost always one or two lines of code. That means that, even when a bug is in the UI rather than the back-end, the way the app is factored makes that easy to detect. And since there is so little front-end code, it's easy to find and fix.

Obviously, you could structure any Cocoa app similarly, whether the back-end is Scheme or C or ML or whatever. What makes Gambit great for me, a Lisp hacker by preference, is that over eighty percent of the code I work with is pure Scheme code that I can work with interactively, in the way I prefer.

You could argue that Delectus is really a C program, on the grounds that Gambit-C compiles Scheme to C, before subsequently compiling it to native code. That suits me fine, as long as I can continue to write my C code in Scheme.

I'll say it again: Gambit-C has been a great platform for developing a Cocoa app. I'll enthusiastically use it again in the future to do the same kind of work. I would recommend it to anyone who wants to use Lisp to write a Cocoa app, provided that they're not allergic to C code, and provided that they're okay with using compilers and editors without an IDE to command the servants for them.

Delectus should be out soon. The gating factor right now is the opinion of the testers. When they're happy with the feature set and the stability of the product, I'll release it.

After the release of Delectus, I'll begin work on a web application aimed at MMORPG players. Most likely, the server side of that application will be written in Clojure.

A little while ago, I promised interested people that they would soon be able to get their hands on my Categories object system. The object system had to take a back seat to revenue-generating work, but when Delectus is out, I'll be working on a release of Categories. I intend to use it in my next product anyway, and so I may as well also package it for release to the tiny community of people who are interested in such things.

The current working prototype of Categories runs on Gambit, and it's likely that's the version I'll clean up and release first. Then I'll port it back to Clojure (which is where I developed the first versions of it), and make that available as well. It may be a little while before I do either; we must now wait on the verdict of my testers. When they say Delectus is done, then I can move forward.

I have several other plans in the works, including the resurrection of some old friends. After six years, I still occasionally get fan mail about Alpaca, the text editor. Those few fans may be glad to know that a new version of Alpaca is on the roadmap. Another old project that I'm still sometimes asked about is Bosco, a simple set of tools for building a Cocoa application in Clozure Common Lisp. Well, Bosco was absorbed into Clozure Common Lisp a couple of years ago, but there stlll seems to be a place under the sun for a small package of files that shows how to build a minimal Cocoa application with the smallest possible amount of Lisp code. I have another project called Apis that can serve that purpose, among others. Apis, and other things derived from it, are also on the roadmap.

There are other things, but they're even further down the road. For now, I'm still squarely in the midst of Delectus, and loving Gambit. Turns out it's still a great platform for developing Cocoa apps.

Oct. 12th, 2009

Could Be a Contender

Champions Online is a flawed, brilliant game that dares to try injecting a few really novel ideas into MMORPGs. Its developer, Cryptic Studios, is struggling a little with the issues raised by their departures from the beaten path, but I have to hope they succeed in what they're trying to do.

Fast Fun

Obviously, when you design a game, you want it to be fun. If it isn't fun, a game has no reason to exist. There are a couple of different ways to approach fun in MMORPGs, though, because of the kind of game that they are. On the one hand, the MMORPG developer hopes to seduce players into coming back again and again, and devoting hundreds of hours of leisure time to the product. To accomplish that goal, a game needs fun aspects that emerge over time; it needs surprises; hidden treasures; happy discoveries that a player has to discover through long labor and exploration.

On the other hand, if the first few minutes and hours of play are not fun, then players might never discover any of those lovingly-crafted surprises.

Of course, in an ideal world of games, every MMORPG would be both instantly exciting and lastingly rewarding, but the reality is that every development team has to make tradeoffs in order to get a product out the door. There is never the time, money, or team needed to polish absolutely every aspect of a game to the high gloss that its inventors would wish. Decisions have to be made. Do you focus your efforts primarily on getting buyers' attentions in the first place, or in hanging on to it once you've got it? Different studios go different ways. Although World of Warcraft is certainly a rich, complex, deep game at this point, at launch the emphasis was pretty clearly on that first impression. Blizzard worked hard to make sure you'd have a lot of fun in the first couple of hours. Turbine's Lord of the Rings Online is an example of a game whose design leans the other way. The best things about LOTRO are not obvious in the first couple of hours of play. They take time to find and appreciate.

With Champions Online, Cryptic has gone the same way as Blizzard, and with a vengeance. The new player experience is crammed with lights, whizzy options, and action. The fun starts with the character creator, which provides seemingly unlimited power to build any kind of character you want. Height, weight, and hair, eye, and skin color are only the beginning. You can make hulking green behemoths with hands the size of a small car, or tiny, wispy fairies with butterfly wings. Robots, werewolves, slacker thugs, and little old ladies are all well within the range of the character creator. You can have a good time for hours just picking an idea for a character and seeing how close you can come with Cryptic's tools. Usually, you can get nearly as close as you want to.

The freedom to explore doesn't stop with your character's looks. Abandoning the now-traditional half-dozen classes, Cryptic instead gives us eighteen "Power Sets": collections of abilities that revolve around a common theme and a common pair of supporting statistics. You can choose from options like Fire, Ice, Force, Munitions (guns and bombs), four flavors of Martial Arts, Gadgeteering (robots! attack toys! orbital beam weapons!), Might (brute force) and a slew of magical options. More interestingly, the Power Sets are not mutually exclusive as are the classes in most games. With minor restrictions, you can cherry pick abilities from the full range of Power Sets, creating your own style of character by the simple expedient of picking abilities that match the concept, regardless of the Power Set that provides them.

Once you actually begin to play, the fun kicks into high gear. In no time flat, you're blasting, chopping, capping, stomping, or incinerating hostile aliens in the middle of explosions, wailing sirens, and hysterical NPCs screaming for your help. The game propels you through a whirlwind tutorial that spits you out into one of two quest hubs, where you can then acquire then next big dose of fun: your first Travel Power.

There's no lengthy grind through thirty or forty or fifty levels before you have the opportunity to spend the wealth acquired in hundreds of hours of play to buy some sort of banal mount to ride around the landscape. Nope; in Champions, you get to about level five, whiz off to a new zone, and buy any one of over a dozen different ways to zip around the landscape like a superhero. You can learn to fly, jump a quarter mile, swing from the rooftops, run at formula-one speed, or tunnel through the earth like Bugs Bunny taking a wrong turn at Albuquerque. By itself, the travel power is good for a decent amount of fun, and if you pick the right one for your character and learn to use it well, it adds a new dimension to your fighting abilities.

Truly, Champions delivers a truckload of fun right at the start of play. For the first couple of hours it seems like you'll never stop saying, "wow! that's cool!"

Fast Flaw

Along with this freedom, though, Champions offers us the first serious flaw in the game. Not all combinations of powers work equally well. One of the first questions an experienced MMORPG player wants answered about a new game is: is it possible to gimp your character? Will an unfortunate choice of powers make your character weak and ineffective? Will it hamper your experience of the game? In Champions, the truthful answer has to be yes; you can easily make an unfortunate choice that pretty much kills all the fun.

Balance is always a tough problem in MMORPGs. They're big, complicated games with a lot of variables in play. It's inevitable that some design decisions will have unexpected and unfortunate consequences for players. The players know this, and make some allowances for it. With eighteen Power Sets (and more on the way), each with dozens of powers, there are bound to be a few glitches and gaffes. We all understand that, and it doesn't have to be a serious problem. But this is the first place that Cryptic shoots itself in the foot: Champions Online shipped with a mechanism for rebuilding characters that got in the way more than it helped.

You would think that in a game whose new player experience so much emphasizes freedom of choice--freedom to choose your looks, your theme, your powers and abilities--that it would be dead easy to change your choices if you find that you've made some bad ones. It isn't. You can visit the Powerhouse--the same location where you buy new powers--and remove powers that you'd acquired, to make room for different choices. So far, so good. Unfortunately, in order to remove a power that you acquired a couple of visits back, you have to first remove all the ones you acquired after it. If you decide that the lightning bolts you bought three visits ago are the wrong thing, then you need to get rid of the other things you bought after them before you can touch them. That wouldn't be so bad in itself, but you also have to pay to remove each power, and the cost of each power you remove goes up significantly. If the bad choice you made is more than five or six visits ago, you're looking at a serious chunk of change. Ouch.

To make matter worse, on the day Champions launched, Cryptic hastily issued a patch that drastically reduced the toughness and effectiveness of player characters across the board. Beta testers were gobsmacked by the changes. The same characters who had, one day previously, mopped the floor with hordes of bad guys, now struggled to complete tasks that required defeating two or three mobs. In fairness, there had been some complaint that the game was a little too easy, and the game after the patch is not unplayable. But to issue such a drastically game-changing patch on the day of launch was pretty ham-handed, and when you combine it with the high expense of removing powers at launch, it felt to many players like a slap in the face. In effect, Cryptic took away all that made your character fun, and simultaneously made it so expensive to change builds that the only realistic option was to dump your character and start over. Poor form, Cryptic; poor form.

There were worse effects, too, but they were less obvious. We'll get to those soon enough.

Recently, Cryptic lowered the cost of removing powers significantly, which is a step in the right direction. The mystery is why, in a game where the freedom to experiment with different combinations of powers is so important, they raised that barrier in the first place. It takes experimentation to find the right combination of theme and powers, to create a character that is right aesthetically and that is also fun to play. That Cryptic would put an arbitrary barrier in the way of that discovery is mystifying.

The Color of Funny

Once you're past the first few hours of rapid-fire fun, you want to know that the game is going to remain involving. We play MMORPGs because we like playing in an imaginary world we can come back to. We like to come back to a character that is in some way better to play with than the last time, and where we can roam around and find new things to do, new challenges to face with our increasingly mighty toys.

Champions gives us a brightly-colored comic-book world that is great to look at. Moreover, the responsiveness of the game and the quick-moving style of combat is intensely engaging. The emphasis in Champions is on powers that you can use on the move. You often find yourself hurtling through the air tossing things that light up and explode and zap your targets. With a little practice, combat starts to resemble the ballet of violence in an action movie more than the relatively static slugfests with light shows that are more traditional in MMORPGs. Probably too much has been made of Champions being an "action" MMORPG; the differences rom older games are not all that earth-shaking. Still, Champions does bring something new to the table. It's positive contributions in combat have as much to do with characters that bounce off each other, real line-of-sight, and destructible objects that you can blow up or throw, as with moving combat, but the innovations are real, and they're fun. Champions offers tactics that aren't available in older games, and this new freedom of action feels like more power. Often, if a bad guy was too tough for you on the first try, you can think of ways to exploit terrain and environment to win your second fight with him.

It's a shame that the UI often feels balky. Between a complicated set of independent cooldowns and the occasional bug, you sometimes feel like you're just banging buttons to no effect. The problem doesn't happen all that often, but when it does, it's inevitably when you are in the middle of some complicated fight against multiple enemies, and you really need that ability to fire when you hit the button. If it as just a matter of learning the abilities and the cooldowns and the power requirements, then you'd shrug and say, "Hey, I'll get better." But there really are times, occasionally, when you hit a button, and nothing happens, and there's no discernible reason for it. All the cooldowns are over; you have plenty of power; there are no debuffs on you; the target is in range; and still, you hit the button and nothing happens. Operate some other control or move a millimeter one way or another, and suddenly it works again.

This balkiness is not a deal-breaker. The game is still huge fun, and undoubtedly incidents like this are just the inevitable bugs. Without doubt, Cryptic will find and fix them in due course.

Maybe more troublesome is the issue of leveling content, and the larger, more subtle issue of what makes a good game world.

When Cryptic was adjusting the mightiness of player characters, it was also monkeying with the experience rewards. Late in the Beta testing process, it seems that Cryptic concluded that, between the might of the player characters and the fast rate of leveling, it looked like players might rocket to the endgame before there was any endgame for them to play. We can forgive them for being nervous about that prospect. We've seen that happen in other games, and we've seen the inevitable effect of bored endgamers on subscription numbers. There had better be something for players at maximum level to do. If there isn't, it's only a matter of time before they go looking for another game.

Cryptic's solution was to slow down leveling. A natural enough choice, and it solves the problem of bored endgamers--or rather, it delays it long enough to give the studio a chance to come up with more content--but in this case it led to another problem.

Champions has just about enough missions available to keep a leveling player busy, if you are diligent about finding all of them, and if you complete every single one of them. Missions get a little thin in the low twenties, which leads to lots of people running missions above their level. For people with really strong character builds, that works pretty well, apart from the fact that you're eating into the content that should be there for you at those higher levels. For people with weaker builds, the situation is tougher. In some games, you could address the problem of a lack of content by grinding mobs for experience. That's kind of a rough way to go in Champions, which strongly emphasizes questing as a means of advancement, and therefore awards fairly paltry experience for mob kills.

When you combine just enough missions, a low experience return on kills, and patches that reduce the experience return from completed missions, what was a bit of an inconvenience becomes a real pain. MMORPG players have become accustomed to games that have so many quests available that we can afford to pick and choose. We can run the ones that we find fun, and give the boring or annoying ones a pass. That doesn't really work when you need every last mission just to reach your next level. Maybe we wouldn't mind a gap in the fun quests now and again if we could make up the experience in mob kills. Maybe we wouldn't mind paltry XP returns from mobs if our characters were still the godlike figures of Beta. But when quests are scarce, mobs are stingy, and our superpowers have been reduced to shadows of their former selves, the fun starts to grow scarcer, too.

There's a sameness to a lot of the missions that starts to wear on you after a while, too. By some time in the twenties you begin to realize that any time you accept a mission, there is a better than even chance it's going to be eerily familiar. Go to this address (haven't I been here before? Like, several times?), go inside and find a group of [demon worshippers/paramilitary insurgents/mobsters] trying to do Some Bad Thing, knock twenty or thirty of them down, maybe pick up a thingie from them, and out again, you're done. These missions are basically fun, and there is some variety. I'm a little concerned, though, that the sameness is going to start wearing on us after a couple of months of play.

We need not despair. For one thing, even when you're grumbling around looking for a quest in your level range and not finding one, the basic mechanics of your travel powers and clobbering random bad guys is so much fun that you're willing to forgive. For a while, at least. Surely, Cryptic is using the time and money that launch bought them to prepare more content for us, with greater variety. They'd better be.

The Big, Bright Room

We expect an MMORPG to present us with a virtual world that seems, to a certain extent, real. It's not actually realism we want, of course; it's verisimilitude. We don't really want it to take days of riding to cross a continent. We don't want our characters to come down with an infectious disease and be bedridden for days. We want just enough of the suggestion of reality that we can easily suspend disbelief just enough to enjoy the action and the story of the game.

Different developers devote different levels of effort to creating and maintaining the illusion of a world. Like every other aspect of designing an MMORPG, the game world is a large and complex undertaking, and hard choices have to be made about how much time, effort, and money will be spent on it. Sometimes, as with Lord of the Rings Online, the nature of the property demands an extraordinary effort of craftsmanship, and the result is a rich, varied, subtle, and believable world. In other cases, that level of craftsmanship in world-building is not a priority.

Champions is a game of this latter kind. It gives us, not a world, but three great big, brightly-lit rooms in which to play. Each one is very large--larger than it appears at first--and each one is packed with places to go and things to do. None of them feels much like a world, though, once you get past the initial couple of hours of play.

One reason that Champion's world doesn't seem like a world is that there are really only three places to go (neglecting Monster Island and Lemuria, which only become available after level 30). There is Millennium City, the transformed vision of Detroit where the Tutorial starts; there is the Southwest Desert; and there is the Canadian Wilderness.

Naturally, each of these destinations is spacious and each contains many smaller destinations within it. As with the day-to-day missions, though, there is a sameness about everything in each of these places. The desert, the city, and Canada are distinct enough from each other, but within any of these spaces, one place looks much like another. There is none of the exquisitely subtle care seen in a game like Lord of the Rings Online to make each small place distinctive and different from every other; nor is there the relentlessly organized approach that we see in WoW, where each zone is consciously made to starkly contrast with its neighbors. There is no rounding the crest of a hill to find revealed some new and enchantingly different landscape before us. Instead, there's a great big rectangular room decorated in Urban Modern; a great big rectangular room decorated in Santa Fe Style; and a great big rectangular room decorated in Arctic Tundra; that, in Champions, makes up the world.

It's not only that there are only three scenes, and each of them is a uniform set piece. It's that Champions makes not even a token attempt to conceal the edges of the stage. Blizzard took some care to place the edges of its world out of easy reach, and to discourage players from finding them by placing everything interesting you'd want to do far away from them. Turbine went further with LOTRO, consciously and carefully designing every zone to put the edges not only out of reach, but out of view, and working hard to make every boundary seem a natural part of a believable landscape.

Champions doesn't even try to do any of this. Each zone is a big rectangle and the edge is the edge, full stop. You can be running down a street in Millennium City and suddenly smack into an invisible wall that has no relation at all to the scenery around you. There's no wall, no gate, no unpassable chasm; there's just a street with cars and pedestrians, and many more blocks of street ahead of you, and you can;t go there. When you try, you just bang your head on the invisible wall.

Partly, this design decision has to be an acknowledgement of the problems that travel powers create: how are you going to carefully craft terrain that conceals the world's edges, when players can fly anywhere they want? Well, Blizzard's work on The Burning Crusade provides one answer, but that's a heck of a lot of work, and deadlines have to be met. We can forgive Cryptic the decision to put their efforts elsewhere, especially since they put it into making the first few hours of the game huge fun, and succeeded brilliantly. Prospective players should be aware, though, that if they're looking for a world they can dwell in, a world suited to immersive play, Champions is not it. Those of us looking forward to Cryptic's forthcoming Star Trek Online have to hope they went a different way with that title.

It Ain't Over 'Til It's Over

Okay, Champions has problems. Cryptic has fumbled a little with the gameplay, especially in balancing character power, quest rewards, and customizing characters after they're created. In tuning the gameplay after launch, they've created a bit of a content problem for themselves. Quantity is not the only problem there; they need to work some on variety, too. And if they stick with the aesthetics that drove the design of Millennium City, the Southwest Desert, and the Canadian Wilderness, they're going to have a problem with immersiveness, and with players just plain getting tired of the same thing all the time.

All that said, with all its problems, Champions is still enormous fun to play. All the Power Sets provide a pure, visceral excitement, and advancement is a cafeteria of great abilities that you can use to build nearly anything you can imagine.

Even with all the issues the game has, it's still well worth buying and playing, at least for a few months. Whether it's worth continuing past that point depends on what Cryptic does next. If they can iron out the balance problems, get out of the way of players experimenting with powers, address the sameness and scarceness of mission content, and give us some place more interesting to go than the same three big square rooms, then we'll be playing for a long time.

If not, well, a few years down the road we'll be saying, "Remember how much fun Champions was?" "Yeah, why doesn't somebody give us a real game that's that much fun to start?"

Oct. 1st, 2009

Redefining MMOs: The game no one is making

The "Massively" blog (http://www.massively.com/), which publishes news articles about MMORPGs, is wrapping up a series called "Redefining MMOs", and they've asked readers to tell them what they want to see in next-generation, "redefined" MMORPGs. You can find related articles here:

http://www.massively.com/category/redefining-mmos/

For Massively's sake, my email address is mevins@me.com.

That post provides me a perfect excuse to summarize the goals of the XG gaming project.

Of course, I've written such articles before; "The Whole Elephant", below, gives a bird's-eye view of the qualities I'm looking for in an MMORPG. That's the long-term goal of the XG software project (http://code.google.com/p/explorersguild/). This time, though, let's do it a different way. Let's talk about the nitty-gritty of game features in my ideal MMORPG.

I'd like to see a very large world with a lot of variety in terrain, flora, and fauna. I don't want it to be chopped up into zones by level. In fact, I'd be happier if there were no levels at all. Let the level of danger be determined by what sort of creature my character is and what sort of creature he faces. I've never been happy with the concept of a level one bear. Bears are big, tough, and dangerous. If the time comes that I don't have to worry about bears, it's because I've become pretty darn big, tough, and dangerous myself. Now the bears can worry about me. I'll worry when I run into something that bears are scared of.

Don't just make the world big; design it to grow. Design it with a lot of space for expansion, and keep the new things coming all the time. Let us find them. Exploration is wonderful. Watch what we like to do and where we like to go, and add places for us to find. XG has plans for worlds that can do a lot of that automatically, with some human help, but that's a topic for another time. The main thing is, make worlds that we can help to create by exploring them, and don't make us wait a dog's age for expansions; design the world to grow a little every month, or every week.

I'd like to see mobs that seem to have their own lives, rather than just being spat out arbitrarily by a spawn point. Darkfall, even with all its problems, had the right idea here. That gang of goblins should be in those ruins for some reason. They should have an agenda. If you kill a bunch of them, they shouldn't just respawn; make them run away and look for reinforcements. Maybe they don't come back until you're gone, and then they fortify the place so that it won't be so easy to drive them away next time. Or maybe they give up and move to a less dangerous hideout, and try to sneak whatever it was they were interested in out of those ruins. Point is, give mobs a reason to do what they do. Doing so will give us reasons to do something with them. If the mobs are interesting enough, we don't need as many quests.

I'd like to lose levels altogether. Let me build a character with something like the freedom that Champions gives us--only moreso. Give us skill curves that model actual skill--skilling up is easy to start and gets harder; stop practicing and your skill decreases--and adjust the curves until you reach the point of maximum fun. Give us a rich enough library of skills that we'll have tradeoffs to make. Then don't stick obstacles in the way of acquiring or changing them, unless they contribute positively to our immersion in the game. Losing skill in an ability because I don't use it enough makes sense. Being unable to learn something new because I don't have enough gold to buy a respec doesn't; it's just an arbitrary barrier.

I want to lose classes, too, at least the normal kind of classes. What I want to see instead is a robust system of skills, with progression trees that depend on skilling up and on combining skills. Skilling up tends to translate directly into macroing; Lord of the Rings Online counters this effect with their Deeds system by capping how much you can advance a Deed per day. That works fine; it not only serves a practical purpose, it also serves as a reasonable model of the human limits on skill improvement that athletes actually run into. There's only so much improvement you can make in a short time, no matter how much you want to work at something.

But I don't want to lose classes completely. Instead, I want to see a set of tools that groups of players can use to build their own classes by assembling abilities into skill trees. Force them to make tradeoffs with their skill trees, sure. Make them earn the privilege of creating classes, sure. But give the players the ability to create factions with unique classes.

That approach represents a larger goal I have for this kind of game. I want MMORPGs in which the world is alive and changing, and where what the players do helps to create the world. Not only should player-created factions be able to come up with new and unique classes, they should also be able to earn the right to create quests and rewards. They should be able to look forward to the factions they create becoming part of the game world, part of the story that all other players see.

I want players to have the opportunity to be world-builders, too. When I play conventional games, I'm always frustrated that I can't add content to the world. I want to take a group of Gnomes into Ironforge, set up a shop, hang a sign, and do business. I want to get together with my Hobbit friends and build a brand new watchtower north of Oatbarton, to keep an eye on those goblins and wolves. I want to found a new order of Disciples of Khaine and build a bone tower where they practice their bloody rites. I want players to be able to create new buildings, new towns, new factions, new storylines, and have all of those things available to all players.

I want one world. I don't mean there should only ever be one, true MMORPG world. I mean I want each world to be like EVE Online's world. If you play EVE, you don't need to know what realm or shard your friends are playing on; there's just one. I want a game where each imaginary world gets exactly one copy, like EVE. It's not only so that players don't have to worry about which shard their friends are on; it's so that the game world can have a timeline and a history. It's so that, when you create a character or a faction or a building or a village or a kingdom, your creation will be encountered by the whole world of players. It's so that the shared experience is really shared; so that we're all talking about the same thing when we mention the Battle of Foobar, or the Fall of the Ogre of the West March.

I want to see a system where a group of players can take over control of a group of NPCs, and play them. That might mean a small player group getting together for a short time to make the goblins in the ruins into something a little more fun. Or it might mean a more ambitious group of players taking over some band of ruffians and turning them into a full-fledged faction. Do we all know about Shadowclan? The guild of players who decided to play orcs in Ultima Online to provide a smarter and more entertaining enemy than the mobs, and how in the process they created the concept of monster RP? I hope we as players don't forget that. I hope we as game developers can make room for a lot more of it to happen in our games in the future. I want players like Shadowclan to come into a game and say, "hey! Those NPCs look fun; let's take them over." Or where they can say, "Geez, you know, that road there looks like a good place for a bunch of bloodthirsty goblins. Let get on that." Or even, "wow, you know, this city would be a lot more interesting if it had a big old Thieves' Guild in a big, spooky, labyrinthine guild hall. Let's get started on that right away."

I want to play an MMORPG where the world is a canvas we can use to create things. That means it needs history; it needs a world that the players can change, and a world that stays changed after the players change it. It means it needs ways to build things--buildings, towns, factions, classes--and have them last and be seen by other players.

It also means that it needs destroyers. It is a law of nature that if you hand out paintbrushes, someone's going to paint something rude on the nearest wall. That's where the destroyers come in: beings of godlike power (that is, operations staff) that go around obliterating things and taking power away from people. It would be nice if we didn't need such a thing, but of course we will.

I want to see a game where we don't all work our way through the same sequence of the same quests, and we don't all grind to get the same items. If I kill Mobnorg the ogre, I want him to be dead. I don't want five other people to come along in the next fifteen minutes and kill Mobnorg the ogre. Who cares if I killed Mobnorg the ogre, when four hundred people already did it today before me? I want to see a world that can accommodate unique events. I want characters whose stories are different from every other character's.

While we're at it, let's lose the epic magical items that roll off the assembly line. I mean, how epic and magical is an item really when there are five thousand copies of it? Besides which, surely it should be more important that a fencer is a master of the art of the sword, than whether his sword is green or purple. There's a place for magical items, but in order for them to be magical, they need to be rare and unique. "Unique" means there is exactly one. If there are two Glowing Purple Maces of the Furious Hedgehog, then it's not unique. If we want magical items, let's take a page from Lord of the Rings Online and make them "legendary", unique, and customized to the particular character, so that only you and perhaps your heir ever have your Bright Orange Spatula of the Titans.

I want to see a good, workable version of permanent death. Why? Mortal characters should age and die. If they don't, we can't really have history and stories that we participate in and create. Permadeath doesn't have to happen often, and it doesn't have to be something that blindside new players so that they shun the game. But when you choose to roll a *mortal* character, it should be clear from the get-go that your character will eventually shuffle off its *mortal* coil, from old age, if nothing else. That way, the game world can have generations of characters with histories. There can be statues of the fallen heroes, and those can be players, instead of purely fictional characters. Real people can visit a statute and remember who it was, and what the world was like before that battle. There's no story without history, and there's no history in a world where everyone and everything is reborn a hundred times a day.

Along with permanent death, I want to see mortals, immortals, and transitions that can take you between their worlds. When a mortal dies, I want the option to keep playing--not as the same character magically sprung back to life, but as an undead, or a ghost. I want to see apotheosis, in which mortals may become (minor) gods or demons. I want to see incarnation, in which immortals can be reborn as mortals. I want to see play options for immortals that reflect their legendary natures. For example, if you are a godling, you should be able to gain power by attracting worshippers. You should be limited by the influence of competing gods, and by the damping effect of unbelief. If you are an undead, you should have unearthly powers, sure, but you should also suffer weaknesses inherent in your magical nature--banes, wards, holy symbols: these things should weaken and overcome you, and you should have to work around them.

I'd like to see an MMORPG game world that can simultaneously accommodate several playstyles. I'd like to see a world where you can go adventuring and come across a battlefield where two grand armies (led by players) are contending to decide the fates of kingdoms; where secluded enclaves of wizards and engineers work furiously behind closed gates to launch RTS-style assaults n other enclaves; where you can advance the the highest levels of wealth, prestige, and skill by exploring the uncharted boundaries of the map and bringing back wonders no one has seen before.

I want an MMORPG that is as much a playground for authors as it is for audiences.

Sep. 21st, 2009

Doing It Wrong

Why does it cost a lot to rebuild a character in an MMORPG?

Most MMORPGs provide various ways to customize characters. The details and terminology vary from one game to the next. The 800-pound gorilla, World of Warcraft, requires that you start by choosing a race and class, and then it grants "Talent" points as you level up. You can spend these talent points to modify the details of how your character plays. In Warhammer Online, the customizations are called "Masteries," rather than talents, and, like WoW, WAR gives you a point to spend on them each time you gain a level.

Like most everything it does, Lord of the Rings Online provides a scheme that is generally similar to those of the other games, but with its own twist on the idea, and, just maybe, more careful thought put into making it fun and rewarding. Instead of granting you a point every time you gain a level, LOTRO offers "Deeds", which you gain by doing any of a wide variety of different things. Many Deeds grant Traits, which serve the same purpose as Talents or Masteries, but which are much more interesting to accrue, because, first of all, the Deed is generally related in some way to the particular activity you had to pursue in order to get it (for example, Staff Mastery is gained by using a staff a lot in a particular way), and secondly, because Deeds are completely unrelated to experience and leveling, so the Deeds system feels like a completely different and independent way to customize and advance your character.

The particular set of customizations that a character has is generally called a "build". One thing that all MMORPGs seem to do the same way is, they charge game currency to change builds. Why is that?

To take the most prominent example, in World of Warcraft, you can at any time visit a trainer and reset your build. All your spent talent points are refunded, and all customizations you've made by spending them are removed. The first time you do this, it costs one gold. That's a lot of money to a brand new character, but very little to anyone above level thirty. The second time you do it, it costs five gold. The third time, it costs ten gold. Each time you do it, the price goes up by five gold, until it reaches fifty, which is the cap.

What is that fee for?

For current players of WoW, a cap of fifty gold is trivial. It's maybe enough to keep endgame players from rebuilding their characters several times a day, but I have to wonder why anyone would care if they did.

In some games, changing builds is harder and more expensive. One current controversy in the new superhero game, Champions Online--a very good game in many respects--is over the cost of a "retcon", which is what Champions calls the process of rebuilding a character's customizations. The question is more important in Champions than in many other games, because of some of the game's unique features, and it's a thornier issue, too, because the current cost of retcons is quite high.

Why is it so high?

In fact, why do MMORPGs put any barrier at all in the way of rebuilding character customizations?

Cryptic has said that retcons "can't be" very cheap, but they haven't said why. So what's the reason? What bad thing would happen to an MMORPG if players could painlessly rebuild their customizations any time they wanted?

One argument is that, in the presence of easy rebuilds, diversity would suffer, as players would quickly gravitate to a handful of popular builds. The first thing that occurs to me is that, if this is a problem, then why haven't we seen hundreds of Champions characters that all look alike? It's easy as pie to completely change your appearance several times a day, and yet there are no hordes of identically-uniformed characters plaguing the game. Why not?

How are builds any different from appearance? Well, builds can strongly influence the effectiveness of a character in play; that's a definite difference. Cosmetic appearances don't have any such effect. Okay, so who cares how effective a character is, and why?

Well, obviously, the player who owns the character cares. The more effective a build is, the easier and more fun it will be to play the game. This fact could indeed result in a loss of diversity, as many players converge on the small number of particularly effective builds--but only if some builds are notably more effective than others. That's not an unusual circumstance--in fact, it's nearly inevitable--but it isn't intentional. It happens accidentally. It's a failure of the game-design process, and a wise game designer wants to know about it as quickly as possible, so that he can fix it. Anything that makes it harder to tell which builds are more effective, and which are less, works against the game designers, making it harder for them to do their jobs. It also works against the players. They of course want to know which options are most effective, so that they don't waste a lot of game time building up a character that is crippled, ineffective, and unfun to play.

If the player base converges on just a few builds, it's because something is wrong with the other builds, and they need to be fixed. The quicker and easier it is to find that out, the better. Making it harder and slower to collect that information, which is what raising the costs of rebuilds does, benefits no one. Well, okay, it benefits players who've found good builds and don't want anyone else to find them. I have to say, I don't worry a lot about keeping those guys happy. If you want to play with a stacked deck, tell it to somebody else.

Some players claim that if other players rebuild their characters all the time, that their experience of the game will suffer, that it will break immersion, and so on. This one is pretty hard to believe, if you've spent much time in MMORPGs. First of all, nobody is anywhere near as interested in anyone else's characters as they are in their own, and the odds that anyone would even notice if you completely remade your character every single day for a month are pretty low--excepting, of course, the friends that you regularly play with. And if we're talking about the friends that you regularly play with, well, you and your friends are perfectly capable of deciding for yourselves how much fluctuation you're comfortable with. Heck, if you want standards, form a guild, and put the standards in the rules.

Secondly, it's pretty darn hard to believe that, in games full of people with names like "Invincable" and "Dethmuthakilla", and "Pwnface", that your immersion is going to fall apart because someone switched from casting fire spells to casting ice spells and back again. I just don't buy it, sorry.

Another argument is that if rebuilds were cheap and easy, then replayability would suffer. Instead of starting another character in order to try out a different experience, players would just rebuild an existing, high-level character and try out the game experience that way. Advocates of this view are not thinking things through. A game is replayable if people want to play through it again. You don't rebuild a high-level character because you want to play through the game again. If you want to play through the game again, you start a new character. You rebuild because you don't want to play through it again; you just want to try a different set of high-level options. They're two different things. If rebuilds are expensive, that just means that one of those two things is less available, less appealing. The more expensive rebuilds are, the less appealing it is to try alternatives. You can't reliably influence more people to replay by raising the cost of rebuilds, any more than you can reliably get more people to buy Fords by raising the cost of champagne. The two goods satisfy different demands.

Even if that strategy did work, would it be a good idea? If you're trying to make your game more replayable by increasing that pain-in-the-ass factor of the endgame, rather than by making the early game more fun and varied, then you're doing it wrong. You haven't made your game more replayable. You've added a hazing ritual, and players just have to decide whether they want to put up with it.

And the cost of rebuilds doesn't affect revenues one way or another...unless it exasperates you enough that you decide to leave the game. If you're interested in playing, you'll play--one character at a time, like always, whether you can easily rebuild that character or not. Cheap, easy rebuilds do not harm replayability. Poor replayability harms replayability. Making rebuilds more of a pain does not somehow magically make it more fun to play the same content again.

What possible reason does that leave?

There's the argument that people in real life, and characters in stories, don't drastically change their natures from day to day, so characters in an MMORPG shouldn't, either. This one is totally ridiculous, but I've seen someone seriously proposing it as an argument for high rebuild costs. I mean, come on. We're playing pretend with made up characters. Who cares how many drafts it takes a storyteller to get his story right? Who cares what the names and personalities and backstories of the characters were in the first draft, or in the tenth? Isn't the quality of the final product what we should be interested in?

Maybe it takes you a few tries, or a lot of tries, to get your character to work the way you want. Why is that anyone else's concern? If your back-story, or your appearance, or your powers are different today from what they were yesterday, who gives a rat's ass? Shouldn't we be more interested in how well you play today? Shouldn't we be more interested in how much fun you are to play with? In how much fun you're having, and how much fun we're having? Gimme a break with this one.

Are there any good reasons to impose a high cost on rebuilding character customizations?

Aug. 13th, 2009

Categories

There are a few things I've written that I see cited or quote repeatedly. The oldest is a quip about omnipotent beings that I wrote eighteen years ago in a USENET discussion:

"Perhaps this morning there were only three Euclidean solids, but god changed
its mind retroactively at lunchtime, remaking the whole history of the
universe. That's the way it is with omnipotent beings."

More recent is an explanation I once gave of the concept of "natural law" in politics. There are a couple of basic theories of law; one of them is called "natural law". Because that phrase is also used to mean "law of nature", people sometimes confuse the two concepts, often, I think, because they're not aware that the legal one exists, or are not aware of what it is. This was my attempt to succinctly summarize it in one discussion:

"People will naturally and predictably find some methods for resolving [...] conflicts more congenial than others. There are some classes of conflict for which people will naturally and predictably find certain kinds of resolutions more congenial than others. The procedures people find more congenial will also produce the resolutions people find more congenial. And the procedures and resolutions that people find more congenial will tend to resemble each other across times and cultures."

Two others are more technical articles that I wrote early in the 1990s about programming. They were published in a magazine aimed at Mac developers, called Frameworks (now archived at MacTech).

"Objects Without Classes" was republished by the ACM's Computer magazine in Volume 27 , Issue 3 (March 1994) . It's a basic description of prototype-based object systems, such as those found in languages like Self and Javascript. Languages with prototype-based object systems probably seemed novel to more people then than they do now. Lots of people use Javascript now, but at that time you might never have heard of prototype-based object systems unless you were at Sun working on Self, or in the AI business, working with frame languages, or at Apple working on Newton or SK8.

The topic of this post is the ideas presented in "Protocols," originally published in the March, 1994 issue of Frameworks, and archived here. It's an article about how representation, behavior, and taxonomy are distinct concepts that can be handled separately, despite the fact that object-oriented languages tend to confuse them.

Those points need clarifying, I know.

By "representation," I mean how we concretely lay out data. As an example, you can represent an array as a contiguous sequence of memory locations, or as a table of indexes paired with pointers, or as a tree of cells in which bit patterns are mapped to subtrees, or, of course, in many other ways. There are circumstances in which each of the different approaches might be advantageous. These are different representations of a common abstract concept that I have here called an "array".

By "behavior," I mean the set of operations that is defined on any given set of values. Taking the abovementioned abstract concept of an "array" as an example, you can use any of the mentioned representations to support a common behavior. You can straightforwardly implement functions that fetch an element of an array by index, that iterate over the members of an array, that write a new value to the array at some specified index. The implementation and performance details will differ, of course, because the representation differs, but the behavior—that is, the API and what it accomplishes—is the same.

By "taxonomy," I mean the relationship between one defined set of values and another. Types are categories of values. They are (possibly unbounded) collections of data objects. Types naturally have subtypes; a collection of values has a natural relation to a smaller collection of some of the same values: the smaller set is a subtype of the larger one. It's natural to think of obtaining the smaller set by starting with the larger one and adding restrictions that filter out some values. You can think of taxonomies of types, such as the class hierarchies in languages like Smalltalk and Java, as sets of values that begin with a very inclusive type, like Java's Object, and develops more and more refined types by adding more and more exclusive restrictions. Object is all the values (I know; it's not really all of them.) Number excludes all those objects that aren't representations of magnitudes. Integer excludes all that are not representations of whole numbers. And so on.

These three concepts, representation, behavior, and taxonomy, are quite distinct, but most object-oriented languages conflate at least two of them. Some combine all three. Smalltalk classes, for example, are representation, behavior, and taxonomy all rolled into one. The representation is in the instance variables; the behavior is in the methods; the taxonomy is in the subclass/superclass relations. THe trouble with that approach is that when you ask for one of the three, you get the other two whether you want them or not. For example, if you create a new subclass, you inherit representation, behavior, and taxonomy, even if all you wanted was behavior. If you create some subclass because you want a certain taxonomic relation, you also get a representation and a behavior that may or may not be what you need.

The claim of the "Prototypes" article was that you can treat these three concepts separately, and by doing so develop a discipline that makes object-oriented design and implementation feasible in any language. Furthermore, by doing so, you can develop APIs that are language independent. To take the "array" example, what makes it an "array" is that you can get and set elements by index, and iterate over them in index order. That's behavior. If representation, behavior, and taxonomy are properly separated, you can represent "arrays" any way you like, and you can arrange for them to be subtypes of any type you like, and they'll still be arrays, because they support "array" behavior. Representation and taxonomy can be treated independently as well, but not if your tools insist on conflating them.

I still think that's true, and useful, but I was always interested in codifying the ideas of that article more concretely. I was interested in working with an object system designed around clearly distinguishing representation, behavior, and taxonomy.

One language that pretty much nails it is Haskell. In Haskell, representation is the province of datatypes. Behavior is handled by functions. Taxonomy belongs to typeclasses.

For those unfamiliar with Haskell, the terminology is probably confusing. Without some experience with Haskell, it's probably not at all clear how and why "datatypes" and "typeclasses" are different. Briefly, a Haskell datatype is a named description of an arrangement of data. A typeclass is a named description of a set of operations. You can make a datatype into a member of a typeclass by defining functions that implement the operations specified by the typeclass.

This is pretty close to what I was talking about in "Protocols;" it's probably closer than anything else I've seen to language support for those concepts. The next closest thing, I think, is the style of object system exemplified by CLOS (the Common Lisp Object System). In CLOS, classes describe representation and taxonomy. Generic functions and methods describe behavior. It's easy and convenient to describe behavior in CLOS independently of representation or taxonomy. CLOS does still conflate representation with taxonomy, though it provides facilities for modifying itself that enable you to work around that conflation if you really want to.

In February of 2009 I had been using the new Lisp dialect, Clojure, for about five months on some projects, and was generally pretty happy with it. One area I wasn't happy with, though, was Clojure's approach to types and polymorphic functions. Clojure doesn't really have a type system as such. It has a small number of well-chosen and well-designed types, and it can transparently use Java's types (Clojure's main implementation is built on the JVM). For most uses, these two facilities are more than sufficient, and they work very well. They fell a little short of what I wanted for some of my work, though. One of my projects requires ways to specify a large number of structured data elements with taxonomic relations. The set of elements is open, and expected to grow over time, so I need a convenient way to add descriptions of new ones, and ways to ensure that relevant APIs are defined to work in the proper way over all the values currently described, and over all those that are yet to be described.

Clojure gives me a lot of what I want to support this scenario, but not all of it. Clojure's maps provide a great way to describe structured data, but not a great way to place restrictions on it. I can say that Foo has fields A, B, and C, but there's no convenient way to say that A is an automobile and B is a hypotenuse; nor is there a convenient way to say that a Foo has A,B, and C, and nothing else.

I was even more dissatisfied with the facilities that Clojure provided for defining taxonomy. Clojure's documentation, and its justifiably enthusiastic users, make much of the fact that Clojure's derive function and its polymorphic MultiFns make it possible to define arbitrary taxonomies. That's true for small values of "arbitrary". You can easily construct any taxonomy, as long as it's a taxonomy that Clojure was designed to easily construct. Mine wasn't.

The details of the problems don't matter. My main point is that I ran into a couple of insoluble problems with Clojure's MultiFns, derive, and hierarchies, and, after some discussion, satisfied myself that the Clojure community regarded those obstacles as features rather than bugs. So I did what any sensible Lisp hacker does in a situation like that: I wrote my own object system.

It began as an existence proof of an alternative way of handling polymorphic dispatch. There was a little bit of interest in it from a couple of people, but for the most part the Clojure community reacted with a shrug. On the whole, they're happy with Clojure's approach. More power to them.

As I tweaked a few things to respond to casually-mentioned hypothetical objections, I started to like what I had. I was testing it by reimplementing important parts of some production code I was working on. I realized pretty early that the subsystem I was builiding bore more than a passing resemblance to the ideas in "Protocols". I refactored it a few times. I tried a couple of different implementation strategies. It got faster, simpler, and more appealing (to me, that is). Somewhere along the way, I started calling it Categories.

I have a couple of implementations of it in Clojure now, with somewhat different APIs. More recently, I ported it to Scheme, so that I can try it out in a different application context. The API mutated a little more. I'm still refactoring things to try to make the surface API simpler and easier to understand.

Categories represents the concepts from "Protocols" pretty straightforwardly. The basic concepts are:

Types: descriptions of how data are laid out.

Functions: operations that accept zero or more values as parameters, and that compute and return zero or more values as results.

Domains: descriptions of relations among types.

Functions are polymorphic, and are defined in terms of domains. In other words, a functions looks at its arguments at runtime and decides which actual code to run based on what it sees. This is like any other object-oriented language, as far as it goes. The distinguishing characteristic of the system is how a function choses a method.

When you construct a function, one parameter to its constructor is a domain. A domain contains a catalog of types, and a set of rules (represented as functions) that describe how the types are related. Domains can tell you things like whether a type is a member of the domain, whether one type is a subtype of another, and whether a method can be applied to a particular set of argument values.

Importantly, you can have as many domains as you want, and each one can work differently. How you represent the relations among types is entirely up to you. This means that you can pretty easily implement any kind of dispatching you want. Smaltalk-style, Java-style, CLOS-style, predicate dispatch—it's all good. The Categories subsystem defines a default domain that implements a dispatch scheme very similar to those of CLOS and Dylan (because I like those schemes and am comfortable with them), but the default is just one domain. If you want something different, it's easy enough to build it. Just to make sure, I wrote implementations of Clojure's dispatch and of a predicate-dispatch scheme. They were easy to do.

When I was first discussing these ideas, someone mentioned some concern that it wouldn't be possible to implement such a system efficiently, or to optimize it. In practice, it hasn't been a problem. There is a tradeoff between exposing the API you need to implement a domain efficiently, and making the domain API understandable, and that's been a major issue I'm dealing with in rewrites of Categories. It seems clear at this point, though, that efficient implementations are doable. The trick is setting things up so that you can write domains that are efficient without exposing a confusing array of knobs and switches. I'm still working on striking the right balance.

You can't get a current working version of Categories right now; I still have its guts out on the table so I can tinker with them. Some of its early predecessors are readily available if you really want them, but if you read this and are really interested in Categories, I'd counsel patience. I'm folding it into some product code right now, and making corrections and improvements as that process reveals the need. It's my intention to nail it down and ship a product that uses it, then port that version back over to Clojure to support some other work I'm doing in that language. Once I reach that point, if you ask me for it, I'll give it to you.

Why would you want it? I dunno; you might not. I sure did, though, enough to build it. Soon I'll see if it was a waste of time, or a great new tool for my toolbox.

Aug. 12th, 2009

Sometimes you want to play a game

As the XG group has been working on the organization of our latest project, it occurred to me that we're adopting a structure that has served the XG group well through several games. That got me to thinking about guilds and teams in MMORPGs generally, and about common characteristics of the most successful guilds.

[XG's latest project is "Noss Rhiw", a team-oriented roleplaying and questing guild in Lord of the Rings Online, focused on playing through the Epic storyline. If you'd like to know more, contact me here, or speak to Heirobhan or Rhovellon in-game on LOTRO's Landroval server.]

I'd consider a lot of guilds unsuccessful, even when they last for a long time. I've seen some guilds grow large by recruiting anybody who comes along, and some of these have lasted quite a long time, but I don't consider them successful guilds. To be a successful guild, I think you need to involve the members in some common goals, to create a sense of shared community. Without that, a guild, even if it's large and long-lived, isn't successful; it's just a random bunch of people who happen to have the same guild tag under their names. Such a guild is useful for someone who wants to play alone, and who doesn't want to receive guild invitations, but it serves little purpose beyond that.

A successful guild is actually fun to belong to. It's a group effort designed to create fun for its members. There are a few ways to go about this, and a range of sizes from huge to tiny.

At the huge end, you have groups like Shadow Company, a large gaming guild with active communities in five games presently, and in four more games previously. Shadow Company has been in existence and growing since 2004. (Shadow Company's home)

Moving toward smaller groups, the venerable Shadowclan is still a fairly large group, with hundreds of members in some games, and its own approach to organization and recruitment. Shadowclan may be the most famous of these groups; it's been in existence since 1997, and has even been mentioned by name in the collateral materials of some commercially-successful games. (Shadowclan home)

At the small end of the scale, the XG groups have ranged in size from about five people to about fifteen. Once again, XG has its own unique approach to organization and recruitment. The oldest of the examples, XG has been active since 1975. (XG home)

I'd regard all of these examples as successful guilds. Each one has survived for an extended period, and has continued to conceive and create interesting new projects that attract new players. Each one fosters a strong sense of community, and enthusiasm for the group's projects. With the range of gaming options increasing all the time, members of these groups nevertheless continue to chose participation in the group's activities over other options. All three groups actively watch development of new games, and discuss options for the creation of new guild branches and projects.

Besides their continued successes, are there other things these groups have in common?

All three groups have relatively rigid recruitment and membership policies.

Shadowclan will sign up anyone who wants to join, but they first require you to read their rules and agree, in their peculiar dialect, to abide by them. You must then pass a series of tests administered by more senior members before being admitted to full membership.

Shadow Company also accepts most people who want to join, but with a slightly more involved recruitment process. You must apply to their web site and receive approval to contact a recruitment officer in-game. Once invited, you are assigned a commanding officer to whom you must report, and a training officer who will advise and guide you toward acceptance as a full member. Shadow Company uses their psuedo-military organization to advantage. You are expected to learn and obey a comprehensive set of regulations in order to become, and remain, a full member.

XG groups have some relatively rigid policies as well. Generally, the process for joining an XG project is to contact one of the leading members out-of-game to talk about your goals. If you seem like a good fit, you will be referred to someone in-game. You are then expected to schedule questing time with at least two different members. After those members have each had at least two sessions with you, they report to the general membership on their impressions, and if you receive no thumbs-downs, you will be invited aboard as a full member.

All three groups have some fairly inflexible rules for members.

Shadowclan specifies what to wear, what to carry, what and when to ride, what to do with your loot, and even how to speak. Violate any of these rules and you'll be warned, then tossed out.

Shadow Company has a comprehensive military-style set of regulations. Again, violation of regulations is grounds for dismissal from the guild.

XG rules tell you when to play, what level to be, and what group to play with. Depending on the specific project, they impose additional rules; for example, what race to play, what language to speak, what group role to fill, what crafting professions to take, and so on.

All three guilds have small leadership groups that have guided them over an extended period. In Shadowclan, it's "the Helm"--the shadowy set of individuals who are responsible for administration of Shadowclan as a whole. In Shadow Company, it's Commander Bugbig and his close associates. In XG, it's mainly me, plus whichever of my longtime friends is most active in planning at a given moment.

These examples of successful guilds are highly structured organizations with rigid and detailed rules and policies, administered by small groups of dedicated administrators.

Isn't this a little counter-intuitive? We're talking about gaming guilds here. These are groups of people getting together to have fun with computer games, to play pretend, to indulge in simulated violence and mayhem. Now I'm claiming that the most successful ones are rigid, exclusionary hierarchies run by dictatorial juntas?

I think this result is very interesting, and I probably wouldn't have predicted it. Looking back on my experiences in games, I think that the success of groups like these reveal something interesting bout group dynamics, and about how people assess opportunities, costs, and benefits.

MMORPGs are essentially democratic and egalitarian. Everyone playing has exactly the same opportunities to accrue exactly the same rewards from exactly the same investments. We all come in at level one, choosing from exactly the same set of starting options. Guilds all have the same pools of characters to draw from, and the same sets of options for play. Yet some guilds succeed, and others fail. Some grow rapidly before self-destructing in soap operas. Some fall apart because of member or officer misbehavior. Some become nothing more than warehouses for characters; they continue to exist with full rosters, but the members rarely have anything to do with each other--they are guilds in name only.

Why do some of the most vital and active gaming groups exhibit these common traits of regimentation and restrictive rules? Why do they have in common dictatorial leaderships? Nothing about the games requires these characteristics. Guilds can be organized any way the membership likes. They can have any rules they like, or no rules at all. It's up to the guilds themselves.

One insight is something I said in-game once to someone who was going around inviting all and sundry to join his guild. I declined the invitation. When he wanted to know why, I said "If you're inviting everyone, without knowing anything about them, then you have no standards. I don't want to belong to a group with no standards."

I don't want to belong to a group with no standards because not everyone you meet is nice to play with. If the group has no standards, then it's going to have jerks and idiots in it, because there are no standards to keep them out. Worse, there are other groups that do have standards, which means they're getting the people who aren't jerks and idiots, and the groups with no standards recruit from what's left.

Another point is that guilds that impose arbitrary rules are creating artificial barriers to entry, and that has the effect of improving the group's morale. You have to jump through hoops to join. Sure, they might be arbitrary hoops; they might not have a lot of meaning. They are obstacles, nevertheless. Once you get in, you're with other people who all had to jump through the same hoops. They couldn't just wander in; they had to want to be there.

Furthermore, you can easily find out what the membership requirements are before you start the hoop-jumping process. You have a reasonable chance to consider whether earning membership is worth your effort. If the group does things that sound fun and interesting to you, then there's a fair chance that membership is worth the effort. You jump through the hoops because you think you might like the group. So did everyone else. It's not just a random collection of people. It's a collection of people who put in some effort to join a group that's interested in things they're interested in.

Once accepted into these highly-structured guilds, you find that the rigid rules are not as oppressive as they sounded. For one thing, everyone else has to obey them, too, so it's not like you're being singled out and picked on. For another thing, it turns out that you can see that the rukes have been chosen to make the game more fun in some way. The level requirements and team assignments in XG guarantee that every time you log in to a scheduled session, there is a full team of players, at your level, ready to go. The military ranks in Shadow Company provide a clear chain of command that eliminates much of the time-wasting so common in group efforts in MMORPGs. Shadowclan's rules about what you're allowed to wear make it easy to see where your group is and which ones are the leaders, which is invaluable in group combat, especially in PVP. It turns out that all those pesky rules are features, not bugs!

What about the juntas that rule these guilds? They're gaming enthusiasts who have discovered that group efforts can be enough fun to justify the administrative drudgery and abuse that come with running a gaming group. They love playing with good groups so much that they're willing to put up with the boring work and the occasional insults and drama queens, so that they and others will have the opportunity to play good games with good groups.

If you just drift with the current, often as not you end up snagged somewhere. If you want a fun trip down the river, you probably need to do some actual rowing and steering.

Successful guilds don't just happen by accident. Someone has to set out to make them happen, and they have to keep at it. And good groups don't very often just fall together by accident. A good group needs members with common goals, who set out deliberately to achieve them. Successful guilds are structured because they're trying to have fun on purpose, not just wandering around hoping that fun will run up and find them somehow.

Some players disparage the highly structured guilds, complaining that they don't like the arbitrary rules, or the that restrictions interfere with their freedom of choice, or that they don't like having a boss in a game. I think these complaints are misguided. There's nothing forcing anyone to join any of these guilds. They're no threat to anyone's freedom; if you don't like them, don't join one.

Consider this: football's a fun game for a lot of people. Basketball's another. Then there's soccer, baseball, and so on. But all of those games have rigid rules, organized teams, chains of command. Maybe you'd rather wander out onto a field with a couple dozen other people and just knock some balls around and see what happens. There's nothing wrong with that. It might be pretty fun. It won't be a game of soccer or football, though, not unless someone organizes one. And that means rules, structure, and leadership.

Sometimes kicking a ball around the field is good enough. But sometimes you want to play a game.

Jul. 17th, 2009

Heresy

I’m coming to the close of a contract, and I’m spending part time doing what is natural in that situation: looking for new contracts, and preparing some of my personal projects for release as products.

The first product scheduled for delivery is a Cocoa application for Mac OS X. Written in Scheme. This, of course, is heresy.

Cocoa applications are supposed to be written in Objective-C. (Well, to be fair, about a third of the code in this one is Objective-C. The rest I wrote in Scheme.)

Why would I do a crazy thing like that?

Well, I like Lisp. I’m a Lisp programmer for a reason, that reason being that Lisp is the clear winner on the Joy-Per-Unit-Effort scale. I’m not really partisan in my choice of Lisps. I like Scheme and Common Lisp and Clojure all just fine. If I ever had a favorite Lisp, it was Dylan, but it’s been a while since Dylan really felt like a Lisp.

So I was planning to release this product, and I was looking at options for packaging it. I could certainly have just written it in Objective-C. I’ve been using Objective-C and Apple’s development tools (and NeXT’s development tools before that) for nigh onto twenty years now. It’s a comfortable and familiar ecosystem. But I figured I’d give Lisp a fair shot before settling on the conventional choice because, you know, I like Lisp.

Clojure? Nah; the quick route there is a Swing app. The Java Virtual Machine has many advantages, but delivering great Cocoa apps is not one of them. Sure, if you spend enough time and effort, you can achieve a sort of approximation of a Cocoa UI, but it’s not a fun process. Less Joy Is Bad.

Common Lisp? Maybe. I love Clozure Common Lisp, and it has a great Cocoa interface. Only trouble is, universal apps are off the table, for now. Lispworks? Another good possibility. But my license is getting a little long in the tooth. If I was going to build a product on it, I should really get a new license, so I can have the latest version of Lispworks. And y’know? Right now, end of contract, looking for new contracts, and other revenue streams...not the best moment to spend a few thousand bucks speculatively. Prudence. One learns a modicum of prudence.

I was experimenting with a few options, and Gambit-C (http://dynamo.iro.umontreal.ca/~gambit/wiki/index.php/Main_Page) pleasantly surprised me. Gambit’s been installed on my systems since, oh, probably since 1990 at least. It’s a great Scheme system that has gotten steadily better over the years. But there’s not really any Cocoa support there, or so I thought. Go ahead, Google around; you won’t find much of anything. Except this:

http://jlongster.com/blog/

It describes how this fellow set up remote debugging of a Gambit app running on the iPhone. Wait a second; Gambit on the iPhone? Um. Turns out I know something about iPhone apps. Turns out I’ve written some iPhone products (http://www.iphone4kids.net/2009/06/21/firstwords-learning-how-to-spell/). If this guy has Gambit code running on the iPhone, I’m pretty sure I can get Gambit code to run a Cocoa app, as well.

In fact, it was a piece of cake.

I had allocated a number of hours spread over a week or so to evaluate several alternative possibilities before just settling down and building the app in plain, vanilla Objective-C. After the first session with Gambit, I cancelled all the other evaluations and just wrote the app in Gambit.

It’s true that there is no Objective-C interface in Gambit. Turns out you don’t need one. Gambit has a very good foreign-function interface--a C interface really. Gambit compiles Scheme to C code, and then compiles the resulting C code to native code. One advantage of this approach, which is used by several other Schemes (Chicken and Bigloo, for example), is that you can embed C code in your Scheme, and pretty freely mix the two languages. In point of fact, because Gambit uses the platform’s C compiler, and because Apple’s C compiler handles Objective-C, you can in fact embed Objective-C code in your Scheme.

For example,

(define application-main
  (c-lambda () int
#<<c-code
   NSApplication *app = [NSApplication sharedApplication];
   NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   [NSBundle loadNibNamed: [[[NSBundle mainBundle] infoDictionary] objectForKey: @"NSMainNibFile"]
             owner: app];
   [app run];
   [pool release];
   ___result = 0;
c-code
))


Well, whaddya know? We don’t need no steenking Cocoa interface.

So currently the app is about two thirds Scheme code and one third Objective-C code. It works great. It launches in under half a second and loads its test database in about seventy milliseconds. UI responsiveness and scrolling are as fast as you could possibly want. I built the UI the conventional way, in Interface Builder, and it calls into the Scheme code to display and edit data. The delivered app bundle is 7MB and it’s a universal application that runs on Tiger and later.

Turns out Gambit is a great platform for Cocoa app development. Who knew?

Jun. 9th, 2009

The Whole Elephant

Sometimes I criticize existing MMORPGs. Sometimes I describe features that I wish they had, or approaches to game design that I wish they would take.

But today I thought, why not go for the brass ring, and try to describe what I'm really after?

When I read back over my criticisms and wish-lists, they read like I'm trying to describe an elephant to someone who has only seen goldfish.

"Yeah, it only has four fins, but they're really big. Oh, and they're" all on the bottom. Oh! And big and round, sort of like tree trunks. Oh! And gray."

What if I just describe the elephant, instead?

I'll call my imagined MMORPG XG, because that's what we've been calling the software project we're working on to make it possible. ("XG" is short for "Explorers' Guild").

The first and most important thing I want from XG is a world that is singular, persistent, living, malleable, unbounded, and of a piece.

"Singular" means that there is exactly one of each XG world. One Ymra, for example; one Solaria. There are no shards or realms; there is one shared world in which everyone's characters dwell. The less important reason for this choice is that no one has to ask what realm you're playing on; there's just one. If someone is playing the game, they're playing it in that one, singular world, and that's where you'll find them. I said that was the less important reason, but it's still important.

So what's the more important reason? I want an MMORPG that is a world, not just a game. I'm coming to this enterprise from a background of a pencil-and-paper game that the players used as a vehicle for collaborative improvised fiction. Over the decade or so that we played, we tossed out all the official rules and made our own, and we never used any commercially-prepared campaigns. We were essentially doing improvisational theater where we simultaneously wrote and performed stories. The objective was to build up characters and worlds that we wanted to go back to. Everything about my objectives for XG should be seen in that light. The world is singular because it's the stage where we all play out our characters' lives for all to see. It's the world that we all construct for one another to inhabit. It's singular so that, when you create something, everyone gets to experience it; so that when someone else creates something, it's there for you to see.

"Persistent" means that when you change something, the change lasts. Most MMORPGs are described as "persistent," but few of them are persistent in this sense. Most MMORPG worlds are essentially static. If you find a forest with seven piglets in it today, you can pretty well count on there being a forest with seven piglets in it tomorrow or next year. If you kill the piglets or chop down the trees, your changes will be wiped away in a short time.

It's hard to connect with a world in which your actions have so little meaning. How do you make a place for your characters and stories when you can't make anything lasting at all? XG must be persistent in the sense that when a character acts, the action has consequences, and those consequences are not wiped away a few minutes later. If you chop down the trees, they stay chopped down. If you kill the pigs, they stay dead. A new forest may grow, but it's a *new* forest. Pigs may return, but they have to come from somewhere that pigs live. You can change the world, and later see the consequences of your changes.

"Living" means that the things in the world have their own ways of being and changing, and their own reasons for what they do. If there were seven piglets in that forest, it must be because that forest was a good place for piglets--or at least those piglets thought so. If there are wolves in the forest, it's because there is prey there, and protection from the wolves' enemies. If there's a dungeon hidden away in the rocks, it's because someone has something they want to protect there. If someone attacks you, it's because they have some reason want you dead--or because they fear you and are bravely defending something they care about.

"Living" also means that as you do things that change the world, the world adapts. If you chop down all the trees where the piglets lived, well, then piglets that like living in the forest aren't going to live there anymore. When you change the world, its other inhabitants will notice. Something else that likes meadows might move in to where the forest was. Maybe those piglets have cousins who are big and organized, and ticked off that you chopped down those trees. The XG world is alive and adaptive, not static and unchanging. Not only does it change because you change it; it also changes because it has its own agenda.

"Malleable" means that, as much as it's practical, the world is a canvas for players to paint. It's not an empty canvas. XG worlds will be populated at the start with landscapes, peoples, histories, cultures, and adventures to be had. But an XG world is not intended to stay the same. It's intended to be a place where players can create characters, and those characters can have stories, and those stories can create worlds within the world. An XG world should offer you the opportunity to create a person, his family and friends, their village, the clans that populate the village, the customs and crafts of those clans, the history that brought them to this place, the friends and enemies they've made here, the gods and ancestors they pray to, the destiny they seek to fulfill.

In most MMORPGs, "roleplaying" a character means making an avatar that looks approximately right, giving it an appropriate name (or as close as you can get when someone else has already taken all the names you want to use), and telling people you group with this and that about the character's background, as you do your best to act out the character's personality. XG is an attempt to design a game environment in which you can create worlds and characters the way that authors do. To give you the power to create, not just a "toon", but a *character*. In XG, you don't just build the character's look, you build a life story. That story gives your character his or her look, and also skills, powers, scars, and disabilities. The life-story is part of the game, not just a couple of paragraphs of story that you wrote down in a guild website.

In XG, characters come from somewhere, and are related to someone. Your life story tells you whom you love and hate; who is praying for your return and who is relentlessly tracking you down. When you band together with others to create an affinity (what XG calls guilds), that affinity can be a warrior band, or a tribe, or a clan, or a town, or an order of chivalry, and it becomes part of the game world. As your affinity gains wealth, prestige, and reputation, NPCs will flock to join it. Tales of its exploits will circulate in the game. You will meet other affinities that have heard of you long before they ever met any of your members. You may even choose to take over and run one of the many NPC factions in the game--to become the city guards of a port, or the band of goblins that haunts a lonely road, or the mounted raiders harrying the northern towns.

The important point is that you shape the world to your story, and that story becomes part of the game world. What you do and make is part of the world itself, and other players will encounter it as part of the game. It's not just an afterthought stuck away on some website somewhere.

"Unbounded" means that the XG world has not all been discovered yet. There are lands, peoples, creatures, and treasures out there that no one has ever seen. Go adventuring, and you may find things that have never before seen the light of day. You may bring them back and show them to others to astonish them, or you may hide them away and keep them as precious secrets known only to your closest allies; it's up to you. The important thing is that XG worlds are designed to be open-ended, to be explored into existence. No one will ever know all there is to know about an XG world, because there is always more to see, to learn, to discover.

XG worlds are designed to be physically unbounded. Ymra, for example, is not a planet, but a magical realm that inhabits an infinite plane. At its center is the circle of continents that make up the known world. Perhaps a quarter of that landmass has been thoroughly explored and mapped. The Outer Sea stretches to infinity beyond the boundaries of those continents; who knows what lies in the great distances? Even without traveling away from the center, there is more unexplored land than explored.

Another XG world, Solaria, is our own Solar System five thousand years in the future. Its land area is more than two million times larger than the surface of the earth. Thanks to genetic engineering, nanotechnology, and artificial intelligence, thousands upon thousands of intelligent species roam the spaces around the Sun, and extend as far as you care to explore beyond its fringes, into the Kuiper Belt and the Oort Cloud.

XG worlds are designed with procedural libraries that can create terrains, creatures, artifacts, and so on. You can always happen upon something that no one--not even the world's designers--has ever seen before. Once you have found it though, it's part of the world, and others can encounter it too.

"Of a piece" means that each XG world has a guiding vision, conceived and enforced by its designers. Being "malleable" and "unbounded" does not mean that an XG world is a free-for-all. We grant the players broad powers to create and extend the worlds. Then we exercise our editorial powers to cull the results, to keep the world true to the designers' vision. Ymra will remain a world of mythology and of swords-and-horses fantasy. Solaria will remain a far-future science-fiction habitat whose magic is all made possible by artificial intelligence and nanomachinery.

The power to destroy, given to designers of worlds, is how XG enables a visionary to realize a vision that is also a living world. XG gives every player a great deal of power to create, much more than conventional MMORPGs. That's the only way to make possible the kind of invention that we came to take for granted in the old pencil-and-paper incarnation of Explorers' Guild, where a player could begin with a simple adventurer, and come one day to rule a kingdom, or found a religious order, or lead an army of mechanical men, or construct a mountain paradise, or create a new race of magical beings.

To balance that power, the designers take on the cosmic power to destroy, to remove creations that, in their judgment, don't belong in their world. If you cross the creator, the results may be harsh. On the other hand, we intend to make the XG software available to anyone who wants it for free. If you don't like the rules of an XG world, you can always create your own.

XG worlds are not really intended to be MMORPGs, as we are accustomed to them today. They are intended to be what the XG players wish that MMORPGs were: stages for the ongoing adventure of group-directed, improvisational fiction. If the XG project succeeds, if it eventually bears fruit, this is what you will see: a software infrastructure that makes it possible for storytellers to create worlds by having adventures, and to share their created worlds with anyone who likes them.

May. 25th, 2009

Obamus Caesar

In 27 B.C., Augustus Caesar became the first emperor of Rome, marking the final end of the Roman Republic. While officially praising and respecting Rome's republican laws and traditions, he laid the groundwork for five centuries of autocracy that have become synonymous with despotism and corruption.

It has been common since the founding of the American republic to compare and contrast it with that of ancient Rome, and the comparison can be entertaining, and maybe even informative, if we don't try to make the analogy closer than it really is. The American presidency is not, of course, an hereditary monarchy. The powers granted to the office are not absolute. America is not Rome.

Yet the Roman emperor's office did not start out as an absolute or hereditary monarchy either. In fact, Augustus and his immediate successors never held any such office as "Emperor;" Rome had no such office. They were called "Imperator," but that simply meant commander of Rome's legions, like our own "Commander in Chief." The Roman Imperator didn't even have the domestic authority wielded by the American President. Augustus became "emperor," not through succession to a throne, but by adept political maneuvering and deal-making--and the shedding of just the right blood, of course. He held power and authority that are nowhere described or granted in Rome's laws or traditions. Rome was a republic on paper long after its first emperor had consolidated his power.

At what point was the Republic over, and the Empire established? Did Romans during the reign of Augustus know that the Republic was dead? Surely, they must have. They lamented its passing while Julius Caesar still lived. We can measure the death of the Republic by the disappearance of those laments. After the civil wars were over, and Augustus was established in power, he "restored" the Senate, by which we mean that he told the Senate and the people publicly that power was back in their hands, while privately making sure that his hands were the ones on all the important levers. Gradually the laments over the death of the Republic were replaced by praise for its continued vitality, and Romans once again spoke in praise of the Republic and the rights of free Romans.

It was a sham, of course. We can look back and with a superior smile acknowledge what everyone knows: that after the ascension of Augustus, the Romans may have said they were "free citizens" of a "free Republic," but they were in fact subjects of an autocrat, the first in a line that would continue for five centuries and stand forever after as the paradigm of despotism.

Rome did not declare itself an autocracy; its monarchy was furtive. Its citizens wanted to think that they were free people, that their government was constitutionally limited by its laws and traditions, that there were "no kings in Rome." We can chuckle, but what will posterity say of us?

On May 21st, President Barak Obama proposed a new policy of "prolonged detention," a euphemism for indefinite imprisonment without trial or charge. His proposal is a breathtaking power-grab, a long step beyond the worst excesses of the Bush Administration. What's more, he proposed it as the capstone of a speech, delivered in front of the document itself, praising the lasting value of the "rule of law" and the limits placed on government power by the U.S. Constitution. That's irony that you can feel in your belly.

Perhaps it's as I began to think during the presidency of George W. Bush: perhaps the American electorate really doesn't care about the Constitution anymore. That numbness has been coming for generations. Presidents and congresses have been trampling the boundaries of the Constitution and tearing holes in it almost since it was ratified. Each generation extends new outrages past the outer limits of the last, until we are asked to accept legal interpretations of its once-plain language that should embarrass any reasonable person.

Thomas Jefferson fretted over the Louisiana Purchase, suffering misgivings because he didn't believe the Constitution granted him the power to do it. 139 years later, the U.S. Supreme Court could rule with straight faces (in Wickard v. Filburn) that the commerce clause of the Constitution grants to the federal government the power to regulate what a man does with grain produced by his own hands on his own land for his own use. By that point Americans were already living with a system of government whose relationship to its charter was tenuous, if not surreal.

At least, though, politicians had to say that they respected the Constitution. That seems now to have changed. During the presidency of George W. Bush, he is rumored to have said "Stop throwing the Constitution in my face. It's just a goddamned piece of paper!" The remark itself is not all that interesting.No one who was present at the meeting was willing to go on record saying that it happened (though more than one was willing to say so privately), and even if we could prove that he did say it, people say all sorts of ill-considered things without dire consequences. What is more interesting is that the American public didn't much seem to care. That remarkable utterance stimulated no public outrage whatsoever.

Evidently, the same public whose elected representatives had impeached a president for cheating on his wife couldn't bring themselves to care whether his successor meant what he said when he swore to "preserve, protect, and defend" the Constitution of the United States. Evidently, Americans now regard that oath as a bit of theater required by tradition, and nothing more, just as the Romans felt obliged to keep voting certain offices to Augustus, though there was certainly no danger that he would lose power without them.

At the end of that president's term of office, during the election to replace him, only one candidate made an issue of the Constitution's limits on federal power. That candidate was dismissed early as a crank. His critics were perhaps premature; Ron Paul went on to raise far more money, attract far more media attention, and make far more salient points than anyone expected him to. Still, the common consensus remained that he was a fringe candidate, if not a bit of a nut. And why? Because he was resolutely committed to the limits the U.S. Constitution places on governmental authority. How quaint!

We have passed a turning point. The common knowledge is not what it was when I was a child. Once, people took for granted that the Constitution seriously limited the powers of government officials. That notion was wishful thinking, even then; Civil War and its attendant calamities, economic depression, and facile court rulings had long since turned the Constitution into a paper tiger. But public servants were at least expected to act out a pantomime of respect for it.

We're in a new era now. Barack Obama can stand in front of the Constitution and make a lovely speech praising its virtues and the "rule of law" as a prelude to calling for an act of naked despotism. Oh, the usual commentators are shocked and appalled, but there will be another news story tomorrow. And anyway, our own Lex Galbina, the Military Commissions Act of 2006, is still on the books, along with more than a century of retreat from the clear limits and provisions of the Constitution.

Augustus is generally regarded as the first Roman emperor, although he never officially held any such office, and although Rome went on for some time pretending that it was still a republic.

Is that where we are now? A candidate in America wouldn't get far by openly scoffing at the Constitution in so many words, but it's already okay to scoff at those who take the Constitution seriously. It's okay, once you're elected, to say "it's just a goddamn piece of paper," or to laud it with praises and in the same breath grab for despotic power.

Hail Obamus Caesar, Consul of the American Republic.

Previous 20

December 2009

S M T W T F S
  12345
6789101112
13141516171819
20212223242526
2728293031  

Advertisement

Syndicate

RSS Atom
Powered by LiveJournal.com