Replicube Let's Play: Solving 18 Puzzles That Draw Voxel Shapes with Lua Code

Translated from 日本語

Open on YouTube ↗
Overview

Replicube is a stage-based puzzle game in which you recreate a given 3D object. Rather than placing voxels by hand, you place them by writing a program. In this video, the streamer works through the first tutorial puzzle set of 11 puzzles and the 7-puzzle bonus set that arrives next. Rather than aiming to clear every puzzle, the plan is to stop after finishing the two sets. Throughout, the streamer prioritizes writing readable code over squeezing out a better score.

15 min read
0:23

How the Game Works: Take Coordinates, Return a Color

According to the tutorial, the game has you place voxels in 16 colors into a Minecraft-like voxel space. "Voxel" is a coined word meaning a "pixel with volume." You place them using code: write code that always returns white and the whole space fills with white; return purple and it's purple; return blue and it's blue. In other words, you write code that takes each voxel's coordinates and returns the color value to place there. The streamer says, "My head's already starting to hurt," but adds that since they've been playing nothing but combat games lately, a peaceful game like this is nice once in a while.

In the game, you receive an email from the administrator of a place called Cubenet, and the flow is to solve the basic puzzle set attached to it. The target shape is shown at the top of the screen, and the shape drawn by your current code is shown below. Scoring seems to include code size and execution speed, but the streamer saves optimization for "dessert later" and decides to focus on readability first. As the reason, they say, "Code is basically written for humans."

1:47

1-1 to 1-3: Changing Colors and Conditional Branching

In the first puzzle, reading the comments in the existing code reveals that only the returned color is slightly off. Changing PURPLE to RED clears it.

The second puzzle requires coloring the shape in two colors depending on position. Since variables x, y, and z representing the coordinates are provided, the streamer solved it by writing an if statement that returns DARKBLUE if y is 1 or greater, and ORANGE otherwise.

The theme of the third puzzle is comparison operators. The streamer notes that in this language, inequality is written as "~=", and predicts they'll be using it soon. The puzzle itself follows almost the same pattern as the second and can be solved with a condition of "y is at least such-and-such." They mentioned an alternative solution that doesn't use comparison operators, something like return GREEN - (y + 4) // 3 * 2, but didn't adopt it, saying this kind of code tends to confuse readers.

3:55

1-4 and 1-5: Making Things Transparent

From the fourth puzzle on, the x and z coordinates come into play in addition to y. The initial code already has a rainbow color scheme in place. It reuses the y-coordinate value directly as the color code, so the color changes to the next one with each level up. However, all this puzzle requires is making part of the object transparent. According to the comments, returning nothing, or returning 0 or EMPTY, makes a voxel transparent. The streamer cleared it by changing the initial code's condition "when x and z are 2 or greater" to "when they are 0 or greater."

The fifth puzzle has almost the same structure, and they solved it by writing the condition "when x, y, and z are all 1 or greater."

5:42

1-6: Drawing Symmetrical Shapes with Absolute Values

The sixth puzzle introduces the abs function. The comments say it's a function that returns the absolute value and is handy for drawing symmetrical objects. This time, the target shape is symmetrical about every axis.

The streamer first focused on the z-axis, setting the thickness by returning nothing if the absolute value of z is 2 or greater. You could also write "2 or greater, or -2 or less," but the streamer thinks using the concept of absolute value makes for easier-to-understand code. For the remaining hash-shaped form, they also used absolute values to create the vertical and horizontal bars, then joined them with a logical OR to finish. Since symmetrical structures look likely to come up often, the streamer expects to use absolute values a lot.

6:49

1-7: Reading the Error Message and Fixing It

The seventh puzzle shows an error from the start. The streamer first reads the error message. From the text "LUA_ERRSYNTAX," they guessed that the language is Lua. An end to close the if on line 10 is expected, but an if is written on line 13 instead. In other words, an end was forgotten.

Fixing that doesn't finish the job, though: there was still a spot where a box that should be red was GREY, so they changed that too and cleared it. Here, the streamer remarks that opportunities to write code from scratch are actually rare, and that in practice the ability to read other people's code often matters more.

