Previous 10

Feb. 6th, 2010

Look over there

So in the interest of consolidating all the wriggling threads of my life and work, I'm mashing my code repositories and websites and blogs and just, well, everything together over at bywicket.com.

So if you're one of the screaming throngs following my ramblings, look over there for further posts; I imagine I'll let this blog sort of wither on the vine. And don't trip over that other throng on your way out.

Jan. 23rd, 2010

General Public Busybody Theory

I was idly thinking about the GIFT (explained here), which comes up often for me because I not only surf the net, I also play networked games, where the theory plays out so often and so emphatically. I was also thinking about the things that people think are weird and foolish in other people, because I happen to be traveling this week, and those things vary somewhat from one place to another.

It occurred to me when I thought about those things at the same time that they suggest a reason for the generally widespread hatred of gay people.

Personally, I'm male and, sexually speaking, I like women. But I don't particularly care whether another person prefers men or women or both, regardless of their gender. It's a little hard for me to see why anyone would care about such a thing, much less why they would hold demonstrations or pass laws about it. It doesn't seem to me to be a lot different from passing laws about what flavors of ice cream you're allowed to like.

But when I was thinking about things today, a couple of things occurred to me. First, I've observed that there is a tendency sort of similar to the GIFT, which I might call the "general public busybody theory", which is that, first of all, the majority of people are inclined to be busybodies, and the inclination increases as it gets easier and more anonymous. In other words, the cheaper and easier it is to say that somebody ought to do something, and the less well you know them, the more likely you are to tell them what to do.

In general, I mean. Not everyone seems to have this impulse to boss people around, but it does seem to be very common, and it seems like a majority of people have it to some degree, some more than others.

The second piece of the puzzle is that if you have a sexual preference--any sexual preference--then it's pretty likely to gross another person out if he or she doesn't share it. I imagine that's one reason that talking about sex is sort of impolite. That's a tacit acknowledgement that people like different things, and what is appealing to one person is upsetting to another.

This is not too surprising, really. If you're dispassionate about it, all sex is at least a little bit gross and ridiculous. Being aroused, of course, tends to obliterate any sense of embarrassment or distaste, so we never get much chance to notice that the things we like are weird or icky. But if you could somehow switch off all arousal, then I think most people would notice that their own sexual tastes involve things that are a little bit messy and undignified. It's pretty much just the nature of mammalian reproduction to be that way.

But of course, people can't just turn off their sexual feelings, and they're strong feelings. Accidentally discovering that someone is turned on by something you are not can be very awkward. There's a sort of "EEEEEEWWWWW!!!" moment that some folks in kinky-sex communities call being "squicked". You are "squicked" when you are repelled by something that sexually appeals to someone else. The kinky-sex folks run into it kind of a lot, of course, and talk about it and joke about it, and have sort of social conventions for taking the sting out of it, so it doesn't interfere with their hobbies or friendships. Less promiscuous folks don't really have those conventions, because they don't really have the need or occasion to develop them, so their only experience of being "squicked" is generally the thing itself--the experience of stumbling upon someone with a sexual appetite that makes them go "EEEEEEWWWWW!!!"

Well, nobody likes that, of course.

When you combine that with the general public busybody theory, you have a situation that seems like it's almost tailor-made for creating prejudice against gay people. An average heterosexual person (who is fairly likely to be a busybody, because they seem to be in the majority) encounters a random gay couple holding hands or otherwise acting like they care for one another. This suggests the thought that this couple might be sexually involved. That creates the opportunity to imagine a sexual situation that makes our random busybody go "EEEEEEWWWWW!!!", which, by the general public busybody theory, immediately creates a desire to say that they shouldn't be allowed to do that.

Once I think of it that way, the prejudice, demonstrations, and legislation seem almost inevitable.

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.

Previous 10