Suckless Libre Games?
Posted: 31 Dec 2020, 19:39
So, after releasing Anarch, a game on which I "tested" some of my specific development philisophies, I would like to talk with you about those philosophies, having something concrete to back them up. There are other projects created with similar ideas in mind, e.g. the Simon Tatham's Portable Puzzle Collection.
My goal with this post is to perhaps gain a fellow programmer or programmers to make similar games with me. Let's create a comfy suckless libre game collection!
Let me preface with saying that it is of course okay not to follow these, you can make your games however you wish, I am not here to bash your programming style etc., I am here to possibly start a small community of developers who create a specific kind of games that the world is currently lacking.
I think my way is a legitimate way with many advantages, which however isn't much practiced because of the huge prevalence of the mainstream game dev and pressure of the business world, consumerism, short term planning, resulting school education etcetc. In a mostly non-commercial/hobbyist community like this one I am offering this alternative development style. As the suckless philosophy many times sparks heated debates, let me again stress this is not an offense to anyone's programming or tastes, this is not a promotion of the suckless group, this is a friendly invitation to join and explore a game development area holding some potential, an area that would maybe deserve a distinct name.
What is this philosophy?
I will call this the "suckless" or "Unix" philosophy because these are the closest, but we can invent another term as there are some specifics. While a lot of libre games try to imitate or chase the AAA games, with this philosophy we try to go the other way, towards minimalism and simplicity. Basically, we try to:
- Create games simply, to be minimalist and easy to use, compile, modify, reuse, distribute etc. Not just on paper, but also in practice. For all people.
- Create time-proof games, mainly by dropping dependencies and big frameworks. Achieve true independence on any other project.
- Create very portable games, again by dropping dependencies and keeping things simple.
- Get rid of burdening "bullshit" in games as well as in development. This means e.g. dropping fancy graphics, huge development environments etc.
- Utilize the less is more principle. I.e. a pixelated graphics can be better than HD graphics in some situations, so try to put yourself in that situation.
So, specifically, SOME of the guidelines are these:
- Write games in pure C99, because that is the most portable, efficient and suckless language. No C++, no Python, no Java, ... If that is possible.
- Do not use OOP and many of so called "good practice". These are considered "bloat", corporate style programming for HUGE projects. They teach you these for "safety" and because they are standard in the commercial sphere, but are burdening and limiting to us. Avoid unnecessary abstractions. Use simple imperative programming with functions, global variables etc.
- Avoid ANY dependency that is not completely necessary. This means mainly libraries, but also for example hardware. If your game can run without floating point (it most likely can), only use integers! Many CPUs (embedded) do not have floating point coprocessor and floating point operations are slow there! Even if you don't plan porting to embedded, don't use it if you don't need it. Don't even use standard library if not necessary.
- Use as little computational resources (RAM, CPU, ...) as possible. This helps portability and accessibility, and is simply just a good engineering habit.
- Drop "bullshit features" which are also dependencies and burdens. Will your game be less fun with pure ASCII non-antialiased font rendering? Then don't use Unicode and don't use anti aliased font rendering library. Is the only purpose of mouse in your game to click on things in the menu? Then don't use mouse, use only keys.
- Be smart and hacky. For example using arbitrary sized textures can be a burden if you don't need this feature. In mainstream dev no one cares, everyone simply uses an "image library" and doesn't care about any overhead. However, it can help if you e.g. purposefully limit yourself to textures of size 32x32, as this will have quicker access (powers of two dimension, compile-time known bounds, ...), smaller code, fewer bugs etc.
- Don't use "bullshit" complex/complicated licenses and rules (whateverGPL). Don't multi license. Preferably use completely public domain (CC0) or simple permissive licenses (MIT) for whole repository.
- Avoid hard I/O dependencies by creating a simple abstraction so that your I/O library can be very easily switched for whatever is available on given platform. E.g. in Anarch I write to screen via simple abstract function drawPixel(), which each frontend implements its own way, usually as a single line call to its own pixel drawing function.
- If you can, avoid using harddisk storage and compile your resources into the executable. Many platforms don't have harddisk, or the libraries further bloat your program.
- Make things optional, don't force anything. E.g. in Anarch saving/loading is optional. In case the platform doesn't have persistent storage for saves, you can simply access all levels from the start.
- Do not use config files, write configuration and settings right in the source code, e.g. in a special "settings.h" file. Remember, your game recompiles in less than a second with a single command.
- Use single compilation unit, best if you can fit your whole program into a single file (which also forces you a bit to keep the code short and simple). If you can compile your code with a single call of the compiler, you're doing it right. Avoid build systems such as CMake, at worst use a simple Makefile.
- Don't write level editors/formats if you can use existing generic tools and formats. E.g. in Anarch I don't have a special level editor, my levels are editable right in the source code or can be created as images in any simple bitmap editor.
- Don't use dynamic scripting languages if not needed. You can "script" your game in the language you are writing the game in, especially if your game is so easy and fast to recompile.
- Don't rely on GPUs, try to use SW rendering.
- Make your game work with as few buttons as possible to help portability. You can add additional keys for comfort as long as they are optional.
- Write nice, self-documenting code, make it accessible to other programmers. Explain what each file does in the file header comment, suppose someone else will be trying to understand your code with just the source code available. There are people who work offline etc.
Why?
These games have many values that are pretty underappreciated by today's society, but they are still there and useful to many people.
Yes, this does cost something. You may spend more time on making your game consume less resources than if you simply made it in a premade framework and accepting that "everyone has a good CPU nowadays". But your extra time and effort will pay off.
For example, don't you hate it when you find a game that is completely libre, but you still cannot compile it because some of the dozens of dependencies is broken? Or because there pops up an error in the build system that you don't understand and the original author is long gone and uninterested in fixing it? Even though the game is libre legally, it is NOT libre in practice, because you can not compile it in practice. Personally I am very sad that even libre games die this way, and I am often discouraged from playing a game that I think may die soon.
It doesn't have to be this way! A suckless game greatly avoids this issue. For example, my game Anarch only requires C99 compiler, which is something that will most definitely exist there as long as there exist computers, as so many things are written in it and depend on it. Java and C++ may die one day, but C will be there forever.
Yes, Anarch also requires SDL for its PC frontend, but this is a very soft dependency that can be replaced by anything that can draw pixels and read keyboard. Even if SDL dies, there will always be something like it you can use AND it takes only a few hours to write a new frontend. I have actually written many frontends for the game with many other libraries.
Having ported the game to all the different platforms also helped me test it for hardware-specific things like endianness etc.
Similarly if the game is too complex, it can be seen as little less "libre" or "free", simply because fewer people can truly modify it. Even if the game is under a free license, if it has hundreds of thousands of lines of code, it resists modification by simply being very complex and requiring very much effort to modify. A game written in a simpler way is much more accessible to programmers and "more free" in practice.
A libre game will have close to zero maintenance cost, because firstly it will have fewer bugs, and secondly it will almost eliminate the dependency maintenance. Much of the maintenance of the big projects consists of keeping up with library updates, which you don't need to do here.
A suckless game runs on many platforms and is accessible to more people! It doesn't make you buy a specific platform or expensive hardware. It also respects the people in the future, who may have completely different operating systems, platforms and libraries, and perhaps even less powerful computers (e.g. after technological collapse). If there is one piece of technology that will remain from today, it is the C compiler.
A suckless game thinks long term, it is not a game you consume and throw away, as most mainstream games. It may require a little more effort from you, but in the end pays off much more, as it will be like the legendary Doom, resisting decades and technological changes, to always be there for the people.
It also encourages forking and creativity, by being simple to tinker with. It may be used by a scientist for research, because it is so fast and efficient it is possible to run many thousands of these games at once and help e.g. with machine learning. It may be used by a programming teacher for his students to experiment on. You never know what will be, all you can do is to try to create the best engineering work you can.
And last but not least, programming a suckless game is simply joy You stop caring about frustrating bugs deep inside your framework, of which you don't even know how they work. You stop caring about painstakingly debugging GLSL shaders. You create most of your game from scratch, and that's quite a rewarding accomplishment. And it doesn't have to take longer than creating the game the mainstream way.
-------------------
So, what do you think? Would you want to give this a try? I think there's a good motivation in knowing almost no one is doing this -- quite some people are writing suckless software, but not games. No one is writing completely public domain games. You may be among the world's first people and create something truly new, unlike with "classical" indie/libre dev.
I was thinking a good project to start with might be a minigame collection, something like the famous 99 in 1, that would be super portable. Despite the simplicity of games like snake or chess, there are still very few of these done completely right. Something like a Super Mario clone would be even better.
I have written two libraries that might help you in your projects: small3dlib and raycastlib.
Is anyone even remotely interested in this please?
My goal with this post is to perhaps gain a fellow programmer or programmers to make similar games with me. Let's create a comfy suckless libre game collection!
Let me preface with saying that it is of course okay not to follow these, you can make your games however you wish, I am not here to bash your programming style etc., I am here to possibly start a small community of developers who create a specific kind of games that the world is currently lacking.
I think my way is a legitimate way with many advantages, which however isn't much practiced because of the huge prevalence of the mainstream game dev and pressure of the business world, consumerism, short term planning, resulting school education etcetc. In a mostly non-commercial/hobbyist community like this one I am offering this alternative development style. As the suckless philosophy many times sparks heated debates, let me again stress this is not an offense to anyone's programming or tastes, this is not a promotion of the suckless group, this is a friendly invitation to join and explore a game development area holding some potential, an area that would maybe deserve a distinct name.
What is this philosophy?
I will call this the "suckless" or "Unix" philosophy because these are the closest, but we can invent another term as there are some specifics. While a lot of libre games try to imitate or chase the AAA games, with this philosophy we try to go the other way, towards minimalism and simplicity. Basically, we try to:
- Create games simply, to be minimalist and easy to use, compile, modify, reuse, distribute etc. Not just on paper, but also in practice. For all people.
- Create time-proof games, mainly by dropping dependencies and big frameworks. Achieve true independence on any other project.
- Create very portable games, again by dropping dependencies and keeping things simple.
- Get rid of burdening "bullshit" in games as well as in development. This means e.g. dropping fancy graphics, huge development environments etc.
- Utilize the less is more principle. I.e. a pixelated graphics can be better than HD graphics in some situations, so try to put yourself in that situation.
So, specifically, SOME of the guidelines are these:
- Write games in pure C99, because that is the most portable, efficient and suckless language. No C++, no Python, no Java, ... If that is possible.
- Do not use OOP and many of so called "good practice". These are considered "bloat", corporate style programming for HUGE projects. They teach you these for "safety" and because they are standard in the commercial sphere, but are burdening and limiting to us. Avoid unnecessary abstractions. Use simple imperative programming with functions, global variables etc.
- Avoid ANY dependency that is not completely necessary. This means mainly libraries, but also for example hardware. If your game can run without floating point (it most likely can), only use integers! Many CPUs (embedded) do not have floating point coprocessor and floating point operations are slow there! Even if you don't plan porting to embedded, don't use it if you don't need it. Don't even use standard library if not necessary.
- Use as little computational resources (RAM, CPU, ...) as possible. This helps portability and accessibility, and is simply just a good engineering habit.
- Drop "bullshit features" which are also dependencies and burdens. Will your game be less fun with pure ASCII non-antialiased font rendering? Then don't use Unicode and don't use anti aliased font rendering library. Is the only purpose of mouse in your game to click on things in the menu? Then don't use mouse, use only keys.
- Be smart and hacky. For example using arbitrary sized textures can be a burden if you don't need this feature. In mainstream dev no one cares, everyone simply uses an "image library" and doesn't care about any overhead. However, it can help if you e.g. purposefully limit yourself to textures of size 32x32, as this will have quicker access (powers of two dimension, compile-time known bounds, ...), smaller code, fewer bugs etc.
- Don't use "bullshit" complex/complicated licenses and rules (whateverGPL). Don't multi license. Preferably use completely public domain (CC0) or simple permissive licenses (MIT) for whole repository.
- Avoid hard I/O dependencies by creating a simple abstraction so that your I/O library can be very easily switched for whatever is available on given platform. E.g. in Anarch I write to screen via simple abstract function drawPixel(), which each frontend implements its own way, usually as a single line call to its own pixel drawing function.
- If you can, avoid using harddisk storage and compile your resources into the executable. Many platforms don't have harddisk, or the libraries further bloat your program.
- Make things optional, don't force anything. E.g. in Anarch saving/loading is optional. In case the platform doesn't have persistent storage for saves, you can simply access all levels from the start.
- Do not use config files, write configuration and settings right in the source code, e.g. in a special "settings.h" file. Remember, your game recompiles in less than a second with a single command.
- Use single compilation unit, best if you can fit your whole program into a single file (which also forces you a bit to keep the code short and simple). If you can compile your code with a single call of the compiler, you're doing it right. Avoid build systems such as CMake, at worst use a simple Makefile.
- Don't write level editors/formats if you can use existing generic tools and formats. E.g. in Anarch I don't have a special level editor, my levels are editable right in the source code or can be created as images in any simple bitmap editor.
- Don't use dynamic scripting languages if not needed. You can "script" your game in the language you are writing the game in, especially if your game is so easy and fast to recompile.
- Don't rely on GPUs, try to use SW rendering.
- Make your game work with as few buttons as possible to help portability. You can add additional keys for comfort as long as they are optional.
- Write nice, self-documenting code, make it accessible to other programmers. Explain what each file does in the file header comment, suppose someone else will be trying to understand your code with just the source code available. There are people who work offline etc.
Why?
These games have many values that are pretty underappreciated by today's society, but they are still there and useful to many people.
Yes, this does cost something. You may spend more time on making your game consume less resources than if you simply made it in a premade framework and accepting that "everyone has a good CPU nowadays". But your extra time and effort will pay off.
For example, don't you hate it when you find a game that is completely libre, but you still cannot compile it because some of the dozens of dependencies is broken? Or because there pops up an error in the build system that you don't understand and the original author is long gone and uninterested in fixing it? Even though the game is libre legally, it is NOT libre in practice, because you can not compile it in practice. Personally I am very sad that even libre games die this way, and I am often discouraged from playing a game that I think may die soon.
It doesn't have to be this way! A suckless game greatly avoids this issue. For example, my game Anarch only requires C99 compiler, which is something that will most definitely exist there as long as there exist computers, as so many things are written in it and depend on it. Java and C++ may die one day, but C will be there forever.
Yes, Anarch also requires SDL for its PC frontend, but this is a very soft dependency that can be replaced by anything that can draw pixels and read keyboard. Even if SDL dies, there will always be something like it you can use AND it takes only a few hours to write a new frontend. I have actually written many frontends for the game with many other libraries.
Having ported the game to all the different platforms also helped me test it for hardware-specific things like endianness etc.
Similarly if the game is too complex, it can be seen as little less "libre" or "free", simply because fewer people can truly modify it. Even if the game is under a free license, if it has hundreds of thousands of lines of code, it resists modification by simply being very complex and requiring very much effort to modify. A game written in a simpler way is much more accessible to programmers and "more free" in practice.
A libre game will have close to zero maintenance cost, because firstly it will have fewer bugs, and secondly it will almost eliminate the dependency maintenance. Much of the maintenance of the big projects consists of keeping up with library updates, which you don't need to do here.
A suckless game runs on many platforms and is accessible to more people! It doesn't make you buy a specific platform or expensive hardware. It also respects the people in the future, who may have completely different operating systems, platforms and libraries, and perhaps even less powerful computers (e.g. after technological collapse). If there is one piece of technology that will remain from today, it is the C compiler.
A suckless game thinks long term, it is not a game you consume and throw away, as most mainstream games. It may require a little more effort from you, but in the end pays off much more, as it will be like the legendary Doom, resisting decades and technological changes, to always be there for the people.
It also encourages forking and creativity, by being simple to tinker with. It may be used by a scientist for research, because it is so fast and efficient it is possible to run many thousands of these games at once and help e.g. with machine learning. It may be used by a programming teacher for his students to experiment on. You never know what will be, all you can do is to try to create the best engineering work you can.
And last but not least, programming a suckless game is simply joy You stop caring about frustrating bugs deep inside your framework, of which you don't even know how they work. You stop caring about painstakingly debugging GLSL shaders. You create most of your game from scratch, and that's quite a rewarding accomplishment. And it doesn't have to take longer than creating the game the mainstream way.
-------------------
So, what do you think? Would you want to give this a try? I think there's a good motivation in knowing almost no one is doing this -- quite some people are writing suckless software, but not games. No one is writing completely public domain games. You may be among the world's first people and create something truly new, unlike with "classical" indie/libre dev.
I was thinking a good project to start with might be a minigame collection, something like the famous 99 in 1, that would be super portable. Despite the simplicity of games like snake or chess, there are still very few of these done completely right. Something like a Super Mario clone would be even better.
I have written two libraries that might help you in your projects: small3dlib and raycastlib.
Is anyone even remotely interested in this please?