I hope you all enjoy my thoughts on VVFF. It was rewarding for me to conceive and write, and I hope you were able to enjoy it and my thoughts. Perhaps it’s partly down to experience as well, but I found it easier and more relaxing to focus on the post-comp release than ever before. After the judging period ended, I merged a few changes and fixed a few bugs. I felt ready to complete VVFF and move on. I hope everyone who’s ever put a few months’ effort into writing anything has had the opportunity to feel the same.
How it Started
First of all, I realized what my pen name should have been. Parsin’ Pro Carson Crowe. But Billy Boling will do.
Like Ailihphilia, I thought this would be a short game, or a part of a short game. I like making limericks in my spare time, so I am a frequent visitor to Rhymezone.com, and I must have stumbled on very/fairy and vile/file about the same time back in June 2018. I figured a quality game with lots of limericks was unrealistic (it’s good to be proven wrong,) but there were others that worked. Joey Jones/Eggerich von Eggermond’s Danse Nocturne, Michael Martin’s EXTERMINATE! (SpeedIF 2008) and DCBSupafly’s Beythilda the Witch Queen showed it could be done.
Plus the phrase ‘very vile fairy file’ amused me, but what could I do with it? I figured there couldn’t be too many rhymes where we changed the first sound.
But there was enough obvious stuff to start. The final command had to be BURY BILE. And you could do so in the Merry Mile, or perhaps the Airy Isle. The character’s name fell out, too. You could be Kerry Kyle. I’m not good with creating female characters, but the least I can do is try and not make the character obviously male, so this seemed like a good step forward. I didn’t know how much else there could be, so maybe it would just be a one-room EctoComp game.
Writing the beginning end end
With dual rhymes in my orbit, I slowly started peeling things off. Anything with an alliterative name, I went through the 44 English sounds to see if they could be fungible. (I didn’t put a reference of sounds in an easy-to-reach spot early on. This cost me time. Eventually I put it at the top of my notes file.) Some things fell early, because they were straightforward, like GET GOOD in the wet wood. It seemed like an ideal start. Some were a bit trickier. Some went nowhere despite having promise. And my favorites were the ones that seemed unlikely, but I wanted to give them a chance. FIND FAULT was a big example of this. It worked so perfectly that you could do so in a Vined Vault, and that made up an early puzzle. Another flyer gave me the idea for Fall Fest as a place to maybe start your game. That turned up a whole ton of rhymes that led to the introduction!
So I had my notes file, and I had a list of double-rhymes. And, like so many games, I thought I had some good introductory puzzles, and the ending puzzle took shape quickly. So did the penultimate puzzle, with the Bot Board. Board, Lord and Horde just seemed to be itching for another rhyme if I could find it. The Bot Board fell out from the working title of my game, The Problems Compound (“The Directors of Bored.”) I loved it but could never quite justify it, and the Bot Board feels like what they should’ve been. Summoning the Lot Lord and Hot Horde seemed perfect to take down the board. I actually didn’t figure out the Sought Sword until a tester’s good try very shortly before the deadline–I wrote in a Shot Sword with a month left, mentioning it looked slightly out of place, as a Sot Sword seemed a bit silly. I took forever to see the homophone. Testers constantly hammering me with homophones put me in position to see this, but sometimes you just miss stuff. I’ve had a lot of games work like this, with the start and end just so, and I needed to fill out the middle.
But one thing VVFF testers did for me was to give alternative solutions. Testers often help me with cluing, and while they’re always very good for saying when I need clues, they showed me good alternate verbs to solve a puzzle–or in some cases, gave me verbs that overwrote the main ones. WINDING WAYS replacing MINDING MAZE was an example.
Combining isolated ideas
The middlegame was tricky, though! Last Lap was pretty clear, and I had a Hard Hat, but I wanted something more. I had some vague ideas for Creased Cross and the Beast Boss you needed to fight there. I had a lake to the west of the cross, and it eventually got moved to an isolated area. “Lake” rhymed so well I knew I had to include it, but one problem was, it also could create a dead end. At some point I realized “boat” rhymed with a few things, and that helped.
the hint device and options
I knew I needed a hint device, too. Programming seemed too tricky for it to be alphabet-based. In other words, a needle for each word goes one way if you guess earlier in the alphabet and another if you guess higher. And I was still worried the hinting device just wasn’t good enough. I probably should have sent what I had off earlier, even though the game was incomplete. I’d have gotten some valuable feedback earlier, and nobody would’ve hit the unsolvable middlegame yet. (I did have a jump command for the end area.) Their efforts helped–I needed to work on making the intro more welcome and the ending and the hinting.
Also, the volume of good guesses quickly gave me confidence that people would have fun guessing wrong, and I wanted to reward them. So it looked like I was going to have two hint items, and I didn’t want them to overlap or be too confusing. I was, however, extremely frustrated that they would guess one word right but not others. Probably almost as frustrated as they were!
I already had the Leet Learner, but it was color-based: yellow meant that the answer had the same number of letters in each word. Blue meant you added to the letters in each word, and green meant only one. Red and orange meant take away letters from each, or just from one. This was awkward, and my testers, who came up with lots of wonderful original guesses didn’t figure it out, but I’m glad I had the foresight to define cheat-states as leteq, bothplus, oneplus, oneminus, and bothminus. Because when I realized it’d probably be better to have a needle swinging (partially) left or right, I only had to change one line of code. This was handy, two weeks before deadline. I had to clean up any text saying yellow/orange/green/red/blue, but I’d kept all that text in one line. So being organized saved me here.
But a bit of free association helped me with the warp item. I remember writing a mail to a tester. “I should write a hint item.” But I didn’t click send–maybe I could take a swipe at an item? They’d offered a lot of specific details, and I didn’t want to send them a blanket statement. So I’d take a swipe. Something that helped you jump? But a lump was not interesting … and there aren’t many words with J. Ah, heck, “lurking lump” with “jerking jump” would be a good first guess, a placeholder if nothing else. I don’t think I ever had a placeholder work out this well! And I think the tester’s attention to detail helped push this through sooner rather than later.
And I’m also pleased I implemented it earlier than in Ailihphilia. A month before deadline instead of four days…and it made a big difference. The eye and the pip in the pact cap lit up, but I had a silly bug in there, because that’s a risk so near to deadline.
I hope it never gets old, saying “Oh, I’d like to make a hint item but it might be too on-the-nose, or I might not have anything at all,” and being able to chip away to make it reasonably believable and yet not too obvious. I feel fortunate. But the first draft–well, it was not so hot. And I know I need that push from my testers so I’m not just saying I should make a hint item.
Abusing the parser: point scoring actions
I mentioned this big problem with hinting: a tester would guess one word right, but not another. I wanted to give them credit for this. I also ran into a problem where I exceeded the number of verbs the Z-machine could handle, both with valid verbs and good guesses. These two problems had a related solution, but it required intricate programming and testing.
Inform’s usual syntax might be: understand “find fault” as findfaulting / carry out findfaulting, etc. This created too many verbs, and it didn’t help me track half-right guesses. So instead I moved the code a parser-error function, and it was nice to have everything in one place. I hope you get something out of this whether or not you’re an Inform programmer. The code below is for Find Fault.
table of verb checks [xxvc]
w1 (text) w2 (text) okflip core idid ver-rule do-rule wfull (topic)
“find” “fault” true true false vc-find-fault rule vr-find-fault rule –
this is the vc-find-fault rule:
if player is not in Vined Vault, the rule fails;
if mean mass is in Vined Vault:
if print-why-fail, vcal “You already did, and things got worse. You’ll have to try something else.”;
continue the action;
the rule succeeds;
this is the vr-find-fault rule:
loop-note “FIND FAULT”;
say “It sure seems, at first glance, like the Vined Vault is inescapable. But you notice a few flaws. A loose tile, a crack in the wall … you have all sorts of time, and there are no guards. And here you go … if you do THIS, and THIS …[wfak]”;
say “[line break]But of course something outside rushes into the fault you found in the vault. A mean mass roars in and mangles the packet of Mind Malt! It pulses threateningly, and while it hasn’t attacked you, it now blocks your way out!”;
move mean mass to Vined Vault;
moot mind malt;
phbt Vined Vault;
Some of the text may seem odd (“moot” means move to the done room) but the basic idea is that the vc (verb check) rules make sure an action is valud, and a vr (verb result) rule executes that action. (If you’re curious, OKFLIP means Fault Find is okay too, CORE means the action is necessary to complete the game, and IDID (“I did”) checks if it’s been done–so, for instance, you couldn’t get infinite points for alternately typing SOFT SAND and LOFT LAND. wfull is useful for if there is more than one possible solution e.g. “mash map” or “bash bap.”) VCAL/VCP are for if you use the Lurking Lump. It checks through all the rules, so a simple “say” would print a lot of excess text.
And if the command only matches one of w1 and w2, then the Leet Learner tracks that and prints out an “ooh! Close!” if half-detection is on, which it should be, by default. (Also, I was proud of the toggle command, though I suspect people didn’t need the extra difficulty. I always wanted to use “NAFF” in a game.)
There were a lot more bugs in this mechanism than I thought, but they were worth working out. And it also played into one other thing: easier credit for good guesses. Since “understand X as a mistake” counted against verbs, I wondered if putting things in a table was worth it. It turns out it was, because I was able to simplify the leet learner cluing mechanism, and the memory used in the z-machine was cut down, too.
Abusing the parser: good guess detection
The mistake table was a bit different.
table of mistake substitutions
mist-cmd(topic) mist-rule got-yet w1let w2let leet-rule mist-txt
“binding bays/baize” in-blaze-ways rule false 7 4 blaze-before-maze rule “You need to break free here, not get more tied up.” [start blinding blaze]
There’s a lot to unpack in this row, but it describes all I needed to check. The mist-rule simply checks if you are in Blinding Blaze (later called Winding Ways and Grinding Grays.) If not, the user’s input is ignored. The got-yet entry merely makes sure you don’t double-dip to charge the lurking lump. This means “binding bays” and “binding baize” aren’t different enough to give two guesses, but on the other hand, I wanted give a lot of credit for homophones in general. A fellow competitor pointed out an easy one I missed here (“Finding fay/fey”) which inspired me to find a Python package to check things programmatiacally. This is going in a post-comp release. I’m disappointed I missed this, but it’s not a HUGE miss. I’m glad I fixed other bugs.
w1let and w2let track the letters you want and need. In this case, you need 7 and 4 to say Winding Ways or Minding Maze. (Finding Phase also works, but it has a different number of letters. It’d be confusing for the player to take this obscure–but sensible and creative–guess into account. I think allowing for alternate solutions is good, but having the Leet Learner account for all of them would be too awkward.) So the game knows that binding bays would give a center reading (7/4 vs 7/4) but binding baize would give a center-right reading (7/5 vs 7/4). The blaze-before-maze rule is the final bit. If you’ve already gotten rid of the blaze, a clue from the Leet Learner would be misleading. So that is the check for a clue after displaying the mist-txt.
This made it easy to add good guesses my testers turned up, which is one thing I worried about at the start. It required a lot of programming on my own but 1. was a rewarding project and 2. paid me back quickly. I’d never really subverted the parser before, but here I had an excellent reason to, and subverting the parser made me realize how robust it was and how well it served for, well, games that didn’t abuse the parser like VVFF did.
One other problem with hints is that I didn’t hint when to use Toe Tappin’ Row Rappin’ until almost too late. This had testers finding the song puzzles obscure. But fortunately I had enough of a burst of insight to allow the player to toggle the song with SAVE SONG and RAVE WRONG.
Creative bits: stumbling on stuff
You need to expect a lot of fishing expeditions will turn up empty, and a lot that seem silly will wind up okay. There were dry spells from about May to July. I didn’t do much more than add in a death rooms or write up and inspect daily notes. But it was enough. Still, when something dropped, it DROPPED.
The angst puzzles on Been Buggin (so sad / way wrong) were originally dropped in after you scored 20 or 30 points, which was random, and if the bull was chasing you … uh oh! And not just for you, but for me, the coder.
But I wanted them in there. I didn’t know what to do! Then one Friday night I meant to go out. I almost didn’t. I misplaced my keys, cleaned up a lot, and finally found them and got where I wanted to be two or three hours late. One person I met was wearing a “MEAN MUGGIN” t-shirt, and so a quick flip through sounds in my head gave me BEEN BUGGIN and LEAN LUGGIN. But no, that was just a bit silly without… whoah! So sad and Way wrong were a form of buggin’! This could work! But one does not simply walk into a location called “Been Buggin.” Maybe get there via boat. This prompted all kinds of changes. I eventually pulled Lake Lap from the main area to the island to the side, and I figured the boat could go two places. So maybe if I hadn’t gotten to that party, VVFF could’ve stalled or been lesser. Or less frustrating for some–I knew these were slang, and I don’t think I had Dean Duggan be explicit about that in the initial comp release. (He didn’t come by til later. Before, it was just an abstract puzzle.)
Dean Duggan actually didn’t come by until later. I forget what you were doing there beforehand.
The Real Rear was another one that seemed too plain once I saw it. Sometimes you look so much for a tough idea that you ignore easy intuitive ones. But I think it started from when I had the Beer Bull and DEAR DULL/NEAR NULL as a point-scoring command and at first I worried things would be too similar–but Real Rear just had so many rhymes. So things grew in leaps and bounds, but being impatient for the next leap never worked.
Other stuff that took too long to hit me on the head was including the stark store before the Mystery Mall. Of course malls have stores! But the map was too linear at first, and the mall was west of the cross. That seemed too close.
Fleshing out details
I had fun imagining the responses to BURY BILE as the game went through. At first, you couldn’t just say it, you had to live it and be a worthy hero. I wanted to play this angle more, and for humor. I’m not sure if it worked, and unfortunately I forget to write down some of my ideas because I enjoy poking at them in my head, but I was thrilled I was able to allow the player to guess the winning command before scoring a single point. I’d played a lot of games where you could get a good ending, then replay and do something at the start to unlock something else perhaps even better, but I am not aware of any game that let you guess what to do right away and have to hold onto it.
And I suppose there’s some emotional component to all this. If you’ve ever heard “Ahh, deal with it,” over something you were upset about–well, not being able to BURY BILE effectively until you’ve fought through that kind of flips that advice on its head. So I was pleased with that.
Other stuff joggled around until the final day. I was curious why my observant testers hadn’t found more bonus points, and then with a manual playthrough, I realized that’s because those bonus points were mostly or completely unobservable. I’m glad I didn’t put too much time into them, but on the other hand, I wish I’d had a “play-dumb-through” before then. Maybe I should do it more–I fixed up a lot of narrative stuff I had meant to.
But I’d left holes it wasn’t really possible for my testers to plug. There were holes behind holes. Some puzzles that were horribly clued at first, so my testers had to use the walkthrough, which meant they couldn’t use their energies for more interesting bugs. This happened with COUPLE CAPS, which was badly clued at first, so nobody tried it after getting all three caps. I clued it much better in response to testers having trouble, and the result was–COUPLE CAPS right after getting all three caps turned up a bug where you were sent back to Lake Lap instead of Been Buggin’. Since my main sanity-check walkthrough didn’t COUPLE CAPS until the very end, and it was easier to find, well…ouch!
So this is a cautionary tale about how bad hinting doesn’t just annoy the judges, and even if you fix the bad hinting late on, there’s still an increased chance of bugs popping up, because you never gave your testers a chance to find things. I know I did a lot of automated testing which helped a lot, and I think that left my testers freedom to be creative. I suppose I thought I could skate a bit with walking through my own game, since I was able to run scripts. I don’t know what I did with the time I saved. Probably wasted it somewhere less productive where I came up with fewer ideas.
That’s a big pitfall of testing. If something turns up, oh no, I messed up, but if it doesn’t, I feel like I wasted time instead of saying–yeah, that’s OK, I don’t need my testers to check that. It doesn’t feel like as much of an accomplishment as winning some click-around game I won before, but it is a far better use of time. You can certainly fear finding too many bugs (all the work ahead) or too few (time wasted.)
I know I certainly didn’t run some simple tests I could’ve because they seemed boring and probably would not turn anything up. I keep forgetting that if they pass, it’s one less dumb bug that slips through, and it’s easy to test later. If they fail, that’s one less annoying thing for testers–and it’s probably a bug I’m better positioned to find than they are.
So I spent a lot of time in-comp creating the test scripts I could and should have created earlier. It was rewarding when I did so.
Short version: use it, if only to track issues and keep a backup of your code. you don’t need to know super-technical things.
GitHub allowing private repos helped me a lot. I like BitBucket, but GitHub tracking daily streaks helps motivate me a bit more.
And with VVFF, I did things I hadn’t done before, like squashing commits. I’d branched before with Ailihphilia, but I did so more this year.
So yeah. Only things that are broken are fixed in-comp.
I quickly got useful feedback in-comp for things to do. I didn’t really look at all possible rhymes, because that was more a feature, so I wound up with fifty to add to my table of good guesses. That went/will go into the post-comp changes, along with changing the vapor vile to a vapor vial. I’d written that about noon of the deadline date, and I just forgot it with other stuff to do, which was more important anyway. I realized making the player wait to get the big bag was silly–I wanted to avoid something that wasn’t worth avoiding. I added a few death rooms. I forgot the post-game option to show all random text, but that wasn’t critical–I included the source.
Afte nailing down the main bugs, I discovered a bug where guesses made the leet learner light up erroneously. Someone else found a bug where you could have -1 good guesses til your next lump charge–again due to a last-minute fix where I gave you 2 points for some guesses and only changed = to >= in one place. Someone else noticed the Gear Gull wasn’t visible in Here Hull–it took me two tries to understand I’d let the player go to Here Hull when I thought I’d blocked them. I realized I wasn’t rejecting homophones as specifically (“Hey! You’re super-close!”) as I thought I was. I realized the GO TO command had obscure bugs.
These all required some testing and thought, but I think they are exactly the sort of in-comp bugs you should fix. I in fact dropped work on some of the guess-processing code, which may have confused the player.
The only thing that makes me cringe, though, is that I had these rules
And they never fired because I didn’t disable the “block eating/drinking/wearing” rules. It’s something I thought I checked, but I didn’t. You can fool yourself that way. This doesn’t destroy things, and I’m glad I fixed other bugs instead–they were more critical to the story and puzzles. But if I’d run a test script for weird verbs, I’d have knocked things out easily.
Probably the main thing I got tangled up with is that I kept the comp branch as the main branch, as I created other branches for various issues. This seemed natural, but looking back, the comp fixes were localized bug patches, and so those should have been in a branch. Now I know, and if you use source control, now you know. I was happy with the experience learning to make branching and merge conflicts easier, but next year I don’t want the extra work. It’s not much, and GitHub’s online merge conflict resolver is nice, but merge conflicts are tricky and worth avoiding.
However, once voting closed, I felt relaxed enough to start with those merges. Verifying them uncovered some bugs I maybe should’ve seen earlier. I’ve gotten through all of them except one where I meant to add 50 good guesses and still have a pile more to add. I didn’t even want to look at the merge conflicts there.
With some general guidelines for in-comp changes, and with things to delay for post-comp, well, I think I already have a bunch of interesting features. More death rooms. Another bonus point. Stuff like kicking you back to the Fen after the Beast Boss beats you up. This seemed too restrictive at first, but it also reinforces that you need to visit the Real Rear, and it prevents the awkwardness of wandering around the Beast Boss.
I think the big thing I need to scour my notes for is a small narrative that builds as you score more points. For instance, if you trip 10 points, you remember insults from your past, and these build until recollections become more positive or you use double rhymes to deflect others. Maybe it’s not enough story for some, but I hope anyone who is curious and doesn’t want to replay is able to at least open up the tables file to see the narrative and enjoy it.
I think this may make up for how I didn’t make the File itself a part of the game. I meant to have it hanging there comic-menacingly, but I don’t think it did. So I’d love to tune that up!
The post-comp releases are targeted for 11/22 (general technical) and 12/12 (narrative.) Because of course they have to be.
[spoiler=thoughts on difficulty]
I’d rather have my game not give everyone a solution on a platter. Sometimes I err by making things way too tough. Many people pointed out that the dialect made things tricky. I hoped that giving people a cheat item after enough good guesses would keep this in check. I know, for instance, Been Buggin probably should’ve mentioned that you can brute force your way to peace of mind.
I was also disappointed some smart people got stuck on the first puzzle, not realizing you could just type GET GOOD. As a programmer, you obviously want to avoid this sort of thing, and I should’ve used progressive cluing as HHGG did with the dark. Though maybe not quite so snarky.