Meet Logike 🔵🔺🔶

This fall, I started building a puzzle app called Logike. It’s a game that focuses on building logic skills, and from a programming and design perspective, it’s also the most challenging project I’ve ever brought to fruition. There’s a lot to talk about, so I broke it down into a few parts 😉

TLDR: If you just want to try Logike, you can here!

The story

With few exceptions, most of the memories from when I was very young are faint at best. One such exception relates to when I was in Kindergarten. We had a lot of “free play” time, as you do when you’re 5 years old, and during that time we could chose from a whole bunch of different activities. Actual examples include: making necklaces with beads, taking apart old broken motherboards using pliers and hammers, or in the more educational department, puzzle games to develop logic skills.

My favourite game involved placing coloured shapes on a grid in order to satisfy a logical conditions on the supplied cards. They’d start out really easy and get progressively more difficult, to the point where they were no longer feasible for the average 5 year old. It was a lot like Sudoku, but the difference was that this game mixed and matched and layered many different and nuanced types of logic. Sudoku games can be solved with the same algorithm each time, whereas the one to solve this game was far more complex and varied.

child playing with legos

Here’s a picture of a kid playing with legos, which will be replaced with a picture of ME playing with legos, once my mom finds it 😂  
photo by Kelly Sikkema

Fast forward twenty years and I’m looking for a project idea to help me learn front-end. I don’t remember what made me think of the puzzle game I played as a kid, but it popped into my mind and I went with it! No-one seemed to have digitized the game, and I realized that through code there were ways to take it even further.

What it looks like

There are two major things that the app lets you do: solve puzzles, and build them. Lets start with the part where the fun happens!

Solving Puzzles
an easy puzzle

Logike’s tutorial puzzle.

Solving puzzles is pretty straightforward: each puzzle consists of a set of logical conditions, and it’s up to you to move coloured blocks onto the board so that all of the conditions will be true.

However, the conditions can become quite complex

The logical conditions for a moderately difficult puzzle.

The logical conditions for a moderately difficult puzzle.

Or downright difficult, like this one…

The logical conditions for a difficult puzzle

The logical conditions for a difficult puzzle

Instead of telling you where specific entities (the coloured shapes in this case) need to be, this difficult puzzle only tells you about entity properties (colours, shapes) that could apply to a slew of different entities!

For now, the logical conditions are:

  • Some entity or property is here.
  • Some entity or property is not here.
  • Some entity or property could be here.
  • Some entity or property is/isn’t/could be here relative to some other entity or property.

Additionally, the grids for the logical conditions can also be smaller than the puzzle board itself, meaning that a 2×2 condition could theoretically apply to one of 4 places of a 3×3 board.

Building Puzzles

As for the puzzle builder, it’s a lot less mature than the rest of Logike, but functionally it does what it needs to. Initially, I wrote all the puzzles by hand in one massive JavaScript class. It was great for prototyping, but it wasn’t ideal for production, so I refactored all of the puzzles into JSON files. This is what one logical condition looks like in JSON now:

one logical condition, in JSON

one logical condition, in JSON

Imagine writing dozens of chunks of code like this by hand, and trying to visualize a puzzle with them. It just isn’t pleasant, so I made a GUI (Graphical User Interface) that writes the JSON for you! 🎉

The builder puzzle

The puzzle builder.

I talked about entities and properties a bit earlier, but it’s really in the builder that they start to shine! By abstracting the different parts of the puzzles above, I realized that the code I was writing could be applied to far more than just coloured shapes.

In the first part of the builder, you can chose a different set of entities than the classic shapes, and you get to chose the size of the puzzle as well! Technically, there’s no maximum size for the puzzle, but it’s currently limited to a 5×5 grid until I smooth out the design to accommodate larger ones.

The logical condition builder.

The logical condition builder, being used with the “animals” entity set.

The most important part of the builder is the part that writes the logical conditions. Each one is comprised of a selector (the entity or property you’re referring to in the logical condition) and a grid filled with conditions. The tool lets you visually build each grid, and see the puzzle as it will appear when someone’s trying to solve it.

When you’re done building a puzzle, it’s time to name it and download it!

When you’re done, you come up with a clever name, rank the difficulty of the puzzle, and the download the resulting JSON. There’s currently no user accounts, or database to deal with storing user-generated puzzles, but this is a good first step. A teacher could technically build a bunch of puzzles and send them to their students, who can load them up on the puzzle selection screen.

Under the hood

In the past, I would go into a programming project head-first, and start coding immediately. While this would be great for my short term motivation (features being built, and fast), in the long run it led to depressingly messy code, and made for unsustainable projects. Logike was the first project where I actually took some time to work on the architecture, and boy did that pay off!

Part of the architecture for Logike.

Part of the architecture for Logike.

This planning allowed me to build the app in the most efficient way possible, given my current skill level. It also made it possible to shrink my puzzle files down to sizes measurable in bytes!

