Example of a rotated image, corners have missing pixels because it’s not a circle.

опубликовали  arrow in my gluteus maximus, stringweasel, Nanogamer7, Conor_, Therenas, Firerazer

You remember April Fool’s day this year? Was quite a while ago already, but if you visited the subreddit on that day, you probably saw arrow in my gluteus maximus’s mind-bending video. If not, this week’s issue #44 of Alt-F4 will catch you up and then go over how exactly this dark magic presentation was achieved!

A new perspective on “A new perspective on trains in Factorio” arrow in my gluteus maximus

Four months ago I released a video called: “A new perspective on trains in Factorio”. If you haven’t seen it yet, please watch it before reading the article, as it won’t make too much sense otherwise.

Some people have reportedly experienced headaches after viewing this video. You have been warned.

Those who downloaded the mod linked in the description know that this was an April Fool’s joke. For those who didn’t figure it out: I’m sorry. A few people have asked me for details on how I made this video, so I decided to write up a quick explanation. Don’t try this at home.

I’ve seen some people speculating that I somehow extracted 3D models from the game. That’s not needed, it’s a simple rotation of what’s already shown on screen. While the idea might be simple though, the execution is a bit more complicated. The first problem you come across is that screens aren’t circles. When rotating, parts of the image gets cut off, while other parts such as the GUI are missing.

Example of a rotated image, corners have missing pixels because it’s not a circle.

I ended up applying my usual solution to recording problems for Factorio: use screenshots instead. Ingame screenshots are not bound by the limitations of normal screen recording. Therefore to capture the video I simply capture a screenshot every tick over a larger area than is normally visible. That way, no part of the screen is ever cut off when rotated.

The next problem is that the UI also rotates, this is not something we want. Screenshots also come to the rescue here. The take_screenshot() command has an option called show_gui. The trick is to take two screenshots every tick, one with the UI visible and one without it. If we take only the parts that differ, then we end up with only the UI, which we can then superimpose over the screenshot without UI. At least that was the plan. Various video editing problems made this unviable. For example, my video editor did not support lossless formats (that I could find, I tried a bunch). Small differences in encoding thus end up in the UI.

However, I found out that in recent Factorio versions the UI is no longer fixed to your player’s position in screenshots. It is always visible no matter what part of the map you take a screenshot of. So I looked for a colour far away from other colours that occur in the game. I settled on pink. And I changed the image of some concrete to be pure pink and turned clouds off. I changed the location of my UI screenshot so only the pink concrete is visible. This way I can get the UI by using a sort of greenscreen, or rather a pinkscreen in this case.

Pinkscreened UI

There were a few small problems with that though. Turns out there are transparent parts in the UI, namely the details panel that shows up when you hover over things with your mouse. It looked purple now. I ended up manually cutting it out of the UI, and nobody seems to have noticed.

Next, I created a small mod that played a sound whenever I started recording screenshots, this way I could sync up the in-game sounds with the screenshots. Similarly to how movie studios use clappers. The mod also wrote out the value of game.players[1].vehicle.orientation into a text file. I used this to calculate how much rotation is needed but smoothed out using splines.

I feared that these steps would not have been enough to make it believable. Taking that many screenshots slows down the game enormously. I was worried that it would be obvious that the footage was sped up by looking at my motion in-game. So I looked for a way to make the recording go faster. After recording the screenshots I encoded them into an mp4 with FFmpeg, so why not cut out the middleman and try to hook up FFmpeg directly to Factorio. Both encoding pngs and writing them to disks are expensive operations. So if I could skip these steps it would go a lot faster.

Step one would be to extract the raw image data (not to be confused with the .raw format) directly from Factorio instead of encoding it in a png. I couldn’t find an easy way to do it, but turns out a .bmp is very close. It’s the image data backwards with a header slapped in front. So this should be way faster to encode than a png.

Next to get this into FFmpeg without saving to disk first. Turns out FFmpeg has built-in features for piping images, so a named pipe with a .bmp extension did the trick. (Example command: ffmpeg -f image2pipe -framerate 60 -i - -r 60 -c:v libx264 -vf format=yuv420p -crf 1 example.mp4 -y < pipe.bmp)

Don’t forget to keep the pipe open between screenshots with a sleep command: sleep 10000000 > pipe.bmp, kill the sleep command at the end to let FFmpeg finish the recording. I did a test run at a low fps and … that’s not right! What’s going on here?

The problem is that images are getting mixed. Factorio rendering is multithreaded. While one frame is still being written to the pipe, the next one might already start. Essentially mixing the pixels of both frames together. The fix is to force Factorio to wait until the previous frame is rendered before starting the next one. This can be done with by calling game.set_wait_for_screenshots_to_finish() every frame. This however slows down Factorio enough that we no longer can call it real-time. Although I still have some ideas to speed it up, at this point I spent way too much time on this project already and decided to go with the tried and true method of using replays.