7:45

1-8: Solving the Free-Form Puzzle "sushi?" with Chessboard Distance and a Table

As it turns out, the eighth puzzle makes you write code from scratch. The puzzle is titled "sushi?", and the streamer senses an "incredible sensibility" behind it. Since it seemed they could build the shape however they liked, they decided to color it red, white, and green according to distance from the center.

The distance used here is known as chessboard distance. It's the number of steps a piece that can move in eight directions needs to reach a square, and the streamer explains it's a concept they occasionally rely on in roguelikes such as Shiren the Wanderer. This distance is easy to compute with a max function, so they opened the Documentation tab to look it up. The documentation has four chapters: chapter 1 is an overview, chapter 2 covers drawing in detail, and chapter 3 seemed to have the information they were after. There, they confirmed that you can define variables, that operators like + and - are available, and that there's a max function.

As for converting to red, white, and green, the streamer intended to brute-force it with if statements if there was no convenient feature. As a "fun implementation" idea, they also mentioned taking 0xb17 — 7, 1, and 11 lined up in hexadecimal — and right-shifting it according to the distance.

At this point, as an aside, the streamer mentions that plugins for OBS, which they normally use to record videos, can also be written in Lua. They once wrote a simple plugin that automatically generates YouTube timestamps, and that may be the only time in their life they've touched Lua.

For the implementation, they first took the maximum of the absolute value of x and the absolute value of y to get the chessboard distance from the origin. This time it would be 0, 1, or 2, so they needed a mechanism to convert it as 0→7 (red), 1→1 (white), 2→11 (green). Having glimpsed the word "table" in the documentation, they guessed an array-like structure was available. They wrote an array literal with square brackets, which works in many languages, but it didn't work in Lua. So, reasoning from the name "Table" that it probably used curly braces, they rewrote it, and it almost worked. However, the colors were off by one, revealing that Lua indices start at 1. After adjusting for that, the sushi was complete.

The elements used were a bit complicated, but the streamer says that looking at the code, it seems surprisingly concise. They add, however, that usually the only person who thinks so is the one who wrote it.

11:25

1-9 and 1-10: "Where Not to Paint" and Nested ifs

The ninth puzzle is close to a controls tutorial, encouraging you to move the camera with the mouse and examine the shape carefully. It's an open-topped box, and you just need to return BROWN when x or z is ±3, or when y is -3. Excluding the case where y is +3 leaves the top open. Again, they used absolute values. The comments seemed to want you to express it in terms of "where not to paint" rather than "where to paint," but the streamer decided either way was fine. Having put so much effort into the previous sushi, they found this one a bit anticlimactic.

The tenth puzzle has, in the streamer's words, a Google Chrome-like color scheme, but there's no distinctive pattern to the arrangement of colors. Since the comments also seemed to expect nested ifs, they wrote straightforward conditional branches. When y is 1 or greater, return GREEN if x is 1 or greater, and ORANGE otherwise. When y is not 1 or greater, return BLUE if z is 1 or greater, and RED otherwise. The streamer wrote it while rotating the view to make the axes easier to see.

13:34

1-11: A Double Spelling Mistake and How the X Shape Works

The eleventh and final tutorial puzzle also has a bug from the start. According to the error message, line 31 references an unknown variable called "colo." Guessing this was a typo for "color," they fixed it. But that alone only drew part of the staircase. Reading further into the code, they found a spot using the British spelling "colour," and fixing that completed it.

As for why this code can draw an X shape, the streamer worked out that it's because it uses the expressions x==y and x==-y. Using linear functions as equalities lets you draw shapes like this. Here, the streamer says, "Well, that's probably knowledge that has nothing to do with me."

14:40

2-1 to 2-3: Drawing Diagonal Lines with Equalities

After finishing the tutorial, a welcome email and a bonus set of 7 puzzles arrive from the community.