The whole thing is built in React, so it’s a mix of HTML, CSS, and JavaScript. Additionally, anything that isn’t part of the core application logic is JSON. All of this lives on a free Heroku server, at least for now.

As far as technologies go, there’s not much fancy programming witchcraft going on, but that doesn’t mean that the project itself is simple. There were a bunch of technical challenges that had very little to do with the tech used, the biggest one was making the code sufficiently generic.

I could have taken a bunch of shortcuts and just hard-coded everything based on the coloured shapes and left it at that, but then I’d be missing out on the chance to make a much more powerful too. So I ended up with a bunch of classes like this one:

// an Entity is the main element that is manipulated in the puzzle.
// it has properties, a name based on the properties,
// a common name which may differ from the name, and an image
// ex: red square, potato, JK Rowling

class Entity {
    constructor(commonName, properties, img) {
        this.properties = properties; // an array;
        this.name = Object.values(properties.map((property) => {
                return property.name
            }
        )).join("-");
        this.commonName = commonName; // for display purposes ONLY
        this.img = img;
    }
}

export default Entity;

With all this abstraction, consistent and meaningful naming becomes super important, and at a certain point collisions can occur between your app’s logic and the programming language’s reserved keywords and pattern names.

  • Entities could have been called objects, but Object is a pretty important keyword that’s part of JavaScript.
  • Properties could have been called parameters, or attributes, but parameters are found in JavaScript functions, and attributes are found in HTML tags. Technically, in React, props stands for properties, but no-one writes it out the long way, even in their code, so this was the safer option.
  • Selectors are used in CSS, but at least they behave the exact same way in Logike’s logical conditions, and it wasn’t a reserved keyword.

The second biggest challenge was validating the pure logic found in the puzzles.

This is a bit of code that validates whether an individual logic cell in the logical condition is being respected.

// returns false if the selector is found in a place it's not supposed to be. Otherwise returns true
    const validateLogicCell = (selector, ansCell, logicCell) => {

        var matchesSelector = false;
        // checks to see if the answer matches the selector
        if (selector === ansCell) {
            matchesSelector = true;
        } else if (selectorIsPartial(selector, entities)
            &&
            ansCell.includes(selector)
        ) {
            matchesSelector = true;
        }

        var selectorCanBeHere = false;
        if (logicCell == null || logicCell === "empty") {
            selectorCanBeHere = true;
        }
        var selectorIsHere = false;
        if (logicCell === true) {
            selectorIsHere = true;
        }

        if ((matchesSelector
                &&
                (selectorCanBeHere || selectorIsHere))
            // matches selector in specific cell, therefore the cell needs to contain true or null
            ||
            (!matchesSelector
                &&
                (!selectorIsHere || typeof logicCell === "string")))
        // doesn't match selector, therefore the cell must contain false or another selector
        {
            return true;
        }
        else {
            return false;
        }
    };

Does your head hurt? 😂

Validating that a blue circle is in the top-right cell is easy. Validating that and every other thing I’ve mentioned is a whole other story, and likely makes a terrifying looking flowchart!

How to try it

The puzzle app lives at logike.confusedretriever.com and eventually at logike.app once I figure out how SSL works.

It works on desktop or mobile, though there’s some features that are restricted in the puzzle builder on iOS for the moment.

Let me know what you think, and if you make some cool puzzles be sure to share them with me! 😄

What’s next

What I’ve made so far is just the tip of the iceberg. I see a lot of potential with Logike, so I’d like to keep developing it.

Here’s the current to-do list, more or less in order:

  • Puzzle Builder design improvements
  • enable editing logical conditions
  • enable reordering logical conditions
  • Persistent save state after end of browser session (accounts + database?, Cookie?)
  • Ability to share puzzles without downloading/uploading.
  • JSON V2 (remove ALL duplicate data and add IDs to entities and properties instead)
  • more robust entity validation (unique names that aren’t based on properties)
  • Creating new puzzles
  • Tweaking old puzzles
  • improving entity set images
  • Fixing nasty iOS bugs
  • Fixing toast jitters
  • Improve test suite
  • Validation improvements (duplicate entities, more robust property selection)
  • Puzzle builder validation (to give feedback preventing impossible puzzles)
  • Ghost images to fix sizing issues
  • Design improvements to support large puzzles
  • Shuffle-able logical conditions
  • Onboarding flow
  • Entity set builder
  • URLs that lead to specific parts of the app (builder, specific puzzles, etc)
  • logike.app SSL

For now I’m taking a bit of a break from the puzzle app to work on Compass, but I plan on alternating between the two projects until I feel like Logike is pretty mature.

Phew! 😌 That was a lot!

Thanks for taking the time to give this a read, and I’ll keep posting updates here whenever I start chipping away at the next next Logike release 😊

Until then, keep being awesome! 🌠

Leave a Reply