Factorio has this wonderful feature where it doesn’t check if the code of the mods used during the recording and playback of a replay are the same. So I first recorded a replay normally at a normal speed. Then I edited one of my mods to take screenshots every tick. Then, when playing the replay, Factorio will start taking screenshots. That is assuming the changes you made to the mod don’t change the game state.

Sadly due to using replays, I had to cut a few scenes. I was going to show how weird it feels to build things from a rotated perspective, but it turns out Factorio doesn’t save your mouse position in the replay. So in the replay, the UI follows your mouse at the time of playback, not the position your mouse was in when you recorded it.

Comparison how building looks normally (left) or when viewing a replay (right)

All in all, this was a fun challenge and I enjoyed confusing the Factorio players.

Contributing

As always, we’re looking for people that want to contribute to Alt-F4, be it by submitting an article or by helping with translation. If you have something interesting in mind that you want to share with the community in a polished way, this is the place to do it. If you’re not too sure about it we’ll gladly help by discussing content ideas and structure questions. If that sounds like something that’s up your alley, join the Discord to get started!

Spaghetti in automation games.

Written by Nanogamer7, edited by stringweasel, Conor_, Therenas, Firerazer

In this week’s issue #42 of Alt-F4, after previously investigating the games that influenced Factorio, we’ll now be looking at how Factorio influenced the automation genre as a whole, if that’s even a thing. Maybe it isn’t. After 7.5 million years of contemplation, Nanogamer7 has an answer, and it might surprise you.

The Best of Its Genre – The Influence of a Game Nanogamer7

