Current Dev Notes - RyanBabij/WorldSim GitHub Wiki
Random unorganised notes which will probably be extracted and put in their own pages at some point.
The current focus is to get resources placed down on the map, and to program some basic AI to make use of them. Additionally I will also make Tribes put down some artifacts.
Once these features are implemented, I think I will consider that a milestone.
Hardcoded biomes
Currently I'm working on Biome handling. I was initially going to have them dynamic, that is, the user may specify their own biomes. I am not sure if this is going to be a practical approach. It will complicate the gameplay and development too much. Therefore I've decided to go with hardcoded biomes. Biome settings can still be tweaked of course. So if you want to make a desert planet for some strange reason then you could do that.
Resources
Each tile can have resources. For now I'm working on getting Metal into the game. For now there's just going to be a generic Metal resource, and it will be located in mountains. Once I have that implemented, I will want to make the Dwarves mine it and hopefully do something useful with it.
Dwarven civs will accumulate resources based on their mining. For now there will be nothing but a number displayed. Dwarves might be able to convert 1 metal into 1 soldier or something.
Artifacts
Human Tribes will sometimes drop an artifact on the World. Right now I am making them drop gems, because I thought the sprite looked cool. The artifacts will sometimes need information linking them back to the person/tribe/culture that created them. This is cool because when a player discovers an arrowhead on the ground, they might not actually just see an arrowhead, but it might be an ancient dwarven arrowhead dating back to the year X. I dunno I think it will be cool.
Anways the next step is to work on this linking feature. I will make it so you can click on the gems and maybe it'll make up something about them, and it'll also tell you who made them (for now it'll just pick a random person from the tribe).
GUI
We need even more menus. There's a list of Tribes and a list of Civs. Tribe details menu goes to a list of Characters in that tribe. Civ details menu must go to a list of settlements owned by that Civ, and then of course each settlement gets its own menu. It feels a bit redundant having both a Tribe and Civ menu, so I might merge them in the future. For now I think I'll keep the menus all spread out.
There also needs to be a a part of the HUD which will show info about the tile/unit you clicked on. Minimap will also be necessary.
Tribe and City expansion
I'm getting close to reaching a major milestone. I think the main thing we need from this point is to let the civs expand and fill up the map. Right now a single tribe becomes a single civ and then becomes a single settlement. I need to make it so that a tribe can split into smaller tribes, and a civ can found multiple settlements.
Making tribes split shouldn't be too hard. I can just decide the conditions and then make the Tribe object make a copy with a subset of the population.
Making civs expand will be a bit more complicated. There will need to be code to decide where to put a new settlements. Also later on there will be a lot of factors like exploration and conflict which will also determine where new settlements go.
Another important feature will be interaction between Tribes. Mostly in the form of interbreeding and conflict. The issue is deciding what conditions will cause Tribes to have conflict.
Once all of this is in place, things might start to get interesting. I will be able to add in stuff like stats, histories and bios for characters. It should be possible to mark a particular character and then see how their life goes, that sort of thing. They will have various events occur in their life, and these events will impact their future, as well as the future of their tribe.
Tribal splitting
After thinking about the races a bit, it would make sense that Humans tend to fragment more than the other races. Therefore I'll implement this feature for Human tribes first.
Tribal interbreeding
Currently bloodlines stay strictly within the tribe. Obviously this is not realistic. Interbreeding could be implemented in a very basic manner simply by having random Characters shift to their nearest neighbour. This could be expanded upon later.
Tribal conflict
Tribes will sometimes violently compete for resources. Initially it'll probably take the form of a bunch of dice rolls. Later on it will maybe be expanded a bit.
So how much tribal conflict should there be? Well that varies depending on a lot of conditions. Some tribes are peaceful. Other tribes kill outsiders on sight. The real-world stats are around 5% violent deaths in peaceful tribes, and 60% violent deaths in aggressive tribes. For my game, conflict is mostly proportional to availability of resources. Tribes which have what they need will be peaceful. Tribes that are suffering starvation will be more aggressive.
There seems to be an issue with Tribes getting annihilated too easily. What should happen is that smaller tribes should be more careful about wandering into enemy territory. I think I'll also modify the annihilation algorithm.
I changed the code so that outnumbered tribes don't automatically get annihilated. I also made small tribes more cautious. However they are still getting annihilated too much. I think I can fix this by expanding combat a bit to involve hitpoints and wounding. Attacker will then only attack when they have people who aren't wounded. This should decrease the frequency and intensity of the fighting.
Okay I put in some rolls to reduce chances of combat occurring. It seems to have made things better. Now I will just expand the fighting algorithm a bit and it should be okay. I will also need to add interbreeding because all of the bloodlines keep exterminating each other.
Tribe Wandering
New algorithm idea: Tribes should wander beyond their own territory, but only by 1 tile. This will prevent them from getting lost and won't require complex pathfinding. It will also create opportunities for conflict which will be tied to the amount of territory available. Tribes with a small amount of territory will wander outside more often. Tribes with a large amount of territory will have little need for conflict.
Food algorithms
A tribe that owns fertile lands should be able to support a higher population than a tribe that lives in the desert. Therefore each tile will have a food value. One question to ask is whether hunting/gathering and agriculture should be separate values.
Starvation
When the Tribe is unable to obtain enough food, it will enter starvation. Tribes will not immediately die from starvation, and it is a common occurrence in some places. After a tribe has endured starvation for a certain amount of time, characters will begin to die off. The weakest characters will die first. This process will continue until there is enough food, or the tribe is annihilated. Starvation should make tribes more inclined to attack each other. One key benefit of attacking a neighbouring tribe is gaining resources, including food.
Dead Tribes
I had to remove some code which deleted dead tribes. It made me think that perhaps tiles where a tribe died could become a kind of evil or haunted tile.
Event tracking
To start I will stick with a list of enums to track particular events. In the future I might create an event object, and events could be created, linked and pruned. Considering the game tracks upwards of a million characters, it may become necessary to do this early on to get around memory limitations. We might be looking at upwards of 1KB of data per character object, so with a population of 1 million that can end up being 1GB of RAM just for characters. Therefore in the future it may be necessary to make use of file swapping (although the OS may be able to do this automatically). Save files are another consideration.
List of some events to track:
- Birth (date, location, parents)
- Death (cause of death, location, date)
- Battle (location, characters involved, tribes involved)
Gender and sex
Now that I've implemented the ability for men to kill each other, we are running into an issue of gender imbalance. There are two directions we can go with this. We can go for the historical approach, which is to make combat male-dominated, and balance the gender imbalance with polygamy. Or we can make it so that both men and women engage in combat. Or we could just make it so that widows will stay single for the rest of their lives... Or perhaps avoid polygamy but allow remarriage. HMM.
Age
Obviously children should have less strength than adults. There are two potential approaches. I can have age as a modifier, or I can increment stats slowly over time. The first one will be simpler, but the second would be kinda interesting.
Family names
Kind of a difficult topic. Given names are simple enough. Most cultures name their children after an object, an idea, or a famous person. Family names however are not picked. We inherited them a long time ago. I believe family names largely came about due to a need to keep track of large numbers of people... Taxation basically. However in my game each character is required to have a family name, with or without taxation. Additionally family names don't get corrupted like they do in the real world, for example the original form of my name is Babić. So how can we introduce a large array of family names, preferably with meaning, while starting out with only a small number of characters?
One idea is that champions will be able to take on a new last name, as a kind of indication that people who come after this guy will emphasise their connection with this person. We might be able to append a suffix or prefix to indicate this, so the user can easily see this. For example the ić in Babić means "child of". This is a common thing. For example the name Ivanov means "son of Ivan", and of course we have names like Stephenson, which is obvious enough. So maybe I can create some basic rules for prefixes and suffixes, and use them to create meaningful family names.
Megabeasts aka DRAGONS
Might put this in now. I dunno. Dragons will spawn in and walk around randomly, and if they land on a tribe or settlement, it will get hot and spicy.
Local map and global map
Global map is the map you see when you generate a world. Each tile on the global map will get its own "local map". So in theory, when there's a battle on the global map, you should be able to zoom into the local map and see people stabbing each other. That's the plan anyway.
The maps are supposed to be 5km^2, with a single local tile representing about 1.6m. Therefore a local map should be about 3,000 tiles across. However this may end up being excessive, so I'll need to do testing to decide on a reasonable scale.
Currently local maps are bland and boring. Just an open field of grass. I am hoping to create local maps that feel interesting to explore. There might be caves, small forests, wild animals, ruins, etc. However this will take a lot of work.
Settlements will also be on the local map. To start off with they will probably be highly structured and hardcoded. Writing code to dynamically expand a city is not simple. However the long-term plan is to create settlements that the player will want to visit.
Local map boundaries
The world map is broken up into smaller pieces which I call local maps. There are various conventions when it comes to this practice. For example in Minecraft the world is broken into chunks, and in Elder Scrolls game they have cells. In my work I usually refer to them as "maps" because they are a lot larger.
A big issue is how to handle movement between one map and another. The plan is to have this happen seamlessly. This will likely require that adjacent maps will also be loaded into memory. This means a total of 9 map will need to be in memory. Considering a single map could have as much as 9 million tiles, it might be difficult to implement. However it will likely be necessary. One possibility is to only load an adjacent map if the player is near it. This will reduce the maximum total to 4.
When it comes to handling game logic, things might be a bit complicated, especially if there is more going on in the world than the CPU can keep up with. I have a few potential solutions to this. Firstly, my game is designed so that work may be performed between player moves. A thread will be able to constantly work on updating the world even while the player is doing something like going through a menu. Even so, there could be potentially millions of maps to update.
Secondly there should be a system to allow maps to abstract longer time periods. The map the player is in will be simulated most likely without any abstraction. Everything will be calculated as though the player is watching. However in distant maps, entire days may be calculated in one pass. This will probably lead to a loss in detail, but I will try to avoid it being noticeable.
One more critical part of the plan is to allow maps to fall behind in their logic ticks. When the player makes 10 moves in quick succession, it isn't possible to make 10 full loops through the millions of maps in the world. Therefore maps are allowed to build up a backlog which can be processed later. As the backlog falls behind, abstraction can increase. As the backlog catches up, abstraction can decrease. The interesting side-effect is that a player with a more powerful CPU will be able to more accurately simulate their world. Whether they will notice this is uncertain.
Map layers
There is one more aspect to the whole map thing, and that is layers. There are situations where a player will want to explore a cave, or dig a tunnel, or maybe even dive underwater. These activities can't take place on the local map because only the surface is simulated. Simulating multiple z-levels will complicate things like pathfinding and AI too much. Not only that, but rendering 3D space on a 2D projection is pretty sketchy... I don't know of any good system for doing this. However by creating a second map, we will be able to provide these abilities.
This second layer will basically represent a potential second z-level, providing an extra dimension of gameplay without requiring simulation of a bunch of z-levels. Caves, tunnels, dungeons, and also the seabed will be represented on this single level. In some cases we might even be able to simulate multi-level buildings with this.
0.0.021 Release
Wow 21 is a big number. Anyway I am thinking about the next logical thing to work on from here. There's a lot to do but it's kinda lame that the Dwarves do mining basically by just having a number increment every month. This looks like a good opportunity to get some action happening on the local map. So I will write algorithms to put precious metals and whatnot on mountain maps, and the Dwarves will go nuts and mine those bad boys. Oh the maps will be 2D tho. I mean cmon there's like 2 million local maps, how am I gonna store z-levels lol.
Loading and saving
I'm working on very basic loading and saving. For now just being able to load/save a generated world. This should be easy enough because it will be mostly just terrain values. Later on it will get a bit confusing when I need to save links between objects. I can do this by using ID values... But I'll need to write code to convert between pointers and IDs. It shouldn't be too crazy hard but it'll take some work.
Local maps all get their own savefile. This is probably the best way, because I won't need to be scanning through one huge file.
Local Map ideas
Local maps should have interesting features. Some ideas:
- Caves - Should lead to the subterranean layer.
- Ruins
- Ancient artifacts
- Elevation - Maybe 3 different types
- Rocks/flora/trees
- Creatures
- Any terrain improvements should be visible on local map.
Mountains
I've made a fair bit of progress with local maps. Currently you can generate and then seamlessly zoom into local maps. Now I need to work on natural features of these local maps. I think mountains would be a good starting point, because I can also work on implementing the Dwarves.
Mountains will function as barriers on the world map, creating strategic chokepoints. However on the local map it will generally be possible to travel across these tiles. However it will not be easy or safe to do so. Basically I'm thinking the map will contain a lot of barriers like cliff-faces and rocks, and also dangerous events like rockslides. However it should be possible to navigate around these obstacles to reach the summit, which basically will be the middle of the map. Certain equipment like a climbing rope might make things easier.
Different mountains will have different heights. Smaller mountains will basically just take up less of the local map. This game places a combination of individual mountains and mountain ranges. On the global map, some units may be able to travel over mountain tiles (basically mountain infantry, or in this game maybe something like Dwarven mercenaries). Also, some generals may have a special ability to move their army over mountains (think Hannibal).
Mountain ranges will be much more difficult to travel through, because obviously there's going to be more mountain tiles to travel over.
Anyway I don't expect it to be an amazing killer feature, but this is what I'm planning on implementing soon.
Since all of this will be on the surface, the Dwarves will likely use the subterranean layer (which I haven't implemented yet). The Dwarves will have an entrance to their fort near the base of the mountain, and pressing tab will switch the view from a view of the mountain to a view of the fort. I think it will look a bit like Dwarf Fortress when it was 2D, basically just solid rock which the Dwarves can carve out any blueprint they want. It'll make it easier for me that way.
Elevation
Elevation is a tricky one when you're making a top-down 2D game. In 3D you can just look at something and immediately have an idea of how high it is. In 2D there's not an easy way to do this. So this tempts me to simply remove elevation altogether. However, elevation is an important part of natural environments, and can make them more interesting. I could make it so that moving uphill will tire a character out faster, and therefore they will want to avoid it. Elevation is also very important in battles. Attacking downhill allows you to attack a person's head more easily, and you can swing down with more force.
One option is applying a white filter to tiles which are at a higher elevation. So basically higher tiles will look lighter. Another option is putting little arrow indicators on tiles to indicate which direction is uphill. Possibly both at once will be ideal. I don't want it to be too complex though. Only particularly steep areas will provide these indications.
Anyways I'll try to apply a heightmap fractal to the local maps and see what happens.
Okay. A shading system works okay for relatively flat ground. However for a mountain the shading system simply isn't going to work. Therefore there will need to be a contour or slope indicator system. I think for now I'll stick with the basic shading system and work on the other bit later.
0.0.31 Adventurer mode
Currently I'm working on making it so that you can possess a character and then move them around the map. I think this will be a good start for local map interaction. It turns out I need to update the WorldViewer to support this. There is no code for centering on local tiles, only on world tiles. It might take a bit of work to fix that. After that, a new interface must be designed for adventurer mode. But to start out it could just be empty. Then I will need to add code to load neighboring local maps, so the player will be able to seamlessly explore the entire world. Then I will probably be able to work on basic NPC stuff. There's a lot of difficult stuff there, so this might take a while. Also I will be going overseas soon, so things might be disrupted for a while.
0.0.034 Local Maps
Okay first it seems I must get local maps working better. No point controlling a character if there isn't any defined place for the character to be. So I will work on that. Basically code for spawning Characters into the local map when you load a tile with a tribe on it. This raises some issues, because I want to limit abstraction as much as possible, however simulating millions of characters at a time on all of the local maps will not be possible. I will need to come up with a system to simulate the characters as much as possible without using too much CPU. For now I will simply be spawning in the Characters as they are needed.
I did successfully port local map code into the Local_Map class. This is cool because now World has a vector of Local_Maps, and multiple Local_Maps may be simulated at once. Whenever I want to simulate a local map, I can simply generate it and push it onto the vector. Well I think it's cool anyway.
I should also update my website lol, I haven't touched that thing in years.
0.0.035: WorldObject_Tree
I am working on vegetation spawning. However for now everything is static: Trees can't grow over time. In order to fix this, must implement logic ticks on local maps. However the big catch is that local maps are not always in memory. They are loaded in when they are needed, and then must be saved to HDD when they aren't needed anymore. Saving/loading of local maps is what needs to be done next. Oh, loading/saving of global maps also needs to be done.
This kind of work sucks because progress isn't very visible. I think I'll make a release and then get on with this part.
0.0.036: Loading/Saving (Release)
Made the release and now will work on loading/saving. First I will make it so that you can load a world on the Generator menu. After that I will need to make it so that local maps can be saved and loaded. Then I guess I will need to make it so you can load save a game in the Simulator. Complicated stuff.
0.0.037: Loading/Saving
Currently to load a world you must manually type in the name of the world and then click "load world". It's a strange system which exists because I don't feel like writing yet another menu to list all save files. I'll do that at some point. Anyway I think the best way to manage save file data is to write a class to handle it. I have some strange thing called "GaroDataFileManager" which I wrote ages ago, but it's not really functional. I'll have to write a new one.
0.0.038: Loading/Saving
I have been trying to come up with a decent system for loading/saving objects. I tried to come up with some dynamic way of generating save data so that I only need to call something like world.save(). However this might not be ideal. If all of the save data becomes nested inside of each other, then it must all be loaded into memory before being written. This could cause big problems. Therefore I should break up the saving into different functions.
At least having a uid for every object might be a good idea. Using pointer addresses for ids could be a problem if an object is moved in memory for some reason.
0.0.039: Loading/Saving
Okay I have settled on a decent setup for loading/saving. Initially I was hoping that I would only need to save the seed, and everything could be regenerated from that, but yeah that's not gonna happen lol. Better to allow customisation anyway. People will be able to procedurally generate worlds, and then manually put in special stuff. Might be cool. I also want to test the system by making an earth map.
Oh and some map data will be saved in PNG format. I don't know why I moved away from that in the first place. People can then easily make custom maps using image editing software.
Okay I've got png importing happening. Still needs a lot of work but here you can see I've imported a map of earth... Wait no
0.0.040: World_Viewer and Loading/Saving
In addition to the loading/saving, I'm also working on getting the World_Viewer to work with local tiles. World_Viewer does a lot of confusing math to figure out how to offset everything, scrolling, zooming, etc... Now I get to do more of that. World_Viewer was not designed for local tiles, but fortunately it uses decimals... So to center on a local tile, I just add fractions to it. Seems to be working okay so far.
I want to get local map stuff working so that I can start work on the adventure mode. I want to make a fun test map which will just have random features I want to put in the full game eventually.
0.0.045: Menu management
I'm currently working on the complete mess of a menu system I designed. I used to go with a hierarchical approach. This causes problems when suddenly you have submenus inside of submenus, and you need a million flags to figure out what is actually supposed to be rendering. I am switching to a simpler system where all menus are available at any time and only one can be active.
0.0.050: Menu management
Changes are now done, and Adventure Mode menu has been added in and is functional. Now I can work on adding Adventure Mode features. Basically I want to make it so you can select a character and then wander around the map.
0.0.051: Adventure Mode
Woo, the World Viewer can now center on the Character. I just need to add in the ability to move them around the map and things should be pretty cool. Once I have added basic Adventure Mode features, and also gotten load/save to a point of not crashing, I will consider a release and increment to 0.1.
0.0.053: Adventure Mode
It's now possible to move your character around a local map, but not beyond the local map boundaries. I will work on expanding that. I have pulled out load/save functionality so I can make another release soon.
I have noticed World Generation has multiple memory leaks. I patched some small ones but there seems to be a significant one hidden somewhere. I will have to patch them soon. However it's only a problem if you generate a lot of worlds.
0.0.054: Memory leak fix
Okay I found the bad memory leak. There's a small one which leaks maybe 10 KB per worldgen. Oh well it's good enough for now.
0.0.056: Memory leak fix. Crash fix. Adventure mode.
I been thinking about the GUI for Adventure mode. Mostly how to lay out the inventory. Probably I will want to put in some character customisation stuff too. Like hair and outfits or whatevs. Also I need to put in basic world interaction. Like chop down trees and build a house or something. Oh also I go to Germany next week so might not have much time for this project for a bit.