<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: dalerank</title>
    <description>The latest articles on Forem by dalerank (@dalerank).</description>
    <link>https://forem.com/dalerank</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1900679%2F0ef8f0f1-45e5-40f2-b957-1aee5b4c4891.png</url>
      <title>Forem: dalerank</title>
      <link>https://forem.com/dalerank</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dalerank"/>
    <language>en</language>
    <item>
      <title>Playfull programming (0x1)</title>
      <dc:creator>dalerank</dc:creator>
      <pubDate>Wed, 25 Mar 2026 11:45:37 +0000</pubDate>
      <link>https://forem.com/dalerank/playfull-programming-0x1-741</link>
      <guid>https://forem.com/dalerank/playfull-programming-0x1-741</guid>
      <description>&lt;p&gt;Generalizations in C++&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh70flbttve6hank6jjzl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh70flbttve6hank6jjzl.png" alt=" " width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine for a moment that C++ is not a set of odd keywords and linker errors, but simply another way to talk about the world around us: people, numbers, colors, events, and cats. We are used to thinking of programming as something purely technical, where it matters to memorize syntax, place semicolons, and "guess" what the compiler wants right now.&lt;/p&gt;

&lt;p&gt;But if we ask ourselves "what does a program actually operate on?", it suddenly turns out that behind all those int, struct, and template there are rather simple and clear ideas: things, their properties, groups of similar things, and rules by which some things turn into others.&lt;/p&gt;

&lt;p&gt;And when trying to explain what objects, types, and other fundamental concepts of computer science are, one inevitably has to go beyond purely technical language and speak of more general categories of ideas that humanity has been working with for thousands of years—and it is here that the words "entity", "kind", and "genus" become useful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Abstract and Concrete Entities&lt;/strong&gt;&lt;br&gt;
When philosophers and logicians speak of abstract entities, they mean individual things that do not exist in space and time the way a table, a person, or a computer do, but as something unchanging: for example, the number 13 or the color blue as such were not born at some moment and do not "die" after some time; they are not objects of the physical world but ideas we work with in our heads and in mathematics.&lt;/p&gt;

&lt;p&gt;A concrete entity, by contrast, is always tied to history, to a moment of appearance and a moment of disappearance: Socrates was once born and once died; any country as a political entity was created on a certain date, and although the country continues to exist, it is clear that at some point it will no longer exist or may change radically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Attributes and Identity&lt;/strong&gt;&lt;br&gt;
At the same time, we can speak not only of entities themselves but also of their attributes—the correspondence between a concrete entity and an abstract entity that describes some property: Socrates' eye color can be described as a concrete instance of an abstract color; the number of German states as a concrete value of the abstract natural number.&lt;/p&gt;

&lt;p&gt;If at some moment we take a "snapshot" of a concrete entity and fix the full set of its attributes here and now, we see that over time individual attributes may change while identity remains, and it is identity—this very primitive but deep sense of "it is still the same one"—that lets us say that a person, a country, or a program object continues to be itself even as its properties change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kinds and Genera&lt;/strong&gt;&lt;br&gt;
Next arises the need to group entities in some way, and here the notions of kind and genus enter the stage; each of these categories can itself be abstract or concrete. When we speak of an abstract kind, we describe the common properties of a whole family of abstract entities.&lt;/p&gt;

&lt;p&gt;Thus the kind "natural number" covers all individual numbers 0, 1, 2, 3, and so on (zero may or may not be included in the naturals and may be treated as the empty set); the kind "color" covers all possible shades from dark blue to bright orange, and we can reason about them as something general without tying ourselves to a concrete instance.&lt;/p&gt;

&lt;p&gt;A concrete kind, by contrast, describes a set of attributes for a family of concrete entities: when we say "human", we mean a concrete kind that includes all humans with a certain set of characteristics such as biology, consciousness, etc.; when we say "continent", we describe a concrete kind that includes Europe, America, or Asia, each with boundaries, population, area, and other attributes. They differ as entities, but within the kind "human" or "continent" we can speak of recurring structural properties and model them in code as objects of one data type.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Functions as Rules&lt;/strong&gt;&lt;br&gt;
An important role in this picture is played by the notion of function, and here the mathematical definition carries over into programming almost verbatim: a function is a rule that maps some set of abstract entities, called arguments and belonging to certain kinds, to another abstract entity, called the result, belonging possibly to another kind.&lt;/p&gt;

