Wednesday, May 17, 2017

Why Kotlin Is Better Than Whatever Dumb Language You're Using

Ah, clickbait.  Where would the internet be without it?  The answer will shock you!


But seriously, I didn't mean to insult your favorite languageā€¦ much.  After all, your language of choice is probably getting better at a glacial pace.  Right?  If your language isn't dead, then it's gradually getting better as they release updates to it.


How slowly, though?  Well... If the language you're using happens to be Java, then you've no doubt realized that by the time Java becomes a really good language, you'll be dead.  Loooong dead.  I know we don't like to contemplate our own mortality, but when you plot the trajectory of Java from its birth 20+ years ago to its full knee and hip replacement with Java 8, you can't help but wonder, "Am I going to be stuck with this for literally the rest of my life? What if this is as good as it gets?"


Anyhoo, I ran across the old language question again because I finally tried my hand at Android development.  I have an iOS client for my old game Wyvern, and I decided somewhat recently to take the plunge and write an Android version.  I didn't realize that it would turn into a language question (as in, "What the hell am I doing with my life?")  But then, if you've done any Android programming at all, you'll know that this is in fact a burning question in Android-land.


My first attempt at doing Android was last summer, and my god it sucked.  I mean, they warned me.  Everyone warned me. "The APIs are terrible", they all said.  I can't say I wasn't warned.


How terrible could they be, though?  It's just Java, right?


Legacy Yuck


Unfortunately -- for long complicated legacy reasons that nobody cares about -- some of Android's core APIs really are bad.  I mean baaaaad bad.  Shut the book, take a deep breath, and go out for coffee bad.  The warnings were spot on.


It's a mixed bag, though.  A lot of their APIs are just ducky. I found plenty of things that are hard in iOS and easy in Android.  Product flavors, the Downloads service, findViewById(), the Preferences activity, etc.  There is a ton of stuff in Android that has no equivalent at all in iOS, so in iOS you wind up writing gross hacky code or building elaborate libraries to work around it.


But!  There's a big "But".  When you're learning and writing for Android, everyone focuses on the bad APIs, for the same reason that when you're in traffic you focus on the red lights, not the green lights. You tend to judge your commute by how many red lights it has.


And Android has some pretty big red-light APIs.  Fragments, for example, are a well-known Flagship Bad API in Android.  In fact the entire lifecycle is maddeningly awful, for both Activities and Fragments.  iOS is living proof that it didn't have to be that bad.  There's no defending it.  It's so bad that when I tried it for the first time last summer, I just gave up.  Threw in the towel.  Screw it, I said to myself -- I'll hire someone to do this port, someday.


And I didn't look at Android programming again for another half a year.


Rescued by Russians


I kept hearing about this new-ish programming language for the JVM and Android called Kotlin.  From Russia, of all places.  More specifically, from JetBrains, the makers of the world-famous IntelliJ IDEA IDE, whose primary claim to fame is its lovely orange, green, purple and black 'Darcula' theme.




     Figure 1:  A thousand-year-old vampire expressing his excitement over Java 8.


So why is it called Kotlin?  Well, there's a clear play on incrementing the 'J' in Java.  Beyond that, one can only assume that 'Kremlin', 'Khrushchev' and 'KGB' were already taken, probably by UC Berkeley.  So they did the next best thing and named it after a Russian military base.  It's not a bad name, though.  You get used to it.


Last year I noticed that Kotlin had a fair amount of buzz.  Not hype, just... buzz.  People were low-key buzzing about it.  So, sure, whatever, I took a look, just like I've done for fifty or a hundred other languages in the past 15 years, on my Quest to Replace Java with Anything Reasonable.


Kotlin first impressions


When I first looked at Kotlin, I honestly didn't think there was any chance I'd use it in real life, not even the remotest possibility.  I was just window shopping.  First glance? Nothing immediately wrong with it. It's clean and modern. If anything it felt almost hipsterish in its adoption of all the latest new trends in language design.  But there are oodles of languages like that.  Just look at Rust.  Another solid, appropriately-named language that almost nobody uses. How "good" a language is doesn't really matter from an adoption standpoint.


Kotlin came across as strangely familiar, though, and eventually I realized it's because it looks like Swift -- which I was slow to notice because my iOS app is in Objective C for irritating legacy reasons.  And of course now I know that's backwards:  Kotlin predates Swift by several years, so it's more accurate to say that Swift is like Kotlin.


But none of this made me want to sit down and use it.  Kotlin was just another decent-looking language, and as a working stiff, I didn't really feel like putting in the effort to learn it well enough to do anything real.


From Kotlin Experiment to Java Expatriate


I don't remember exactly when or how I fell in love with Kotlin.  I can tell you I sure as hell wasn't expecting it.


As best I can remember, my players had been begging me to do an Android version of my game. It launched to the Apple App Store in December, and within a few weeks, tons of old fans emerged to tell me that they couldn't play unless it was on Android.  So, despite my swearing off Android "forever", I decided I'd better give it one more try.  But something had to change -- I wasn't going to be able to stomach the vanilla Android Java programming language experience.  I needed a framework or whatever, to ease the pain.


In mid-January I did a quick-and-dirty evaluation and decided to try Kotlin, which also targets the Android Dalvik and Art runtimes. I think my evaluation was equal parts (a) Kotlin buzz, (b) wishing I'd written my iOS app in Swift, and (c) Kotlin had some sort of clever Android DSL called Anko, which I never wound up using, but which initially piqued my interest.


So I took it for a test drive. And within maybe four or five weeks, just like that, I was rewriting my 20-year-old game server platform in Kotlin.  One month of using Kotlin and I was sold.  I mean, I'm not knocking Scala or any of those other languages, but for an ordinary working clod like me, Kotlin is perfect. I just want street food, you know? Scala is nice but it's just too fancy for me, all frog legs and calf brains and truffled snails. I'm too blue-collar to use Clojure or Scala or any of those guys.

It only took maybe 3 days to learn Kotlin well enough to start busting out code, fully aware that I didn't know what the hell I was doing, but knowing the language and IDE were doing a great job of keeping me out of trouble anyway.


And once I was a bit fluent, well, wow.  I'm so jaded that I didn't think it was possible to love a language ever again, but Kotlin is just gorgeous.  Everything you write in it feels like you made something cool.  I've certainly felt that way with other languages before.  But most of them had really steep learning curves. Kotlin is just butter: Tailor-made for us Java programmers who are still sort of scratching our heads over Java 8's parallel streaming filterable collecting scheduled completable callbacking futuring listening forking executor noun kingdom. Kotlin gives you all the same power -- substantially more, actually, with its coroutines support -- but makes it way easier to say stuff. Java 8 lets you say interesting things, but you have to do it with a mouthful of sand.


I think a fair share of why Kotlin is so easy to pick up, though, owes to its IDE support.  The IDE support for pretty much every other JVM or Android language (besides Java) tends to be bolted on by a couple of community volunteers.  Whereas Kotlin is made by world-class IDE vendors, so right from the start it has the best tooling support ever.  How many languages can you name that were built with IDE support from the ground up?  Languages don't usually evolve like that; in fact many language designers outright eschew IDEs. (Hi Rob!) The only other one I can think of offhand is C# -- and C# is easily one of the best languages on earth, hands-down.


The upshot of being an IDE-first language is that you can type pretty much anything even approximately correct in a Kotlin buffer, and the IDE will gently tell you what you meant to type.  Heck, you can even paste in Java code and it'll convert it for you automatically. If you like Java's IDE support, well, I'm pleased to report that Kotlin has pushed that experience to unprecedented levels. Even ex-Microsoft engineers tell me, "I used to think Visual Studio was the unbeatable flagship IDE, but IntelliJ is actually better!" I mean, I don't know Visual Studio, so I'm just relating what they say. But I'm betting IDEA is at least on par with VS.


