Released The Rapids!

I started work on the first challenge in my game, The Rapids, on March 8.

That day of work included the creation of two files and the modification of two other files.

At least 100 hours of work later, I have a challenge. And it, you know, works. And people can’t cheat! (Well, I’ll say that they probably can’t easily cheat because I probably haven’t fixed every possible way to cheat, but I did a lot to try to prevent it!)

If I didn’t care about people cheating, I would have had it much easier. The issue here is that people are playing in a web browser. They’re not playing in an environment that I can tightly control, like an app on the phone or an actual application you run on the computer. The text-based games on Bulletin Board Systems, like Legend of the Red Dragon and Trade Wars 2002 and Sky Mountain never had to contend with back buttons and reloading. It’s making me wonder how easily I could port this to an iOS game. I’m pretty sure the answer to that is “not easily”, but it certainly bears more investigation. Any kind of app is probably something to look at for another game in the future, rather than for this one.

As such, I have to bear in mind that the back button and reloading are things that can happen and so I have to account for them.

So the first challenge is implemented and works. Failure has the right results and so do the varying levels of success. And I even partially rewrote my maintenance script so that everything that has to be reset at maintenance does get reset. (And it should be easier to implement more maintenance events going forward.)

More than two months after starting it, I’m basically done. There are a couple of tweaks to make, such as a nicer transition from the normal paddling to the challenge stuff, but that’s… it’s not even secondary at this point, it’s tertiary.

And so now, what do I turn my attention to?

There’s the obvious: the second challenge. But I also have more than 50 open issues in my GitHub repo and should, you know, start looking at those things. I also want to bring the currency (Fire Opals) into the game with more regularity than just doing well in the first challenge. And… and… and… The list never stops.

So rather than think about the literal dozens of things I could do, I spent a few hours on Monday thinking about the second challenge.

Part of my problem here is that I like the idea of a river. And so any obstacles necessarily have to be water-based. And, for best results in terms of believability, should be things you’d encounter on a river.

So the first is The Rapids, mostly based on the rapids up near my parents’ cottage in the Laurentians. Like, that particular set of rapids is what I think of when I’m thinking of the rapids in my game. It was pretty easy for me to say that the key to the challenge about rapids would be answering questions quickly. It just makes sense.

In thinking of these challenges, I also decided that the third and final challenge should be a waterfall. Let’s ignore the fact that I have no idea (yet) how that translates into gameplay.

But I was stuck on the second challenge and only sort of came up with a half-assed idea of a whirlpool. Why? Well, it’s a water hazard that people can easily visualize. How would it play, though? So I spent some time brainstorming and researching and I think I’ve figured it out.

A whirlpool can easily mix things up. It can also pull in nearby items, objects, debris, that sort of thing. So I’m thinking that it’ll be some challenge-specific categories (unlike the first challenge, which draws on the regular categories and questions) that will be all mixed up together, and then, in terms of debris, it’ll be multiple choice, with one right answer and multiple wrong answers. In this way, it’ll be a bit easier, which should mitigate the fact that you’re not choosing your category, like you can with the first challenge.

And, like the prior challenge, very similar (if not identical) rewards. Oh, and it won’t be timed.

So, what’s next? Probably a small release dealing with a couple of small fixes/enhancements, followed by the second challenge. The good part about the second challenge is that most of the database is set up for it already, and I already have a good idea of how to prevent cheating based on the first challenge, so I shouldn’t need two months to get it done. Maybe the end of June is feasible? We’ll see.

In the meantime, all existing users who have completed the intro (and then all subsequent users who complete the intro) will begin at 475km in order to better be able to hit the first challenge at (around) 500km.

Have you tried it out? If not, what are you waiting for?

https://www.riverofkurn.com/

Hope to see you out there on the river!

Brilliance, Stupidity, Scope Creep and More

One of the most interesting things to me about this game project is that I am constantly astonished by myself because I was either really smart about something or really stupid about something.

For example, I’ve been working on the rewards for the first challenge and I realized that I was really smart in terms of how I charge my user energy for paddling down the river. I only charge them for it once they answer the question, one way or another. So in building a way to skip a question at no extra cost (but no forward movement), I was like… oh, so I can just generate the new question without including the trigger to charge them until they answer the newly-generated question! Sweet!

(We shall ignore the moment of late-night panic when my brain screeched to a halt and was like WAIT SHOULD THEY EVEN BE CHARGED HERE???? and thank my friend Lisa who helped me logic my way through things at 3am to realize I was, in fact, correct.)

Then, though, then I am faced with my absolutely terrible forward planning skills when it comes to my maintenance routine. Because, you know, I now need to add several changes to the maintenance routine to accommodate the changes brought on by the first challenge. (All the rewards are done, victory stuff is working fine, and even failure stuff is fine. It’s just maintenance that’s killing me now.)

So the main issue is that my original maintenance routine was written, uh, late last August or early September. I was eager to get things working because I wanted to launch the game and maintenance was one of the last things I needed to work on.

Presently, it works via bash script which is automated by a cronjob. So at 07:00 UTC every day it:

  • runs Green Game maintenance
  • runs Blue Game maintenance
  • does a database dump
  • uploads the database backup to the S3 bucket

The problem is how it runs Green and Blue maintenances. It just runs these two .php files, each of which define some variables that are specific to the game, and then runs the runMaintenance() function with those variables. In theory, this is super clever. In actuality, the positioning of the files, in order to not make them accessible via the web, confuses matters.