&lt;p&gt;A classic example from mathematics is the successor function, which maps each natural number to the next one—the function "n → n + 1" in terms of the natural-number kind; another, more figurative example is a color-blending function that maps two arguments of kind "color" to a third color as the result of mixing them—and if you have ever written code that takes two Color values and returns a new Color, you were in effect implementing such a function.&lt;/p&gt;

&lt;p&gt;In programming we live inside this definition: any function call in C++ is the application of a rule to arguments that are concrete "casts" of abstract entities, and the result is a new object that can also be viewed as a concrete embodiment of an abstract entity of a given kind.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Kind: natural number&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;Natural&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Successor function: n → n + 1&lt;/span&gt;
&lt;span class="c1"&gt;// Rule that maps each Natural to the next Natural&lt;/span&gt;
&lt;span class="n"&gt;Natural&lt;/span&gt; &lt;span class="nf"&gt;successor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Natural&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Genera as Generalizations of Kinds&lt;/strong&gt;&lt;br&gt;
If we move up one level of abstraction and speak of genera, they let us talk not only about concrete values or even kinds, but about large classes of notions.&lt;/p&gt;

&lt;p&gt;Abstractly, a genus is a way to describe a set of different abstract kinds that are similar in some respect: for example, the genus "number" includes kinds such as "natural number", "integer", "real number", each with its own rules of existence, but we can reason about them as number in general without specifying the kind; the genus "binary operator" includes both arithmetic operations (addition, multiplication) and logical operations (and, or) and bitwise operations, but all of them follow the general scheme "take two arguments and produce a result".&lt;/p&gt;

&lt;p&gt;A concrete genus, in turn, describes a set of different concrete kinds similar in some respects: "mammal" describes different concrete kinds such as human, cat, and whale; "biped" describes another classification that includes humans, birds, and perhaps some fictional creatures—and one and the same entity (e.g. Socrates) can be viewed simultaneously as an instance of the kind "human" and as a member of the genera "mammal" and "biped". It is important to understand that any entity belongs to exactly one kind, which defines the rules of its construction or existence, but can belong to many genera, each of which describes only one aspect of its properties—and in programming it is the same: an object of one concrete type can implement many interfaces or concepts, each emphasizing only part of its behavior.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Genus: template—a rule over kinds&lt;/span&gt;
&lt;span class="c1"&gt;// This is the "genus" level: Pair&amp;lt;T, U&amp;gt; is not a concrete kind&lt;/span&gt;
&lt;span class="c1"&gt;// but a rule that maps two kinds to a new kind&lt;/span&gt;
&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;typename&lt;/span&gt; &lt;span class="nc"&gt;U&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Pair&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;U&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Function at the genus level: for any kind T&lt;/span&gt;
&lt;span class="c1"&gt;// returns a pair of two elements of that kind&lt;/span&gt;
&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;Pair&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;make_pair_of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Types in C++ as Kinds&lt;/strong&gt;&lt;br&gt;
If we build a bridge from this philosophical picture of the world to our world of compilers and C++, we can see that a type in the language plays the role of both a concrete kind and an abstract kind, depending on the level we look at.&lt;/p&gt;

&lt;p&gt;From the program's point of view, a class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;defines the kind "person in our model", specifying the set of attributes we chose as essential: name and age; and an object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Socrat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is a concrete entity—one person in our program with its attribute values at the current moment in time.&lt;/p&gt;