Of course, I always need to switch over to Emacs to get real work done.  IntelliJ doesn't like it when you type fast. Its completions can't keep up and you wind up with half-identifiers everywhere. And it's just as awful for raw text manipulation as every other IDE out there. So you need to use both. The Emacs Kotlin support is unfortunately only so-so right now, but presumably it'll improve over time.  I constantly switch back and forth between Emacs and IntelliJ and I'm getting by. Good enough for now.


And there you have it. I spent over a decade searching for a language to replace Java. I mean I looked hard. Ironically, it was only after I gave up that it finally came along.  Go figure.  Kudos to JetBrains for an amazing achievement.


Android:  Kotlin's Killer App


It's nigh-impossible for any new language to get traction these days.  That's not to say there are no new languages.  There are neat new ones almost every year! But nobody will ever, ever use them.  It's hard bordering on impossible. The language market is fully saturated.  The only way a new language can make a big splash -- and I think this has been true for at least ten, maybe twenty years -- is for it to have a "killer app". It needs a platform that everyone wants to use so badly that they're willing to put up with learning a new language in order to program on that platform.


It turns out the perfect killer app here -- and this brings us full circle -- is Android's crappy Red Light APIs.  When you're zooming along the road in Android-land, every time you hit an API that stops you in your tracks, you curse the platform.  It doesn't actually matter how many good APIs Android has, as long as there are sufficiently many bad ones to make you pause and look around for big solutions.


And boyo, do big "solutions" ever abound in Android.  For starters, there are a bunch of Java annotation processors, which are a sure sign there's a language problem afoot.  And there are a bunch of mini-frameworks like (say) Lyft's Scoop.  There are even full-on departures from Android:  React Native, Cordova, Xamarin, Flutter and so on.  Make no mistake -- people are looking for alternatives.


When you have a big gap like that, there's an opportunity for a language-based solution.  And unsurprisingly, the full-on departures are all based around specific languages that aren't Java.


Kotlin's competitive advantage, though, is that it's not a full-on departure.  It's completely 100% interoperable and even interminglable with Java, almost (though not quite) to the extent that C++ was to C.  Kotlin feels like an evolutionary step. You can just start mixing it right into your existing Android project, right there in the same directories, and call back and forth without batting an eyelash.


All the other big Android platform contenders force you to learn and use a completely different language and platform, each with its own paradigms and idioms and quirks.  Kotlin just lets you program Android like regular old working-class Android programmers do.  It's all the same APIs, but they're somehow better now.  It feels an order of magnitude better.


I was first in line to throw the Android book at the wall and give up last summer, but now with Kotlin I'm finding Android programming is, dare I say it -- enjoyable?  I think this suggests that Android's "bad" APIs weren't all that bad to begin with, but rather that Java has been masking Android's neat functionality with a bunch of Java-y cruft.


Kotlin manages to help you route around just about all of Android's Red Lights, and turns the experience into something that on the whole I now find superior to iOS development.  Well, at least for Objective-C -- I'm sure Swift is awesome. Because it's like Kotlin!


What I specifically like about Kotlin


Well now, the specifics will be another large write-up, so I'll have to do a separate post.  Here I'll just mention a few high-level generalities.


  • It works like Java.  It's not "weird" like Clojure or Scala (and let's face it, they're both pretty weird.)  You can learn it quickly.  It was obviously designed to be accessible to Java developers.
  • It's safer than Java.  It provides built-in support for many things that are handled in Java these days with annotation processors -- override checking, nullability analysis, etc.  It also has safer numeric conversion rules, and although I'm not sure I like them, I have to appreciate how they force me to think about all my number representations.
  • It's interoperable with Java.  And I mean their interop is flawless.  I've seen too many JVM languages go down in flames because you couldn't subclass, I dunno, a static inner class of a nonstatic inner class, or whatever weird-ass edge case you needed at the time.  Kotlin has made Java interop a top priority, which means migration to Kotlin can be done incrementally, one file at a time.
  • It's succinct.  I'm a bit of a golfer, I'll be honest.  All else being equal, I like shorter programs that do the same thing, if they're clear enough.  Kotlin makes for a great round of golf.  On average I find it to be about 5-10% shorter than the equivalent Jython code (which is sort of my gold standard), while remaining more readable and far more typesafe.
  • It's practical.  Kotlin allows multiple classes per file, top-level functions, operator overloading, extension methods, type aliasing, string templating, and a whole bunch of other bog-standard language features that for whatever reason Java just never adopted even though everyone wanted them.
  • It's evolving fast.  For instance they just launched coroutine support, which is going to provide the foundation for async/await, generators and all your other favorite non-threaded concurrency features.
  • It's unashamed.  Kotlin often borrows great ideas from other languages, and doesn't try to hide it.  They'll say, "We liked C#'s generics, so we did it that way."  I like that.
  • It's got DSLs.  No DSL should ever be created without serious consideration of the alternatives -- but a DSL done well can be a powerful tool. Look at Gradle's DSL, for instance, in comparison to the thousands of lines of XML in a typical Maven project. Kotlin makes that kind of thing easy.
  • It's got one hell of an IDE.  Lately I've taken to writing new files in Emacs, which lets me bust out a ton of code very quickly, code which just happens to be full of horrible errors.  And then I open it in IntelliJ and hit Alt-Enter like 50 times while the IDE fixes everything for me.  It's a great symbiosis.
  • It's fun.  Kotlin is just plain fun.  Maybe it's subliminal advertising, since their keyword for declaring methods is fun.  But it's somehow turned me from a surly professional programmer into a hobbyist again.


Anyhoo, you get the idea.  I'm packed up and moving into a new neighborhood called Kotlin.  I've raved about other languages plenty of times before, but never once, not ever, did I rewrite any of my precious Java game server code in any of them.  But here I am, busily rewriting everything in Kotlin as fast as I can.


I know a few other programmers who've also full-on converted to Kotlin. Most of them beat me to it by at least a year or two.  We buzz about it sometimes.  "Kotlin makes programming fun again," we tell each other.  The funny thing is, we hadn't fully grasped that programming had become non-fun until we tried Kotlin.  It takes you back to when you were first learning programming and everything seemed achievable.


Once again, big kudos to JetBrains.  They've done an amazing job with this language. I am hats-off impressed.


Is Kotlin better than whatever dumb language you're using?  I think so. Certainly so, if the language you're using happens to be Java.  If your daily routine involves coding in Java, I think you'll find Kotlin is an unexpected breath of fresh air.  Let me know what you think!

Disclaimer:  These are my own personal opinions based on personal Android development, and are not endorsed in any way by my employer nor JetBrains.

Wednesday, November 16, 2016

The Monkey and the Apple

It's been a while!

I took a couple of years off blogging because I felt I didn't have much left in the way of interesting things to say.  So I've been just been programming, and studying, and learning this and that.  I've been doing a bit of Cloud development, and I taught myself iOS development, and after years in the Google cocoon I poked my head out and learned how people do things in the real world with open source technologies.

And lo at long last, after some five years of tinkering, I finally have something kind of interesting to share.  I wrote a game!  Well, to be more precise, I took an old game that I wrote, which I've perhaps mentioned once or twice before, and I turned it into a mobile game, with a Cloud backend.

It has been waaaay more work than I expected. Starting with a more-or-less working game, and tweaking it to work on Cloud and mobile -- I mean, come on, how hard can it be, really?  Turns out, yeah, yep, very hard. Stupidly hard. Especially since out of brand loyalty I chose Google's cloud platform, which 3 or 4 years ago was pretty raw.  And let's face it, iOS APIs have evolved a ton in that timeframe as well.  So even as "recently" as 2013 I was working with some pretty immature technology stacks, all of which have come leaps and bounds since then.

And now I have all sorts of stuff to share.  Definitely enough for a series of blog posts.  But I also have less time than before, because it's all happening in my non-copious spare time, all late nights and weekends.  And running an MMORPG is a fearsome task in its own right.

Incidentally, I've just opened the game up for beta testing.  So if you want to try it out while you read along, visit http://ghosttrack.com to request an invite.  (Edit, 12/13/16 -- BETA IS NOW CLOSED.) You'll need an iPhone, iPad, or iPod running iOS 10.2 (Edit: 9.2!) or later.  I'd love to do Android and PC, but there's only one of me.  For now.

