Two postmortems for two not-quite-board games (Fourbyfouria, Walking Into It)

First, the process of creating two (relatively short) entries for IFComp:

I had much grander plans for two related games at the end of 2020. I’m not going to tell you what they were, because they also conflicted with something else I noticed: a hundred games is a lot, and I’d like, if I could, to make something clearly shorter than Under They Thunder! The two games in question are still worth writing one day, but I’m sort of glad they never gained full traction even though I wrote a lot of notes. I still feel like I was missing the big picture–or at least the mid-to-big picture. I know how they start and end. I have a few good moments in the middle. I haven’t pulled them together. Nevertheless, my goal (not just due to laziness) was to write two games shorter, but hopefully more memorable, than my 2017 entry The Cube in the Cavern. Each one actually grew from another competition, and each grew from a relatively famous chess puzzle. It’s about three pawns breaking through against three pawns. You can do it by trial and error. Don’t let the thumbnail fool you.

The idea is this–something that looks simple or boring actually has a surprise ending, and you can only see it once before it flips to from “what the heck” to obvious. Now I actually implemented this specific puzzle long ago in a minor puzzlefest game for the Apollo album. It was a technical exercise for myself. But I wanted to do more, and I didn’t want to do just chess. This had been on my mind a lot.

It wasn’t until my bigger games fell through that I went with the smaller ones. I think each has enough a-ha moments to be a neat sort of game. So I present the separate postmortems, as well as thoughts on trying to write two similar games at a time. Also, they got kind of long, and I couldn’t decide whether to place them in this topic, or another one, and how much to put behind a “details” tag.

4x4Q postmortem

Walking Into It postmortem

Perhaps the oddest thing about these two games compared to my usual fare is that you don’t really need a map for either. Cube in the Cavern could be visualized, but you still needed to map it out. WII has no rooms, and 4x4’s is (apart from the trivially mappable introductory areas) just, well, a 5x5 board. So I always wanted to write a roomless or quasi-roomless game, and I sort of got both, since you can just type a3 or c5 or whatever into 4x4Q.

It was tough to switch gears between games and programming languages. I’d hoped one would provide a vacation/change of pace from the other, but due to me starting in 4x4Q later than I usually do for IFComp and some disappointment my bigger game didn’t fall into place, I was always a bit distracted from each game. (Also, I felt weird writing 2 chess games in 3 months.) Things like reading and programming and general writing notes provided a break from each other, so I thought different languages would, too. Not so much, though. I think the big problem is: Python is interpretive, Inform is compiled. So I kept having to look for quantitatively different errors as I engineering-tested.

The games’ (relative) simplicity also may have made for a mental snafu, too–I alternatively worried I had bugs and also that I hadn’t added enough bells and whistles to keep things entertaining. And the tutorials were another thing–people know Tic-Tac-Toe, but for chess, how much is enough without potentially spoon-feeding the reader and annoying them that way? So I thought I would have two similar entries in terms of execution, but they turned out to have more differences than I’d thought.

I wasn’t expecting a chess-based game to get a ton of reviews, and if you told me the review totals, I’d have been pretty happy–but I’d have assumed WII had gotten fewer reviews. So that made me quite pleased people were willing to give Python a shot. I suspect one reason 4x4Q got so few reviews is that the puzzles are a straight shot. People may concentrate so much on them, they don’t want to bother with the narrative. I can’t blame them.

Looking at other people who submitted multiple entries this year, I think they made good choices. They wrote about stuff that had probably been on their mind for a while. The Dead Account and Weird Grief crossed over with characters. And Then You Come dealt with memories from youth, Off-Season at the Dream Factory with a favorite book, and yes, there’s that third entry, too! Both authors used similar engines–though Adventuron is obviously a different beast from Inform!

My efforts were similar to each other mainly by being abstract, and those similarities weren’t enough to avoid a bit of culture shock when shifting gears. But I wished I’d been able to add more story. Still, I think all three of us should be pleased with our efforts, and I recommend anyone who wants to submit 2 games either 1) make them similar or have clear crossovers or 2) have had them both planned for a long while.