&lt;p&gt;From the point of view of type theory in the compiler, "type" is closer to an abstract kind: the compiler works not with a concrete p but with the set of all possible values of type Person; it knows their size, layout, copy and destruction rules, and checks that you apply functions (in our sense—rules) correctly to entities of the corresponding kinds—i.e. that you do not pass a std::string to a function expecting double, and vice versa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Evolution of Type Representation in Compilers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Historically, different compilers implemented this model differently at the level of internal program representation, but the conceptual picture was always similar: in the compiler's internal data structures there are entities corresponding to abstract kinds and genera—nodes of the type tree, tables of information about classes, functions, and templates; there are entities corresponding to concrete entities—variables, objects, temporaries that appear and disappear during program execution; and there are functions that, in the form of intermediate representation (IR), become a set of rules for transforming one set of values into another.&lt;/p&gt;

&lt;p&gt;In early compilers like cfront, many of these things were encoded in the textual C code produced by the translator, and the notions of kind and genus existed only in the author's head and in the design. As GCC, Clang, and MSVC evolved, increasingly sophisticated type systems and checking emerged that formalize these categories and allow, for example, at the LLVM IR level, to speak of a type as a well-defined "kind" of values for which equivalence, compatibility, and validity of operations can be checked.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faeon1wudpgctt4itwo4q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faeon1wudpgctt4itwo4q.png" alt=" " width="735" height="1250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More information:&lt;br&gt;
boosty: &lt;a href="https://boosty.to/dalerank" rel="noopener noreferrer"&gt;https://boosty.to/dalerank&lt;/a&gt;&lt;br&gt;
github: &lt;a href="https://github.com/dalerank/playful_programming_cpp" rel="noopener noreferrer"&gt;https://github.com/dalerank/playful_programming_cpp&lt;/a&gt;&lt;/p&gt;

</description>
      <category>generalizations</category>
      <category>values</category>
      <category>objects</category>
    </item>
    <item>
      <title>Red barrels problem</title>
      <dc:creator>dalerank</dc:creator>
      <pubDate>Thu, 05 Mar 2026 09:53:14 +0000</pubDate>
      <link>https://forem.com/dalerank/red-barrels-problem-2ghb</link>
      <guid>https://forem.com/dalerank/red-barrels-problem-2ghb</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2w40vsrudm45r2u66jjm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2w40vsrudm45r2u66jjm.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You're probably familiar with the fear a poet feels facing a blank page - it's a psychological state people experience when starting something new. It can arise in various situations, from drawing to creating music, any activity that requires creativity and starting from scratch without prompts. Behind this fear lies a reluctance to make mistakes or overly high expectations, fear of criticism and negative evaluations, and a lack of clear understanding of where to start.&lt;/p&gt;

&lt;p&gt;In game development, there's a similar issue but concerning existing elements, and it's called "red barrel." I've heard this term several times from my game-designer colleagues. The fears are the same: criticism, negative attitude towards changes, and a lack of a clear action plan.&lt;/p&gt;

&lt;p&gt;In the heat of battle, for example in a shooter game, if you see a red barrel, you'll definitely shoot at it because 9 out of 10 games encourage such behavior - red barrels explode. The barrel will explode and damage enemies who (quite foolishly) not only placed fuel barrels throughout the level but also smoke nearby (everyone knows smoking kills). I'll explain why barrels became a problem below.&lt;/p&gt;

&lt;h2&gt;
  
  
  The History of Red Barrels
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6uzm3vonbqh8q6swoc7x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6uzm3vonbqh8q6swoc7x.png" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The mechanic with barrels is simple and straightforward, but it wasn't always this way. Red fuel barrels are roughly the same worldwide; you can easily recognize them by their appearance. The color red has always been associated with danger and fire from childhood, making red barrels easily readable in battles and fitting seamlessly into the environment of shooters. In the 80s and 90s, riding the wave of successful James Bond and Rambo movies (such as "License to Kill" and "Rambo III"), barrels made their appearance in games. They were scattered around levels and served decorative purposes.&lt;/p&gt;

