Hey, what are the algorithms behind the vegetation generation? It looks like you are generating bushes and trees in a natural manner, I'm trying to make procedural maps for my game and I'm not sure where to start.
Thank you for your interest! The best way to start is KISS: Keep it simple, stupid :>
The apparently natural manner I'm using in 1812 is very simple. You can find the details in builder.cpp. Look for the buildWilderness() function.
The 1812 map has the overmap, and each tile of the overmap corresponds to a large submap. buildWildreness() builds one of these submaps. Each square in the submap is populated with merely a
set(x, y, weight.pickRandom());
where the pickRandom picks tree, bush, grass, dirt at random according to a weighted distribution. Now, if each submap had its own distribution, there'd be a harsh line between submaps when you are at the local level. To avoid that, the weights of each submap (that comes from the chosen overland symbol for that submap) is averaged to the corners of the submaps. Then each submap linearly interpolates the corner values within itself - that is that weight averaging you see in buildWilderness.
So the heart is very simple - spatially-independent weighted selection. The two next bits are important: how to generate the overmap; and how to set the weights.
The weights are setup in the source.txt, which is a grab bag for all my declarative constants. Deep in this you'll find DEFINE TERRAIN, followed by the weights for each type of terrain.
TERRAIN PLAINS { tile GRASS
grass 90 bush 10 sightrange 100 armyrange 500 }
TERRAIN BUSHES { tile BUSH
grass 10 bush 90 sightrange 40 armyrange 300 }
TERRAIN FOREST { tile FOREST
tree 90 bush 10 sightrange 15 armyrange 100 }
TERRAIN WASTE { tile DIRT
dirt 90 grass 10 sightrange 130 armyrange 600 }
My setup here was simple - I had a sort of hierarchy of terrain in mind, of what valid things are. The usual ecological cycle in my part of the world is pond -> meadow -> bush -> forest -> pond, so thus that natural grass/bush/forest transition order.
So then comes the question of the overmap. This you can find in the buildOvermap function in builder.cpp. This works at the very coarse level, as we are just picking the overmap terrain type. The system is a simple randomized markov chain on each tile. However, the probability tables are controlled by the surrounding tiles.
There are two transition tables used, one in the grow bushes, the second in grow forests. You'll note a comment about GS - that is Gauss-Seidel. Since we are processing the tiles in a fixed order, you'll get strong biases as the next tile will see the updated values for its upper left neighbours, and the old values for lower right. Ideally you randomize sweep orders to avoid this, but I was lazy and instead relied on the fact the noise in the transition rules to hide this. (Noise hides many sins!)
The exact nature of these rules was heuristic, and derived by just generating and tweaking until I liked the results. The second pass grow forest, IIRC, was added to try and consolidate the forest networks as otherwise it looked too patchy.
....
But back to your question: Where to start?
Make it easy to experiment. Setup a test harness so you can see your full level, hit a key, see another one, and repeat. Seeing a few hundred is a great way to get a sense of what your algorithm is doing and how to tweak it. Try to keep your level generation stuff high level so you aren't messing around with pointers and edge-cases when writing stuff. In particular, stuff like indexing your map out of bounds should silently *work* usually, because then a lot of this code becomes easier to read. It is also useful to separate the "Dressing" from the "Bones". Ie, often you can just do a 25% replacement of tile X with tile Y at random to break things up. But this can be a post-process, and the earlier stages can just work with tile X. That builder.cpp has a lot of other random algorithms in it as I've built them across many 7DRL, so I'd encourage reading them and seeing how they work.
Thank you, I enjoyed the video! It is always so instructive to see people play something for the first time.
My only serious pain point was that I failed to make clear you can move the telescope even when zoomed in - this lets you frame those big battles so you see both halves, rather than jumping in & out. (The musket range is actually adjusted to ensure you can see both sides :>)
I very much enjoyed your reaction to regiment 7's decision to charge the foe. That is very much the thesis of this entire game.
You are correct it is entirely turn based at heart. Their is a turn-by-turn order and square-by-square movement. But I'd actually disagree strongly that turn based has anything to do with being a roguelike. It is more like how perma-death appears a roguelike feature; not because it is a feature, but because a more essential requirement almost forces that decision.
"Permanent Consequences", or "No Save and Continue" are the cause of Permadeath and Random environment. If you let people screw up permanently, you have to put then out of the misery and restart. And if you keep restarting, you need the start to be interesting,
Tactical game play is what induces the Turn-based, Grid-based, and Non-modal characteristics. It is very hard to focus on tactics with free movement or real time. War of 1812 aggressively removes all tactics from the equation as your level of control is too coarse, leaving it with only strategy. (And how much strategy there is can be debated. My interpretation of Tolstoy's argument in War & Peace is that there is no actual strategy in the Napoleonic wars)
Totally agree about the UI complaints. So much of my 7DRL time is spent on polishing UX, and there is always so many more things I could have done!
Oh wow, can't believe I missed the zoomed in telescope thing, that sounds great! I admittedly wasn't paying very close attention to some of the messages and instructions in the bottom-right after I felt like I had a good feel of the game ':-)
I may have described it poorly but I actually don't consider turn-based gameplay a requirement of the traditional roguelike either (although I don't think I've played any yet that aren't turn-based). It's subjective, but 1812 falls short of that definition for me more because it plays like a large-scale battle simulator than a roguelike. And that's just in its current form, I could see a game like this becoming something that I'd personally consider a tradtional roguelike if it were expanded somewhat. But that's all semantics to me anyways and I don't find it very interesting arguing about definitions -- all I know is that War of 1812 is a very neat game and I'm happy I got to play it!
I like that insight about removing the tactics from the game. 1812 definitely accomplishes that. I didn't consciously pick up on that while playing, but it's certainly an interesting lens to view the gameplay experience through.
Have seen the video. Very interesting game. The real-time movement and combat on massive scale was pleasant to watch, especially with smoke from rifles covering the battlefield.
Great entry into the 7drl! It's difficult to represent such a large battle with a tiny screen and only ascii, but I think this works great. I like the ability to switch between layers of view. This would make a great playground battle game similar to Totally Accurate Battle Simulator.
ASCII actually helps, I think. If you try and have a 100x100 grid of fancy graphics it becomes mush. To fit that number of tiles on the screen you need to go symbolic. And most people have highly trained symbol-recognition systems for ASCII.
I agree, you can squeeze in much more info onto the display. I wonder if adjusting colors would help the player prioritize visual info too. like if the terrain was less saturated so that it was even easier to parse the troops and such. OVerall this was so fun to experience.
← Return to game
Comments
Log in with itch.io to leave a comment.
Hey, what are the algorithms behind the vegetation generation? It looks like you are generating bushes and trees in a natural manner, I'm trying to make procedural maps for my game and I'm not sure where to start.
Thank you for your interest! The best way to start is KISS: Keep it simple, stupid :>
The apparently natural manner I'm using in 1812 is very simple. You can find the details in builder.cpp. Look for the buildWilderness() function.
The 1812 map has the overmap, and each tile of the overmap corresponds to a large submap. buildWildreness() builds one of these submaps. Each square in the submap is populated with merely a
set(x, y, weight.pickRandom());
where the pickRandom picks tree, bush, grass, dirt at random according to a weighted distribution. Now, if each submap had its own distribution, there'd be a harsh line between submaps when you are at the local level. To avoid that, the weights of each submap (that comes from the chosen overland symbol for that submap) is averaged to the corners of the submaps. Then each submap linearly interpolates the corner values within itself - that is that weight averaging you see in buildWilderness.
So the heart is very simple - spatially-independent weighted selection. The two next bits are important: how to generate the overmap; and how to set the weights.
The weights are setup in the source.txt, which is a grab bag for all my declarative constants. Deep in this you'll find DEFINE TERRAIN, followed by the weights for each type of terrain.
TERRAIN PLAINS
{
tile GRASS
grass 90
bush 10
sightrange 100
armyrange 500
}
TERRAIN BUSHES
{
tile BUSH
grass 10
bush 90
sightrange 40
armyrange 300
}
TERRAIN FOREST
{
tile FOREST
tree 90
bush 10
sightrange 15
armyrange 100
}
TERRAIN WASTE
{
tile DIRT
dirt 90
grass 10
sightrange 130
armyrange 600
}
My setup here was simple - I had a sort of hierarchy of terrain in mind, of what valid things are. The usual ecological cycle in my part of the world is pond -> meadow -> bush -> forest -> pond, so thus that natural grass/bush/forest transition order.
So then comes the question of the overmap. This you can find in the buildOvermap function in builder.cpp. This works at the very coarse level, as we are just picking the overmap terrain type. The system is a simple randomized markov chain on each tile. However, the probability tables are controlled by the surrounding tiles.
There are two transition tables used, one in the grow bushes, the second in grow forests. You'll note a comment about GS - that is Gauss-Seidel. Since we are processing the tiles in a fixed order, you'll get strong biases as the next tile will see the updated values for its upper left neighbours, and the old values for lower right. Ideally you randomize sweep orders to avoid this, but I was lazy and instead relied on the fact the noise in the transition rules to hide this. (Noise hides many sins!)
The exact nature of these rules was heuristic, and derived by just generating and tweaking until I liked the results. The second pass grow forest, IIRC, was added to try and consolidate the forest networks as otherwise it looked too patchy.
....
But back to your question: Where to start?
Make it easy to experiment. Setup a test harness so you can see your full level, hit a key, see another one, and repeat. Seeing a few hundred is a great way to get a sense of what your algorithm is doing and how to tweak it. Try to keep your level generation stuff high level so you aren't messing around with pointers and edge-cases when writing stuff. In particular, stuff like indexing your map out of bounds should silently *work* usually, because then a lot of this code becomes easier to read. It is also useful to separate the "Dressing" from the "Bones". Ie, often you can just do a 25% replacement of tile X with tile Y at random to break things up. But this can be a post-process, and the earlier stages can just work with tile X. That builder.cpp has a lot of other random algorithms in it as I've built them across many 7DRL, so I'd encourage reading them and seeing how they work.
I really loved the concept of this game, and the scale and autonomy of everything and how it was all implemented -- nice job with this one :-)
By the way I made a short video of the gameplay you might enjoy:
https://www.youtube.com/watch?v=MZNIEtacLfU
Thank you, I enjoyed the video! It is always so instructive to see people play something for the first time.
My only serious pain point was that I failed to make clear you can move the telescope even when zoomed in - this lets you frame those big battles so you see both halves, rather than jumping in & out. (The musket range is actually adjusted to ensure you can see both sides :>)
I very much enjoyed your reaction to regiment 7's decision to charge the foe. That is very much the thesis of this entire game.
You are correct it is entirely turn based at heart. Their is a turn-by-turn order and square-by-square movement. But I'd actually disagree strongly that turn based has anything to do with being a roguelike. It is more like how perma-death appears a roguelike feature; not because it is a feature, but because a more essential requirement almost forces that decision.
"Permanent Consequences", or "No Save and Continue" are the cause of Permadeath and Random environment. If you let people screw up permanently, you have to put then out of the misery and restart. And if you keep restarting, you need the start to be interesting,
Tactical game play is what induces the Turn-based, Grid-based, and Non-modal characteristics. It is very hard to focus on tactics with free movement or real time. War of 1812 aggressively removes all tactics from the equation as your level of control is too coarse, leaving it with only strategy. (And how much strategy there is can be debated. My interpretation of Tolstoy's argument in War & Peace is that there is no actual strategy in the Napoleonic wars)
Totally agree about the UI complaints. So much of my 7DRL time is spent on polishing UX, and there is always so many more things I could have done!
Oh wow, can't believe I missed the zoomed in telescope thing, that sounds great! I admittedly wasn't paying very close attention to some of the messages and instructions in the bottom-right after I felt like I had a good feel of the game ':-)
I may have described it poorly but I actually don't consider turn-based gameplay a requirement of the traditional roguelike either (although I don't think I've played any yet that aren't turn-based). It's subjective, but 1812 falls short of that definition for me more because it plays like a large-scale battle simulator than a roguelike. And that's just in its current form, I could see a game like this becoming something that I'd personally consider a tradtional roguelike if it were expanded somewhat. But that's all semantics to me anyways and I don't find it very interesting arguing about definitions -- all I know is that War of 1812 is a very neat game and I'm happy I got to play it!
I like that insight about removing the tactics from the game. 1812 definitely accomplishes that. I didn't consciously pick up on that while playing, but it's certainly an interesting lens to view the gameplay experience through.
Have seen the video. Very interesting game. The real-time movement and combat on massive scale was pleasant to watch, especially with smoke from rifles covering the battlefield.
It's really cool. Works fine running linux mint in oracle virtualbox on windows 10.
Subscribing for Windows. Godspeed Jeff.
I have no idea how subscriptions work, but at least if I reply you should be pinged!
Whoo hoo!
Linux binaries only for now. Source builds on windows and linux.
Unfortunately it is seems my coding style flags Windows Defender, so I had to delay a windows release until I get a build MS is happy with.
Linux only?
Great entry into the 7drl! It's difficult to represent such a large battle with a tiny screen and only ascii, but I think this works great. I like the ability to switch between layers of view. This would make a great playground battle game similar to Totally Accurate Battle Simulator.
ASCII actually helps, I think. If you try and have a 100x100 grid of fancy graphics it becomes mush. To fit that number of tiles on the screen you need to go symbolic. And most people have highly trained symbol-recognition systems for ASCII.
I agree, you can squeeze in much more info onto the display. I wonder if adjusting colors would help the player prioritize visual info too. like if the terrain was less saturated so that it was even easier to parse the troops and such. OVerall this was so fun to experience.
You should have seen the earlier versions before I started toning down the terrain! I had bright green for everything, and * for bushes.
A good point though, I really should have pushed the terrain way down, and then brought it back until it looked good.
Very glad you enjoyed it!