In terms of placing, I was hoping to have a composite place less than or equal to (# of entries + 1). But I really do think competition entries have gotten stronger and more robust over the years. I’m happy with what I have.

13 Likes

Things like reading and programming and general writing notes provided a break from each other, so I thought different languages would, too. Not so much, though. I think the big problem is: Python is interpretive, Inform is compiled. So I kept having to look for quantitatively different errors as I engineering-tested.

I’m curious as to why you chose Python specifically for "Walking Into It. " I know very little programming, but why not something that could create an online game like Javascript?

That’s a great question! I don’t really know JavaScript in the way I know Python, but it’d pretty clearly have advantages. You could adjust the colors and so forth and have a sidewalk-texture.jpg background for the page.

The main reason I went with Python was that I knew it well, and I wasn’t confident in my ability to learn enough JavaScript to do what I wanted. I thought about web-based stuff, but the big sticking point was building the database of kid-response moves and dialogue–in retrospect, the kid didn’t have much to say. However, I had enough of an engineering project in Python to be able to detect rotations and flips of the board. For instance,

x|o|
-+-+-
 |x|
-+-+-
 | |o

Has 8 different positions that are similar/identical by rotation/flipping. I wound up not using a minimax algorithm so I either had to write in all possible rotations manually, or I had to write a function saying “OK, we have a board layout, and we check to see if it’s a rotation of something in the known database. If so, make your move on the known database, then see where it’d appear on the rotated/flipped board.”

This is clearly doable in JavaScript, but I got/had a much better handle on it in Python.

Also there was probably some stubbornness/carryover from my failed EctoComp petite mort project (that was overambitious) and since I’d already gotten a good basic chunk of Python done, I just kept it there. I didn’t have the confidence I could learn the JavaScript I needed/wanted to. But Python seemed like a sure thing.

I’d be interested in learning more detailed JavaScript and also maybe to see if Twine can do this sort of thing. Perhaps I should be more aggressive making that time.

2 Likes

I briefly looked into the code earlier and saw the board rotation thing.

It’s still quite a bit beyond my programming knowledge, but I imagine it’s a lot easier just to check whether the game has been won or lost compared to what your game involved, right? I assume you had to check every stage of the game, which means there are a lot more possibilities, and that’s why the rotations were needed?

Doing it with Twine sounds like a nightmare… I think you’d have to mix macros and actual JS. I can’t think of anything in Sugarcube that would be useful except for the ability to replace page elements, which is already in basic JS and Jquery.

If you do get around to it, I’d be happy to provide a CSS design for it.

When I did Tic Tac Toe in Javascript, I didn’t bother doing the rotation/mirror thing. There’s only about 100,000 positions, after all. Once I implemented look up tables for the first two moves, the rest comes quickly enough to be usable without too much time.

If I remember it right, I had to implement my own stack for the recursion.

@PBParjeter thanks for the technical overview and also for the kind offer! Yes, I think it would make WII a lot more accessible, but there are so many other projects. I could picture myself leaving you hanging. Who knows–it might be a neat back-garden game.

Well, yes and no, if I understand the question right. Checking if the game has been won or lost comes first, as does having the kid win if it’s available. But you also have to check that the game was won with the moves in the right order. I think there are cases where I had similar winning positions where 1 arose from a fork and one didn’t. So I needed to check if the kid had a fork at some point. If I did, I set a flag, and if you successfully blocked one path the next move, it was a “real” win. If not, the kid complains.

another reason why the position wasn't enough

I thought it would be easy, but there is in fact a case where starting on a corner square transposes to starting on an edge square. This almost busted the game for me, because

  1. there was only 1 way to win with you starting in the corner (by “way to win” I mean position when the kid achieved a fork, or rotation thereof)
  2. there were (thankfully) 2 ways to win with you starting on the edge

This case was probably the most intricate to program for! It also allowed me to offer a little more (very basic) cooperation and discussion of basic mathematical concepts (rotation, symmetry, transitivity) if you discovered it.

(Hm. I should put this in the postmortem, as I don’t think I fully detailed that.)

And if I didn’t understand the question, let me know!

I’d also add that if you feel it’s beyond your programming knowledge, well–based on your observations about why a twine port would be tricky, you’d figure it quickly once you saw it.

There's no deep magic, but it requires thought

At its base, it’s just a matter of swapping array elements and seeing if they still work. One of the first things you see in group theory (“Wait! Stop running!”) is the Quaternion group - Wikipedia, which here is just “how many ways can you rotate the board?” (Note: sometimes the board has its own symmetries, which make it easier.)

So you can just use brute force calculation.

But if we consider the board as an array [0, 1, 2, 3, 4, 5, 6, 7, 8], with 0 in the upper left, going right then down, we can manually calculate where each number moves, and put them in an array.

Or we can just say haveFor instance, horizontal flip would be (ary[2+3x], ary[0+3x]) = (ary[0+3x], ary[2+3x]), vertical would be (ary[6+x], ary == ary, ary[6+x]) for x from 0 to 2, and the diagonal case is a bit trickier, but you flip 1/3 2/6 and 5/7.

for x = 0 to 7 inclusive:
    new_array = list(old_array)
    if x % 2: new_array = diagonal_flip(new_array)
    if (x>>1) % 2: new_array = horizontal_flip(new_array)
    if (x>>2) % 2: new_array = vertical_flip(new_array)
    (calculate game state number from new array, where it's the sum of (array entry x) * (3^x))
    (see if game state is a number that can be acted on)

@ramstrong

Yes, that’s a good approach. I suspect I didn’t implement everything perfectly. Though in this case I have to account for how it’s not enough for the kid to win. They have to win right. So the database of moves seemed to work best for me.

I wanted the kid to have a response for every move that might pop up. In retrospect, I think with some thought I could’ve based the kid’s response on the possibilities still left in the position. (For instance, when it’s obvious early it’ll be a draw.) That would’ve been a neat bit of programming to accomplish. But you can’t do/have everything.