The first puzzle of the bonus set immediately throws in a linear function problem — right after they'd said it had "nothing to do with" them. It's the line y = -x, which in Lua can be written as x == -y. A == comparison returns true or false, and in Replicube these are drawn as white and nothing, respectively, so simply returning the comparison result cleared it.

The second puzzle is also a diagonal line, but it needs to be narrowed down further by the z coordinate. They first drew a plane with x == y, then joined the condition x == z with a logical AND to complete the shape. To make the return value GREEN or nothing instead of true/false, they appended and GREEN at the end, taking advantage of short-circuit evaluation.

The third puzzle is a symmetrical version of the second, so it could be solved just by changing the expression to use absolute values. Computing abs(x) twice is a bit wasteful, but since it isn't a slow operation, they decided not to worry about it.

17:00

2-4 to 2-6: Making Patterns with Modulo and Addition

The fourth puzzle introduces the % operator, which returns the remainder of a division. The initial code takes the remainder of y divided by 3, distributing values to 0, 1, and 2 in turn. Looking at the target shape, it seemed to convert the value of x to 0 or 1, so they guessed that using the remainder of division by 2 would work. It was off by one cell, so they adjusted by subtracting 1 from x and cleared it.

The fifth puzzle is a checkerboard. First, to make it a plane, they tried to write logic returning nothing when the value isn't 0, but initially wrote the condition using z and then changed it to y. The RGB arrows correspond to XYZ, but they say they sometimes forget and get confused. For the pattern, they had "sneaked a peek" at the fact that adding with return x+y, as in the second puzzle's initial code, produces diagonal stripes. Wrapping that with % gives a checkerboard. At first it came out pink, so they changed it to return black and cleared it. They showed that if you want to avoid conditional branching, it can also be done with an expression that converts the remainders 0 and 1 into 1 and 3 for white and black, but the streamer notes that this makes the conversion to colors very hard to follow.

The sixth puzzle is a diagonal rainbow pattern. Using the fact that addition draws diagonal stripes, they first added x and y. This gave a roughly similar look. However, while the streamer's code returned 0 at the origin, the target had LIGHTGREEN there, so they added LIGHTGREEN to match. Finally, they returned nothing when z was anything other than 0 to adjust the thickness, and finished it.

19:55

2-7: A Four-Legged Table and Organizing with Functions

The final puzzle is a classic four-legged table, made entirely of BROWN. Since only the shape needs thinking about, the streamer followed the real-world assembly process and handled the tabletop and legs separately. Having found that comments can be written with --, they added comments too. The tabletop is just a plane that returns BROWN when y is 1. For the legs, they first limited the drawing range to y of 0 or less to set the height. The positions are symmetrical, so as usual they used absolute values, drawing only when the absolute values of both x and z are 2. They joined these conditions with and, returning BROWN when all are satisfied, and completed it.

Still, the streamer felt a little reluctant to let go and decided to tinker some more. According to the documentation, it should be possible to define your own functions, and they wanted to try that. The current code wrote return BROWN twice even though everything is BROWN, so if someone said, "Actually, could you make it WHITE?", it would mean doing the work twice. So they rewrote it with functions that deal only with the shape, deciding the color in a single place.

Specifically, they defined an isTopPlate function that returns whether a coordinate is part of the tabletop and an isLeg function that returns whether it's part of a leg, and wrote "return BROWN if it's the tabletop or a leg." They say snake_case is probably more common for Lua function names, but since the screen is extremely narrow this time, they went with camelCase just to be safe. Although function calls carry some cost, the streamer judged it wasn't a problem, since drawing a static object doesn't demand much performance. On the other hand, they note that since the game apparently also lets you create animations, it might be worth paying a bit more attention to that in such cases.

22:52

The Streamer's Verdict

Having finished the two puzzle sets, the streamer evaluates Replicube as follows. At first it gave an unapproachable impression, but the UI and introduction are very thoughtful, and it's a lot of fun once you play it. It's an excellent puzzle game with a variety of perspectives and solutions, and it can also be enjoyed as a way to spark interest in programming. It also connects with mathematical fields, and they concluded that they found it a game that can be enjoyed on many levels.