So where do I start?  I guess the logical thing to do would be to start at the beginning, but screw all that, I'm starting with the monkey.

The Monkey


I had the following conversation with my wife the other day. It went something like:

Wifey: Baby, I lost all my stuff!

(A lot of our conversations have started this way since April, give or take, when she started playing the game.)

Me:  What stuff baby?

Wifey: (wailing) All the stuff I had in my house!!  I dropped it all there and them boom, it disappeared, right in front of my eyes.  I was watching it and then five seconds later it was gone.  This happened before, and I didn't want to tell you because I wasn't sure, but I just saw it!  It happened!

Me:  OK baby I'll come look.

Wifey:  See?  It was right there!  I had a lot of good stuff there and it's gone!

Me:  (looking around)  I believe you baby.

Me:  (looking around some more)  I think... I think the Monkey did it.

Wifey:  What monkey?  What!?  That monkey took my stuff?

Me:  (checking)  Yep.  It picked it all up and it's carrying it now.

Sure enough, her pet monkey had picked up all her precious loot and valuables.  But while she stared in disbelief at this unexpected betrayal, I was worrying about how I was going to get her stuff back.  Because there were two problems.

First, the monkey wasn't killable via combat, since I had marked pet creatures in your personal home as non-attackable.  I don't know if that was the best decision ever, but it seemed reasonable at the time.  And second, there was a chance that if I pulled out the big guns and killed it myself, for instance by invoking its kill() method directly at runtime, its inventory (her loot) would be replaced with the default monkey inventory of bananas and fur, or whatever I'd given them.

I'm pretty sure that in most states, accidentally replacing your wife's hard-earned treasure with bananas and bits of fur is legal grounds for divorce.  So I was in a bit of a pickle.

Wifey: How are you going to get it back?  I can't believe that monkey!  Can you just make it drop it?

Me:  Well I could, but the AI will just immediately pick everything up again.

Wifey: I worked hard for that stuff!  I can't even remember what I had!  An amulet, a sword, a girdle, all kinds of stuff!

Me: Don't worry, baby.  Tap on the monkey, you can see it carrying everything.  Just give me a second to figure it out.

The picture below shows the predicament.  Wifey is the naga warrior, I'm the old guy in the blue pajamas, just like in real life, and the monkey is barely visible 2 squares below her, by the Japanese shoji screen.



Every creature in the game has an event queue and a command processor, and can respond to generally the same set of commands as players.  Normally the AI decides what commands to give a monster, but you can inject your own commands under the right circumstances, or even take control for a while (e.g. with the Charm Monster spell).  So I decided I'd try to command the monkey to give me the items, one at a time.

The game is written mostly in Java, but a good portion (maybe 25%) is written in Jython, which is an implementation of the Python language on the Java virtual machine.  And, usefully, Jython has eval and exec functions for interactive code evaluation.  So I opened up my command interpreter and went to work.

> exec monsters = me().map.monsterList
Ok
> eval monsters
[monkey]
> exec monkey = monsters.iterator().next()
Ok
> eval monkey
Monkey
> eval monkey.inventory
The MonsterInventory contains:
 - bit of fur (0.06 lb)
 - bone (1.5 lb)
 - Amulet of Acid Resistance (0.12 lb)
 - bag (0.5 lb)
 ...

So far, so good.  I had a reference to the monkey in my interpreter, and I was seeing Wifey's stolen valuables, plus the expected monkey inventory.  Now for the coup de grace.

> eval monkey.commandNow("give amulet to rhialto")
> None
> Monkey gives you Amulet of Acid Resistance.

Woot!  Success.  I had to keep chasing the monkey around, since offhand I couldn't think of a way to make it stand still.  In retrospect I could have paralyzed it, or set its AI to the stationary AI used for immobile monsters.  But I couldn't be bothered to look up how right then, since I hadn't ever been in a situation quite like this before, and my wife was alternating between indignation, amused disbelief, and near panic over her stolen stuff.

I had a mechanism for getting the items back, so I just followed the monkey and issued those commandNow() instructions.

Unfortunately, and to my lasting surprise, the monkey started ignoring me after the fourth or fifth item.  It continued about its business, but it would not give me any more items.  I still don't know exactly why, since this was such an edge case scenario.  I have a large toolchest of utilities and commands for manipulating player inventories and map contents.  But it's rare that you need to command a monster to give you stuff.  Normally you get a monster's inventory the old-fashioned way. You pay the iron price.

I was irked by the monkey's emergent nonchalance, so I pulled out the hammer:

> eval monkey.kill(me())
> Ok
> You killed monkey.

Where me() in this case is the attacker.

As I feared, the corpse's inventory was completely empty, because I clear out the inventory for pet monsters, to prevent abuses where you just create them in builder mode, take their stuff, and make infinite cash.

So I busted out the clone() command and manually recreated the rest of the missing items as best I could, and gave them all back to Wifey.  I'm pleased to report that this story had a happy ending.

How to Make a Game


You look at a game like Wyvern, which is at its heart just a tiles game like the old roguelikes, and maybe a bit of a MUD, and you think, gosh, I could do that.  And you can!

Off the top of my head, you will need:

  * A cloud computing platform such as AWS, Azure or GCP.
  * Xcode and a Mac, or else Android Studio and a whatever-you-want.
  * A programming language and a compiler. These days, I would go with Kotlin.
  * A service for browsing and licensing music and sound effects. They have those now.
  * A service for hiring contractors for artwork and maybe level design. They have those too!
  * A hosted datastore, because seriously it's 2016, don't administer your own.
  * A source hosting and bug tracking service, such as Bitbucket.
  * A good lawyer and a good accountant.
  * About twenty years.

Ha!  I kid.  I've only put about ten years into it, spread over the past twenty years.  I started in 1996; my character Rhialto will turn 20 on March 1st.  But in terms of total person-years, it's in the hundreds, largely due to area design contributed by dozens of passionate volunteers.

It's amazing how much stuff we have access to since I started this project back in 1996.  Back then, I had Java, and we're not talking about Java 8 with fancy lambdas and streams.  We're talking Java 1.0.2, with that O'Reilly book with the referees on the the front.  You had to roll everything yourself back then.  Uphill both ways, in the snow.  (Actually the game started in C++ in 1995, but I migrated to Java and never looked back.)

I went through something of a life crisis in 2004, after 8 years of working on the game, because my productivity had tanked as the code base grew, and I wanted it back.  So I stopped working on the game, for the most part, and went on a Grail-like quest to find a good language -- one that was ultimately unsuccessful, although I learned a lot and got some good rants out of it all.

Nowadays, though, sheesh.  Between GitHub and its infinite supply of high-quality libraries, cloud providers and their hosted services, Stack Overflow and its infinite supply of answers to just about every question you'll ever encounter, and all the services available for payments and contractors and everything else you could want -- I mean, it's a startup's dream come true.  I am way more productive than I was in 2003.  All I needed was a time machine.

Even so, a game like this -- which, despite its simple appearance, is a true MMORPG with surprising depth -- is basically an infinite amount of work.  Lifetimes of work.  So you have to practice triage, time management, and stress management.

But really, anyone can do it.  You just gotta _want_ it bad enough.

Apple vs. Android


I have enough material for lots of blog posts now, and I'd love to spend some time exploring Google's Cloud Platform (GCP) in future articles.  I've learned a thing or two about Android as well.  And Kotlin is absolutely entrancing.  I haven't used it yet for anything serious, but it's one of the best new languages to emerge in a long, long time.  Would love to talk more about Kotlin at some point.

For today, though, I thought I'd offer a few musings on Apple, iOS, and their store ecosystem.  I'm still no expert, and I don't do anything iOS-related at work.  This is just some very personal impressions I've collected while making the game.

