Sunday, September 16, 2012

FTL isn't a Roguelike -- or if it is, its a very bad one.

FTL was just released this week -- it's the space ship management game where you cut a swathe of destruction across the galaxy because something bigger and badder than you is doing just the same, nipping on your heels the entire time.

The game is pretty simple: you got crew inside your tiny tin-can cruising the galaxy. You got weapons, you got shields. You got systems the enemy can target on your ship to disable your shields, life support, steering, and you can do the same thing to them.

It sounds like fun, and it is, for awhile.

It purports itself to be a roguelike though, and that just ain't so. It is entirely too random to be a roguelike. In a roguelike, when you die, there's that moment where you go, "Why did I do that?"

You ask yourself "why did I do that?" because you understand that your character's death was totally avoidable. You could have checked the room you just entered more thoroughly. Maybe you were distracted and were just mashing one of the direction buttons, and your character walked over a trap or fell into a barely noticeable crevice to his doom. You could have totally looked at the frost giant in that next room (the one that killed you with one shot), decided you weren't ready, then turned around and went looking for better equipment, or a way around. Or maybe you just had to drink that unidentified potion because you are a freakin' lush and can't stop rolling the dice with your intestines on the line. In a roguelike, death sucks, but you did it to yourself, so while it is annoying, it rarely becomes too frustrating, because "how can I avoid that next time?" immediately follows. That's where some of the fun is.

FTL is the exact opposite of that. The game can and will literally set you up to fail; it is unavoidable and incredibly unfun. I'll go as far as to say that the game is more frustrating than fun once the charm wears off -- there is nothing like canting your head to side, staring at the screen and muttering "wtf?" because in the second sector you ran across an enemy that has 3 shields -- and you only have enough weapons power to fire 3 laser shots at a time. The game is structured in a way that you are either lucky or you are not. If you are lucky, you will come across some weak enemies, get some missiles and "drone" weaponry early on. If you are unlucky, you will barely scrape along, if you survive at all.

And barely scraping along is meaningless, as I found out the first time I made it the boss.

The boss had four shields, a laser cannon, a beam cannon, and something that fired at least 3 missiles every volley. I had four lasers shots a volley, an empty missile launcher, and a beam weapon that doesn't work if shields are up.

Despite the enemy ship being the size of a small planet, if I missed even /one/ laser shot, it would be impossible for me to damage the boss ship at all -- in FTL shields regenerate a few seconds after they've been depleted, leaving you with a very narrow opening. So in one volley you absolutely need to knock down all four shields with all four shots, or else you'll have to wait another 15 seconds to try again. If you miss one its a meaningless gesture; you can't damage the hull, so you can't destroy the ship.

So of course that's what happened: the game, having decided I would fail early on, let me struggle through to this last moment, where it put me in front of an enemy I had no way of beating.

You can only visit a handful of planets in a sector before the enemy armada starts blocking off the left side of the map, encroaching ever closer to your current position., You don't have the choice of sticking around and trying to scrap together as much "scrap" as you can get to afford new weaponry and crew members; you are either lucky, and on the journey to the sector's exit you got some easy scrap and nice weapons, or you are unlucky, in which case you will be unable to achieve victory.

Once I realized how the core of the game worked, I would be a few sectors in, less than halfway to the final showdown, and I'd look at the state of my ship and go "I'm not going to make it to the end." It's a realization that sucks the life out of the game, because there's nothing you can do to correct your course. You're screwed.

For a $9 game, I guess it was worth the 6 or so hours I got out of it, though.

Saturday, September 08, 2012

Boobytrap your Monkey Patches!

If you are going to override an entire method with a monkey patch, at least do this:

raise "Make sure I'm still required!" unless Gem.loaded_specs["GEM_NAME"].version.to_s == "VERSION_THAT_REQUIRED_PATCH"

somewhere inside the file that does the monkey patching. Consider it a courtesy for everyone else, including yourself.


Okay, so I spent about 7 hours fiddle-fucking around with an inexplicable circumstance that came down to someone monkey patching an entire goddamn class by copying and pasting the Git HEAD version of that class so that an older version of the gem could use some of the newer version's functionality. Of course, 10 months later the underlying gem got upgraded way past the version the monkey patch came from, so a whole subset of functionality just broke "like magic!"

Devise: Logging in a user from a custom controller.

"Devise is a nightmare I have suffered only for the shining jewel called Omniauth clutched jealously within its thorny tentacles." -- a wild Arron under the influence of several frappucinos.

If you want to log in a user from a custom controller in Omniauth, this is your only hope:

user_params = params[:user] || {}

user = User.find_by_username(user_params[:username]) || User.find_by_email(user_params[:email])

if user && user.valid_password?(user_params[:password])
  sign_in :user, user
  # destroy the world.


You're probably thinking, "Can't I use warden.authenticate and cut down on the code and not have to do that nasty || at the beginning?"

No. See this question on StackOverflow for an explanation, but the short version is Devise doesn't want you to be able to use warden.authenticate anywhere outside of Devise::SessionController derived classes. Hilariously, if you go trolling for information on warden.authenticate you will find mostly unreplied to threads in Devise's Google Group, which is too many capitalized words in a row. If Google is a verb, can I refer to its products in lower case as well?

Goddamn. Does anyone remember Authlogic?

User#authenticate anywhere you wanted and you were fucking done, son. Yeah, Authlogic doesn't (or didn't) come with pre-built views like Clearance or Devise, which probably had a hand in it falling out of favor, but still, it was simple and almost impossible to screw up.

Theoretically you can get Omniauth up and running with anything, really, including Authlogic, but realistically setting up Facebook / Twitter login with Devise + Omniauth takes only seconds, and by the time you are screaming obscenities at your IDE it's too late to use anything else, assuming you even could -- I'm seeing that a lot of nifty stuff like rails_admin uses Devise under the hood.

Still hate the shit out of Devise for custom stuff, though.

That's right, hate. I am a mean coder. Rawr. Rawr!

Get out of here. Shoo.