&lt;p&gt;Designers, in their quest for new game solutions, brought all sorts of items to the levels, from wooden crates to Godzilla. However, the barrels were not yet red and did not explode. In 1986, the racing arcade game "Speed Rumbler" was released, inspired by the Mad Max universe and post-apocalypse settings, where barrels beautifully exploded. This idea resonated with many, so within a year, this mechanic began to appear in all more or less well-known projects, but still as inactive objects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqs10qmomptnoyh2a3apu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqs10qmomptnoyh2a3apu.png" alt=" " width="800" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Starting from the early '90s, barrels began to be frequently used as an element of game mechanics. Especially after the release of Doom in 1993, where barrels were carefully placed at mob spawning locations and exploded from a single pellet, wiping out a handful of enemies around them. Other developers, in an attempt to replicate Doom's success, copied this mechanic, some successfully, some not so much. It was after the release of Doom that barrels became an integral part of most shooters.&lt;/p&gt;

&lt;p&gt;And of course, Half-Life 2, which not only provided barrels as a gameplay element but also allowed interaction with them through a physics model. It was particularly satisfying to hurl a barrel into a crowd of enemies using the gravity gun. Over time, game developers tried everything possible with this mechanic. Barrels became a cliché, and interaction with them returned to the shoot-it-and-it-explodes level.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzo0z859vq81u3gpir16e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzo0z859vq81u3gpir16e.png" alt=" " width="750" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  More does not mean better. Better is better.
&lt;/h2&gt;

&lt;p&gt;Returning to the "problem of red barrels" - this is the term used for a mechanic or typical game object, a cliché that has long been ingrained in games. It's challenging to improve without breaking the overall perception, but its absence would be even more noticeable. Trying to make them "differently" or diversifying with new ideas doesn't always work. As a result, when a designer is face to face with their "red barrel", the list of questions they have to answer grows exponentially.&lt;/p&gt;

&lt;p&gt;Often, such "red barrels" become unsuccessful mechanics from previous games in a series. They migrate between games, attempts are made to refine them, better integrate them into the game, but if the mechanic was unsuccessful from the start, no changes will fix it. Several times I witnessed such discussions among game designers who tried to change such a mechanic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Possible brainstorming session
&lt;/h2&gt;

&lt;p&gt;"Do we even need barrels in the game?" - Of course, red barrels have been in all games.&lt;br&gt;
"Can the player throw and explode them?" - Both throw and explode.&lt;br&gt;
"Can the player throw any barrels?" - No, our physics won't handle it, only red ones.&lt;br&gt;
"So, some barrels can't be thrown (concrete ones, bolted to the floor)?" - Right, let there be concrete ones.&lt;br&gt;
"How will the player know a barrel is concrete?" - Let it be a different color, like green.&lt;br&gt;
"What if the barrel is yellow?" - Let it explode with a delay.&lt;br&gt;
"Does the player know how to explode the barrel, shoot it, throw a knife at it, kick it, wait for a script?" - We need to include this in the tutorial.&lt;br&gt;
"What do enemies do near the barrels? Do they smoke? Just stand?" - We'll decide later, let's burden the level designers with that.&lt;br&gt;
"How does the player explode the barrels? Can enemies explode them?" - Both options, but we need to ask the physicists; we might not be able to handle both.&lt;br&gt;
"Do barrels damage the player?" - We need to ask the gameplay designers; a player death from a barrel might be a bad decision.&lt;br&gt;
"What about enemies? Should they run away from the barrel or hide behind it?" - Well, they were smoking there, let them hide already.&lt;br&gt;
"How do barrels affect the level; they might damage the geometry? What to do in this case?" - Let's ask the lead.&lt;br&gt;
"What size should the barrels be?" - Let the concept artists decide along with the environment.&lt;br&gt;
"Should a barrel block the passage? What if the player runs out of ammo?" - We should allow the player to move it.&lt;br&gt;
"What about enemies, can they also move barrels?" - No, let's not let them move them for now.&lt;br&gt;
"What about allies, can they move barrels?" - Yes, but only for the story.&lt;br&gt;
"With bosses, we'll come up with special mechanics for barrels, like throwing them?" - That's interesting, let's postpone it for the next milestone.&lt;/p&gt;

&lt;p&gt;Colleagues left the office well past midnight, both sides of the paper were filled with ideas.&lt;/p&gt;