A lot of people have asked me why I did my first mobile client in iOS rather than Android.  The answer is monetization.  iOS is straight-up easier to monetize.  Android has cultivated a frugal audience, through both marketing and hardware choices, and that cultivation has been a success.  Android users tend to be frugal.  That doesn't mean they don't spend money, but it does mean they are more cautious about it.  I have friends who've done simultaneous iOS/Android releases for their apps, and invariably the iOS users outspend the Android users by anywhere from 4:1 to 10:1 -- anecdotally, to be sure, but a little Googling is enough to support just about any confirmation bias you like.  So I picked iOS.

When I started, I didn't know Objective-C, and I started just before Swift came out, just a couple of months.  But by then I was far enough into development, and wary enough from prior experiences with new languages, that I opted to continue in Obj-C.  Obviously today I'd do it in Swift, and if I weren't always so time-constrained, I could even start introducing Swift class-by-class.  Swift is cool.  It actually reminds me a lot of Kotlin.  I think language designers must have some sort of clique these days, whether they know it or not.

What about iOS?  Well, there's not much to it.  And that's a good thing.  It feels familiar, at least if you've done any sort of UI programming at all in your career.  I've done some Java AWT and Swing, some Microsoft MFC and whatnot, some X-windows work, some web programming, whatever -- rarely anything major, but I've tinkered with UI throughout my career.  Frontend UI is a skill every engineer should have, even if it's just one framework that you know well.

Coming from all those frameworks, I had certain expectations, and they were 100% met by iOS.  It has an MVC framework, and you add views and subviews, and you have all the hooks and lifecycle events you'd expect -- after learning Objective-C, I'd say it was only about four days (thanks to the excellent Big Nerd Ranch book) before I was able to start cranking out reams of code by copying it all directly from Stack Overflow, as is tradition.

Why am I making such a big deal about iOS's almost boring familiarity?  Because Android is the exact opposite of intuitive and familiar.  I've gotta be a little careful here, since I recently joined the Android tools team at Google, and I don't want to throw anyone under the bus.  They did the best they could with the environment and situation they had when they started back in the early 2000s, which featured phones that didn't even have memory -- they just had "address/contact slots".  It was awful.  They did fine.

But now, thanks to Moore's Law, even your wearable Android or iOS watch has gigs of storage and a phat CPU, so all the decisions they made turned out in retrospect to be overly conservative.  And as a result, the Android APIs and frameworks are far, far, FAR from what you would expect if you've come from literally any other UI framework on the planet.  They feel alien.  This reddit thread pretty well sums up my early experiences with Android development.

So as much as I'd love to make an Android client for my game, it's not going to happen for a while.  Plus I'm still iterating heavily on the iOS UI, so I might as well wait until it stabilizes a bit.

That's enough about Android for today.  I always gauge how edgy my blog posts are by how likely I am to get fired over them, and my little indicator is redlining, so let's move back to Apple and iOS.

Apple:  The Good, the Bad, and the Ugly


Objective C isn't so bad.  They have continued iterating on it, so even though its string handling is comically verbose, and it has no namespacing, and there are tons of other modern features missing, the language is pretty capable overall.  It has generics, literal syntax for sets/dictionaries/arrays, try/catch/finally macros, extremely well-implemented lambdas with proper closure capturing (unlike nearly every other non-functional language out there), properties, and many other modern conveniences.  The syntax is awful, and it can get pretty weird when you're bridging to the C APIs, but on the whole you wind up writing less code than you'd think.

In fact, various bloggers have measured it, and if I recall correctly, the consensus is that Android Java is about 30% more verbose than Objective-C.  Which is pretty counterintuitive, because the Java language itself, verbose as it may be, is clearly less verbose than Objective-C.  What's happening here is that iOS has such good APIs, you wind up needing to write a lot less code to get your job done.

So Obj-C isn't bad, and Swift looks really good.  The APIs are good, the documentation is solid, and Apple is aggressively deprecating crummy old APIs (like UIAlertView) in favor of better-designed ones.  Everything is still there in the system, and you can see generations of whole layers of API access dating all the way back to the old NeXT computers from the late '80s (heck, everything in iOS starts with NS, for NeXTStep)

But you don't have to use most of that stuff, because Apple has been constantly layering on new APIs that modernize it all.  Unlike, you know... some other, uh, people. >.>

Xcode is pretty good. It used to be bad, but now it's not bad at all.  Yes, it crashes more than I'd like, and yes, its refactoring support is abysmal.  It's no Visual Studio.  But "pretty good" is good enough.  Because all I'm doing is copying code from Stack Overflow, really I have no shame whatsoever, and Xcode works great for that.  It even formats it for me.  Who am I to complain?  Besides, I use Emacs for any serious editing.

So for the Good, we have the languages, the APIs, and the tools.  What about the Bad?

Well, Apple's review process is really, really, really long and convoluted.  Sure, I can totally understand why.  They have millions of developers trying to shoehorn crap into their store, and they are trying to make a strong quality stand.  But it means you're in for a wild ride if you're making anything more complicated than a flashlight app.

First you have to go through their checklist of roughly seventeen thousand rules, and make sure you have addressed each of them, since all of them can result a veto.  And wouldn't you know it, I checked exactly sixteen thousand, nine hundred and ninety-nine of those rules very carefully, so my app was rejected.  Because they don't mess about.  You have to follow all of them.

The story of my app's rejection is epic enough for an opera, but in a nutshell, Apple requires that all apps support ipv6-only networks.  But none of the major Cloud providers supported ipv6 at the time of my submission, in late September.  You're pretty well covered if you're just doing HTTP(S), but if you use sockets you're hosed.  My game uses direct TCP/TLS connections to my cloud instances, so it didn't work on an ipv6-only network, and my app was kicked to the curb like so much garbage.  At least they did it quickly.

After some technical consideration, I did the only logical thing, and got on my knees and begged them for an exception, because what am I gonna do?  Some cheesy hack with an ipv6 tunnel provider to a fixed IP address on a single instance?  Well, yeah, that's exactly what I was going to do, if push came to shove, just to get through the review. Even though it's completely non-scalable.  Desperate times.

Fortunately, after a mere six weeks, and me finally sending them an angry-ish (but still cravenly and begging) note asking WTH, they granted me the exception for 1 year, backdated so it was really only 11 months, but whatevs.  I was approved!

The Ugly

Just kidding, haha joke's on me, I was NOT approved.  Because when they gave me the exception, they also threw in a major feature request.  Lordy.  It's almost like they're a monopoly or something.  They didn't like that my game required you to sign in via a social network -- Facebook, Google, or Twitter for now, since those are the sign-in SDKs that I've managed to wire up so far.  So they asked me to implement Wyvern Accounts.

Sigh.  I was so relieved that I got the exception, I didn't fight it.  I called back to ask if it was OK to require an email address, for account/password recovery functionality (but also because I use the email address to tie your characters together), and they said that was fine.

So I went to work, even though my game had already been in Alpha for six weeks too long, and I implemented Wyvern accounts.  New database table, new web service, new API service, new UI screens for registration and account creation and password resetting, new plumbing for passing credentials to the server, blah blah blah.  God dammit, the nerve of them to ask for such a big feature.

A week later when it was all finished, I realized FB/Google/Twitter all have minimum age requirements (all 13 years minimum because of COPPA), so I had been protected until Apple threw their curveball at me.  Now I need underage reporting and god knows what else.  Still working through it with the lawyers.

I'd go back to Plan B (in iOS-land, B is for Begging), except that I actually sort of agree with Apple that I need this feature.  Not everyone is on a social network.  For example, there is an uncontacted tribe deep in the South American rainforest who are not on Facebook yet, although I believe they are still eligible for Amazon Prime.  And also some of my alpha testers were struggling with it.  I guess there are a lot of people who not only don't have GMail, but they prefer not to sign up for a free account.  I can only assume the NSA is responsible for this phenomenon.  But it means I most likely need Wyvern accounts.

Another reason I sort of need Wyvern accounts is that Facebook, Google and Twitter all have very different philosophies about email-verification APIs.