Even apart from that, my runMaintenance() function is also a nightmare because it’s got about 13 function calls within it. So I’m legitimately thinking about ripping out maintenance entirely and starting from scratch, all because it’s just too janky for my liking.

Scope creep is also real and annoying. I have to find a way to add more Fire Opals to the game and not just as a reward for doing well in the first challenge. But I also want the first challenge to be your introduction to them, so I’m going to need to insert random events to come across them if your location is greater than 500km.

Speaking of scope creep, I have to do the same with the companion for your travels, in addition to deciding when the companion decides to leave you.

I’ve rescheduled a potential launch no less than four times in the last month. I am determined to do it this weekend. It’s just going to be a long week before I get there.

Oh, and as to my ponderings about spelling and stuff, I’m going to implement a similarity match of about 90% just on the challenge page to start and we’ll see how that goes. If it goes well, I’ll expand it to the rest of the game. If it doesn’t, I’ll retool it. I’m also going to have Dorene tell you that you spelled it wrong and what the actual spelling is. However, there won’t be any bonuses for someone spelling it perfectly, nor will there be any downside to spelling it wrong (within that ~10% margin of error). More stuff to code if it goes well in the challenge.

It just never ends. Here’s hoping that whatever I come up with for maintenance is less janky and more reliable going forward so that I don’t want to throw the computer out the window when I have to modify it to include the second challenge stuff.

String Comparisons vs. Fuzzy Matching

A friend of mine finally started playing my game this weekend. I’d sent out a general email to a bunch of my friends last September and most of them played around a bit. This particular friend decided to look at it this past weekend and boy did she have some comments!

I have like seven emails from her with various complaints, ranging from what the hell to this is the correct answer to implement a spellcheck.

While I argue that someone who is as much of a Star Wars fan as she is (PS: May the Fourth be with you!) should be able to spell Alderaan, I do admit that the strict comparison I currently perform in the game is a little, how shall I put this, unyielding.

Look, I’ve always been a good speller. I know which to/too/two to use. I know how to spell antidisestablishmentarianism. I know how to spell supercalifragilisticexialidocious. I often take it for granted that other people can, or perhaps should, spell things properly.

So when I was writing the early code for my game, I was like, yes, sure, let’s do a strict string comparison on the submitted answer and compare it with the correct answer and the alternate answer.

At the time, I knew that it would be unforgiving and I thought to myself meh, I’ll worry about that later.

So with my friend having written me several emails to complain, I figure that now is later.

As such, rather than do any of the things I desperately have to do in order to finish up the first challenge, I spent any time coding this weekend on researching fuzzy matching in PHP.

There are apparently four ways to do this. The one that looks the absolute easiest is the similar_text() function. You can use it to compare one thing to another and it’ll give you a percentage of how much it matches. So, for example, if I have “Beverly” as the answer to a Star Trek: The Next Generation question, but someone answers “Beverley”, I can do this:

similar_text(“beverley”, “beverly”, $percent);

echo $percent;

And that gives you 93.333333 (repeating, of course).

So that means that the user-submitted string of “beverley” is a 93.33% match to the actual correct answer of “beverly”.

Using this, I can set an appropriate percentage limit to grant a correct answer. So like, if the limit is 93% or under, then “beverley” will match “beverly” and will get the question correct.

HOWEVER.

A lot of this works on length. So while adding an extra letter to Beverly isn’t a big deal, what about Data’s cat, Spot? If we’re looking for “spot” as an answer, what if someone adds an S and says “spots”? It’s a shorter word, so that only gives an 88.88888% (repeating) match. Should be simple, right? Just set the limit to 90ish percent and we’re good, right?

Well, what if it’s a Red Dwarf question and I’m looking for the answer is “dave” but someone submits “david”? Again, since it’s such a short word and because two letters are different (the e replaced for the i and the d added), this is only a 66.66666% (repeating) match. Shouldn’t someone who types in “david” get points for “dave”?

What about the poor person who typos dave as save? There’s one letter different and so this gives a flat 75% percentage match. While I would argue that save does not equal dave in the least, the S and the D are right next to one another.

What about things that are very similar and yet different? Say I’m looking for ursa major as an answer and someone types in ursa minor. That’s an 80% match. So maybe the match criteria needs to be higher than 80%. But where does that leave us with Dave vs. David, or Dave vs. Save?

Even aside from “what should the limit be”, I’m now also thinking about whether or not there’s a notice to the user that “mmm, that’s not quite right, but I’ll accept it” and then show them the correct answers. Does it matter if someone spells it Beverley if they get it right? Does it matter if they eventually learn that it’s Beverly? How important is that knowledge if it doesn’t do anything different in the game?

And then, of course, one has to think about whether or not properly spelling something should be an advantage in the game. Should I go farther if I can spell Beverly right as compared to Beverley? Maybe I could show a notice saying “mmmm, I’ll accept it, but you’ll only go half as far for this one” and then divide by two and round down to the nearest whole number (unless the number is zero, in which case it would become one).

But does that unfairly reward the good speller? What if I do show the proper spelling, which then gives someone the chance to improve next time?

One of the most fascinating parts of game design, to me, is the question of “sure, I can do it, but should I?”. That question has been a constant presence in the back of my mind since I started out on this project. I can do just about anything. But I’m coming at this from my own biases and perspectives, obviously. As someone who is a good speller, it’s only natural to me that I would want to be rewarded for that. But if I were a terrible speller, I think it would suck to only get a portion of what a good speller gets.

Food for thought!