How Dwarf Fortress is built
stackoverflow.blog
stackoverflow.blog
> A: It’s probably boring for me to say, but I just can’t beat the drunken cat bug... That was the one where the cats were showing up dead all over the tavern floor, and it turned out they were ingesting spilled alcohol when they cleaned their paws.
I think that bug explains very well just how deeply complex Dwarf Fortress really is. Drinks can be spilled. Some drinks have alcohol. If cats step in something it sticks to their paws. Cats clean their paws, causing them to ingest what's on them. Enough alcohol will kill a cat. Put together: dead drunken cats.
Clearly there's a bug here where the cat will keep wandering around on the sticky floor, and then keep consuming the alcohol off it's paws.
The obvious fix is to add a feature wherein different creatures have preferences about where they go next, and then use that to have the cats avoid the bar floor if they can.
As a bonus you can include stuff like "Cats don't like hanging out in crowded areas" so that they'll also stay out of the main hall when the army is gathering to muster forth, etc.
(/s, but only slightly :) )
When you look at an item listing and you see something like “Mead”, that is truly all the item is —- it isn’t a cup of mead, it’s just a vague amount of the liquid mead itself, as if your hand was the only thing keeping it from hitting the ground.
But there are containers that can hold your liquid. You have mugs and goblets that hold one quantity of “Mead”, giving the impression that one count of mead is like a generic serving size. You also have barrels and pots that hold stacks of “Mead”.
Creatures are kind of like walking containers and have their own detailed inventories. Among the things you’d expect to find like armor, weapons, and books, you might also find a “coating of tears” on a crying dwarf, or perhaps a “spattering of blood” on a murderous elf.
They’re not just static inventories for the fun of a story, creatures do interact with them and use them. Dwarves covered in a vomit item will (hopefully) put any available soap in their inventory and use it to clean themselves in water, for example.
Cats are simple and just clean themselves with no water or soap needed. The catch with them is that they ingest whatever they have cleaned off of them.
So, putting all this together: The problem was that cats pick up a whole “serving size” of alcohol and proceed to clean themselves, ingesting the entire serving. The bug surrounds the vagueness of liquid sizes.
And it was fixed accordingly! Cats are still vulnerable to the effects of self-cleaned alcohol, but the strength is now proportional.
https://www.bay12games.com/dwarves/mantisbt/view.php?id=9195...
https://www.nytimes.com/2011/07/24/magazine/the-brilliance-o...
https://twitter.com/DwarfFortBugs
It's just funny Dwarf Fortress bugs.
That's not even (necessarily) a bug: whether convicts can win/hold elected positions is a aspect of applicable law (albeit a weird one), vampires (IIRC) have high social stats and skills and so are well-postioned to win elections in general, and dwarves (and for that matter humans) don't necessarily update their opinion of someone just because they were convicted of a crime (especially if they don't hear about the conviction, which (knowledge transmission) I recall was added to the game modeling at some point). So this is like a headline "Bob Smith Convicted of Murder; Wins Mayoral Election Anyway", which seems weird-but-possible in real life.
It turns out that my dogs weren't alcoholics - it just happened to be that beer was the only food source they had zoned access to, so they were drinking it out of hungry desperation, and while it gave them enough calories to live on, it also gave them cirrhosis.
Beer brewed from hops doesn't cause hyperthermia, it's harmful to dogs because they experience the same effects of ethanol poisoning that humans do (e.g. cirrhosis), at much smaller doses.
And now that I dug up the Reddit AmA thread (https://old.reddit.com/r/Games/comments/d7cqjz/we_are_nolla_...), there's a comment there about the drunken dead cats ...
Dwarfs trying to clean their inner organs (dwarf wounded, doctor closes the wound, dirt stay inside)
Undying children in the moat water (for years... just swimming there...)
Killer carps (there was a long time during which carps were really overpowered because constant swimming was buffing them up really good, dwarfs getting close to water sources were eaten by carps)
Catplosions (Tarn loves cats, cats reproduce, too many cats kills DF performance)
This was a particularly insidious one because the usual strategy of culling excess livestock doesn't work out when applied to dwarfs' pets (pets can't be designated for slaughter, and other means of making pets die will make their owners upset). With most animals, you can avoid the pet adoption issue by just not marking them as available for adoption, so you wouldn't have to worry about a dogsplosion, sheepsplosion, etc. Cats do not become pets through that system. Instead, a cat adopts a dwarf.
And get sad because his pet died. And then eventually start tantruming and a tantrum spiral would begin.
It's so crazy when you try to make dwarves feel great all the time and then the simulation comes up with some completely insane causal chain that messes up everything.
I once tried to isolate a miasma problem with a wall. Which works fine, unless the dwarf tasked with building the wall decides he needs a break, sleeps on the floor and then gets grumpy because he just slept on a hard surface in a smelly area.
A somewhat effective solution is to use male cats for stockpile protection, and keep female cats caged (which IIRC stops both adoption and breeding) and only let one out at time (cage any resulting (female) kittens immediately). There's not (yet) any simulation of evolutionary pressure to adopt a owner quickly, so you can just prefer kittens that do so for the next breeder when the current one dies of old age.
Gelding (neutering) the male cats also works, but is less sustainable if you don't have a reliable source of replacement cats from migrants or trade caravans for when the current ones die of old age. Spaying is not supported AFAIK.
You can also just remove the ADOPTS_OWNER token via raws editing.
H. W.> You're implying that a group composed entirely of female animals will… breed?
I. M.> No. I'm, I'm simply saying that life, uh… finds a way.
TIL this was a bug and how it was a bug! Wow! Back when I played DF it really seemed like it was simply accepted folklore that the carps in DF were really strong and the common advice was don't build your base too close to rivers. Having not played in a long while, I had always thought this was intended.
At some point, we got into a discussion over art style and realism. He made an observation that still sticks with me.
"The style sets expectations. When something breaks a real world law of nature or logic because of a bug, it doesn't feel as jarring, because the style is already cartoon-y."
It made me think about just how malleable expectations are with regards to game systems. Train a player to expect realism, and breaches become infuriating. Train a player to expect the unexpected, and the unexpected becomes intriguing and fun.
(More modern tip of the hat to Fortnite)
Even fortnite has a kind of logic to it, haphazard as they may be (though it’s also so loosely defined, that I find it completely uninteresting — it’s a dumpster fire of cosmetic items with no real theme or nuance; this is because its more a modern shopping mall [ an arbitrary context for social groups ] than a game system).
It’s why simpsons can revert (nearly) all damages every episode (that’s simply the rule of the world), but if it tried to violate that rule and persisted those changes in any meaningful way, it would feel like complete nonsense. (They do however do it for self-referential jokes and such, but these aren’t persistence so much as temporary anomalies) At best, they’re allowed to forget something exists altogether.
Sounds like the answer is more taverns.
My understanding of the legend is that a player began experiencing a catsplosion, and wanted to find a way to get rid of the cats. So he started tinkering with the game a bit, and eventually tried setting the blood temperature to a very high number. This killed the cats, but also had the unfortunate side effect of setting them on fire. And the cats were multiplying faster than they were dying, so there was a massive, expanding fireball of burning cats.
If this legend is wrong, I'd love to hear another version.
I'm curious if the fix was to just remove the dirt from the simulation or if Tarn actually went ahead and simulated infections (or more realistically, used an existing infection mechanic).
Imagine getting drunk by licking beer residue off your hands.
That's what intrigues me, Not played the game but this must because there were a list of things which could get the cat killed right? Then how come this is an unexpected bug?
Q: Why was this was a mistake?
A: When you declare a class that’s a kind of item, it locks you into that structure much more tightly than if you just have member elements. It’s nice to be able to use virtual functions and that kind of thing, but the tradeoffs are just too much. I started using a “tool” item in the hierarchy, which started to get various functionality, and can now support anything from a stepladder to a beehive to a mortar (and pestle, separately, ha ha), and it just feels more flexible, and I wish every crafted item in the game were under that umbrella.
We do a lot of procedural generation, and if we wanted to, say, generate an item that acts partially like one thing and partially like another, it’s just way harder to do that when you are locked down in a class hierarchy.
Preach:
https://ericlippert.com/2015/04/27/wizards-and-warriors-part...
https://ericlippert.com/2015/04/30/wizards-and-warriors-part...
https://ericlippert.com/2015/05/04/wizards-and-warriors-part...
https://ericlippert.com/2015/05/07/wizards-and-warriors-part...
https://ericlippert.com/2015/05/11/wizards-and-warriors-part...
I have certainly committed all of these sins, too.
Good point! Skimmed the blog posts, seemed to have useful enumeration of techniques with considerations.
My policy: OOP is like salt. Use little and that's great. I only allow a single inheritance layer, and ideally no inheritance at all.
The trouble is C++ and similar object models poor support for composition and implicitly penalizing uniform object structure.
(E.g. call multiple base methods in a subclass - pain ensues. Add virtual calls to the mix, it gets really iffy.)
Even Python and Ruby with explicit mixins but the old model get hairy.
I'm not being critical either, I'm seriously curious how somebody would implement this behavior in Go. Like you say, just struct with methods is a very appealing mental model since you have fewer moving parts, but how does it deal with a scenario like this which is very common in game dev?
I'm slightly confused about what you're trying to describe, but maybe it's something like this?
https://play.golang.org/p/smPyWvBvWWp
We can make both Food and Animal statisfy the "Animateable" interface.
Go also has a syntactic shortcut which is similar to inheritence, but more explicit. If you include a field in a struct without any name, it is considered "embedded", and you can call methods on the field directly, without referencing its name, which ends up looking the same, at the call site, as inheritence.
https://play.golang.org/p/cIMqQqE0eVc
But everything is still explicitly laid out in the struct -- it's just a simple struct, no inheritence shenanigans.
I think interheritence is a mistake, but interfaces are the bees-knees. Even in C# (which is my main language these days, 'cuz that's what you use if you're making a game in unity), I just use interfaces, not implementation inheritence.
(And even interfaces I don't use much -- but when you need it, you need it!)
The idea I was going with Animateable was not animation (poor wording on my part), but effictively giving the properties of a creature to a thing, ie magically animating it. So I have an ability in-game that lets me turn anything into a creature, thus merging the Creature interface with whatever other interface this has. From what I'm getting from you, that means every single thing in the game must implement the Animateable interface.
Now lets do another one, I want a Metalic property. Say these are things that when hit by lightning will give off lightning damage. Then there's a curse called Midas that will let me turn anything metallic.
So I have a Wooden Hammer object which I midas curse mixing in metalic, then a wizard animates it so that it has the properties of a creature, and I have a creature that when I hit with lightning gives off sparks that I can also use to hammer nails.
Point being, in this world you're basically requiring every single thing to implement every single interface which sounds like a nightmare, where with more of an ECS style system, you just merge in the new behavior and call it a day.
(I would say interfaces/inheritence are useful for simple high level abstraction of basic concepts with multiple implementations (here's an interface for a compression algorithm, or a RNG, or whatever), not so useful for trying to model complex game-world relationships. And to me, the useful part is the interface, whereas inheritence mixes in two unrelated concepts: implemementation-sharing and interface.)
But you don't need either of those for ECS, right?
If I understand it correctly, ECS at its core is basically an optimization of the struct-of-arrays datastructure. E.g., something like this is a super-basic ECS:
struct World {
Comp1[] Comp1
bool[] HasComp1
Comp2[] Comp2
bool[] HasComp2
...
int NumEntities // all arrays have this length
}
I'm a big fan in general of struct-of-arrays vs collection-disparate-structs-with-pointers. Besides being way faster, it tends to make code clearer, too. ECS seems like a more efficient and convenient evolution of that pattern.At least from what I've read. No real experience. Take with 13 grains of salt. :-)
P.S. If you feel like it, I'd be happy to explore some concrete code (you first!). It's always very interesting to me to try to explore all possible ways to express some concept in code.
By structural typing. It’s a form of satisfying an interface by composition.
edit: You cannot, however, explicitly declare that a "Chicken" is supposed to be a Food and/or an Animal. And you can't directly inherit implementations; to make Chicken directly use a generic function you need to do something like implement "baseSpoil(Food)", and then have the body of "spoil(Chicken)" explicitly call "baseSpoil(self)".
As mentioned in another reply, there is a shortcut. You can declare that the Chicken structure includes (anonymous) Food and Animal fields. Then, if you call "spoil(myChicken)", Go will automatically replace it with "spoil(myChicken.Food)".
That's been my observation as well - there's no free lunch and DRY isn't free either, certainly not if you use inheritance chains to achieve it.
I'm starting to think that the only programming axiom that will survive in the end is KISS.
And what an acronym given the context!
NSM would be the minimum element set of concepts shared by all human cultures, which can be used to derive the rest of concepts, and it's heavily based on anthropological field studies.
And it includes the numbers one, two and many, (also few, some & all). So that indicates some special meaningful distinction for us in that jump from two repetitions to start abstracting away.
But the single responsibility principle and the idea that you should divide your code in components where the lower components should be abstract by the point of view of the higher ones are almost never wrong.
Not by coincidence, those last two are consequences of how people think. While KISS is kind of a physics law.
I would agree to that as a goal, but not as a dogma. It depends what you build, I guess.
Nobody on the face of the earth has ever used Functional Reactive Programming. It's a made up concept. In fact it's also definitely not one of the concepts that inspired the most popular pattern in React.
Of course it's relatively easy to build shiny clean wrappers around the dirty work that others have had to do on your behalf.
First off FRP is actually a term. Functional Reactive Programming. It is 100% a functional paradigm that gasp by DEFINITION cannot be procedural. So you truly didn't know what you were talking about here: https://en.wikipedia.org/wiki/Functional_reactive_programmin...
Second there are many languages/frameworks that use this paradigm. React partially uses this paradigm. But I will list two popular ones that strictly follow it... just note that there are more. Much more.
Take a look at elm. Elm is a fully functional UI library and language that is 100% pure, functional and has no OOP. Believe it or not ELM is not some toy, it is production ready and actually measurably faster than react. This language is what popularized the FRP pattern which is partially used by React today. See here: https://elm-lang.org/examples/mario
Note the load time and latency on the mario game. React doing the same thing will be slower.
Another language is ReasonML. ReasonML is essentially a language that compiles to the browser and has one to one correspondence with another functional language... OCaml.
ReasonML is Created by the creator of React, Jordan Walke. Coupled with React as framework, ReasonML is essentially the ideal GUI paradigm that Jordan would recommend everyone to use in the ideal world. However due to the fact that everyone is use to javascript, Jordan instead as a first step, ported FRP concepts over to a language called JSX (essentially JavaScript mixed with html) and is slowly nudging the world in the direction of GUI programming using the functional style: https://reasonml.github.io/
Make no mistake the creator, of the most popular GUI framework in the world is a supporter of the pure functional paradigm, and he is heavily and successfully pushing the functional style programming of GUIs into the mainstream.
OOPs being the dominant paradigm for GUIs has, in the past five years, become a false statement.
You're right on the wrapper part though. Assembly language is essentially a procedural language so every functional thing that exists on top of it, is a wrapper. But I mean this is a pointless observation.
How does it run on the browser?
I can't speak to ReasonML, as I have not used it, but my impression also is that it takes advantage of other people's GUI libraries considering that I've heard Revery compared to Flutter (and Flutter outsources its rendering to Skia as well as relies on rather imperative RenderObjects beneath the functional reactive layers). Please correct me if I'm wrong.
I would be very interested indeed to see a GUI framework built from the actual ground level up in an entirely functional reactive manner. Do you know of any?
Unfortunately it's discontinued, probably rightly because it's definitely not for teamwork. But really, it doesn't depend on anything OOP in the strict sense.
MVU is more towards functional rather than imperative programming.
You still don't necessarily need to model the graph at the object level though. You could model your graph as a set of pairs, ie edges. If performance was more of a concern you could do it as a map where each object was a key and the values were a list of the connected objects. You could also separate out the value from the graph behavior and have a GraphNode object that wraps each value object.
The bigger point though is when you have networks of objects that are relying on each other to perform functions, that's where the problem is, and where you start to rely on mocks and stubs for testing, which really should be considered a smell in its own right. Your better off making the interface between objects values rather than having hard references between objects as described in this talk: https://www.destroyallsoftware.com/talks/boundaries. Once the interfaces between your objects are values instead of references you're free to connect your objects together in any way you need and are not stuck with the fixed graph as originally designed.
> Once the interfaces between your objects are values instead of references you're free to connect your objects together in any way you need and are not stuck with the fixed graph as originally designed.
Absolutely, same can be said about relational data representation for example.
I have a gorilla class and a banana method on the class, can I ever use banana without the gorilla? No. The simple act of having a class screws it all up.
Make the banana a pure function, or one that is defined in terms of a polymorphic parameter that it mutates.
func banana(x: animal){...}
banana(gorilla);
The way to do it via OOP is base class methods and importing the method to all children via inheritance which is just bad and universally reviled among even practitioners of OOP. class Animal()
{
banana()
}
class Gorilla() : Animal {
}
Technically there are slight fair advantages and disadvantages to the OOP way when you don't account for inheritance and polymorphism but all that is gone once you do account for them.In my experience it is nigh impossible to design-pattern your way out of a language simply being unable to express what you need it to express without incurring a severe performance penalty (anathema for game development) or resorting to code generation (which is itself prone to ending up as a Gordian knot).
No it's not. I'm talking about having nominal typing but easy support for delegation (e.g. look at how Kotlin does it).
But as the other reply said, patterns are a language smell - the language needs to support that style and make it idiomatic. Otherwise, if you give people the choice between doing it right but verbosely and doing it wrong but more quickly, guess which one they'll choose. https://www.haskellforall.com/2016/04/worst-practices-should...
I have a player, NPCs, enemies, and wild animals. Should they have any class hierarchy at all? If my code matches the game world, what happens when I was to add golems and let mages turn castle's into entities that act just like an NPC would? Should my class design be so tightly coupled with the elements of my world? I don't think so but what alternative works best?
Its the fragility of large inheritance hierarchies. They work well for very rigidly defined real world structures but not so well in most real-world usages.
Tarn was wrong about this though:
> Using a single object with different allocated subobjects is almost certainly worse for cache misses
It depends a little on the context, but having object pools is exactly the right thing to do when you're trying to scale. It allows you to group together similar data, reducing cache misses when batch processing. You can even cache-align your primitives, or even run SIMD and multi-core jobs to batch update an entire set of attributes that belong to multiple objects.
Goes until 43:25.
The whole talk is worth watching. It's basically about the higher level problems of business app development, how to address them, and how Clojure does address them.
By creating a tool class you haven't extended the set, you've instantiated a subset of the set of items that contains the items that are tools but nothing else. It's obvious why it is so difficult to represent a tool that is also e.g. a consumable item. The set of items that are both tools and consumables is a superset of the set of tools and set of items. You can't represent it through a second layer of inheritance because it only lets you create a subset of the items that are tools. You obviously have to use multiple inheritance for something like this because it will let you form the set of items that are both tools and consumables. Of course, multiple inheritance is very messy so you should try to avoid it.
Entity component systems are still in a half-baked state, with everyone rolling their own slightly different conceptual model. They're solving a problem, but not solving it well.
One promising direction is getting rid of entities. Components need to link to entities and other components anyway, so one may as well treat entities as zero-size components. Old writeup (not mine): https://github.com/kvark/froggy/wiki/Component-Graph-System
ECS is so common and easy in lisps that it doesn't even warrant its own name.
https://en.wikipedia.org/wiki/Component-based_software_engin...
"Component Software: Beyond Object-Oriented Programming"
https://www.amazon.com/Component-Software-Beyond-Object-Orie...
You are essentially describing ECS here. In ECS, entities are nothing but a "handle" without any additional data, normally just an integer used to link common components together.
If entities could be IDs to which components are connected, or containers holding components. Either case has disadvantages.
If entities hold components, then iterating over components means iterating over entities, which slows down all systems. A rare type of component still degrades with adding entities.
If instead components link to entities, and you want multiple components to interact, then these interactions slow down the system because of multiple lookups that need to be done.
Author proposes to use a graph structure between components, getting rid of entities-component duality. Proposes to use pointers which allows calling into any component and process then all required components.
I am not entirely sure if this would solve all problems, but this seems to be the proposal. It seems setting up the graph dynamically would be quite the task, though. For example, I don't immediately see how to guard against cyclic behavior and too many calls into a single component etc.
This is far from ideal, and is equivalent to a very naive implementation of ECS. Having the user have to use pointers is not ergonomic, and the random access of secondary components via those pointers destroys the caching benefits of data-oriented design. Having a memory pool don't automatically give optimal cache usage, only if you have very little data.
Most modern ECS frameworks solve the issues you mention by allowing systems that "query" more than one component at a time, not requiring a lookup. For example:
system<Position, Velocity>().each([](auto p, auto v) {
p.x += v.x;
p.y += v.y;
});
This is supported by lots of mainstream ECS libraries already. It doesn't require lookups inside the System's hot loop, doesn't require random memory access via pointers, and also doesn't require managing/cleaning up those pointers.The nice thing about keeping Entities as opaque handlers is that a "System Iterator" is able to abstract away the issues mentioned and implementation becomes a mere detail. An ECS library could even use the implementation the GitHub wiki link suggested, since ECS is currently abstract enough to allow it, because of the opaque handlers.
Nevertheless, I wanted to highlight that the quoted article clearly states that the proposal is not an ECS and is in fact superior to it.
Got it! Yeah, I totally agree with you.
A program that puts a handful of form widgets, consumes a bunch of text or spends most of its time waiting for I/O is far from the same domain.
The only time I used inheritance was while implementing a job execution framework. It fit the pattern nicely.
IIRC I already wrote that here on HN, but I think implementing a simple rogue-like is an excellent exercise to get familiar with any programming language.
https://www.youtube.com/watch?v=wfMtDGfHWpA
I think inheritance makes the most sense when your problem domain has been known for decades - like airline reservations. But for new blue sky projects - you always seem to wind up in these snafus that break your rigid class hierarchy.
I like the way you put that. Though humans and dogs are 85% similar at a DNA level, so makes sense for them to inherit from a common parent. And my guess is robots and robot dogs would be ~85% similar at a building block level, so dog would inherit from robot.
I think go easy on levels of inheritance but have really strong root classes that most things inherit from.
In what concerns Java you have multiple inheritance of interfaces, and as of Java 8, traits.
Windows C++ frameworks, from Microsoft and Borland/Embarcadero make use of multiple inheritance.
is a good read on that... or rather, its a spot to start thinking from.
It ends with:
> A nun of the temple whispered to Jinyu: “This problem has several solutions, but I dislike all of them.”
> “Therein lies its value,” whispered the abbess in reply. “For we are all of us doomed in this profession: our designs may aspire to celestial purity, yet all requirements are born in the muck of a pig-sty. I trust that this monk can succeed when the stars align in his favor, but when they do not, how will he choose to fail? By cowardly surrender? By costly victory? By erroneous compromise? For it is not he alone but the temple that must bear the consequences.”
There are also a set of "topics" hidden with a mouseover at the bottom that can waste a day away without difficulty.
They make changing behavior dynamically extremely simple. Instead of needing to hardcode classes for each different type of thing players may want to create in your world, you just assign and unassign components. Give a rock the Moveable component and now it moves. Remove the PlayerControl component from the player and put it on, I don't know, an orc -- now you've implemented body swapping. They're even more useful in a game like traditional roguelikes, where you don't have to worry about animating all these dynamic states.
I've actually never thought about how a component system might fit into a more traditional business application; it's an interesting thought experiment but I'm not quite sure it would be a strong benefit.
and a bit about multiple inheritance in LPC - http://graphcomp.com/info/mud/mudos/lpc/constructs/inherit.h...
And another bit - http://www.geas.de/tutorial/lpc_57.html
As to seeing it in other languages... this gets into a mixing - https://en.wikipedia.org/wiki/Mixin
An example of that in Scala - https://docs.scala-lang.org/tour/mixin-class-composition.htm... or https://www.baeldung.com/scala/class-composition-mixins
The issue is that for most situations, the additional conceptual load of multiple inheritance gets difficult.
He also goes on to show a text editor written entirely in the rules engine (which he uses to develop the game in), really cool stuff!
Kudos Mr. Adams for making the achievement and moves gaming history.
Going back to the interview, I found this line (and the logic attached) interesting:
>Making the item system polymorphic was ultimately a mistake, but that was a big one.
>When you declare a class that’s a kind of item, it locks you into that structure much more tightly than if you just have member elements.
I guess when the game becomes moderately complex then ECS or something similar suddenly makes a lot sense.
I can get with that take when it comes to Patreon but it's harder to demonstrate ok-ness-with-it with family. Let's say she's really not all that jazzed about it, actually. What is she gonna do, throw her son out on the street? A lot of parents don't have it in them to do that even if they think they would be justified and it would be the best thing for their child. An adult shouldn't put their parents in that position. He should be making sure his mom is provided for, not the other way around
For example: https://www.middleclasspaas.com/
But if it comes from a friend, or a colleague then I'm super focused on it until it's done.
It's almost as if I do projects to show off to other people or I like to serve other people.
I think Joel and Fogcreek is a great example. He started out with the premis that you don't need an idea for a successful software company, you just need to find great devs and create the best working conditions and then success would come. This was a novel idea at the time since Apple was the only FAANG that even existed and this was their "beleaguered" period. As should come as no surprise to anybody, they ended up creating...bug tracking tools and a kanban board, albeit quite good ones.
Another thing that helps, since the problem is not your own but somebody elses, you don't get bogged down trying to figure out the best way to solve it for yourself, you just solve it for somebody else without all the emotional attachment to the problem. This lets you instead be emotionally attached to the process.
Point being, I think you're selling yourself short.
This rings very true to me
So it is quite natural that we prefer to do things for others. It makes you feel great when others thank you for it.
I think it's because the early stages of a new project, where you're doing a ton of googling and head-scratching, are kind of painful for me. I need that team or client or business owner counting on me in order to push through that part.
Then I can roll on my own when I get to the fun stuff (for me) - creating features with well-understood tools, and refining and organizing code.
> Whether it is successful is irrelevant.
At some point something needs to be successful or you can't keep working on it, right?
Well.. until you accidentally create a broken release, that is. That's _real_ sweat.
I do think there is a huge hazard of working for oneself that is not getting paid and may literally starve. The guy who made HolyC comes in mind but he also has mental issues.
That said, I've always wondered if Dwarf Fortress would be a more smooth experience if it had more developers or was just open source (understandable that it's not though since it's basically Tad's passion project). The biggest headache was always the lack of multithreading, since your fortress really starts to chug once you pass maybe 150 dwarves or do anything exciting with fluids. Regardless, it's amazing what one developer with a great idea and an enthusiastic community has been able to do with the game.
Even if I deployed his code tonight, there's no guarantee users would switch over to my LeeChess clone :)
In the case of Dwarf Fortress it's just "download my exe and please donate if you like it!"
You're not an employee for somebody else (correct? It's your own project) - it's not a salaried or hourly position where somebody else is currently signing your paycheck. You obviously don't hate it (I hope? If so, not sure why you wouldn't have canned it yet)
Thus, this is what most people would refer to as a passion project. You may have a different meaning of that term in your own mind, but I think, on average, most people would refer to what you're doing as such, and not to be malicious in doing so. I wouldn't let it hurt you, I'm sure that's likely not a friend's intention.
FWIW I have found that three things help me deal with this sensitivity:
1) Take it as motivation to be more outwardly "professional" about my art. Improve the website, be more active on social media, try harder to exhibit, even (ugh) sell things.
2) Remember that most people are just saying that out of ignorance: they don't have a mental model for anything outside of "work for the Man" or "mess around in free time."
3) Have examples ready if someone needs an explanation, and also as inspiration for yourself. For instance: was William Carlos Williams[0] a "hobby" poet?
[0]: https://www.poetryfoundation.org/poets/william-carlos-willia...
In the case of Dwarf Fortress, I would say for him it is "the sole project he's been working on for 20 years now, which takes up $large_number of hours per week, and which has been sustaining his life now thanks to a fan base which have proven themselves reliable contributors of financial support. And he really enjoys writing the code too"
This is spot on. If only you would articulate my feelings for me all the time, that would be great!
Once you get absorted at night by imagining your surroudings upon reading the game actions, the game feels scarier and more "real" than any current 3D adventure game.
It would literally be easier to completely make a new game from scratch with async and threading designs taken into account, instead of trying to adapt an existing monolith.
Async and multithreading are complex and introduce many subtle bugs. It's not so easy to just move to that from a single-thread event loop.
Maybe, but only if it was under the benevolent dictator model.
He perfected a Patreon-style support system before Patreon was really a thing, and he keeps plugging away at it, keeping people interested.
(Dirty secret - he’s found ways to let people access parts of the code he doesn’t care about such as the sound or SDL)
Often if you have an idea but aren’t doing the low level implementation it’s harder to understand why something should change vs doing it yourself - in the latter case you just change the implementation and the design at the same time.
It's even more than that - I can spend ridiculous time in legends mode just reading facts and events going from one personality to another trying to "feel" the world. It's like from these pieces of trivial information a bigger picture emerges, partially consisting of the facts and partially of random connections my brain made. It's an amazing experience.
Something I found insightful about TFA was this:
> Q: With your ~90 side projects, have you explored any other programming languages? If so, any favorites?
> A: Ha ha, nope! I’m more of a noodler over on the design side, rather than with the tech. I’m sure some things would really speed up the realization of my designs though, so I should probably at least learn some scripting and play around with threading more. People have even been kind enough to supply some libraries and things to help out there, but it’s just difficult to block side project time out for tech learning when my side project time is for relaxing.
This is interesting. I constantly feel the temptation to learn new tools, new languages, new stuff. I get sidetracked by the tech. But the key to successful games seems to be designing them and sticking to the work of making them work no matter the tech or language. If Toady had kept playing with programming languages and frameworks instead of sticking to his actual project -- creating a game -- maybe Dwarf Fortress wouldn't exist, or it wouldn't be as featureful.
You can see the new tileset in action here, demoed by Tarn: https://www.youtube.com/watch?v=LlzCrJS1Fho
[1]: https://dwarffortresswiki.org/index.php/Utility:Lazy_Newb_Pa...
DF lives in my blood, however.
http://web.archive.org/web/20080408110250/http://www.geociti...
There are lots of scams out there.
Same for Minecraft and similar. Figuring out the software and the cool way it came into existence is the problem to solve, actually playing it is (perhaps incorrectly) predictable details and so boring.
The draw for me was the steep learning curve that rewards you with logical complexity when you finally understand it. The lore that your fortress generates, as well as the random stories, is just icing on the cake. It's definitely not for everyone though since the UI requires additional programs like DF Therapist and DF Hack to be manageable still.
There are just too many dwarves to care for. Even DF Therapist doesn't (or didn't?) really help micromanaging jobs. It becomes tedious quickly.
I remember seeing something about auto-allocating jobs, but it didn't work for me.
Watching someone else play Dwarf Fortress can be surprisingly entertaining. Just start one of his series from the start.
They are somewhat similar with Tarn, also a pure passion project that made it, with all the hand drawn pictures and down to earth approach.
DF is an honest attempt at simulating things thoroughly.
Therefore, DF is an honest attempt at making a thorough game.
Very few games can make such a claim
In my opinion game developers have mostly stopped trying to simulate things. The focus is on clothes, rigid crafting systems, skill trees, storyline, cutscenes, vehicles, item collection. It's sandboxes, not simulations. Does Witcher 3 have emergence? Does GTA?
Compare that to Bullfrog, a game company which made simulations almost exclusively. In the 90's "simulation" was a game genre.
It’s an honest attempt at making a thorough simulation. Most games attempt only shallow rules and simulations — nearly everything that happens in Witcher 3 is encoded precisely, with few knock-on effects (because there’s nothing underneath the immediate effect + visualization — what’s modeled is precisely what you see); leading to the lack of emergent behavior. You’re dealing with a fairly rudimentary and static system. GTA is more flexible, but ultimately nothing follows any particular logic that doesn’t revolve around the player. More notably, in both games, if the player doesn’t exist, the world can no longer reasonably operate.
Simulation is inherent to game design, but very few games actively work towards it, as you’ve seen.
The simulation games of the 90’s were in the right vein — they faltered for practical reasons. As a result, they often make for thorough simulations that are dishonest — the internal logic of the simulation is violated for reasons of hardware limitations, UX simplicity, fun, etc. Tornados happen because it’s fun. DF is honest in the sense that it is only compromised by Tarn’s inability to implement something (and practical impact — it’s not worth trying to model atoms when fluid dynamics will suffice).
I don’t mean that DF produces a “realistic” simulation (as a climate scientist might) but that he produces a uncompromisingly logically consistent one (as a fiction author might)
For what it's worth, "immersive sim" is more a sub-genre of first-person action game (games with a heavy focus on world-building, player choice, and stealth, heavily inspired by the games Thief and Deus Ex) than a descriptor. It fit better when it was first introduced in the early aughts, when those games were notably more interactive than the more static worlds of fast-paced, action-first, twitchy shooters of the era (Quake, Half-Life, Unreal, etc).
It did not work. The version didn’t allow for the new adventurer to become a resident of the original base.
Futzed around with dfhack to force residence permissions and so on, ended up breaking the game and changing the species or some other weird bug.
But I did learn that adventure mode mine carts are ridiculously fast. As in survival is highly unlikely fast. There was a lot of saving and reloads due to the difficulty of banking turns at speeds that outran cheetahs.
P.S.: A lot of you are confusing "complicated" with "difficult".
Since he's working alone, he can easily use the local backup feature of it, which allow to easily rollback to automatically made copies of files, diff and cherry pick between current and backups, etc ... It's basically done automatically for you.
As long as you save your project regularly and don't need to merge code with anyone, it can go a long way.
It only gets complicated if you try to do complicated things.
git add -A
With a capital A.You can try and convince me until you're blue in the face dude, but I've tried it and I just don't like it. End of story.
I don't much read my git-commit-comments but I think it is useful to write them.
I don't usually branch, at least at this stage of the project. Probably yes when I go to production when there is a need to fix bugs in the released version(s) without having to put all the latest code into it.
Even without branching commits are a good way to save the latest known good state I can easily go back to if things didn't work out.
I've used source control for all personal projects since, and it's in no way a burden. In fact, there have been another couple of instances since the first, where I would have lost a bunch of work without it.
That's very valuable even when solo, and worth typing a "commit" command once in a while.
You can create as many branches as you want and do all the experimentation you want.
When I stopped caring about committing and branching (something I’ve too long associated with pushing code, like reaching milestones) and started doing both as much as possible I really felt lots of freedom.
Instead of overthinking I can create parallel different approaches and see where they lead to. It’s amazing.
If you have a remote repo then, you can also have offsite backups. If you never branch, it's still massively worth it.
Are git commands obtuse and unfriendly, yes.
The problem is that git is not intuitive and isn't automatic. I've seen more people loose code to git than be saved by having their repo offsite.
There's really no reason to be surprised at all about this unless you're the kind of person who never did any programming before, like, 2010 and lack the imagination or knowledge to understand how programming could be done without it.
As someone who is on the other side and believes in the value of continuously growing one's skills, I want to convince people that Git has value in learning and using. More tools in our toolbelt makes us more effective craftsmen. Which the DF developer did get around to doing...
If you want the absolute simplest way to use git, just setup an alias to do:
alias gcmp="git add -A && git commit && git push"
Now all you need to do is run gcmp every time you're ready to log the new state of your codebase. How could it be simpler?git only becomes more complex as your needs become more complex. At which point I'd recommend using something like https://magit.vc/ which makes complex git operations far easier. The CLI can only take you so far effectively unfortunately.
That would have been the OS tool back in 1998.
If I switched to working with a team I'd definitely use git. But for just me, cvs is all I really need. The most complicated thing I do is probably tag a release or revert to a previous revision of something, which is pretty rare.
There are even git repos of 99% done .gitignore files for most needs [1], which is most of the setup work for a solo project.
Git is also incredibly simple on single person personal projects, just git init, git add, git commit and some way to view the history and pending changes (either the command line, or most editors have a built in viewer).
And especially if you don't have to work with a team.
Is it possible to climb a mountain without equipment? Sure, but it's a lot more dangerous and it'll take you longer to reach your goal.
I've seen this post brought up as relevant regularly up till 2010.
You may have been lucky to avoid the dredges but SW industry in the 2000s was a copy-paste fest (not in the "copy from stack overflow" sense but as in "copy paste instead of creating a function"), PHP with SQL in templates and string concat queries all over the place, MVC was a revolution. I'm not saying this was everywhere just that it was very common.
I'm sure some wise guy will come up with retort that MVC was used in the 70s and what not, but my point is a lot of the industry discovered it with Rails and Django.
The way that we teach programming these days and languages/tools/frameworks just make some bottom tier mistakes from the past impossible (or very impractical). People often ignore this context when evaluating modern framework
It was really, really bad.
My second employer used CVS. Tags were fun back then -- each file was versioned separately so committing multiple files while a tag was in progress might result in only some of your changes making it into the tag. My big innovation there was to add a validation step to our build machine to ensure that the tag matched the state of the branch once the tag had finished, and add the tag to the build version number. Presto: we can actually see which code was built into that day's full build :).
At another job I had the misfortune to get to know Rational ClearCase.
There may have been small teams that didn't use SC in the 1990s, but this has absolutely been a basic best practice for decades.
more like 30, at least in a lot of the industry. Even just looking at open-ish systems, people were excited about SVN in what, 2000?, because they had been working with CVS for years, if not a decade or more, at that point.
like this one https://www.youtube.com/watch?v=ZMRsScwdPcE
I'm hopeful that the upcoming Kitfox Games version makes it very accessible to lots more people.
Dwarf Fortress is something like vim, where usually on the first interaction people don't even know how to start the game, let alone do anything in it.
Chess is easy to start, the rules fit on a post it note basically. Dwarf Fortress is difficult to start, and even more difficult to master.
Next week was spent on trying to survive the first winter...
As a 15 years vim user though - vim has a much more gradual but also much higher learning curve, I'm still learning new tricks in vim on a weekly basis.
Vim is mainly difficult to get into because the model itself is so different from what people are used to and there's inherent complexity. But, quirks aside, it's mostly very consistent and learning a few patterns will get you very far.
In Dwarf Fortress you need to fight not only incredible complexity, but also so very much bad UI/UX and inconsistencies between what should have been identical actions. A great example is searching a list of items. This is done with q for query. Or sometimes s for search. And in some cases f for filter. Or even better, the way k, v, t, q, are all just needles variants of "look at thing under cursor". And none of them work for some activity zones such as pastures, then you need i.
As much as I love DF I'm very much looking forward to the Steam version, mainly for the UI overhaul, which is so far looking really promising.
It's really not that difficult once you get started, especially if you're used to learning some esoteric keybinds.
[0]: https://docs.dfhack.org/en/stable/docs/Introduction.html
Which platform? Mobile, PC, console? Any good introductions on the subject of solo game development? I know I can google this, but I trust HN users more than the Google algo.
There are lots of engines out there that can take care of things for you, or act as full fledged studios, like Game Maker. Some prefer to start from scratch of course. Again, the idea should be follow what you're interested in so that you can actually get something done.
https://itch.io/jam/game-off-2020
Scroll down to the " Help—I’ve never created a game before!" section and there are some suggestions like Phaser or Godot.
Fair warning, the syntax is python inspired but not compatible, which most of the time that will trip you up.
My second suggestion, is for your first project to develop a top down 2D (instead of a classical side scroller), using itch.io assets. To get a nice jump feeling for a side scroller 2D game, you straight ahead have to start using a state machine and fiddle a bunch, no hand holding with that.
Depends on what you want to do. If you want to code games because you find the programming aspect interesting, start small by writing your own versions of some simple games. I personally wouldn't recommend any frameworks or libraries other than (maybe) SDL. Implement everything in the simplest way you can think of that will actually work and only go back and refactor if you need to, that's the time to look up how other people have solved that problem [0]. Resist the urge to over engineer. I might be biased but I say target PC first. Windows specifically, but Linux isn't much worse as long as you never plan to deploy the thing. This is because these platforms are incredibly open and there is a lot of information and tooling available. After you get a feel for it, and have a good idea of what you want to make next, start incrementally branching out in directions that interest you.
If you have a good idea of the kind of game you want to make and want to start making it with as little friction as possible, then your best bet is to find an engine that is already well suited to that kind of game and learn just the things you need to in order to make it happen. Again, you'll want to start small regardless of what it is you actually want to make, just ensure that you're always moving toward that goal. That is very much not my path, so I have little other advice.
[0] If you look it up first without trying it yourself, you won't have a good understanding of the problem space. You'll end up believing in the commonly accepted answer as dogma and severely limit yourself.
Parts of it may be a bit dated now, though.
I really regret that I don't have it any more for the sentimental value it held.
I see archive.org has it in their library [0], though it is is marked as "not for borrow"
[0] https://archive.org/details/teachyourselfgam00lamo
EDIT: Doh, I recogonised the author's name, but I'm thinking of a different book: "Teach yourself game-programming in 21 days"
You might be good at puzzles. Or stories. Maybe visuals ain't your thing and you can write a text based game - there are great engines for that. Maybe you're a great dev and can start hack your own Dwarf Fortress and keep on doing it for the rest of your life.
Gaming and tech behind is so varied that whoever you are, you'll find something that plays to your skills.
Plus what do you mean by coding games specifically? Is it game engine programming? Game design? Or other related stuff?
It was extremely pleasant to fix some old bugs that kept annoying people (and me!)
I spend more time in the game guts, than playing though
I believe it's easier to start with existing game, than creating new one from scratch
The reason for this is: we all want to make beautiful AAA games. But if you have no clue where to begin, it means that you need to develop your intuition for the game logic first – otherwise, you would probably know what to look for :)
If you start by downloading Unity or similar, now you'll be bogged down trying to learn all its systems (without a clear understanding of _what_ you need to learn and what you can ignore, for now). You'll also be bogged down by the need for assets. Sure, you will have a full blown 3D engine, but it's still incredibly boring when all you have is a bunch of cubes or premade assets, so you are right back to square one. Only with more complexity. A lot more - the more visually complex the game, the more code you will have to write that's only concerned about visuals. Getting a character to, say, swing an axe and make it look right and that it is actually hitting something involves a surprising amount of work. Yeah, you could use existing sample games nowadays, but that isn't really teaching you much.
Then it depends on how much background you have. If you were, say, a front-end developer with any experience, you could use that to add some basic visuals. Think Tetris. You can do a lot with very rudimentary tools, as long as everything is kept simple.
At some point, you might _need_ to display graphics (maybe that's the whole point of your game idea). I say "might", because Dwarf Fortress, which is the subject of this thread, never really did. In which case you have some more decisions to make. Is it a 2D game? Maybe use something like Pygame, Löve (for Lua), etc.
At some point you'd be looking into Godot, Unity or similar. And guess what, you could take your basic text-based game, and re-use parts of it as the brains for your game.
Don't get into the game-engine building rabbit hole. It's very fun if you are into that, but know you are unlikely to release anything by going that route. Ask me how I know.
Platform: start with whatever machine you use for development. Presumably you know a lot about it, don't start a side-quest :) Specially, avoid consoles for now. Cross-platform development is getting easier than ever - sometimes all you need to do to start running your game on mobile is to click a dropdown. But that simplicity is deceiving, there's lots you'll have to learn about other platforms. Stick with what you know, until you are comfortable.
I'll let others provide reference material, my sources are outdated as I'm past my Gamedev.net days (for the time being).
The engine and language does not matter for this first game. The only thing that matters is completing one small game.
After that, you'll have the level of knowledge to make somewhat informed choices about project #2, where you can expand and innovate. You can use hobbyist engines like Godot and have more control, or more professional engines like Unity or Unreal if you want access to those tools and asset libraries.
/r/gamedev has a useful article: https://www.reddit.com/r/gamedev/wiki/faq#wiki_getting_start...
If you're looking to get things done fast I think Unity is an excellent choice. After coming from years of working with custom engines and Frostbite, Unity feels like such a breeze.
As for r/gamedev I'm quite active there myself and while I like it and it's gotten a lot better recently it still has an issue where it's largely hobbyists and inexperienced indie developers. Their uninformed opinion will often drown out more qualified voices. So take information there with a grain of salt.
Nowadays though, I mostly play Rimworld for my colony management fix. I love Dwarf Fortress, but I could never comfortably learn it's mechanics in a lifetime (let alone several). Even still, the emergent, chaotic gameplay of Dwarf Fortress should be picked apart by any budding game developers. Even after 15 years of playing PC games, Dwarf Fortress still feels the most "next gen" out of them all.
I really liked how he explains generating the map.
[1]: https://www.gamasutra.com/view/news/343859/QA_Dissecting_the...
I failed.
> "In enterprise organizations (meaning those with >250 PCs or >$1 Million US Dollars in annual revenue), no use is permitted beyond the open source, academic research, and classroom learning environment scenarios described above."
Surely there has been years where his revenue has exceeded $1 million.
> 2020: $130801.30
> 2019: $119133.25
> 2018: $92558.50
> 2017: $83491.24
> 2016: $89423.38
> 2015: $60603.43
> 2014: $66765.31
> 2013: $48999.11
> 2012: $57854.88
> 2011: $42294.19
> 2010: $54501.15
> 2009: $32516.44
> 2008: $32318.46
> 2007: $19052.28
Once he releases the paid Steam version with updated graphics he'll likely be making millions in revenue though.
Don't think too much about it.
I found Rimworld to scratch the same itch and have sunk many hours into it. I feel like it is spiritually very similar, even if the depth of simulation is not as deep as DF.
> When you declare a class that’s a kind of item, it locks you into that structure much more tightly than if you just have member elements. It’s nice to be able to use virtual functions and that kind of thing, but the tradeoffs are just too much.
Aka, OOP is a bad design even when you take the benefits of its virtual method system.
Stick with struct and functions.
But honestly Rimworld is better and a bit deeper.
But what really annoyed me about Rimworld, and why I never really got into it, was how "gamey" it feels.
One element is, the mechanics of random events, which feel extremely arbitrary. I'm not talking about random animals coming onto the map, that's little different from a legendary beast turning up in DF, but things like a solar event causing all your batteries to blow up for no reason. And random events seem to happen every few minutes. Whereas in DF, pretty much everything that happens, happens for a reason. There's randomness, but it's not completely random. If your fortress is wealthy, it will attract invasions. Forgotten beasts actually exist on the world map and have a history. That sort of thing.
In addition to that, crafting and combat are extremely simplistic compared to DF. In DF, bootstrapping an economy which can actually craft everything you need from scratch is actually fairly difficult and requires significant planning and investment. Many things require multiple stages of processing, and it can be very hard to find the particular raw material you need. In Rimworld, you pick up a few raw materials and can manufacture an assault rifle in a couple of minutes. And that assault rifle doesn't need ammunition, and is hopelessly inaccurate beyond 10m or so, for some reason. Compare that to DF where when a dwarf shoots a crossbow it actually does a 3D simulation of the bolt's trajectory. And in the background it's also simulating things like the bolt's temperature, and when it hits the target, it determines what happens based on the density and strength of the bolt's material and the material of whatever it hit.
There's a sense of something missing, and RimWorld tries to fill that void with its random event generator, the "storyteller system". A better game would at least give you ways to interact with them - to predict solar flares or prevent electrical shorts - and indeed there are mods which help with this. But it just underlines the shallowness of the simulation, how these events are truly random and not connected to the game world in any meaningful way.