Facebook's philosophy is, roughly: "What's a few API calls between friends?"  They have quotas, but they're so high that I won't have to worry about them for years.

Google's philosophy is, roughly: "Our APIs should scale with your business."  They have quotas, but they're so high that I won't have to worry about them for years.

Twitter's philosophy is, roughly: "Go fuck yourself."  I exhaust their tiny quotas every day, even after adding credential caching so that players only re-validate once every 8 hours or so.  Even though I only have a few dozen, maybe fifty regular players right now, only a handful of which use Twitter.  Their quotas are comically, absurdly low.

So I'm probably going to have to yank Twitter out before launch, which would limit people to FB and Google sign-in.  And that seems like... not enough options.  I don't like having to maintain my own accounts, but I think I'm pretty well stuck with it.

The takeaway (well, other than "don't use Twitter APIs"), is that Apple can jerk you around pretty much all they want, and you'd better like it.  You should basically prepare for a long review.

Back to The Good

Despite the bumps in the (long) road so far, some stuff has been great.  TestFlight, which is Apple's beta testing system, is working nicely for me.  It provides me with crash reports which have identified half a dozen real issues so far.  The sign-up is a snap, and they'll let me have up to 2000 testers, which will help me make sure my stuff scales, if I can get that many.

And their review turnaround time has been pretty good.  It generally takes about a day, in my experience.  I'm not sure why they require a manual review for my Beta builds, after they've already approved me for the actual store launch.  And every build requires another 1-3 day review.  But I've got a pipeline going, and I'm pleased overall with how straightforward it has been.

I'm really worried about In-App Purchases.  I offer them in my game (though it's definitely not pay-to-play), but Apple's testing for IAP leaves a lot to be desired.  You have to sandbox it, and this requires setting up separate accounts.  It's not possible to enable production IAP (with real money) before the actual launch.  But their sandbox environment makes it really easy to screw up a transaction, after which your device will prompt you for a store login every 5 minutes for the rest of your miserable life, and likely into the hereafter.  It's a mess.

You can sort of enable IAP in Beta/TestFlight, but it's *free*, which means players would be able to acquire millions of coins for free, and it would require me to perform a full reset of everyone back to level 1 before launch.  I'm trying to avoid that.

So I have no idea if my IAP really works.  I got it working in the sandbox at one point, and I'm hoping it works in prod, but until I'm confident that it's working, I'm going to have to charge for my app, to forestall the possibility of a massive meltdown from casual players (tourists, basically) eating up my server resources.  I don't want to get a gigantic bill from Google.  So I need to limit the growth as best I can for a while.

Going Forward


Building this game has been a lot of fun.  I've learned more from doing this project than from anything I've ever done that was work-related, at any job I've had.  Something about having to do a big project yourself forces you to pay attention to everything in a way that you rarely have to do at a corporation.

I don't know if it's going to be a hit.  Statistically, probably not.  But I have some pretty darn loyal players.  The game was down for five years (2011-2016), and when I brought it back up, a hundred or so old timers appeared out of nowhere.  Many of them had to purchase iOS devices just to play, but they splurged.  And they started playing insane hours.  The ratio of 7-day-active to concurrent players has been crazy.  In the old days it was about 100:1, so on a server that could comfortably support 100 concurrent players, I'd typically have about 10k 7-day actives.  It was self-limiting because I only had one server back then.

With these alpha testers, the ratio has been about 4:1.  They're playing upwards of 8 hours a day, around the clock.  And they're all over the world -- I have testers in Japan, England, New Zealand, Spain, Nigeria, Toronto, east coast, west coast, I forget where they're all from.  But we're talking about a group of only about 60-70 regulars, so the diversity is quite remarkable.

This letter they wrote me back in 2012, when the game went down so I could port it to Cloud, gives a pretty good sense of how much people like it.

I'll report back in a few months and let you know how the launch went.  Meantime, if you want to play, visit http://ghosttrack.com.  Hope to see you online!

Rhialto

Monday, October 08, 2012

The Borderlands 2 Gun Discarders Club

This is basically a review of, and a pros/cons rant about, Borderlands 2. If you're not into it, just don't read it! I'll write about stuff you like some other time. Maybe.

So!

I'm not the kind of person to say "I told you so." Noooo. Never. Well, never, unless, of course, I get to say it loudly, within hearing of a biggish stadium full of people. Which I can.

So here goes: I told you so. Toldya toldya toldya.

My predictions from my previous post, "The Borderlands Gun Collectors Club", all came completely 100% true, with Hyperionesque accuracy, Jakobsian impact, Maliwaney inflammatoryness, Tedioric blasting and surprisingly, even Vladofish speed. I made out like a Bandit.

I predicted, as you may recall, that (A) it'd be a great game ("duh"), (B) they'd screw up the token economy because they only partly understand it, and (C) as a direct result of B, players would gradually head back to Borderlands.

Three weeks after the release, I had my dreaded first "I really don't want to throw this gun away, but I have NO GODDAMN ROOM FOR IT, THANK YOU RANDY PITCHFORK" gun-discarding experience. And my reaction was, predictably, to think seriously about either creating a mule character or going back to play BL1.

I mean, I knew I'd have this reaction, but I failed to predict how amazingly fast it would happen. A week playing the game, another week on playthrough 2, a final week finishing all the optional side quests, and then boom -- the farming is fundamentally broken, so let's go play something else. But I don't waaaaant to! Why did they have to get this wrong? Why did I have to be so predictively correct? Argh!

Let me make this really simple and clear. You remember that famous exchange in Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb:

Dr. Strangelove: Of course, the whole point of a Doomsday Machine is LOST if you keep it a SECRET! Why didn't you tell the world, EH?
Ambassador de Sadesky: It was to be announced at the Party Congress on Monday. As you know, the Premier loves surprises.

Well, if Dr. Strangelove were alive to play BL2 today, he'd have said:

Dr. Strangelove: Of course, the whole point of 87 Bazillion Guns is LOST, if you don't let people keep them! Why didn't you add more bank slots, EH?

I mean, at least Ambassador de Sadesky had a somewhat plausible excuse. But Gearbox has been thinking over this whole endgame-farming thing for, oh, probably eight years or more. How the hell did they arrive at the conclusion that "We should have 87 bazillion guns, and you personally should be able to keep, like, twelve of them!"

There's only one possible answer: they are clueless. I mean, don't get me wrong: they're also lovable, brilliant, passionate, technically astounding, and outright visionary. But they're also and bumbling and clueless. They're the neighborhood kid who catches a lizard and thinks it's really cool, and it *is* cool, except he puts it in a box and it dies.

I'll do this as a Good, Bad and Ugly post, just so you know it's, like, balanced. If I were just gushing a bunch of fanboy praise, you know as well as I do that it wouldn't be as credible. You have to hear the bad with the good.

But ugh, they were so close. So close! The game is so amazing!

Maybe they'll cut my second prediction in half, and release a DLC or patch within 6 months that gets the folks who drifted back to Borderlands to start collecting in BL2 again.

That, or maybe I'll contribute to the BL2 player-file-editor project. Modding is stupid, stupid, stupid; it's 12 year olds advertising that they are, in fact, mentally and emotionally really twelve years old. The mindset there is so juvenile that it pains me to admit that sometime in my distant past, decades ago, I probably would have thought that way myself. (That is to say: "Hey, I'm going to mod, because it's not allowed so it must be cool, and even though a fugging gorilla could figure out how to do it, and it takes any hint of challenge out of the game and makes me look like I was severely shaken as a baby, but I'm going to go ahead and show off my modded guns as if I'm some sort of super-gorilla." Yeah, that mindset.)

But modding will, to a very limited extent, help work around Gearbox's cluelessness by letting legit endgame farmers have a place to put all their fugging produce.

Very, limited, mind you. I'll tell you how it *should* be in the Ugly section. I'll talk about how to fix this situation, and, well, if Gearbox doesn't understand the fix, you can be sure some other upstart game company _will_ understand it, and it'll all be the upstart's limelight soon enough. A few more years of screwing this up, and as far as Gearbox goes we'll be, like, "hey, remember Diablo?"

