While working on Reiner Knizia's Money I had the privilege of speaking with designer Steve Blanding, who was working on bringing another popular card game, Mü, to the iPhone. Steve was kind enough to offer me an article on his own design experiences on Mü, which I've printed below. If you're interested in playing the game, you can purchase Mü at the Apple iPhone store.
Bringing Mü to
the iPhone
by Steve
Blanding
About a year and a half ago I had a Zune. I'd been given one as a gift
and my beloved iPod classic was broken. Microsoft had just released a free SDK
that let people write code for it. Being the geek I am, I thought it
would be a fun project to write a version of Mü that would run on my Zune.
My friends all thought I was crazy. Surely it wasn't possible to make a
good version of Mü on such a tiny, wimpy device! Nevertheless, I ignorantly
forged ahead and a few months later I had a version of Mü that not only
worked on the Zune, it worked surprisingly well! What I didn't have was a
license to distribute the game. The Zune games market being what it is
(non-existent) I didn't see much of a point.
Fast forward a
few months. My wife and I had just bought iPhones and suddenly I was looking
at some interesting possibilities. Unlike Zune, the iPhone has a very
vibrant games market. While I was pretty sure I wouldn't make any serious
money doing it (let's face it, the game is a little too complicated to
appeal to your average iPhone gamer) I recognized that there just might be a
market for an iPhone version of Mü; and besides, I wanted one for myself!
In this article
I'll discuss some of the challenges I had to overcome and some of the things
that I learned along the way.
Perhaps you'll find it interesting.
Becoming Legal
The first hurdle
that I had to overcome was the fact that Mü is a copyrighted game. I didn't
really fancy the idea of stealing Frank Nestel's game and Doris Matthäus'
artwork so before I even started writing code I sent email to Dr. Nestel,
explained what I wanted to do, and asked if he would be interested in
licensing his game. Happily he replied in the affirmative.
I probably don't
need to tell you that the internet is a pretty wonderful thing. Thanks to
the magic of the internet, finding Frank's contact information was extremely
easy and we were able to handle pretty much everything via email. Still,
conducting international business is never without its challenges. He's in
Germany. I'm in Seattle. Luckily his English is way better than my German.
Negotiations went fairly quickly since we were both pretty enthusiastic from
the start but it still took quite some time to actually get a contract
signed. In the mean time, I had begun development in earnest.
Preparing for
Development
When this project
started, I hadn't used a personal computer made by Apple since the 1980s.
Since iPhone development requires a Mac, I had some shopping to do. I
decided that the cheapest and quickest way to get things going would be to
buy a used Mac Mini. My wife thought I was nuts when I spent most of a
Saturday driving to some stranger's house to buy one that he'd advertised on
Craig's List. It turned out to be a pretty good way to go though. I love the
portability of the machine and while it's not the fastest Mac out there,
it's more than powerful enough for iPhone development.
The other hurdle
I had to overcome was that I had to learn the development environment.
Luckily that didn't prove to be too difficult. Apple's on-line documentation
and videos are surprisingly good. If anything, there was too much
information. Objective C isn't my favorite language but it's not too bad.
I've never been much of a language bigot. Unfortunately, since Zune
development is typically done in C#, virtually none of the code that I'd
done for the Zune version could be used unaltered. I had to essentially
re-write the entire game from scratch. Still, that was probably a good
thing. It forced me to reevaluate most of the decisions that I'd made on the
first version and the result was a much stronger game.
I spent several weeks just pouring over Apple's documentation, trying to
learn the environment and absorbing as many of Apple's recommended best
practices as I could. I installed the SDK, I played around with sample code.
I familiarized myself with the environment. I watched scores of video
presentations. Looking back, I'm glad I did. All of that initial groundwork
would eventually pay off when I submitted Mü to Apple and they approved it
in just two days.
Screen Size
One major hurdle
that any developer has bringing anything to a portable platform such as the
iPhone is the small screen. The iPhone's 320x480 screen is pretty big for a
hand-held device (that's twice as many pixels as there were on my Zune) but
it's still pretty cramped. Furthermore, those pixels are crammed onto a
screen that's only 3 inches high so coming up with cards that are readable
becomes a huge challenge.
The cards
underwent several design changes. I started with raw scans of the original
cards shrunk down to 40x65 pixels. While that had worked OK on the Zune,
that turned out to be way too small for the iPhone so I started over, this
time with cards that were shrunk down to 44x70. That was still too small but
I couldn't really go much bigger and still leave room for bidding areas for
each player so I decided that I had to make some subtle changes to the card
design.
The first thing I did was get rid of most of the white border around each
card. I kept all of Doris' lovely artwork but made all of the elements on
each card just a little bit larger. The numbers were pushed a little bit
closer to the color bands and the color bands were enlarged so that they
more completely filled each card. That left me with virtual cards that
looked almost undistinguishable from the original cards but if you look
closely, you might notice that the numbers are actually a bit larger.
The next thing
that I did was dramatically over-saturate all of the colors on the cards. I
found that the original suit colors were far too difficult to distinguish
when reduced to those sizes. Over saturating and slightly altering all of
the colors made it much easier to tell blue from green from black.
I finally had
cards that were readable and still looked like Doris' originals but that
still wasn't good enough. The ornate numbers on the cards made them a little
difficult to read and one of my testers was really pushing for a solution
that was more friendly to the color-blind. I was really reluctant to abandon
any elements of Doris' card design but I finally realized that it had to be
done. Not wanting to completely abandon the traditional design, I left the
traditional cards in the game as an optional setting but the default card
set was changed to use the cleanest font I could find and different symbols
were used as the pips of each suit.
original colors |
traditional cards
|
final design
|
Screen Layout
The next
difficult decision I had to make was how to arrange all of the game
elements. I had originally
thought that I would lay out the screen in landscape mode as I had done on
the Zune (right) but the more I experimented with my mock-ups the more I began to
drift away from that decision. I realized that if I used the standard iPhone
OS elements of a navigation bar at the top and a status bar at the bottom,
I'd be left with a nearly perfect square in the center of the screen (below). That
would give me a natural place to put menu icons and status text and allow me
to follow iPhone conventions as much as possible. Following iPhone
conventions would mean that users would feel more at home with the user
interface and it would also make it possible for me to use many of the
built-in features of the iPhone operating system.
I also realized
that when I hold my iPhone, it just feels more natural in the portrait
orientation. Landscape is fine for two-handed action games like shooters and
the like but for a card game, where one hand cradles the device and the
other hand is used to interact with the game, portrait mode just feels more
natural to me. That's a personal preference of course but hey, it's my game
so I get to do what I like.
Early in the
development process I realized one other unanticipated benefit of sticking
with portrait mode. I could use the iPhone's built-in accelerator functionality to
attach subordinate UI screens to the two landscape orientations. I
decided to use the left landscape orientation to display the summary cards
and the right landscape orientation to display a score sheet.
The game screen
can still get quite crowded because I had to make it possible to represent
the scenario where the maximum of six players have bid nearly all of their
cards, and I needed room for essential scoring information, player names,
link status and bidding feedback. Despite being a little crowded, I think it
works pretty well.
One request that
I've had from time to time is to display points taken during the current
hand while the hand is in progress. Early on I decided not to do that for a
number of reasons: first, it would be yet another set of numbers on an already
crowded screen; second, it's information that you normally would be required
to keep in your head during a real game; but third, and more importantly, if
you stop to think about it, it's not really very useful information. Think
about it. Are you really likely to change the way you play on a trick based on that
knowledge? Almost certainly not. You're going to try to give as many points
to your team as you can while keeping as many points away from your
opponents. It doesn't really matter if the bid is already made or not. The
only scenario where it might matter is if you've already got the result you
wanted and you're deciding whether to give a point card to a partner or
trying to keep it for yourself, and that scenario really isn't all that
important in the grand scheme of things. If you're the type of player for
whom that one or two points really matters, then you can track the points in
your head, just as you would have to do in a live game.
Input Method
Another
difficult, and perhaps somewhat controversial decision that I had to make
was to decide how the user would select, bid, and play cards.
I looked at several different methods before finally making a choice.
The most obvious
method for playing a card would be simply to allow the player to touch the
card he wants to play. On its surface this seems like a good idea but I
quickly rejected it. Fat fingers touching tiny cards on a tiny screen are
not very precise. The cards are small enough that it is all too easy to
accidentally touch the wrong card. There are few things more frustrating
than playing a card by mistake. That clearly wasn't going to work.
Tapping a card
and dragging or flicking it to the middle of the screen worked a little
better but I still found it too easy to accidentally select the wrong card.
What I wanted was an input method that was very clear and as error free as I could
make it.
Eventually I
settled on an input method where the selected card is always shown in front of the
rest of the hand, making it very obvious which one is selected. If you've
got the wrong card you can tap on a different one or slide your finger to one side or the other
until you find the card you want. An arrow icon
appears above the selected card, further reinforcing the selection.
Only after tapping on that icon is the card actually played to the
table. This extra step has seemed a little awkward to some but of all the
input methods that I experimented with, this one was by far the most error
resistant.
Bidding uses
exactly the same method except that instead of playing your card to the
trick, it pushes your card forward in a "marked for bidding" state.
The icon above the card changes to a down arrow. Touch the down arrow
and the card will be pulled back into your hand.
A second icon, pointing to your opponent, is used to lock in your bid
and yield control to the next player. This results in an input method that
is consistent across the entire game and very resistant to accidental taps,
touches or swipes. It may take a little bit of getting used to at first but
I remain convinced that it's the best solution.
From the start, I
disallowed selecting illegal cards but one of my testers suggested a
wonderful finishing touch: that I grey out or dim illegal cards, making it
easy to tell at a glance which cards are legal to play and which ones are
not.
Artificial
Intelligence
Of all the
obstacles that I had to overcome on this project, the AI was certainly the
most challenging. Mü is a very complicated game with a rich bidding mechanic. When I was doing the initial Zune version I did a lot of research
on the topic and I have to say that what I learned was not very encouraging.
After decades of research and development, computers are only just now able
to play a decent game of Bridge, and that's on a very powerful computer!
Card play isn't too terribly difficult but even that's not easy (witness all
of the really crappy Hearts games out there) but bidding! that's another
matter entirely. Getting bidding right is a notoriously hard problem.
Step one to
creating a good game of Mü is just to get the computer to play a hand
correctly. I didn't even think about bidding at the start. Card play is
complicated by the fact that trump changes dramatically from hand to hand,
as do partnerships, and the cards are not all worth the same amount of
points. That meant that a lot of the conventional optimization tricks that
are used to speed card play in a Bridge game just don't apply. I
had to come up with my own optimization techniques, based on some of what
I'd seen in Bridge implementations to be sure, but my own nonetheless.
The card play
logic in Mü (like most card games) is handled using something called a Monte
Carlo routine. In a Monte Carlo routine you start with all of the cards that
you know (because they've already been played or because they've been bid or
because they're in your own hand) and you randomly assign all of the others.
Then you play a number of tricks and you evaluate the outcome. Repeat that
process a number of times and whichever card gives the best results, that is
the card you play. It's a brute-force implementation that, given enough
random samples, and given that you play enough tricks ahead, will result in
optimal play. The problem is that on the iPhone we don't have nearly enough
computing power to evaluate enough tricks or samples to arrive at optimal
play so on top of this foundation I poured a little bit of secret sauce
that allows the computer to make slightly better than average choices
despite the very limited thinking time. The computer DOES NOT CHEAT but it
does get a little bit of help from my experience as a player. There isn't
enough time to really analyze the hand properly so it will occasionally make
a blunder or two but most of the time it gets it right and in my opinion,
that only serves to make the game a little more interesting and lifelike.
Bidding is a much
harder problem. At its core, it still works much the same way: you take a
whole bunch of random samples, you analyze them, and you make the choice
that seems to yield the best results. Unfortunately, if computing power was
scarce during card play, it's REALLY scarce during bidding so I had to take
a lot of short cuts. Still, I
did manage to leave most of the bidding decisions up to the computer. It
analyzes the current bids to determine who it thinks is likely to be chief,
who is likely to be partner, who is likely to be vice, and what is likely to
be trump. At each stage in the
bidding it needs to decide if it should take chief, take vice, put itself on
the hook, position itself to be partner, or just pass. Every major decision
is made by playing a number of randomized hands to completion and deciding
what it thinks the score in a given situation is likely to be. It doesn't
take chief or vice unless it thinks there is a material advantage to doing
so within a given margin for error. Deciding what that margin for error
should be can be tricky. I probably played thousands of hands where the
computer played against me or against itself. I analyzed so many hands that
I got well and truly sick of looking at them but the results were worth it.
It still doesn't play perfectly but given the limitations of the hardware,
I'm very satisfied. The fact
that I can regularly lose to my own game is quite satisfying.
Linked Play
The final
challenge, and certainly a formidable one, was getting linked play to work.
I really wanted to be able to play a game with several human players, all
linked over the network. Getting there turned out to be a lot of work.
I immediately
discarded the idea of linking arbitrary iPhones over the internet. That
would require some sort of match-making service or dedicated server to
enable players to find one another and that was way beyond the scope of what
I was interested in doing.
Instead, I focused on linking over Bluetooth. That had some immediate
advantages: first, it meant that I didn't also have to implement some sort
of chat facility because using Bluetooth implies that all players are within
shouting distance of one another; second, the iPhone v3.0 SDK has built in
matchmaking facilities for linking players over Bluetooth.
The only real drawback there was that I wanted to be able to link
more than two players at a time and nowhere could I find any examples of
code that did that. I couldn't even find any games in the App Store that did
that. (I'm sure they must exist but I couldn't find any in my admittedly
short search.)
Once I'd figured out how to link multiple players, I still had other
challenges. Even though I had designed the game from the start with the
knowledge that I would be adding networked play, and even though I had
experience working on other networked games, I still found it more difficult
than I had anticipated. When you have two computers linked together, all
playing the same game, you need to be very careful that they both stay in
sync. Furthermore,
because they ARE separate computers, there is a built-in expectation that
they should both be able to be doing different things at the same time. For
instance, one player could be reviewing the score sheet while another player
is bidding. Keeping all of those states synchronized and dealing with the
fact that you could be getting messages (or not getting messages) from
another player at any time is really challenging. Despite all of my careful
planning, I still went through several builds where I was unable to play
more than a hand or two without encountering really strange behavior.
Players would play cards that had already been played. I'd end up with
multiple partners, or sometimes no partner at all. Cards would mysteriously
move about the screen. Good times.
That was
complicated further by the fact that none of my beta testers seemed to be
much help where multi-player games were concerned. Most of my beta testers
lived in different cities (or even countries) and therefore they couldn't
really test linked play. Luckily my wife and I both have iPhones and my son
has an iPod Touch so I was able to test linked play myself. My son and I
played a lot of games but I still wish we'd had a lot more time to test. I'm
keeping my fingers crossed that someone won't run into some really hideous
bug when playing with six humans all linked over Bluetooth.
There were some
other really interesting limitations imposed by the iPhone form factor. The
iPhone does not support running more than one application at once and your
application can be shut down at any time for any number of reasons. That
meant that the game had to be designed from the start to be able to save and
resume automatically and with a minimum amount of user interaction.
Furthermore, what
do you do if someone gets a phone call or a text message in the middle of
your linked game and he has to exit the game to answer it? How do you get
that player back into the game? And what if someone has to go home? Do you
force everyone to quit the game just because little Bobby's out past his
curfew? Clearly I needed to allow players to jump back into the middle of a
game in progress and I needed to allow the computer to fill in should
someone leave. Making that happen in a way that was as simple as possible
for the user was a bit of a challenge.
Localization
Both Frank and I
really wanted Mü to be available in more languages than just English. One of
the first things that Frank requested was that we do a German version. I was
completely on board with that idea, especially knowing that the German board
game market is so active, so from the start, I structured the game to allow
localization. That turns out to be really easy on the iPhone. The iPhone has
built-in facilities for separating localizable resources and bundling
multiple languages into the same application package. I also had past
experience with localization so I was aware of virtually all of the issues I
would come up against. From the start I made sure that any localizable
strings used the NSLocalizedString macros. I used icons instead of text
whenever it made sense to do so. I was also very careful to avoid writing
code that would build sentences from component phrases. That resulted in
some redundant strings here and there but it gave me the luxury of rewording
longer sentences if they became too long to fit on screen after localization
and it meant that localizers were always free to use the proper grammar.
I speak
Portuguese so I did a very rough Portuguese translation early on which I
used to work out any kinks in the process.
Unfortunately, my Portuguese isn't good enough that I could release
THAT version of the game. It's currently being proof-read by a native
speaker to fix all of my many embarrassing mistakes.
All of the
in-game documentation (and there is quite a bit of it) is displayed using
the iPhone's wonderful built-in web controls so I was able to put it all in
html files which made localizing the rules and credits a breeze.
Conclusion
This was a
phenomenally satisfying project. I feel that I've produced a fantastic game
and I've learned a lot along the way. I can now play my favorite card game
during my commute! Will it prove to be financially profitable? That remains
to be seen but either way it was well worth the undertaking. Bringing a game
I love to the iPhone has been a reward unto itself.
Thanks for
reading. Now go play Mü!