A few months ago (in issue #34) I tried to find the origins of Factorio, and with it the origins of the automation genre. But since the time Wube pioneered this genre in 2013, many games adapted and embraced its ideas, like Satisfactory and Dyson Sphere Program, but also games more focused on survival like Astroneer, later versions of Minecraft and more recent mods for it. In this article I want to explore what became of the automation genre, and how automation games are differentiated to survival games with some automation.

Part 1: The Big Three

Spaghetti in automation games.

When you ask someone to name some automation games other than Factorio, the most common response you’ll get are Satisfactory and Dyson Sphere Program. Together with Factorio, they are even regarded as the (un-)holy trinity of automation by some players. But what makes these games stand out from the rest (apart from their rating, the highest among all games on Steam with the “automation” tag)?

Screenshot of SteamDB showing Factorio 1st, DSP 2nd and Satisfactory 3rd
The top rated games on steamdb with the automation tag
  • All three games are set in an open world and you, the player, are an entity in it, building the factory. Neither of these are required for automation, as for example shapez.io perfectly works without a playable character, and there a plenty of games like Opus Magnum that are in a level-based puzzle environment.
  • Your progression is mainly through a skill/technology tree (be it a very shallow one in Satisfactory); Special technology to send through a space elevator in Satisfactory, research matrixes in DSP, and finally, the bottle-shaped science packs in Factorio. Most open world (survival) games feature some sort of skill tree, but acquiring new points rarely features a connection to the game world. The factories, however, have to be built primarily for the tech tree itself; you don’t have some requirements to limit your progress in the “story”, the requirements are directly tied to the progress towards the final goal.
  • And finally, all three games mainly challenge your knowledge and understanding of logistics. While the spaghetti of some bases might suggest otherwise, space isn’t actually an issue (or at least not a big one) due to the open world, but getting massive amounts of raw resources from a mining outpost back to your main base requires you to overcome obstacles like mechanics, throughput, and environment. And it can get even more challenging, for example moving production to said outpost to export the most dense/compact products (see Alt-F4 #7) uses complex ratios to get the most efficiency. This challenge might be a direct result of the open-world nature of these games, but especially long range trucks and trains provide a much needed “unknown” variable to the defined ratios (unknown as in not as obvious as items per second on belts), as well as a challenge, a bottle neck scaling inversely with production.

The different research trees, with DSP more similar to Factorio, and Satisfactory in its shallow tier system.

Apart from the similarities in gameplay, the three games also feature a remarkably similar scenario of the player being dropped on an empty planet; however this is probably of the most obvious narrative reasons for the player to start from scratch. This article won’t elaborate on the story behind the games, but rather focus on the gameplay itself.

These are some of the most important similarities between the three games. There are definitely more smaller ones, or in areas other than gameplay, but if you get to the core of it these three are what define the games, trains unfortunately not being one of them. But how do games not generally regarded as automation fall into this scheme?

Part 2: Automation in Other Games

Speaking of scenario, there is a forth game with this scenario, with a similar theme of multiple, small planets, with a great rating, with the “automation” tag on steam, and it is arguably even more popular than the other three games: ASTRONEER. Why didn’t I mention it before? It certainly has a similar scenario, you can automate large parts of your production, and so on.

Let’s get back to the previous article, what does automation even mean?

One could loosely define automation as “making stuff that makes stuff”

— Nano

Keep in mind this is only one possible definition of the genre, but it already runs into some problems. For example Nanocarbon Alloy, one of the most important Astroneer endgame materials, already fails to be automated at one of the most basic steps of getting all required resources together—which isn’t necessarily bad though, the game wasn’t developed as an automation game. The auto arm—and with it some other tools to automate—only got added in version 1.13, a full year after the original 1.0 release of the pure survival game.

Many (survival) games feature some sort of automation today: Minecraft’s hopper, added with version 1.5 in early 2013 is the first example of a simple machine to machine transfer I could find, and might have influenced Factorio’s inserter too, but ASTRONEER’s auto arm, the auto miner, the conveyors in TerraTech, the belts in some Overcooked levels are all reminiscent of similar Factorio mechanics, and all got released after Factorio first got popular. And then there are mods: Basically every tech Minecraft mod since 1.6.4 (although those might also be influenced by the earlier Minecraft mods) features automation.

Still, none of the games above have automation as the defining mechanic, it only gets complimented by it. You might spend way to long building complex machineries, intricate factories, and tightly packed rovers, but none of them progress your gameplay directly. You still need to explore, discover, fight, and decorate your way further towards your final goal. There can however be made an argument for SkyFactory, one of my favourite Minecraft mod packs, which circumvents the problem of exploration by having nothing to explore. It still allows you to incase your factory in nice blocks, decorate it with flowers, which is the other main goal of Minecraft, only coming as a secondary possibility in Factorio.

How do games not generally regarded as automation fall into the scheme from part one then? Logistics present themselves in the form of inventory management, and is a common part of survival games, as is the open world. And the skill tree, which the automation games make completely unfeasible to hand craft, is just supplemented by automation in the other games. This supplementation is the important part, adding automation as another mechanic among many has become popular with the popularity of automation games.

Part 3: Simulation, Idle, and Puzzle Games

Most games so far are in some way an open-world survival or sandbox game, however there is a subgenre of automation most of us have come on contact with and regularly play: Designing the assembly line itself. There are numerous automation puzzlers which exclusively focus on that part of automation. One example is Opus Magnum, as already mentioned, or factori, a game scoring one of the first places in the recent GMTK 2021 game jam. But fit the definition (“you make stuff that makes stuff”) chemicals in one, and letters in the other. Does Emergency Protocol (there area lot of puzzle games in game jams btw) fit the definition? You make a pattern that makes a path? In its core it sounds like automation—you tell a little robot what to do (program it), and it repeats your commands—but that also sounds similar to idle games—set something up, and it does a job for you while you are away.

Speaking of which, idle games aren’t really considered automation games, and neither are management games or simulation games, as I discussed in my last article. But then again, there is the meme of automating Factorio itself, which some players have successfully done. On a more serious note, some players really do play Factorio as a management game—city block blueprints often have every assembly line, every problem already solved, your job now is to balance the different resources and power, and manage the factory on the larger scale.

Conclusion

To summarise, automation still isn’t a type of game like “puzzler’, but it can definitely be the defining genre. However it is still possible to add automation to game, without having it at its core. That being said, my last article left automation a bit more open, and I hope a could give a more SATISFACTORY definition and conclusion this time by FACTORIOing in more recent games.

Contributing

As always, we’re looking for people that want to contribute to Alt-F4, be it by submitting an article or by helping with translation. If you have something interesting in mind that you want to share with the community in a polished way, this is the place to do it. If you’re not too sure about it we’ll gladly help by discussing content ideas and structure questions. If that sounds like something that’s up your alley, join the Discord to get started!

Franqly laying on rocks staring up into the sky.

опубликовали stringweasel, Nanogamer7, Conor_, Therenas, Firerazer

After a semi-intentional two-week mid-summer break, Alt-F4 makes its glorious return with issue #40. In it, fan-favorite and editor extraordinaire stringweasel does another one of his interviews that gets us some perspective on a Nauvis-related topic. A Nauvian Perspective, if you will. This time, he talked to Franqly who’ll be representing Factorio for the first time at the Summer Games Done Quick charity event. More info on that at the end!

The Nauvian Perspective: Franqly stringweasel

The fastest Factorio singleplayer speedrunner in the world – at time of writing – is a new-ish player called Franqly. He joined the Factorio speedrunner community very recently with his first entry on speedrun.com in October of last year. Today however, he is out-running legends like AntiElitz and Nefrums, and is the only player alive that has single-handedly finished Factorio in 90 minutes flat. In the time it takes you to watch the Bee Movie he can complete everything from crash landing on Nauvis to launching the rocket.

It’s no suprise then that Franqly was recently accepted to take part in the Summer Games Done Quick, or SGDQ for short, which is happening from the 4th to the 11th of July 2021. This event is an enormous yearly speedrunning marathon which showcases over 140 different runs. Various big names in the speedrunning community such as TheMexicanRunner and mitchflowerpower take part. And it’s for a great and noble cause too! The goal of this marathon to raise funds for Doctors Without Borders, being its largest fundraising event in the world! Being accepted into SGDQ is no small feat either – this year the event received almost 2000 submissions of which only about 150 were selected to take part. Talented Factorio players had submitted their runs in the past, hoping to join this prestigeous event, but were denied because Factorio was not “officially released” yet.

The base that Franqly launched a rocket from in under 90 minutes. A part of this base can also be seen in the unofficial Factorio Hall of Fame.

Speeding Through Factorio

Currently, Franqly is the king of the Any% speedrunning category. The rules for this category are simple: The run is completed by launching the rocket, all by yourself. You are free to change the map generator settings, including enabling Peaceful Mode and using a specific Map Seed. The importing of blueprints however is not allowed, but you may use blueprints created during the run. The rest is up to you.

Finishing Factorio in 90 minutes is no trivial task. There’s a reason the There is no Spoon achievement requires you to finish the game in under 8 hours! It’s also one of the few games that has no bugs that can be exploited during speedruns! Rather, the factory needs to be designed and built perfectly to research as fast as possible while still expanding production as fast as possible to then research even faster – all to launch the rocket in the shortest time. Runners will easily spend hundreds of hours designing and fine-tuning their factories to maintain this fine balance of research and expansion. Luckily the legendary runner Nefrums created a helpful beginner’s guide for the community on how to design such a base. Nefrums really plays a big role in the community and a few top speedrunners even use Nefrums’ personal base design for their own runs.

However, even if the factory design is perfect, it will take even more time to practice and perfect the actual building of the factory. There are many different approaches and strategies to speedrunning, and they all require runners to perfectly balance many different aspects of the game all while racing against the clock. One example is hand-crafting where some runners have pre-calculated lists with exact amounts of what they need to craft at specific times to always be ready for the next build. Some also need to be able to build the most of the factory from memory, sometimes having only pictures on hand as reference, all while already being under time pressure. And because a factory is such a complex mechanism, one wrong placement can easily cost you the world record.

Who is Franqly

Now, who is Franqly? The speedrunning scene was dominated for a long time by names like AntiElitz, Nefrums, and Phoenix27833 – only to name a few. However, Franqly soon came around, and through practice and dedication he became one of the best. I reached out to him to ask him a few questions about his time in Factorio and how he managed to reach the top so fast after previously only speedrunning The Legend of Zelda: Ocarina of Time a few times. He was very gracious and gave us a glimpse into his speedrunning career.

Is there someone specific that got you into Factorio, and how much time have you spent with the game?

No one specific. I can’t quite remember how I found it, but I probably saw someone playing on twitch. I thought it looked like s**t tbh, but was interested in the concept. Then a few months after, I saw it on steam. It looked much better with [version] 0.12, and decided to pick it up. I had about 1500 hours before starting to speedrun. [I am at] about 2200 [hours] now.

— Franqly

When did you start speedrunning, and is there someone who inspired you to start? Is there someone now that you see as a sort of mentor?

I started relatively recently, about August last year. I had contemplated it in the past, as I had watched Anti’s streams off and on for a while. Nefrums created an introduction to speedrunning guide, and that gave me the push to try it. I’d recommend that guide to anyone thinking about trying out factorio speedrunning. I would consider Nef the most mentor-like person in the community for me, but everyone in the Discord and on Twitch chat chimes in with advice and strategy ideas, and that helped me come up to speed very quickly.

— Franqly

Speedruns tend to look very similar between different players to the untrained eye. What sets your run apart from the others?

I think what sets me apart from anti, nef, and other talented runners and planners is having never designed a base myself, I’m not tied to any initial concept of what the run is suppose to be, what it specifically was designed for. Unfortunately, I don’t have the creative or intellectual ability to design a run like I can perform. But I can analyze well, and I can figure out micro optimizations, at least for my own play-style. I also practice all the details in short segments, in a very grindy fashion, and that let’s me have very consistent runs with little to no mistakes.

— Franqly

Do you think a large part of your success is that you practice more? Not so much optimizing the factory, but rather your play-style? As you said, but choosing optimal routes to run for example. Do you think you practice these techniques more than other top runners?

I can’t say for sure. I know I do all my practicing offstream, as I think most speedrunners do. If I had to guess, yes that would be the case. I’ve been in between work this last year and it gave me a lot of time. Now I’m at 56hr/week. Most others in the community have full time jobs.

— Franqly

What is the hardest part of speedrunning Factorio? How does this compare to speedrunning other games?

The hardest part is the part I avoid, the design of the build from beginning to end. I absolutely have stood on the shoulders of giants, in particular Nefrums for the current design we both run. I was pretty hesitant to approach speedrunning the game in this way, but I haven’t really received backlash from others in the community, and Nefrums has been completely on board and very helpful, and of course I didn’t want a one-way street, so I’ve tried contributing in ways that use my strengths. Compared to other games, what really stands Factorio apart is that every single action has a ripple effect to the rest of the run. It is basically impossible to launch the rocket under the same conditions as any other run. In level based games, generally each segment will play the same everytime. I can think of RPG speedruns being kind of on the level of early actions having effects throughout, but even then generally strategies are made to resync progress or adapt to a limited number of alternatives.

— Franqly

I see you also did Zelda Speedruns in the past. How do you compare Zelda speedrunning with Factorio speedrunning?

Completely different to Zelda! Pretty much on every level. I will say, I learned how to grind practice effectively, and that translated well. I was never all that good at Ocarina of Time, but I really enjoyed it all the same. I’ve dabbled in a few other games less seriously, including SM64, Super Metroid, SM Sunshine, Hollow Knight, and Celeste.

— Franqly

What is your favourite part about speedrunning? And the part you dislike the most?

My favorite part is the progression of skill, feelings of getting better at something. Speedrunning becomes very difficult to maintain motivation for after “hitting a wall” with improving your skills, and much less enjoyable. I’ve found taking regular 1-2 week breaks has been very beneficial to not reach a level of burnout, so it continues to be enjoyable longterm.

— Franqly

How often do you practice/plan for you runs? And how long did you do speedruns before you were competing with the top runners?

I pretty much live, eat, breathe, sleep with Factorio when I’ve learned a plan and practice it. I do segmented practice in 2-3 minute chunks, over and over, trying out different movement routes or building placement order until I arrive at something I’m comfortable with and can consistently do fast. While doing runs, I make mental note of segments that didn’t go well, and later grind those again. I began improving my times rapidly with this approach. With the right amount of free time, determination, familiarity with the game, and general gaming skill, I was able to achieve the world record in about 5-6 months.

— Franqly

Why did you decide to send a submission to SGDQ? And were you excited when you received the “letter” saying that you’re in?

I’ve been watching gdqs for years. I wasn’t really expecting to get in, so it was quite a surprise! I’m very happy to be able to showcase factorio to a larger audience. I just thought, what the hell, may as well apply.

— Franqly

Do you still play Factorio “normally”? And if you do, is it hard to “slow down” and play it in a more relaxed fashion?

Not recently, no. I tried Pyanodons suite a few months ago, got overwhelmed and shelved it. The base game is definitely “tainted” for me at this point, but I think that is true for most players that have 2k+ hours in the game. We can never get that first play-through experience again. I play other games to relax.

— Franqly

What other games do you enjoy playing? I saw you’re currently into Satisfactory?

Yeah, Dyson Sphere currently, and Satisfactory are both great and I highly recommend both for those that enjoy factorio. I have played a very wide range of genres in the past, too many to list. In recent years I’ve really narrowed my focus to strategy games. Eu4, Slay the Spire, SC2, and Dominion are also recent games I’ve played. They address different itches. I played copious amounts of WoW and later LoL. Too much time, lol.

— Franqly

How do you find the Factorio speedrunning community? It seems that AntiElitz and Nefrums have created a community with great sportmanship, where runners are competivive but still celebrates others achievements.

As I mentioned before, I had watched anti stream off and on for a fews years before joining. I think our community is great! Good mix of personality and backgrounds with a spirit of cooperation. It’s not overly competitive, but enough so it encourage growth. I’m not personally super entwined in goings on, but I do enjoy popping in for some discussion once in a while.

— Franqly

Do you like watching other streamers/lets-players? If so, who are you following most at the moment? How about anyone else participating in the SGDQ?

I used to watch on Twitch a lot more than I do now. When I do, I’ve been watching Arumba, Zoast, Cheese, and a few others. I’m most excited for Super Metroid at GDQ, oldie but a goodie.

— Franqly

Do you have any other hobbies/activities/profession that you like doing outside of the videogame world?

I enjoy spending time with my wife. We watch shows, go on local walks or drive out to scenic hiking spots. Nothing too crazy, my life is pretty chill atm. Looking forward to having kids, which we’re delaying until we have a house. Saving as much as we can. Housing market is ridiculous though.

— Franqly

 

 

Franqly laying on rocks staring up into the sky.
Franqly quite possibly pondering speedrunning techniques while on a hike with his wife.

 

The Event with a Good Cause

We are all very excited to see Franqly take part in this great event where he will be representing Factorio! He has worked very hard and spent countless hours achieving this amazing goal. Hopefully this will be the first inclusion of many of our favourite factory building game in mainstream events!

We ask you all join and support Franqly with us! He will be joined in his stream by AntiElitz and Thue, while XenoCyber will guide us through what Franqly is doing. His run is scheduled to happen on the GDQ Twitch Channel on Friday, 9 July, at 2:18 PM UTC time.

There will likely be people hanging out watching the run in our Alt-F4 Discord and the Factorio Discord. So dust off your Twitch emotes, warm up your witty remarks, and mute your zoom meetings. We’re going to watch Franqly show the world how Factorio is speedrun!

Contributing

As always, we’re looking for people that want to contribute to Alt-F4, be it by submitting an article or by helping with translation. If you have something interesting in mind that you want to share with the community in a polished way, this is the place to do it. If you’re not too sure about it we’ll gladly help by discussing content ideas and structure questions. If that sounds like something that’s up your alley, join the Discord to get started!

Posted by  kovarex

Hello,
long time no see 🙂

We obviously have a lot to talk about when it comes to the game changes we recently did, or plan to do, but we don’t want to share any of it yet.

Yet, there is currently a topic very relevant to us and we can share it without revealing any specific changes to the game. Today’s post will be quite technical and related to programming, so if you just came for the game news, you can safely skip this one.

Uncle bob

Now that there are only developers here, I can share my new discovery of Uncle Bob and his really nice explanation of some of the fundamental principles related to programming project management, and more. If you have 8.5 free hours on your hands, I propose you watch it, as there will be some references to what he mentions later on.

My general thought was, that we maintain the quality of the code to be quite high, and we have a reasonably good work methodology. But we were the victims of selective blindness in many places actually. It is interesting, how some pieces code were just good from start and stayed pretty good throughout all the years, even when it was expanded a lot… and some of the code just deteriorated heavily.

And the answer is explained with the metaphor of the wax foundation.

What is a wax foundation and how is it related to programming you might ask? My grandfather was a very enthusiastic bee-keeper. My childhood was spent in our garden, where you had to be careful where you step, where you sit down, and you could never leave anything sweet just laying around, because you would find a big pile of bees on top of it quite soon. I had to help him and learn about the bees from time to time, which I honestly hated, because I knew that I will never have any bees of my own. But he was right about one thing, everything you learn will be useful to you in one way or another.

One of the jobs you do around bees, is that when the honey is taken away from the bees, you put the wax foundation in the hive, which looks like this:

Its primary function is that the bees build their tiles evenly and quite fast, as it is just natural to follow the optimised structure that is already there. And this is exactly what happens with code that has a good and expandable design from the start.

On the other hand, there is code that either had a lazy original design, or it was never expected to grow so much in complexity, and each of the changes were just a small addition to the mess. Eventually we got used to the idea that this part of the code is just hell, and that making small changes is annoying. This implies that we just don’t like this part of the code, and we want to spend as little time as possible working with it. And the result is that the problem is slowly spiralling out of control.

When I took the Uncle Bob glasses and started looking around, I quickly identified several problematic places like this. It is not a coincidence, that these places were eating away an disproportionately large amount of the dev time, not only because making changes is hard, but because they are full of regression bugs and generally are a never-ending source of problems.

This is the beautiful thing about having a company that isn’t on the stock market. Imagine you have a company that goes slower and slower every quarter, and then you confront the shareholders with the statement, that the way to solve it, is to do absolutely no new features for a quarter or two, refactor the code, learn new methodologies etc. I doubt that the shareholders would allow that. Luckily, we don’t have any shareholders, and we understand the vital importance of this investment in the long run. Not only in the project, but also in our skill and knowledge, so we do better next time.

This is the timeline of the lines of code in Factorio

It would look pretty reasonable if there was the same amount of people working from start to finish, but it is not. It was just me at the very start, and now there are 9 programmers. It could be explained by the game getting bigger and growing a lot of interconnected mechanics, which is harder to maintain. Or it could also mean that the density of the code improved so much. Both of these are not enough explain why having more programmers doesn’t result in faster development.

This indicates that the problems Uncle Bob describes are relevant to us, and the solution is actually to improve the way we develop rather than just scaling the amount of people. Once we have a nice clean foundation, then hiring new programmers and getting them up to speed with the code will be much faster.

Let me now explain a few typical examples of the problems we had, and how we proceeded to fix them:

Fig. 1 – the GUI interaction

We wrote a lot about the GUI (for example FFF-216) and how we iteratively raised the bar of what we find acceptable both from both the user and programmer perspective. The common takeaways from the FFF and from the coding was, that we always underestimated how complicated GUI logic/styles/layouting etc. can become. This implies that improving the way the GUI is written has large potential gains.

We are happy with the way the GUI objects are structured and laid out since the 0.17 update. But codewise, it still feels much more bloaty than it should be. The main problem was the amount of places you needed to touch to add some interactive element. Let me show you an example, a simple button used to reset presets in the map generator window.

In the class header:

class MapGeneratorGui
{
  ...

We had a button object definition

...
IconButton resetPresetButton;
...

In the constructor of MapGenerator, we needed to construct the button with parameters

...
, resetPresetButton(&global->utilitySprites->reset, // normal
                    &global->utilitySprites->reset, // hovered
                    &global->utilitySprites->resetWhite, // disabled
                    global->style->toolButtonRed())
...

We needed to register as a listener of that button

...
this->resetPresetButton.addActionListener(this);
...

Then, we needed to override the method of the ActionListener in our MapGeneratorClass, so we could listen to the click actions.

...
void onMouseClick(const agui::MouseEvent& event) override;
...

And finally, we could implement the method, where we if/else through the elements we care about, to do the actual logic

void MapGeneratorGui::onMouseClick(const agui::MouseEvent& event)
{
  if (event.getSourceWidget() == &this->resetPresetButton)
    this->onResetSettings();
  else if (event.getSourceWidget() == &this->randomizeSeedButton)
    this->randomizeSeed();
 ...

This is way too much boilerplate for one button with one simple action. We had over 500 places where we registered actionListeners in the code, so imagine the amount of bloat.

We kind of noticed, that when we use lambdas to signal callbacks and similar things in the GUI, it tends to be much more pleasant to use. So what if we made it the primary way to do the GUI?

We decided to completely rewrite the way it works, so instead of adding listeners and the filtering from the event catching functions, we can just specify:

this->resetPresetButton.onClick(this, [this]{ this->onResetSettings(); });

Which is a big improvement already, as adding and maintaining the new logic only requires you to look at one place instead of several, and it makes it generally more readable and less prone to errors.

And since we don’t need to hold the pointer object for comparisons, we can completely remove its definition from the class, and make it anonymous on many places in this fashion:

*this << agui::iconButton(&global->utilitySprites->reset,
                          global->style->toolButtonRed(),
                          this, [this]{ this->resetPreset(); })

Rewriting all the GUI internals (again) was a big task, but in the end it really felt to be well worth it, as now I can’t imagine how we could stand doing it the old way. It also resulted in several thousands of lines of code being removed.

The only way to go fast is to go well!

Fig 2 – The manual building

There are several main goals to pursue when you try to make the code cleaner. Removing code duplication is the first and biggest priority. It is reasonably easy to solve when the code isn’t structured well, functions are too long, or names are weird, but if you have 5 versions of the same pile of code with slight changes here and there, it is the worst beast. It is just a question of time, until bugfixes/changes are only applied to some variants, and it becomes less and less obvious whether the differences between the variants are intended or circumstantial.

The manual building logic is a monster, because of all the things it supports already:

Then, all of this logic needs to be multiplied by 2 (when you are lazy and copy paste), as you can have normal building and ghost building.

And then, you multiply this whole code abomination by 2 again. Why? Because we also need to do all this logic in the latency hiding mode. Sounds bad already, but it isn’t all of it, since this logic was continually being patched and touched by different people throughout history, the core of the code was a crazy long method with the code looking like the horizon mentioned by Uncle Bob.

Now imagine that you need to change something about this code, especially when you take into consideration, that the code naturally had many corner cases wrong, or fixed only in some variant of the code. This is a great example of how lazy long-term design leads to poor productivity.

Long story short, this was approached like a hobby side project of mine that took weeks to be finished, but in the end, all the duplications were merged, the code is well structured and fully tested. Managing the code requires a small fraction of the time compared to the previous state, because the reader is not required to read a huge pile of code just to get the big picture and to be able to change anything.

This reminds me a quote from Lou after a similar kind of refactoring: “Once we are done with this, it will be actually a pleasure to add stuff to this code.“. Isn’t it beautiful? It is not only more efficient and less buggy, it is also more fun to work with, and working on something enjoyable tends to go faster regardless of other aspects.

The only way to go fast is to go well!

Fig 3 – GUI tests

No, we obviously didn’t get to this point without automated tests, and we mentioned them several times already (FFF-29FFF-288, and more). We try to continuously raise the bar of what code areas are covered by tests, and this lead us to cover yet another area, the GUI. This aligns with the ever repeating underestimation of the amount of engineering care the GUI needs. Having it not tested at all is part of this underestimation, how many times it happened, that we made a release, and it just crashed on something stupid simple in a GUI, just because we didn’t have a test that would click the buttons. And in the end, it proved to not be hard at all to automate the GUI tests.

We just have a mode in which the testing environment is created with GUI (even when tests are run without graphics). We declared some helper methods, that allow a very simple definition of where we want the cursor to move, or what we want to click, like this:

TEST(ClearQuickbarFilter)
{
  TestScenarioGui scenario;
  scenario.getPlayer()->quickBar[0].setID(ItemFilter("iron-plate"));
  CHECK_EQUAL(scenario.player()->getQuickBar()[0].getFilter(), ItemFilter("iron-plate"));
  scenario.click(scenario.gameView->getQuickBarGui()->getSlot(ItemStackLocation(QuickBar::mainInventoryIndex, 0)),
                 global->controlSettings->toggleFilter);
  CHECK_EQUAL(scenario.player()->getQuickBar()[0].getFilter(), ItemFilter());
}

The clicking method is then calling the low level events of input, so all layers if event processing and GUI logic are tested. This is an example of end-to-end test, which is a controversial topic, because some “schools” of test methodology say, that everything should be tested separately, so in this case, we should theoretically test only, that clicking the button first, which creates an InputAction to be processed, and then, have an independent test of the InputAction working properly. I like this approach in some cases, but most of the time I really like that I can penetrate all layers of the logic with only a few lines of code. (more in the Test dependencies part)

The only way to go fast is to go well!

Fig.4 – TDD – Test driven development

I have to admit, that I didn’t know what TDD really was until recently. I thought that it is some nonsense, because it sounds really impractical and unrealistic to first write all the tests for some feature (without the ability to try it or even compile it), and then try to implement something that satisfies it.

But that is not TDD, and it had to be shown to me in a “for dummies” way for me to realize how wrong I was.

So after the “AHA” moment of realizing what TDD really is, I started to be instant fan. I’m now putting a lot of effort to try to follow the TDD methodology as much as possible, and to force it on others in the team as well. It feels slower, to write tests even for simple pieces of logic that just bound to be right, but the test proved me wrong several times already, and prevented annoying low-level debugging sessions in the near future.

The only way to go fast is to go well!

Fig.5 – Test dependencies

This is a continuation of the test dependency topic from GUI tests.

If tests should be truly independent, test C, should have some mocks of A and B, so the test of C is independent of the system A + B working correctly. The consensus seems to be, that this leads to more independent design etc.

This might be applicable in a lot of cases, but I believe that trying to have this approach everywhere is close to impossible, and it would lead to a lot of clutter and I’m not the only one having problem with this.

For example, lets say that we have a test of electric poles connecting properly on the map. But I can hardly test it when I don’t know that searching for entities on the map works properly.

My conclusion is, that having dependencies like this is fine, as long as the dependencies are also tested, but the problem comes when you break something and a lot of tests start to fail suddenly. When you do small changes the yes/no indication of tests is enough, but it isn’t always an option, especially when you refactor some internal structure, in which case you kind of expect to break a lot of stuff, and you need to have a way to fix them step by step once it can compile again.

If the tests don’t have any special structure, the situation when 100 tests all fail at the same time is very unfortunate, all you are left with is to try to pick some test semi-randomly, and start debugging it. But it is really misleading when some complicated test case fails in the middle, and you spend a long time debugging it, only to realise that it is some very simple low level bug that is causing the failure.

The goal is pretty easy, I want to be given the most simple fail case of my change.

For this, I implemented a simple test dependency system. The tests are executed and listed in a way, that when you get to debug and check a test, you know that all of its dependencies are already working correctly. I tried to search if others use the dependencies as well, and how they do it, and I surprisingly didn’t find anything.

This is an example of a test dependency graph related to electric poles:

I built and used this structure when refactoring away the duplication of ghost/real poles connection logic and it certainly sped up the process of making it work properly, and I’m confident that this is the way to structure test for us in the foreseeable future. Not only it makes test results more useful, but it forces us to split test suites into smaller more-specialised units, which certainly help as well.

The only way to go fast is to go well!

Fig.6 – Test coverage

When Boskid joined the team as the QA guy, one of his main roles was making sure that any discovered bug is first covered by a test before it gets actually fixed, and generally improving our code test coverage. This made the releases much more confident, and we had less regression bugs, which directly transitions into long-term efficiency. I strongly believe that this clearly indicates and supports what Uncle bob is saying. Working with tests feels slower but it is actually faster.

Test coverage is an indicator of which parts of the code are executed when the application runs (which usually means running the tests in this context). I never used a tool to measure test coverage before, but since it was one of the topics Uncle Bob talked about, I tried to use it for the first time. I found a tool that works only on Windows, but requires the least amount of setup, which is OpenCppCoverage, which provides an HTML output like this:

It is immediately visible, that both of the conditional commands are not triggered in tests. It basically means that either the code just isn’t tested, so it should be covered, or it’s dead code, so it should be removed. I’m quite confident (again), that using this can help us a lot to write clean high quality code.

The only way to go fast is to go well!

Conclusion

The only way to go fast is to go well!

If you are moved by this, if your emotion when you read this is, “I wish my boss had these priorities“. Consider applying for a job at Wube!