Let's hope they get the message. Randy, guys, please -- get the message!

The Good -- no, wait -- The GREAT

Actually we should do Great first, then Good/Bad/Ugly. Because BL2 is a capital-G Great game. Best game ever? Well, no. Nobody's gonna top RDR for a while. But dayum, BL2 is a great game. It's actually a great test of whether you're an idiot, because if you don't like it or it doesn't appeal to you... well, you might not be an idiot per se; there's bound to be some explanation... I guess. In theory. There could be some other reason than you being an idiot, however improbable.

Anyhoo, let's get The Big Question out of the way: Is Borderlands II better than Borderlands I? Well, the answer depends on whether you think The Empire Strikes Back was a better movie than Star Wars. It's also the answer to "Should I play BL2 if I haven't played BL1?" If you think watching The Empire Strikes Back after Star Wars yields an acceptably awesome cinematic experience -- which it probably does -- then yeah, play BL2 first. Go for it!

The Lucasian comparison runs pretty deep. Borderlands is dry and dusty, has dome-like dwellings, introduces cute talking robots, features fully armored imperial bad guys with bad aim, and has a slow (but interesting) story arc up to a really dramatic finish in the last act. Whereas Borderlands 2 is lush and fast-paced and story-thick and incest-ridden and stuff, just like Ep. V. Let's just hope they don't carry the metaphor to the third installment, unless of course they want to have Patricia Tannis dressed like Princess Leia as the kept-plaything of some huge talking Thresher, in which case they have my blessing.

BTW, as an aside, and my wife agrees 100% -- all this chatter about Lilith vs. Maya vs. Moxxi is just outright silly. The answer is: Tannis. Followed, we think, by Helena Pierce, eye or no eye.

Anyway, where were we. Oh yeah, The GREAT. Where to begin?

The story is awesome. Burch was amazing. Tiny Tina is incredibly awesome. Other Burch, also amazing. Handsome Jack is so awesome that I found myself rooting for him most of the time. Threshers are way more awesome than they looked in the previews. The AIs are uniformly great, even when they occasionally make the mobs cower in the corner as if you're the Blair Witch. I don't mind. And the guns, oh the guns, they are beautiful and fascinating and a joy to behold.

The voice acting is awesome, with one noteworthy exception: Axton was mis-cast. He looks like Captain America (or Thor, or whoever, take your pick), and he possesses the competent, modest, sexily reserved flawed-hero look of Captain America (or Thor, or whoever, take your pick). But his voice and dialogue are pure Jack Black at his cheesiest. Oops. Oh well. But the rest of them are cool. Can't say much without giving the plot away, but everyone's voice acting was great, and Tiny Tina stole the show. Well her, and the Goliaths.

The game balance is exquisite. THEre have BEEn some missteps, naturally, and people are now vying to slay the much-vaunted raid boss Terramorphous in the fewest number of milliseconds with 100% legit gear. But on the whole the balance is superb.

My only cause for complaint is that the game balance feels far less serendipity-prone than Borderlands often was. They made BL2 so balanced that most of the time the stuff you find is really pretty boring. No one manufacturer shines above all the others, nor is one worse than the others (though I wasn't much of a fan of Jakobs or Pangolin, by and large). All the weapon types are about equally good. It feels as if they tightened the loot-rarity bell curve so they could keep the difficulty progression smooth. The game always felt challenging, albeit without ever descending into Survival Horror territory -- there is always enough ammo around to encourage exploration.

And when you do find the occasional legendary item -- I found only four of them during my first two complete playthroughs -- it will last you a good ten levels. Oranges are the new Pearls. They got this right, I think, and only in the difficult-to-balance endgame did they encounter any issues. In short, the game is challenging in a good way.

They kept the cel shading. Yay. Cel shading helps them avoid the Uncanny Valley where most other games reside today -- they look more and more realistic without actually looking, you know, realistic. The Borderands franchise embraces the graphic-novel look, and it's always stylish and fresh. Plus they don't cel-shade a lot of stuff: water, ice, atmospheric effects, weapon effects, and so on, which makes for some eye-popping moments. And just in case the poetic beauty of their rendering approach is lost on you, they also include some actual eye pops.

They kept the humor. Oh, did they ever. I'd find myself giggling at 3am until I was snorting and wheezing. The humor runs the whole gamut, from the coarse and obvious to the surprisingly subtle. I love the Dr. Zed vending machines (and the voice acting, and Zed's character in general -- he may be my favorite.) And I almost lost consciousness from laughing when I realized, after my second weapon swap, exactly what The Bane's curse was. Oh man, that one almost killed me. That whole mission was extraordinarily well-designed. And of course Claptrap is funny as always. Crazy Earl, too.

Not to mention the talking weapons and armor. I love my Hyperion auditing sniper -- haven't discarded it even though I can't really justify a precious inventory slot for it. There's a lot of genuinely funny stuff in this game.

But I think the Best Humor award has to go to the bad guys. Handsome Jack has his moments, but it's really the bandits that steal the show. Just when you think you've heard them say everything, they'll surprise you. Crazed psycho bandits running at you screaming that Pluto is still a planet, or complaining about how goddamn cold it is outside, or reciting Hamlet... it just never gets old. Bandit humor has quickly become one of the legendary defining hallmarks of the Borderlands experience.

No question about it: this game has it all. It's a huge, sprawling open-world game with an engaging story, superb balance, exciting game mechanics, outstanding writing, and absolutely unparalleled replay value.

The greatness of the game pretty much dwarfs everything else I say here. It's a worthy successor to Borderlands, and at this point it's already become one of the most important franchises in gaming history.

I know the folks at Gearbox love this game and they want to keep refining it, though, so I'll weigh in my $0.02 on how it could be even more awesome next time around -- hopefully as soon as the next DLC.

The Good

The game has some aspects that I feel bordered on greatness without actually achieving it.

The biggest issue I have with the overall world design is that it's a theme park. No other word for it. It's a cool theme park, and I do love me my theme parks -- I'm a Disney Vacation Club member and we go to theme parks several times a year, rain or shine. But there was some sort of dynamic going on, maybe an overreaction to the misguided criticism of the dry dustiness of BL1 (which is about as valid a criticism as saying "Star Wars had too much sand!"), that maybe made them overcompensate a little with the paint gun.

So even though the game is often beautiful, the colors are often too saturated. When they get it right, it's nothing short of stunning. The Southern Shelf and Sawtooth Cauldron are standout examples. Both juxtapose bandit shantytowns with a rugged natural beauty -- but it's a beauty with a relatively subdued palette, dominated by just one or two colors.

Some of the man-made places are gorgeous too -- Opportunity City comes to mind, and the Friendship Gulag. But they, too, have dominant primary colors or motifs that shape and define the visual experience into something unique and refined.