&lt;p&gt;But the most interesting part begins afterwards. Once the designer sold his idea to the team, this red barrel starts doing good for everyone indiscriminately. Overcoming technical challenges, the team rewrites half of the engine to support this mechanic. In the end, players simply don't use it.&lt;/p&gt;

&lt;p&gt;If you remember any "red barrels" from games, share in the comments.&lt;/p&gt;

</description>
      <category>design</category>
      <category>gamedev</category>
      <category>productivity</category>
      <category>psychology</category>
    </item>
    <item>
      <title>How to build a mastaba</title>
      <dc:creator>dalerank</dc:creator>
      <pubDate>Thu, 08 Aug 2024 09:27:50 +0000</pubDate>
      <link>https://forem.com/dalerank/how-to-build-a-mastaba-1m65</link>
      <guid>https://forem.com/dalerank/how-to-build-a-mastaba-1m65</guid>
      <description>&lt;p&gt;The game "Pharaoh," released back in 1999, was one of the first games to offer step-by-step building of structures, which also required various resources. Off the top of my head, I can recall the Settlers series, Majesty, and perhaps a couple more. After "Caesar III," where the primary resource for building was coins, this was truly astonishing and innovative. It was a particular pleasure to watch the city come to life during the construction of monuments. I remember just building the minimum necessary infrastructure for a monument and simply observing as architects complained about the lack of materials, slaves ran back and forth between farms and construction sites, and traders periodically sold bricks. The rest of the city, of course, lived its own life. You could even forget about certain parts of the city for a while, and the game would continue. This is when you realize why the game remains one of the best city-building games: the distinguishing feature of the series is its "balance," a balance perfected down to the smallest detail.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjrogub3lpr4r91j466n5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjrogub3lpr4r91j466n5.png" alt="Image description" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Revisiting this part of the game, I can't stop marveling at how it was all implemented on those hardware resources, which were, I must note, very limited. Not everyone had 64MB of RAM back then. One of the innovations of the monuments was that they were composite buildings; individual parts could be replaced with others, which essentially allowed for creating buildings with different appearances from the same set of textures. Nowadays, it seems like this approach is present in every game, but in '99, only a few games could boast such a mechanic.&lt;/p&gt;

&lt;p&gt;At first, I tried to reconstruct the original drawing algorithm but quickly realized that not only could I not handle so many 'if' statements, but the compiler couldn't either. So, I had to improvise.&lt;br&gt;
In the original game, players gain access to the first monument in the fifth mission of the story campaign, when the map of Egypt and traders become available. The construction of a mastaba is closely tied to teaching the basic rules of trading. Compared to the previous installment of the series, city modeling didn't change significantly. The primary condition for the development of houses remains the same: it depends on the attractiveness of the surrounding land and the availability of goods from the nearest market. If you have residents, you can develop production, build new resource-gathering buildings, and so on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhg3vx8g5vv13ga1059a6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhg3vx8g5vv13ga1059a6.png" alt="Image description" width="755" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The number of people in houses depends on the current level of the house, and each level requires a new type of "resource" for maintenance. Moreover, these resources don't necessarily have to be products or goods; accessibility to temples and services like pharmacies is also required to maintain the house's level. While a single market can suffice for the initial levels of houses covering several dozen homes, it becomes noticeable after the mid-game that the number of buildings a market can support is carefully balanced. Even though reviews never explicitly mentioned it, players figured out that one market can support a maximum of 4 mansions at the highest level. Interestingly, even if their working areas overlap, having two markets doesn't support more than that number.&lt;br&gt;
The hierarchy of needs itself remained unchanged from the previous game in the series. It fit so well with the entire setting of the series that it remained unchanged up to "Emperor: Rise of the Kingdom."&lt;/p&gt;

&lt;h2&gt;
  
  
  How the built in 1999
&lt;/h2&gt;

