Wednesday, November 16, 2016

The Monkey and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Apple

It's been a while!

I took a couple of years off blogging because I felt I didn't have much left in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Google cocoon I poked my head out and learned how people do things in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n.

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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re's only one of me.  For now.

So where do I start?  I guess cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 logical thing to do would be to start at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 beginning, but screw all that, I'm starting with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 monkey.

The Monkey


I had cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following conversation with my wife cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 game.)

Me:  What stuff baby?

Wifey: (wailing) All cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stuff I had in my house!!  I dropped it all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m boom, it disappeared, right in front of my eyes.  I was watching it and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re!  I had a lot of good stuff cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re and it's gone!

Me:  (looking around)  I believe you baby.

Me:  (looking around some more)  I think... I think cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re were two problems.

First, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best decision ever, but it seemed reasonable at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 time.  And second, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re was a chance that if I pulled out cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 big guns and killed it myself, for instance by invoking its kill() method directly at runtime, its inventory (her loot) would be replaced with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 default monkey inventory of bananas and fur, or whatever I'd given cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m.

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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 monkey, you can see it carrying everything.  Just give me a second to figure it out.

The picture below shows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 predicament.  Wifey is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 naga warrior, I'm cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 old guy in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 blue pajamas, just like in real life, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 monkey is barely visible 2 squares below her, by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Japanese shoji screen.



Every creature in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 game has an event queue and a command processor, and can respond to generally cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same set of commands as players.  Normally cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 AI decides what commands to give a monster, but you can inject your own commands under cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 right circumstances, or even take control for a while (e.g. with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Charm Monster spell).  So I decided I'd try to command cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 monkey to give me cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Python language on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 monkey in my interpreter, and I was seeing Wifey's stolen valuables, plus cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 expected monkey inventory.  Now for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stationary AI used for immobile monsters.  But I couldn't be bocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365red to look up how right cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n, 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 items back, so I just followed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 monkey and issued those commandNow() instructions.

Unfortunately, and to my lasting surprise, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 monkey started ignoring me after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 old-fashioned way. You pay cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 iron price.

I was irked by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 monkey's emergent nonchalance, so I pulled out cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hammer:

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

Where me() in this case is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attacker.

As I feared, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 corpse's inventory was completely empty, because I clear out cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 inventory for pet monsters, to prevent abuses where you just create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m in builder mode, take cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir stuff, and make infinite cash.

So I busted out cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 clone() command and manually recreated cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 rest of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 missing items as best I could, and gave cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 old roguelikes, and maybe a bit of a MUD, and you think, gosh, I could do that.  And you can!

Off cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n, 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 referees on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 front.  You had to roll everything yourself back cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n.  Uphill both ways, in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 snow.  (Actually cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 game, because my productivity had tanked as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code base grew, and I wanted it back.  So I stopped working on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 game, for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir hosted services, Stack Overflow and its infinite supply of answers to just about every question you'll ever encounter, and all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 game.

A lot of people have asked me why I did my first mobile client in iOS racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y don't spend money, but it does mean cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are more cautious about it.  I have friends who've done simultaneous iOS/Android releases for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir apps, and invariably cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 iOS users outspend cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se days, whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y know it or not.

What about iOS?  Well, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re'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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y were 100% met by iOS.  It has an MVC framework, and you add views and subviews, and you have all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hooks and lifecycle events you'd expect -- after learning Objective-C, I'd say it was only about four days (thanks to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exact opposite of intuitive and familiar.  I've gotta be a little careful here, since I recently joined cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Android tools team at Google, and I don't want to throw anyone under cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bus.  They did cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y could with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 environment and situation cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y had when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y started back in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 early 2000s, which featured phones that didn't even have memory -- cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 decisions cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y made turned out in retrospect to be overly conservative.  And as a result, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Android APIs and frameworks are far, far, FAR from what you would expect if you've come from literally any ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r UI framework on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m, and my little indicator is redlining, so let's move back to Apple and iOS.

Apple:  The Good, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Bad, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are tons of ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r modern features missing, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r non-functional language out cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re), properties, and many ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r modern conveniences.  The syntax is awful, and it can get pretty weird when you're bridging to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 C APIs, but on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 whole you wind up writing less code than you'd think.

In fact, various bloggers have measured it, and if I recall correctly, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 consensus is that Android Java is about 30% more verbose than Objective-C.  Which is pretty counterintuitive, because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 documentation is solid, and Apple is aggressively deprecating crummy old APIs (like UIAlertView) in favor of better-designed ones.  Everything is still cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system, and you can see generations of whole layers of API access dating all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 way back to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 old NeXT computers from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r, 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Good, we have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 languages, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 APIs, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tools.  What about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir store, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir checklist of roughly seventeen thousand rules, and make sure you have addressed each of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m, since all of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y don't mess about.  You have to follow all of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m.

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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 major Cloud providers supported ipv6 at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 curb like so much garbage.  At least cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y did it quickly.

After some technical consideration, I did cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 only logical thing, and got on my knees and begged cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 review. Even though it's completely non-scalable.  Desperate times.

Fortunately, after a mere six weeks, and me finally sending cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m an angry-ish (but still cravenly and begging) note asking WTH, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y granted me cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y gave me cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exception, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y also threw in a major feature request.  Lordy.  It's almost like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y'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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sign-in SDKs that I've managed to wire up so far.  So cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y asked me to implement Wyvern Accounts.

Sigh.  I was so relieved that I got cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 email address to tie your characters togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r), and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server, blah blah blah.  God dammit, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 nerve of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir curveball at me.  Now I need underage reporting and god knows what else.  Still working through it with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is an uncontacted tribe deep in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 South American rainforest who are not on Facebook yet, although I believe cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are still eligible for Amazon Prime.  And also some of my alpha testers were struggling with it.  I guess cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are a lot of people who not only don't have GMail, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y prefer not to sign up for a free account.  I can only assume cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NSA is responsible for this phenomenon.  But it means I most likely need Wyvern accounts.

Anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y're so high that I won't have to worry about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m for years.

Google's philosophy is, roughly: "Our APIs should scale with your business."  They have quotas, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y're so high that I won't have to worry about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m for years.

Twitter's philosophy is, roughly: "Go fuck yourself."  I exhaust cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir 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, ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r than "don't use Twitter APIs"), is that Apple can jerk you around pretty much all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y want, and you'd better like it.  You should basically prepare for a long review.

Back to The Good

Despite cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bumps in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 (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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y'll let me have up to 2000 testers, which will help me make sure my stuff scales, if I can get that many.

And cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir review turnaround time has been pretty good.  It generally takes about a day, in my experience.  I'm not sure why cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y require a manual review for my Beta builds, after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y've already approved me for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual store launch.  And every build requires anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual launch.  But cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 rest of your miserable life, and likely into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m had to purchase iOS devices just to play, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y splurged.  And cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y started playing insane hours.  The ratio of 7-day-active to concurrent players has been crazy.  In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n.

With cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se alpha testers, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ratio has been about 4:1.  They're playing upwards of 8 hours a day, around cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 clock.  And cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y're all over cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 world -- I have testers in Japan, England, New Zealand, Spain, Nigeria, Toronto, east coast, west coast, I forget where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y're all from.  But we're talking about a group of only about 60-70 regulars, so cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 diversity is quite remarkable.

This letter cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y wrote me back in 2012, when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 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 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 launch went.  Meantime, if you want to play, visit http://ghosttrack.com.  Hope to see you online!

Rhialto