In several other locations they went a little overboard. I'm not sure if it's the cel-shading adding visual clutter (as seemed to be the case in Fink's Slaughterhouse and in Sanctuary), or if it was actual clutter (Thousand Cuts comes to mind), or if they just went a little overboard with the fully-saturated paint gun (Wildlife Preserve, maybe, or Tundra Express). Whatever the reason, the game winds up looking a tad overdone in places. Still awesome, yes, but with colors that clash rather than harmonizing. They need to follow the basic color-matching advice from, say, Vogue or Cosmopolitan: Any three colors go together, and any more than that looks like a peacock shitting rainbows. I'm pretty sure it was Cosmopolitan who said that.

The theme-park quality goes beyond the color scheme. A lot of the areas feel bowl-shaped and directly connected to other equally bowl-shaped areas with completely different styling. So it feels a bit like you're walking from Adventureland to Tomorrowland to Fantasyland.

And there's a lot of... homage, let's say... to other games. It felt almost like they had other-game and/or other-movie envy, even though Borderlands is a game to be envied all on its own. So there's a dash of Skyrim (The Highlands), some Red Dead Redemption (Lynchwood), some Jurassic Park (Wildlife Preserve), and other maybe-unnecessary tributes. And Sanctuary reminds me way too much, ironically, of the towns in Rage.

So the overall world design lacked a certain cohesiveness of vision that was present in Borderlands I. It feels on the one hand like they were trying to elicit a Tolkeinesque or Homeresque journey from humble beginnings, increasing in scope, and ultimately walking into the heart of Mordor. There's a teeny bit of that going on. But it also feels like whoever had that vision was crushed by the weight of game directors all clamoring for unrelated themed areas to show off their... their what, I don't know. Just to show off.

On the whole, though -- coming from a guy who likes theme parks -- they did a really bang-up job of creating a theme park. The individual areas all have their own distinct personality. Some of them even have world-class atmosphere. The Fridge, the Bloodshot Stronghold and Ramparts, Overlook and the Highlands, and several other areas are really memorable. And the Arid Nexus Badlands were... well, that's my favorite area of the game overall, for reasons I can't go into, but wow.

My vote for Overall Best Area Design, though, goes to the Caustic Caverns. This area stood head and shoulders above the rest of the game, in the sense of being new -- who the hell has ever seen anything like that before? -- and creepy. I can only remember one or two times in my 35-year gaming history where I felt the sinking "I am on the WRONG side of the train tracks" feeling that I had upon entering the Nether Hive. The whole area gave me a new-found respect for -- and dread of -- the Dahl Corporation, whom I hope will be the villains of some upcoming installment. Oh, and the, uh, mission I can't give spoilers about, but it takes you to the top floor in the Caverns -- that was hands-down the best side quest of the game.

My third favorite location, after the Badlands and the Caustic Caverns, was Lynchwood. I'm a sucker for that sort of thing. It didn't make any sense AT ALL -- it was a gratuitous anachronism in a game that thrives on anachronisms. But I loved it. Robbing the bank and getting out of town before the posse came: that was straight-up inspired writing. I loved the Lynchwood mini-boss and that whole plot line; I loved the Marshall's announcements; I loved the whole thing. Lynchwood may not have made much sense in the larger story, but it was unquestionably awesome.

Anyway, let's face it: the game is a theme park. Not that this is bad! It's Good. But I'd argue that it's not Great. I think true greatness necessitates a uniformity of vision that admits no room for tongues planted too firmly acheek. BL3 is going to have to make some hard choices about whether to be good or great.

Good is OK, though. Nothing wrong with Good.

The Bad

I'll try to keep this short. Mostly this is stuff that could be addressed in a straightforward way in a patch or DLC.

There was no explanation as to why NPCs don't get to use the New-U stations. Just sayin'. They'd better retcon that in next time.

No in-game explanation of the Golden Key chest in Sanctuary, so I (like half the rest of the civilized world) used both my golden keys right away without realizing what they were. In retrospect I don't think it matters, since having awesome weapons is probably more useful early in the game than later on. But it should have been a conscious choice, and I, like half the rest of the civilized world, was pretty pissed off to find that I'd squandered my keys without so much as a warning dialog.

They changed it so you can't open the menu if you're not on the ground -- that is, when you're jumping, or falling, or climbing a ladder, or being flung through the air by external forces (e.g. geyser, grenade), or stuck atop an enemy you had the misfortune to land on. This is hugely screwed up, so I can only imagine they did it as a last-ditch workaround for a no-holds-barred showstopper Christmas-won't-happen bug, and it'll get fixed in an upcoming release. That, or they hate their customers and think they're scum. Time will tell.

This change did help me understand that one of the habits I'd truly come to enjoy in BL1 was jumping and then opening the menu while in mid-air. Seriously. It was fun. I did it on purpose, all the time. I can't really articulate why, but it was exhilarating. It's as if they took away my childhood with that one simple dick move. I sure hope it was a last-resort thing that they plan to fix.

Inventory management has taken a turn for the worse overall. Yeah, it looks slick, but when has Gearbox ever been about "looks slick" over playability? I mean, no cutscenes, right? (Or at least no cheesy prerendered ones -- they do all their cuts right there in-game, and you can usually walk away from them.)

In BL2 they put a ton of work into the look-and-feel of inventory management, but they failed to nail the usability. In an RPG, even a quasi-RPG like Borderlands, inventory management is all-important. So maybe it's their shooter background at work here. I dunno. But there are a lot of serious wtfs going on. Examples:

* When you want to compare item A to other items, and you eventually navigate to item B, then close the let's-compare transaction, it leaves the selection on item B. Last I checked, this is not the way rational thought worked in any product designed by human beings with good intentions.

* You can mark items as "favorites", and then... nothing. You can't sort on them or do anything useful with them. But, alas, you CAN sell them, without any warnings or indicators that you just sold an item you'd marked as a favorite. So I have accidentally sold some really, really important shit, and only realized a few areas later, when it was too late to go back and buy them back. This has happened at least four or five times in my so-far 2.5 playthroughs of the game. That's too many for an experienced gamer. It means they have a UI problem.

* You can mark stuff as "trash", and sell it all at once. Except that's stupid. Everything should be trash by default. Most of the items you pick up ARE trash -- that is a natural outcome of the tightness of their rarity bell curve. If they had done the whole favorite/trash thing correctly, you'd only need to think about it at all when you picked up a blue-or-better weapon, at which point you could mark it as a favorite to prevent accidental sale. This, friends at Gearbox, would be less error prone AND less effort. Argh.

* There's still no way to "buy all" for ammo. Also, like in BL1, there are two concurrent views of your ammunition while you're shopping: the store's selection and your inventory levels. And, like in BL1, the two have unaccountably different sort orders. So as you move the selection cursor down the store's selection, the inventory cursor jumps around unpredictably. I can't believe they did this two games in a row.

* Unlike in BL1 (I think), when you're buying ammo by mashing buttons (because there's no bulk-buy function), you can very easily scroll past the grenades and start buying shit you didn't want while you're mashing the buttons. Again, no warnings, no "are you sure?", so it's really easy not to notice until a few load levels later.

* Like in BL1, they don't sort insta-health at the top of Zed's vending machines, which means if you run up to a machine to buy health in a firefight -- which is much more commmon now that they've eliminated portable health vials -- or if you're just not paying very close attention because your dog just knocked over your glass of water, then you stand a good chance of buying some expensive class mods and maybe not noticing. I've done this too. In all seriousness, sorting insta-health at the top is OBVIOUS, so only gross negligence can explain how it was done wrong two games in a row.

To be sure, they got a few inventory-management things right that were messed up in BL1. You can now compare items while shopping -- w00t! And the weapon cards show all the data rather than truncating. The item sorting makes a little more sense. The "examine this item" is REALLY cool, and I love just zooming and panning on my items to marvel at the intricate designs. But on the whole it was a step backwards, and it makes me very sad.

Other bad stuff... let's see. They still only let you quick-wield 4 weapons even though modern games all give you 8 slots on a wheel. In a game like BL, with elemental resistances and radically different opponent AIs, 4 slots just isn't enough. You need to be able to carry at least two different "weapon builds" with you. I don't care if we have to purchase them or work our way up, but we need more than 4 equipped-weapon slots. As things stand, swapping out weapons interrupts the otherwise smooth game flow and makes it sort of a drag. Especially when they don't let you open the menu mid-air. Jesus. How can the graphics be so beautiful, and the story so awesome, and the combat so smooth, but the inventory management is so screwed up? Is it different teams? What's going on here?

Let's see, what else, what else... oh yeah. On the PS3 version, every time you set your controller down it triggers a nuclear explosion. No, really. Well, it does if you're playing Axton with the middle skill tree. It's a side-effect of having switched the ability/grenade buttons with the zoom/fire buttons. I haven't made up my mind on this one; overall I think they probably made the right choice, but it reminds me of the Fable II days when you'd try to buy something from a blacksmith, hit the wrong button, destroy his house and send everyone screaming from the village for hours. It's not really ha-ha funny, at least not at the time.

Their bulk-vacuum function still sucks, so to speak. Actually the "interact with stuff" button hasn't changed behaviorally since BL1 in any significant ways. It still has all the old problems, and maybe some new ones.