&lt;p&gt;The first monument available to the player is the mastaba. In the original, it looks like this at the beginning of construction (screenshot from the original game)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7meoidbkdx5u8ab0fpou.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7meoidbkdx5u8ab0fpou.png" alt="Image description" width="458" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And like this upon completion (screenshot from the original game)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flaqsbj2bjkh056jziht5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flaqsbj2bjkh056jziht5.png" alt="Image description" width="499" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I had to tinker with the algorithm for building the mastaba. At first, I tried to restore the original one, but in the end, I gave up and made it simpler. The original algorithm draws the entire mastaba in one pass on the screen, caching identical images and redrawing residents and buildings that are overlapped by the monument during rendering. It turns out to be unnecessarily complex (don't ask how I managed to restore it from the binary, I definitely gained a couple of gray hairs), below is the code for rendering the mastaba itself.&lt;br&gt;
But then I looked at the resulting code and realized that a month would pass, and all of this would be forgotten because it's too complex. So I started digging through the internet in search of something simpler to understand. The solution came together after reading this article, which describes quite well the principles of rendering composite buildings in isometric view. This eventually led to breaking down the mastaba into its component parts and drawing them based on the general rules of isometric perspective.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxgale1xuh4o5k9uim89z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxgale1xuh4o5k9uim89z.png" alt="Image description" width="500" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On one hand, this greatly simplified the rendering logic and completely eliminated the need for overdraw of overlapping parts because each part is considered an independent building and is drawn based on general rules. On the other hand, now the mastaba consists of three types of buildings: slanted wall, entrance, and solid wall. The peculiarity of this implementation is the necessity to recalculate the rotation for each type depending on the map's rotation and the rotation of the mastaba itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gathering bricks
&lt;/h2&gt;

&lt;p&gt;The textures for the mastaba parts are divided into segments of the same size, from which the entire building is assembled. The size of the mastaba can vary from 2x3 to any reasonable size for a specific map, with the one in the pictures above being 2x5. In the resources, this data is split into two files, mastaba.sg3 — this is the description (sg3 stands for Sierra Graphics V3). The texture compression format, developed by Sierra Entertainment employees in 1988 and used in most studio games, but not well-known outside the studio. It provides good results when packing textures with RGB data in 16-bit, all pixels with a value of 0xf81f are interpreted as transparent, this is done with the expectation of subsequent RLE packing, which can compress such sequences of identical pixels into a couple of bytes. You can read more about the format here.&lt;/p&gt;

&lt;p&gt;The texture data is stored in .555 files. Most images are located in the .555 file with the same name as the .sg3 file. This was done with the idea of possible patches, to have the ability to provide users with partial changes. The internet was not particularly fast back then, so saving even 0.5Mb, which the sg3 file occupies, was a significant argument for such an architecture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvosh5kjd44783no27tzy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvosh5kjd44783no27tzy.png" alt="Image description" width="525" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The graphic data can be packed in various ways in the .555 files, depending on the type of texture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uncompressed — such images are stored "as is" by rows, from top to bottom, left to right in each row. Thus, if the image has dimensions of 20x30 pixels, it means that the data for this image consists of 20 * 30 = 600 unsigned 16-bit integers representing the colors of each pixel.&lt;/li&gt;
&lt;li&gt;Compressed — transparent pixels for these images are encoded using run-length encoding. This format has remained since Caesar II and was used less and less over time. The data is processed byte by byte as follows:&lt;/li&gt;
&lt;li&gt;Isometric — textures with a width divisible by 30 pixels and consist of two parts:

&lt;ul&gt;
&lt;li&gt;"Base" part: rhomboid base of the tile, stored in uncompressed form because there should be no transparent pixels. The dimensions of the base texture are determined by the game to which the SG file belongs: Caesar 3, Pharaoh, Zeus use tiles of size 58x30&lt;/li&gt;
&lt;li&gt;"Upper" part: the remaining pixels that are not part of the base, and since they can contain transparent areas, they are stored in compressed form.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;But that's not all, if you look at an isometric tile, you will notice that half of the space is not used, these are transparent pixels and they can be excluded from the encoding by simply skipping these areas. Thus, only significant pixels are recorded, and the texture size becomes even smaller. For example, with such a packing algorithm, a texture of size 10x6 out of 60 pixels is packed into 36.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx9uydk6bqrip683yiuay.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx9uydk6bqrip683yiuay.png" alt="Image description" width="449" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Based on this data, which is read, unpacked, and correctly assembled, full-fledged textures are obtained. The storage format was primarily designed for the Windows operating system family and its graphics stack, allowing for quick blitting (overlaying) of textures without transparent pixels.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzuripkibxmx8ccrlq06.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzuripkibxmx8ccrlq06.png" alt="Image description" width="800" height="643"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing the construction site.
&lt;/h2&gt;

&lt;p&gt;The construction process is divided into 8 parts: two site levelings and 6 stages of laying stones. To build a mastaba, stone is needed, and for laying one segment, 400 stones are required, which must be delivered from the warehouse to the construction site. After that, the bricklayers begin laying the stones (screenshot from the open-source version).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6wh90sdmu3n7cudq51z2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6wh90sdmu3n7cudq51z2.png" alt="Image description" width="463" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The calculation of the required texture turned out to be quite simple; edge textures are used along the edges of the site, while the internal tiles are filled with seamless stone tiles. For animating the monument construction process in the game, separate types of buildings and inhabitants with corresponding sets of animations were added, which was quite bold for games of that time and resource-intensive. The number of animations doubled compared to the previous game in the series, and the texture volume increased accordingly&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq8d16pvj4zjnyhs35ios.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq8d16pvj4zjnyhs35ios.png" alt="Image description" width="525" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing rendering bugs
&lt;/h2&gt;

&lt;p&gt;Due to the new approach to rendering the mastaba, incorrect rendering of individual parts occurred. I had to add a bit more to the renderer to teach the engine to render the top parts of textures. For this, the original texture is divided into two parts: the base and the upper part. Then, when overlaid on top of each other, they will form a cohesive texture, free from rendering order errors in isometric view. All bases can be rendered in the first pass, eliminating overlap with the figures of inhabitants, and then overlay the upper part to hide the inhabitants who ended up behind the building. As a result, we get a normal view of the buildings. (screenshot from the open-source version)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcubhl43jn2nthz2n8i93.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcubhl43jn2nthz2n8i93.png" alt="Image description" width="800" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A little bit of magic with C++, wait for a few in-game years, and the construction is completed. Almost.... I still need to tweak the texture indices a bit when changing the city's orientation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqjrhtgr5t3zpfjy4jiam.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqjrhtgr5t3zpfjy4jiam.png" alt="Image description" width="800" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A little bit of magic with C++, wait for a few in-game years, and the construction is completed. Almost.... I still need to tweak the texture indices a bit when changing the city's orientation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi51lrd8lxy22xsjcdzkh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi51lrd8lxy22xsjcdzkh.gif" alt="Image description" width="752" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code and logic reuse.
&lt;/h2&gt;

&lt;p&gt;Also in Pharaoh, specifically for monuments, a dynamic resource model appeared (as far as I understood from the available source code) — the monument was essentially a warehouse, with set rules for goods. If in Caesar the space for resources was reserved at the warehouse immediately, here the bricks appeared on the construction site only when they were physically delivered on a stretcher. On one hand, this allowed players to abuse the game with save-loads; for example, if you catch the moment when the porter unloads the goods, reloading the save could allow you to get that item again. On the other hand, it added new connections to the simulation and made it more complex.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiv7cry4mzv7hy0a5a5mc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiv7cry4mzv7hy0a5a5mc.png" alt="Image description" width="398" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to see and try
&lt;/h2&gt;

&lt;p&gt;The project lives here (&lt;a href="https://github.com/dalerank/Akhenaten" rel="noopener noreferrer"&gt;https://github.com/dalerank/Akhenaten&lt;/a&gt;). The original render has been restored and partially rewritten; I am restoring the game mechanics, buildings, and inhabitants as I get to them. Missions are restored up to 5; to play, you will need resources from the Steam/GOG/Roger versions. Or join the Discord (&lt;a href="https://discord.gg/HS4njmBvpb" rel="noopener noreferrer"&gt;https://discord.gg/HS4njmBvpb&lt;/a&gt;) channel where I post updates on the development progress.&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>pharaoh</category>
      <category>caesar3</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