For starters, they still have the horrible misfeature that holding the "pick up" button, which is used about 87 bazillion times per game session for bulk vacuuming, has different behavior if you do it on a weapon. What it does in that case is grab it and wield it, even though 9999 times out of ten thousand, the weapon in question is a piece of loot-crap that destined for a vending machine. Way to optimize for that 1 in 10,000 case, Gearbox. Moreover, way to keep it around for game 2.

The vacuum button still does a piss-poor job of actually vacuuming. And they've added "auto-vacuum", which does an equally piss-poor job of auto-vacuuming. I can't tell you how many times I've been standing there with 4 hit points, examining the item-card for a health vial on the ground, obscured only by the "pick up" text because it's within reach, thinking "um, why am I able to read this?"

They really need to fix it so that every replenishing item in a ten-foot radius from your character automatically zooms to you no matter what. Otherwise it devolves into a guessing-game as to whether their algorithm will be smart enough, and of course when the gameplay is fast and furious, you have to guess conservatively -- which defeats the entire purpose of having the feature. Picking stuff up -- heck, being near anything, degenerates into a button-mashfest.

And unless it's just my imagination, it feels like the pick-up button is less responsive than it was in BL1. When you open a chest, there is a nontrivial window during which the items appear to be grabbable, but pressing the button has no effect. You have to jab at it for up to half a second, maybe a second before the game says "aw fuck, that's right, I told them 'Pick Up' and they're pressing the button, so maybe they're actually trying to, you know, pick that shit up."

Is it really that hard to detect that the button is already down, once the items are actually grabbable?

And of course the whole cycle gets repeated twice per container, because the game is just as likely to ignore your button-press to open the container.

The last "Bad" line-item I'll whinge about is that although the game seems really generous about accuracy, they're real bitches about who died first, when you and the last nearby enemy expire at the same time. To illustrate how forgiving they are overall: you can be using a sniper from a thousand yards away, and pull the trigger when the cursor's kinda pretty far away from the mob's head, and it'll explode way more often than probability would dictate that it should. Very gratifying! No complaints here! And they're also really nice when it comes to landing jumps that you didn't quite hit, unlike in many other games. In general the game is pretty forgiving about controller accuracy.

But if you die "at the same time" as an enemy (i.e. it happens within ~100-200 ms before or after), you go into a fight-for-your-life bleedout. Sometimes it seems very, very clear that the enemy died second, but the game didn't actually realize it, and penalizes you. It seems unfair. To avoid any suspicions of stupidity on the part of the detection algorithm, it would be nice if they'd give you a half-second window AFTER the last enemy dies before your own death results in a bleedout. Hell, even 300ms would be nice. There are already plenty of legitimate situations for aggravating bleedouts -- the classic one being when the enemy shoots you and then walks around the corner. So I don't think it'll cause a balance problem to add the short grace period I'm proposing.

I know for a fact that there are some issues with the code that detects whether an enemy is dead. Several of the missions have resulted in me sitting around for a long, long time (several minutes) after the mission was obviously over, except the game couldn't figure out that it was over. Examples include the last round of the Natural Selection Annex, where I just wandered around the arena hoping the game would finally notice I'd won, and the plant-the-flag Sawtooth mission, where twice the last enemy disappeared minutes before the Slab King noticed I was victorious.

So I suspect there's a race condition here, in which you can legitimately die before the last opponent, but the game doesn't notice, and you bleed out while shaking your first at the unfairness of it all. Why go there? Just put in a short grace period, and make sure it's really really clear that you died after the opponent -- often from a long-fused grenade, I've noticed. Then there's no cause for questioning the game code itself, which undermines player confidence in the fairness and quality of the engine.

That's about it for the Bad. Inventory management woes, no menu while jumping, bulk-vacuum issues, and bleedout race conditions. That's pretty good, all things considered. Why not just fix them all in a patch, and make it perfect?

The Ugly

There's only one Ugly in BL2, and it's a big one. The Ugly is that for no reason whatsoever -- negative reason in fact; it's flat-out anti-reason -- they don't give you enough bank slots to make farming fun for more than a few days.

They put an astounding amount of effort into the endgame mechanic, folks. This was not some casual design thing for them. They put in hooks for new raid bosses, tons of one-off unique legendary weapons with custom artwork and code, and a plethora of design decisions to prevent any one raid avenue from dominating the endgame. They made it so that every one of the dozens of bosses and mini-bosses has its own legendary that it can drop, so that farming is distributed across most of the locations in the game, which breaks up the monotony. They even added formal item-twinking across characters, amazingly enough.

But for all that, it's fundamentally broken. And what's more, they have this huge, gaping problem with a substance called Eridium (I'm sure they're sick of hearing about this by now), which lets you buy a limited number of carrying-capacity upgrades, including bank slots. So players are already simultaneously crying out for an Eridium-sink and more bank capacity. I mean, they should have seen this coming months ahead of their code freeze. It would have taken maybe 3 days of engineering and testing effort to make it so that Earl could sell you increased bank capacity at usury rates, even a geometric progression. And it would have been fine. Everyone would have been satisfied.

Here's the thing, though. It's not just about capacity. If Gearbox wants to do this Right, by which I mean pull their heads out and do something that nobody in the game industry has ever done before, what they really need to do is give players a database.

That's what we want, really. You make 87 bazillion guns, and let us collect them? Well then we're going to want hundreds and hundreds, maybe thousands of guns in our collections. Not twenty, or whatever stupidly low number you've given us. That just spawns modding and mule characters and leaving the game altogether -- any outlet from the collection pressure; players will use them all.

What BL1 needed was a way for you to effectively manage a collection of a thousand guns. What if you want to look at all your Mashers? Or all your weapons by type, or by elemental damage, or by manufacturer? I'm not asking for a data warehouse here, or for some fancy text-based console-query UI. I mean, *I* would use it, but obviously we want to keep this mainstream.

If you start by formulating the basic problem as: "How do I manage a collection of a thousand guns," then your UX guys should be able to come up with something acceptable. No — you know what? Fuck acceptable. They should be able to come up with something awesome, something in keeping with the innovation and forward-looking badassery that we've all come to associate with Gearbox and Borderlands.

Ironically, BL1 was better at this -- a LOT better. Of all the inventory "improvements" introduced in BL2, the only one that improves gun collecting as a hobby is the "examine this gun in 3D" feature.

I imagine I'm going to do exactly what I (and everyone else) did in BL1, which is to figure out how to modify the bank-slots and inventory-slots counters in the player save files, and hope like hell that you guys can actually scale up to something reasonable without crashing or locking us out or triggering some other godawful poison-pill.

But just having a lot of slots is only a tiny part of the picture. Gearbox has created a gun-collector's game, but they haven't given us a way to collect guns. How messed up is that?

I think it's pretty messed up.

All this talk about BL1 has given me a major case of nostalgia. I love BL2, but I think I need to kill some Drifters to pull me out of this funk. I remember when I finally reached the point with Brick where I could walk around the sand dunes and mow down drifters -- on foot -- and live to tell the tale. BL2 doesn't have any moments like that, not yet. Nothing you had to work for like that, anyway. It took months of gun collecting before I was that badass in BL1.

And I remember looking through that sepia-tinted window on entering T-Bone Junction, that window filled with promise of adventure, seeing those rowboats suspended over a forty-foot drop to the salt sand, with the scorching wind blowing the makeshift wind socks tied to the Lucasian architecture. I remember hearing Knoxx give his reports to Admiral Mikey, Mr. Shank asking if I thought I was being stealthy, Athena barking her ludicrous military-speak to me -- a merc -- and Thirsty the Midget asking if I could turn the power back on in the Brandywine.

I remember. And I think it's time to head back. I knew this would happen. I knew Gearbox would screw us on the gun collecting, and I knew sooner or later it'd be back to Knoxx and the Armory and Crawmerax.

I just didn't realize it'd happen so fast.

Sigh.