( I’ll give it a better name when I think of one. )
I’ve been playing several xcom games recently and its made me want to create my own such project. I’ve never made this kind of game before so it could be a fun challenge!
Let’s jump right into it.
First, the world. I want it to be procedural.
It bothers me how every game of UFO defense, with exception to unique playthroughs like the Antarctic challenge, almost always begins with a base in the US. This happens because the US provides the best funding and as such it’s objectively the best place to defend.
Every country is important, of course, but you obviously want to prioritize helping the ones that give you the most money first. This is especially true on harder difficulties!
I want to eliminate this minor source of repetition by scrambling the world map.
Instead of going for the same map strategy each playthrough, the player will be forced to analyze each playthrough as a unique situation and formulate new strategies as needed.
This may not sound like a big deal at first, but what if there’s no big country that provides a ton of funding? You’ll have to spread yourself thin defending a bunch of small countries!
I’m also hoping this extra step of randomization, and the many others I’ll be adding later, will help maintain that underdog vibe the xcom games possess. Theirs only so much I can do to keep a player on-edge after their millionth playthrough, but I can nevertheless try.
In the name of progress, I’ll keep things simple. Their will only be two terrain types: land and water. Eventually, though, I’ll add, forests, deserts, cities, and all sorts of other terrains.
In the distant future, their will even be alien landscapes as they begin to terraform Earth.
Here is an animation of the world being built.
Also, here is what the heightmap looks like. Dark areas are low, bright areas are high.
Long story short: I create two different sets of big noise and mix them together. Then I create two sets of small noise and mix those. I then mix these two mixes’ of noise with a circle. This gives the central island shape. Then I do a bit of erosion to scuff the results edges up a little.
It’s not what I wanted, at all, but after a couple of hours of fiddling with the map generator I decided enough time has been wasted and just implemented something I know looks good.
The result I actually wanted was something more Earth-like. I wanted a handful of gigantic continents and some nearby small islands. The result I kept getting, though, was either too stringy or too blobby. I also didn’t want the landmasses touching the map edges.
Example of the previous map generator. Too string, too blobby!
This is what things look like when it’s all said and done. Tiny islands are turned into water, tiny lakes are turned into land, and the edges are smoothed with a small gaussian blur.
What’s next? There’s a million things I could potentially do, but I want something playable as soon as possible. That means its time to place the location of your first base!
However, upon second thought, I realized that adding the ability to place a base would be a decent amount of work. It would require a new menu, interface elements, user mouse input, a base object, and probably some other bothersome stuff. The location doesn’t matter right now since there’s no countries to protect, so I’m going to be lazy and just randomly place it.
Poof. There’s a base now.
I’m using a random seed, by the way, so the map will be changing between screenshots.
Anyway, let’s click on the base. That will bring us to the hideous base management menu.
Looks pretty strange, huh? It’s almost as if I was inspired by something.
I’ll add some nicer ascii graphics at some point. I’m going to add a radar building next.
The radar has been created, but it’s useless. It’s just a generic building object. I’d like to make it functional, but there’s no aliens for it to detect, so the next step is pretty obvious.
I’m going to return to the world map and add some alien ships moving around. For now, their only purpose is to be detected by the radar. The aliens generate random waypoints and then they path to those waypoints. Upon reaching it, they’ll get a new waypoint. Rinse and repeat.
Here we go. The alien ships that enter the radars detection range while aimlessly moving around turn red to indicate they’ve been detected. I also draw a line because it looks cool.
The next thing I’m going to add is scrambling fighters to take the alien ships down. I could easily implement a half assed development version of this to save time, but I’m having fun.
Fighters are automatically launched whenever a threat enters radar range. In the future, the player will have to manually decide when to launch. I’m not going to bother adding a combat system yet, so for now the interceptors always destroy the alien ship once they’re in range.
To prevent the map from being filed with interceptors, I only ever allow one to be active at a time. They must return to base after a successful kill before being launched for a new hunt.
I think an example gif was supposed to go here but I seem to have misplaced it.
Instead of yeeting the aliens from existence when they’re shot down, I’m going to have them crash. This won’t serve any purpose right now, but eventually the player will be able to send their soldiers to investigate the crash site and salvage it for critically important alien supplies.
The orange aliens have been shot down. I also gave them circular icons because saucers.
What’s next? Everything you do in these games is to protect your bottom line, so I guess I’ll start working on the monetary front of things. It’s time to add some countries and their funds.
First, I need to split the map into quadrants. Each country needs to be relatively spaced out, and while I could use distance calculations, collision detections and other overly complicated sounding non-sense to achieve this, I’m just going to use a binary space partition.
What’s that you ask? It splits a space into a bunch of rectangles, basically.
I’m going to place a faction (country) at the center of each rectangle next.
Then I’m going to erase any rectangles that have mostly water beneath them.
In order to exist, a country needs to have at-least 100 land pixels within its rectangle.
This removed most of the sillier countries where their only claim to fame is a single pixel of land on some random corner. I also spaced the countries out so they’re nicer on the eyes.
I’m going to remove any countries whose center most coordinate isn’t land next.
This is good enough for now. I was planning to do a floodfill to generate country borders, but after hours of work it still looks awful. It’s also slow enough to be annoying. I’ll report back at a future date when I either improve the floodfill or discover a better way to create borders.
The abandoned floodfill based country generator in question.
I’ve returned to the ugly rectangles, but this time they’re actually proper countries. I’ve given them colors, and to finally get back on topic, they also possess a random funds variable.
Speaking of funds, the aliens can now attack countries.
They still wander around randomly, but every time they reach a waypoint they’ll land and do some damage to the below country. This process takes 6,000 frames. If they’re intercepted before the timer is up, then the country is spared. Else, they’ll reduce their funding a little.
Countries repair themselves over time, so a few attacks aren’t the end of the world. Their current funding might be reduced but it will slowly tick back upwards towards the old value.
To add even more oomph to the importance of protecting countries, they will cease to exist upon reaching zero funds. This puts the player in a situation with real consequence. If they routinely fail to protect a country then it will permanently collapse and that money is gone.
I’ve also added a new human ship: the bomber. It will automatically go after any landed alien saucers and destroy them. Currently, this is the only means of preventing landed ships from damaging a countries funds. Eventually, though, you’ll be able to send a lander full of troops.
The idea behind the bombers is that their will sometimes be too many downed aliens for you to deal with. It’s better to just bomb them into oblivion than ignore them, as crashed saucers will eventually be rescued by a recovery ship and resume doing fun apocalyptic alien stuff.
In addition, both interceptors and bombers are only able to attack alien ships that are within radar range. This is a step towards making base placement matter. More importantly, it’s a reason for the player to eventually have multiple bases so they can cover more countries.
Finally, alien detection chance via the radar has become chance based. If discovered aliens leave the detection radius then they have a chance to become undetected, too. Interceptors and bombers will automatically disengage if the target vanishes from radar.
Phew. That was a mouthful. Here is everything I just talked about in one big animation.
The grey circles are undetected aliens. I’m only drawing them for debugging purposes.
I dramatically increased the amount of aliens and unlocked how many ships the humans can launch. This makes it easier to get a feel for the simulation without having to wait all day.
I’m sorry if this last update was a bit confusing. I went on a coding spree and forgot to make incremental blog updates, so I had to jam everything into a big wall of text and sped up gif.
This post has gotten so long in the tooth that the wordpress editor is imploding with lag due to all the text blocks. Ill see you in the next post where I’ll begin adding player interaction.
The first official resource I decided to add was food. I think it makes sense to start from the bottom and work my way up. These factions are just springing into existence, after all. They have to worry about the basic necessities! I don’t think you’ll find too many civilizations that decided to settle near a copper deposit instead of food and ended up being too successful.
The stock market might like copper but your tummy sure doesn’t. The production chain for food is also quite a bit simpler than metal. It’s easier to plant, grow, and eat a potato than it is to go through all the steps required to forge a set of armor.
I’m going to add just one type of food resource for each existing terrain type. That’s plains, forests, mountains, lakes, and ocean respectively. Eventually, though, there will be hundreds if not thousands of resources. The more resources there are the more unique the world will be due to factions having access to different materials. I’m also using real-world resources, such as corn or sheep, for the time being. I’ll introduce some make-believe resources later!
The first resource I’ll be adding is corn. I wanted to start with the most useful resources, but after some research, pretty much everyone disagrees on what is historically the most used old-world vegetable. It was a toss-up between grains and stuff like carrots, cabbages, and potatoes. I gave up and just choose what I personally think is the most recognizable veggie.
I set corn to spawn on generic land tiles (which I’m now referring to as plains) and the rest is history. The resource generator is seed friendly so the map will continue looking the same.
Here is what the world looks like after adding corn. It’s not very impressive, admittedly. The resources only occupy a single tile so there’s never going to be much to look at. It’s not like terrain generation where I’m causing huge sweeping changes across the entire map.
That’s actually it for resource generation! It feels odd to suddenly pivot away from resources, but I’d like to focus only on what needs doing rather than adding things for the sake of it.
The next thing I need to do is figure out how to fill the world with factions.
I eventually settled on using a BSP. That stands for binary space partition – which, like most programming related things, sounds way more complicated than it actually is. It’s just an efficient way to cram some arbitrary space with a bunch of rectangles. That’s all. It does this by taking a square and halving it. Then it takes those halves and halves them, too!
Here’s an example animation of the BSP process I painstakingly made by stitching a bunch of screenshots together. I start with a maximum rectangle size of 400 and reduce that by 10 every iteration. Eventually, a threshold is reached and it stops slicing those rectangles up.
How does this help me, though? If you saw the animation then you presumably noticed how quickly it can carve a large space into a bunch of smaller ones. I don’t have to do flood fills, distance calculations, collision detections, or any other time-consuming object placement routines. Instead, I can just take some of those rectangles and shove a faction in them
Each of these spaces is guaranteed to be separate from all the others due to how a BSP works so I can just choose one and spawn a faction at its center. Easy! It’s future-proofed, too. Even if the map size is dramatically increased it will still be just as quick.
I settled on a minimum size of 30. This means the BSP will keep trying to carve the map into pieces until its impossible to shrink any of the rectangles any further. This number results in a good number of spawn locations while also leaving enough room to see whats going on.
This is what the world looks like with the rectangles overlayed on them. Every single one of those rectangles is where a faction object will be placed. It’s not time to spawn any factions yet, though. I need to do some cleanup first to remove bad spawn positions.
I’m going to loop over each of these rectangles and compare it’s center coordinates to the terrain below it. If any of their center coordinates are ocean then I’m going to remove them.
This is what happens after I’ve discarded any rectangles whose center is ocean. I could get way more accurate by only erasing rectangles that are entirely ocean but decided not to. It would be a lot of work to implement that in a performance-friendly way. I’ll probably do that later, but since my current plan is to spawn factions at the center I don’t think it’s necessary.
Also, I’ve slightly shrunk all the rectangles. It’s easier on the eyes when they’re spaced out.
I got some spawn points up and running so now it’s time to start actually adding factions!
There we go. Each faction gets a random lightish color and is named after a random number in the 100-999 range. I wanted to give them randomly generated names but that ended up being too much work. I’ll do that later once I have some history generation to pull data from.
I made the random colors brighter, thickened the rectangle borders and gave them all a dark transparent background. It’s a bit easier to see things now! It’s not perfect but theres only so much I can do. This is just debugging info, anyway, so who cares? It’s for our eyes only.
It’s finally time to start actually simulating things – but what?
The earliest thing I can imagine any civilization doing is growing. That boils down to claiming territory and increasing their population size. I can’t think of a realistic way to simulate this, though, so we’re going to do it in a very programmey way. I’ll think of something better later!
Sure is a lot of ‘later’ going on…
I’m going to start by getting all the factions to look like proper countries. I’ll do this by using a floodfill. Lots of floodfills, actually! Each faction will simultaneously grow outwards and claim any territory they can get their greedy little hands on. They claim one pixel at a time and, at least for the time being, will be respecting one another’s borders by not taking claimed land.
Those wiggly fuzzy pixels are a rendering artifact.
That was pretty weird. It started out looking fine, but as time went on things really went off the rails! Especially in the upper right corner. This is happening because the floodfills are competing for space. The more limited the real estate becomes the more ridiculous things start to look. The factions in crowded areas ended up looking fine-ish due to relatively equal space but those near the ocean have plenty of room to thoughtlessly expand into.
Let’s move on.
I’m going to start off by making each faction’s initial expansion less perfectly square. This is happening because the floodfill is storing its expansion candidates in a list. Lists are ordered which means the order you populate them will also be the order you loop over them.
This is causing a square shape due to how the floodfill is expanding. I’m going to change to a set which isn’t ordered – which basically means the floodfill direction will be randomized.
Also, before any programmers yell at me, I know that using a set isn’t literally the same as randomization. It’s close enough to get the job done, though, and isn’t slow as snails.
That looks better. It’s starting to look like a territory map now! It’s still not perfect, though. I need to change how the floodfill detects neighboring tiles. It’s currently detecting neighbors in all eight directions. This causes the weird noisy looking mixture of territories you can see in some parts of the map. That’s happening because the floodfill is allowed to cut corners by moving diagonally. I’m going to restrict it to cardinal movement only.
Made in professional image editing program paint. The top example (principle) is cutting corners while the below example (cardinal) is not.
Here is a crude example of diagonal versus cardinal floodfilling. That top example is exactly what’s happening to make things look so noisy. Turning off diagonal flooding will fix that.
That’s way better! The map is so much cleaner now.
The next thing I need to do is restrict the floodfill to land tiles only.
Perfecto! The map is now full of a bunch of colored blobs that look vaguely like countries.
This is the kind of map I’m going for, by the way, if you can’t read my mind.
Unfortunately, I’ve decided not to take this approach at all. That’s prototyping, baby! Instead of digging in and doubling down, I’m going to admit my mistake and adjust accordingly. I left in the above content because it was fun to write and was hopefully an interesting read, too.
Let me explain some of my problems with this approach before changing course.
I couldn’t figure out how to fix the out of control flooding issue that you saw in the very first example. It might look fixed right now but it’s not. Limiting the floodfill to land tiles has merely reduced its chance of occurring. The possibility is still there. Lurking in the shadows.
2] The faction borders are way too wiggly. I can’t figure out how to fix this, either. I know that real-world borders can sometimes be pretty funky (wtf Ireland lol) but more often than not they’re relatively straight or otherwise make some kind of sense. Thus, I don’t mind some squiggliness – but every single border shouldn’t be so crazy. More importantly, they should look more unique. They’re not literally the same but if you’ve seen one you’ve seen them all.
3] I’ve decided to handle world generation differently. Most procedural games will simulate things before playing in a process that’s usually called history generation. The issue I have with this approach is that the end result is a stagnant world. Instead of being part of history and helping shape the world, you’re just playing in the afterglow. You get to hear about great events but not take part in them. I’m going to take a more interactive approach by letting the player get directly involved in altering the course of history. I think this is essential for an adventure generator. What kind of great adventure doesn’t end up changing the world in some way shape or form? Can you think of any that don’t? I certainly can’t.
Thus, some change is needed. This method of magically spawning a bunch of factions out of thin air isn’t interactive enough and the territory grabbing floodfill is too artificial. I’m going to switch over to a more organic simulation. I’m going to abandon the idea of pre-generation and instead go for a state where the world is in a constant state of generation.
This idea of constant generation will leave the world open for player manipulation. This idea was inspired by my goals in the Super Project, but it’ll be happening on a smaller scale.
Much like how things are always changing in our world, they will always be changing in this world, too! The first thing I need to do is change how factions are created. They need to be formed in a more natural manner. I’m going to fill the world with agents and have population centers form when enough of them share the same tile. This is to simulate how smart people claim civilization is formed – which is people coming together to make urban settlements.
This is what the world looks like when it’s covered in 10,000 agents. Each of them is placed at a random coordinate. The only placement rule is that they can’t spawn on lake or ocean.
I should simulate movement next, but I don’t think it’s needed yet. There are so many agents on the map that I bet theres a few clumps of them that I can turn into a faction!
I was right, but only marginally so. The map is so big that even with 10,000 agents scattered across its surface there’s barely any agents occupying the same tile. I had to lower the bare minimum number of agents needed per tile to 7 before any factions would pop up. This gave me a grand total of 3 factions. It’s not perfect but its a nice good start!
I’m going to go ahead and get them moving now. Every turn the agents wiggle to a random tile. The idea here is to cross my fingers and hope enough of them visit the same tile.
It’s alive! I disabled the terrain view and faction generator so they’re easier to see.
I enabled faction creation but messed up the faction coordinates. They’re only being made along the x-axis which results in that weird diagonal conga line. Things gradually slow down because hundreds of factions are being created in the same position every single turn. The factions aren’t moving, by the way. It just looks like they are because new factions that have different colors are constantly being spawned. It creates a neat moving line illusion.
Fixed it. Factions are now being created at the correct coordinates! It’s pretty neat watching all these factions pop into existence. I’m going to increase the minimum agent count to a bigger number now. This should thin the faction count down. Also, those long glitchy lines that appear are what happens when text is drawn slightly off-screen in pygame.
I raised the number first to 30 and then gradually all the way down to 10. No deal. I let the simulation run for a good while, too, but nothing happened. The luck required for that many agents to appear on the same tile for one turn must be astronomical. I’d rather not increase the number of agents but I also don’t want to lower the agent per tile threshold. What do?
I think I need to improve the agents’ movement behavior. The whole random movement thing was a good starting point but it’s too unreliable. I was going to try treating the agents like magnets and subtly attracting them to one each other’s coordinates – but that sounds like a nightmare to implement in a performance-friendly way. I’ve messed with this kind of particle physics simulation in pygame before and it’s sloooow. This simulation is going to be running every turn while the player is playing so I have to be cautious. It’s fine if typical map generation takes a few minutes but no one is going to tolerate every turn taking that long!
I’m going to take some inspiration from ants for the next step. They’re individually dumb but capable of seemingly intelligent behavior in groups. They accomplish this by reacting to a few basic senses that can result in sweeping changes. This makes it look like they’re being directed by some kind of leadership when in reality they’re just a bunch of little autonomous drones reacting to basic stimuli.
I’m going to make the agents indirectly smart by feeding them sensory input. This way I can make them do smart things without actually giving them any AI.
Or, in other words, I can process ten thousand agents every turn without lag!
I’m going to create a scent array out of noise and overlay it across the terrain. The agents, when moving, will analyze their neighboring tiles and move to whichever one has the highest scent value. This should cause them to naturally congregate towards the same areas!
Whoa! It worked surprisingly well. That blue overlay is the scent array. It looks like solid blobs of blue, but it’s actually a smooth variety of noise float values. I didn’t choose to make it blue, by the way. It’s the default color that pygame applies to surfarrays. That’s a built-in tool that can be used to rapidly draw entire arrays in one pass instead of having to slowly loop over every single pixel. Either way, it’s a colossal pain in the arse to manually recolor.
Here is a different view that I manually drew one pixel at a time using standard greyscale noise coloration. It lets you better view the gradient of noise values. I wanted some parts of the map to be more attractive than others so I applied an aggressive threshold. That’s why some parts of the noise look so sharp. This way the agents are driven towards certain areas.
This is what the non-thresholded version looks like.
Anyway, the scent approach is far from perfect. If you scroll up and watch the animation you’ll notice how the majority of agents stop moving. That’s because they reach a position where none of their neighboring tiles have a higher scent value than the one they’re on. They’ve basically found the smelliest tile and logically refuse to budge from it.
My first idea was to implement a scaling approach where agents, upon getting stuck, would begin searching further and further out for a higher value tile. However, then I realized they would need to do some form of pathfinding to reach said tile. I’d also have to use a floodfill to find it in the first place. I’m good at optimizing things, but I don’t think even I can squish 10,000 floodfills and pathfinding calculations into a single frame without causing lag…
I’m going to try some simple brute force methods before getting fancy. First, I’m going to turn movement randomization back on – but now they’ll only move if they’re stuck. I’m hoping this will shake them free and help them find a better scent trail to follow.
I expected some progress but I didn’t think it would be almost perfect! Many of the agents that were once stuck are now wiggling themselves free and hooking up with other agents. If you compare this to the previous animation you’ll see way more factions being made.
Theres still some duds, though! I think these guys are remaining stuck because theres no scent trails near them to follow. That’s why the bottom left island populates much slower – especially in the lower middle portion. They’re moving, sure, but they’re in such a wasteland that they never catch a scent to follow. It’s like wandering around in a desert for water.
I think theres also another problem happening. If you pay close attention you’ll notice some agents moving back and forth between the same two spots. They get stuck and randomly move. Then, next turn, they detect their previous position at the best option and move back to it. They’re getting stuck in a back and forth loop instead of stuck idling in one position.
Before applying any fixes, though, I’m going to change something that I think makes a lot of sense. I’m going to delete any agents that exist on the same tile when a faction is made. If a faction is made then it stands to reason that people have created a settlement – so they shouldn’t be moving around anymore!
Here is the result! If you compare it to the previous image it takes longer for factions to start appearing. There’s less faction overlapping, too. The factions were previously flashing like crazy because agents were constantly producing them at the exact same location. This was causing a graphical layering issue that resulted in all that flashing. It can’t happen anymore now, though, because once a faction is created the founding agents are killed.
Changed the color to red in adobe premiere so it’s easier to see.
Then I implemented a heatmap visualizer so I can see the longterm movement of all the agents and it verified my thoughts. It doesn’t take long before movement comes to a halt.
You can see the heatmap die as time goes on. It starts out super hot from all the movement but everything slowly putters out. I’m not sure why but something is gumming up the works.
I think that’s enough for now. It’s been a long time since I posted anything, so I’m going to go ahead and release this post early. See ya next time!
Last time I put together a somewhat rushed post where I discussed my GOAP rewrite and vaguely touched upon a few of the latest additions. I’m going to go into further detail upon some of those additions to clarify things before moving onto the newest stuff. I feel like my writing has improved quite a lot, too, since I’ve found my footing. Time for a refresher!
The first new addition was the history system. This system keeps track of a number of stats that help drive agent behavior and each of these stats is fully integrated into my new GOAP implementation. This means, basically, that each stat behaves as an on and off switch.
The police, for example, will monitor the crime stat. This is a stat that increases when agents do something the game considers a crime – such as murder or stealing. If that stat ever goes beyond a certain threshold then law enforcements’ crime-fighting goal will be activated.
This means they’ll drop whatever they’re currently doing, such as idling at headquarters, to instead go actively search for criminals to arrest. They’ll keep doing this until they’ve brought the crime stat down to a more acceptable level through their own crime-fighting actions.
If any of this sounds familiar than you’re right.
The history system is a larger-scale implementation of the decision weights that my GOAP enabled agents already utilize when trying to decide which action is best. Technically, little has changed. They still use weights, have goals and use actions to accomplish said goals.
The only real difference is that they now have access to a public group of historical stats in addition to their own private stats. Hunger is a good example of a private stat. Each agent is different so they obviously need their own hunger meter. The same goes for health, money and other personal variables. Crime, though, is a historical stat. These stats are something that any agent can look at which is why I interchangeably refer to them as public or global.
The history system being plugged into GOAP means the agents are now super responsive. They’re all going to be reacting to the world around them even more so than they would have with standard GOAP. I’ve basically taken GOAP, which is known for being reactive only to its immediate environment, and dramatically scaled it up. The agents pay attention to the whole map instead of just their current surroundings. Eventually, this will be scaled up even further to include the whole planet and later the galaxy itself once more content is added.
A poor attempt to visualize the public / global stat concept.
The original purpose of the history system was to give my agents some problems so they’re forced to interact with the world in a more organic manner to solve them. I’ve since realized it has more potential than previously envisioned, though. The history system, for example, lets me influence large numbers of agents for almost literally no cost.
Instead of all the agents having to individually calculate whats going on in the world they can instead just take a peek at the history stats and react accordingly. It’s efficiency on the level of reading about some faraway event in the newspaper versus traveling to it yourself. I didn’t add it for performance reasons, but it’s nevertheless a nice bonus! I find it doubly interesting because the agents themselves are the ones making the gains possible. They modify the stats with their own actions and later reap the rewards by just looking at said stats.
It also makes the whole action and reaction thing I keep talking about much easier to add.
Let’s say the rebels just destroyed some kind of moon like space station. Let’s also say there was a historical stat that represents the rebellions threat level. The destruction of this space station would give that stat a dramatic boost – which, in turn, would activate an empire-wide response. This response would lead to a thousand forms of anti-terrorist activity and likely the rebellions demise if they aren’t prepared to deal with a major empire counter-attack.
Hunting rebel leaders, blockading worlds that support the rebellion, cracking down on pro-rebel politicians, interrogating rebel prisoners, searching for rebel bases, increasing foot patrols and producing anti-rebel propaganda are just a few examples I can think of.
The history system makes this kind of mass response a breeze. If empire affiliated agents see that rebellion stat get too high they’ll all begin autonomously taking anti-rebel actions.
It’s my first step towards adding that tug of war gameplay I want. The more the rebels harm the empire the more seriously the empire will respond. It’s an automatically scaling difficulty slider. If you want to actually take the empire down instead of just being a thorn in their side then you’ll have to start taking more extreme actions – which, in turn, will make them respond in kind. It’s inherently a self-destructive mechanic. The empire isn’t just some final boss that sits around all day waiting for you to come to fight them. It’s a faction that will actively move to protect its own interests. The more you poke at them the more aggressively they’ll react.
This fact passively enforces the need for subterfuge. I envision the game having a slow burn feel where you operate in the shadows to build up the rebellion’s strength. You have to treat the empire like a frog in boiling water. Turn up the temperature slowly to avoid attracting too much of their attention. Strike, let things cool off, then strike again. If you act like Rambo and start senselessly blowing shit up then you and the resistance will be dead before you know it. I actually have such a long-term vision that winning will likely require multiple characters.
Dismantling the empire should require several lifetimes due to the colossal amount of effort required. In other words, if you’re not killed in combat then your character will probably die of old age before your task is complete. The game will have one of those save systems where you generate a single world and can then play multiple characters in it. Your character might be dead, but his effects on the world still remain. This way your next character can build upon the success of the last. It’s eerily realistic because such a mechanic would reward you for doing the whole going down in a blaze of glory thing terrorist groups are known for.
I’ll probably make aging an option that can be disabled for those who dislike it. I’m a big supporter of letting people play how they want instead of forcing them to play my way.
Every single agent is goal-driven due to how GOAP works and as a result, the history stats are constantly changing. This results in a conflict of interest since there are so many agent types that prefer certain stat values. I like the way I put it in my previous post. In order for one agent to be happy they’ll have to do things that will make other agents unhappy.
I’m hoping this will help keep things interesting despite the project’s vast scope. I don’t want a Daggerfall-like situation where the game world is huge but empty. I think relying on AI, as in boots on the ground agents, is the best way to avoid the boring sandbox phenomena. I want a gigantic sandbox full of fun stuff. I was once thought procedural generation could be used to fix this problem, but I no longer believe it to be the holy grail I once thought it was.
Ironically, procedural generation probably causes the problem in the first place.
Thus, I’m going to try relying on the AI themselves for content instead. They’ll be the meat and potatoes of gameplay. They’ll make the game so damned interesting that you’ll ignore the repetitive map generation flaws. I think Bethesda and Stalker had the right idea with their Radiant AI and A-Life systems. Living worlds are better than pretty ones! These systems are a major personal inspiration of mine but I’ll talk about them later when they’re more relevant.
The player, of course, can also alter the history stats. This is the first of many steps towards allowing the player to have long-term impacts on the game – which is, of course, necessary for simulating a proper rebellion. Those empire troops you kill, for example, won’t just be magically re-spawned. This isn’t a call of duty match. Each of them will require recruitment, training, equipping and deploying. It takes time and money to replace those losses so even really low-end rebel behavior can have some small effect on the overall status quo. You’re not going to topple the empire by killing random troopers but you might free a town or two!
I’d also like if agents went through entire life cycles. This would make the above example even more important because now the empire doesn’t have an infinite supply of adults to pull from. It’s unrealistic to assume you’ll ever cause enough damage to stop recruitment entirely due to sheer number of people available in a galactic setting, but you’ll definitely be able to empty out small towns or garrisons.
This churn would also help keep the setting fresh by preventing stagnation. Let’s say some talented empire commander has been annihilating the rebels. His death by natural causes would be a huge relief to rebel kind. Lifting that boot from their neck would allow a dynamic resurgence of activity that even the player could notice due to the shift in difficulty.
I’ll probably end up adding such a feature because there are all sorts of sketchy side effects I can explore. Let’s say, for example, that agents are influenced by what they experience while growing up. If you’re willing to be manipulative, then you could go out of your way to cause a brutal empire crack-down on some poor town. This sounds counter-intuitive until you think about the long-term implications. If people grow up in harsh conditions due to said crack-down then they’ll naturally come to hate the empire. They may not join the rebellion itself, but they definitely won’t join or otherwise help the empire! It’s a double-edged sword, though, because those people can just as easily develop empire sympathies.
I like to support morally grey concepts, so the questionable guerrilla tactics such a mechanic would enable pleases me. You don’t have to be a man-slaughtering nutjob, but the option is there! I want the player to be able to fight the empire however they want and I intend to give them all the tools necessary to do so. You can be a bunker-busting commando, trade ship looting pirate, empire headhunting assassin, computer hacker and who knows what else.
I’ve also been thinking about how to give all the agents their roles. I don’t like the idea of just spawning a bunch of gangsters or soldiers. If I’m specifically spawning certain amounts of certain agents then all my work to make a dynamic setting is for naught. I think it’d be better to go for a job approach. Everyone could start as a civilian, for example, but later pick a job for themselves based on their experiences. If someone grows up in a crime-ridden city then they’ll become a police officer. If someone is scarred by rebel terrorism then they’ll sign up to join the empire. That kind of thing. This reactivity gels perfectly with all my previously stated goals so you can expect this to show up sooner rather than later.
Anyway, back to stats. That was a whole spiderweb of tangents.
The first actual stat I added was gang violence. Like I said earlier, all stats are modified by real-world interactions – and as such, it increases by 1 whenever a gangster attacks another gangster. That doesn’t sound like much but when there are hundreds of gangsters attacking each other every single turn that number sure goes up quick!
The next thing I added was two new agent types: civilians and mercenaries. I wanted to put my rewritten version of GOAP through the wringer so I decided to take a more complicated approach to countering the gang violence stat. The solution I came up with is two-fold. The civilians monitor gang violence and once it reaches a certain point they’ll look for a merc to hire. Then, upon finding a mercenary they’ll hire them to go blow up a bunch of gangsters.
This is the point where I decided to handle agent activity in a realistic manor and as such the game doesn’t just tell the civilian where a mercenary is at. Instead, they have to manually find a mercenary. I want the agents to follow the same rules as the player! Thus, to find a mercenary, the civilian just starts exploring the map by pathing to random locations.
I like this because it means there are agents out in the world actually doing things. You could be out in the middle of nowhere and still encounter some agents going about their business. They’re not randomly generated agents that were spawned just to populate the map. They’re actually members of the world on some kind of mission just like you! I think that’s pretty neat.
The civilian, upon stumbling across a mercenary, walks up to them and tells them what faction to hunt. This activates the mercenaries hunt goals which causes them to start searching the map for compatible targets. The gangster factions, in this case.
Attempt at graphing how the civilian / mercenary interaction works. Most functions are shared due to extreme generalization for GOAP which is why some of the arrows converge on the same bubble.
They’ll keep doing this until they’ve racked up 20 gangster kills. This is a hard limit I added just so the mercenary will eventually stop and give a different civilian the opportunity to hire them. In the future, though, the amount of money provided will dictate how many targets the mercenary will hunt. The mercenaries currently work for free since I haven’t added money.
Here is a video of everything discussed in action. Like I said, the civilians will start searching for mercenaries once gang violence is more than or equal to 1000. The mercenaries, when hired, then wander off and start annihilating gangsters until their quota is met. If you watch long enough you’ll notice the gang violence eventually starts getting out of control.
This is due to a bug that I’ve since resolved. It was caused by mercenaries being unable to detect when a gangster they’re targeting occupies the same tile. This, in turn, meant that the gangster couldn’t be killed. Eventually, all the mercenaries would get stuck and without them constantly mowing gangsters down that crime statistic would skyrocket out of control.
Also, you might have noticed the two graphs in the bottom right corner. They’re tracking gangster population levels. The problem I’m running into is that I need a more long-term view of whats going on. My usual method of displaying live debugging stats just isn’t helpful enough. I need to be able to track trends over longer periods of time in order to get a feel of what’s going on under the hood. I’ve thus started building fancier in-game visualizer tools.
This is a nice two birds with one stone situation because I’ll be able to let the player access most of these graphs. They won’t just be tools for me but tools for thee! I think I mentioned this in the past, but it’s critically important to give the player the means to view their impacts on the world. If they’re constantly raiding empire supply lines, for example, then they should be able to see a downward trend on some kind of economic report. It’s unlikely they’ll ever notice an impact through gameplay alone. This game is all about the long-term so changes will occur gradually enough that most people just aren’t going to notice. This means graphs and any other sources of information are vital. If people don’t understand how in-depth the game is then they aren’t going to enjoy interacting with it and otherwise get immersed.
That’s a pretty decent summary of the last post, I think! Let’s move onto the shiny new stuff.
I added a complex interaction last time but there still wasn’t a whole lot of decision making going on. The civilians hire mercenaries when upset and the mercenaries go kill stuff when hired. That’s it. There are no alternative options and as such GOAP’s fancy potential is being squandered. The whole point of GOAP, after all, is that the AI have options and they choose the one that’s right for them based on their current circumstances. The first thing I did to fix the situation was give civilians the ability to take matters into their own hands.
However, before we get into that, I need to explain the new personality system.
I ran into a problem when adding multiple paths of action to choose from. That problem was due to how GOAP works. It uses weighted values to decide which goals to focus on and what actions should be taken to do said goal. The system is too perfect and I was noticing all my agents acting like a hivemind. If there was too much crime, for example, then all the civilians would simultaneously begin searching for mercenaries to hire. This is a flaw with the history system that needs fixing. The agents sharing a single stat means they all react the same way. I could lessen the visibility of this issue by distracting the agents with things like hunger and other personal issues so they’re not always on the same wavelength – but I decided to just buckle down and perform some brain surgery instead of relying on bandaids.
Visualization of the problem I described. I learned how to make gifs in the adventure project. :D
The problem is that hiring mercenaries is objectively the best option. It’s the most effective tool the civilians have for dealing with gangsters. This meant that civilians were refusing to pull out a gun and dish out some much-needed vigilante justice. There are some obvious ways to fix this: such as fine-tuning the weights or adding more goal preconditions for additional granularity but that’s all a bunch of fiddly work!
I refuse to get bogged down with this kind of micromanagement. There might someday be thousands of agent types and god knows how many goals/actions – not to mention whatever other horrifically complicated things I add later! If I change one thing it will absolutely affect countless others. Trying to balance anything would be like untangle a pile of cords or herd cats. It’s possible but tedious and ultimately pointless since the game is still in development and thus constantly changing. Furthermore, I don’t want my game being predictable. If every single thing is perfectly balanced then players will be able to metagame their way into finding the best possible way to win. Introducing some random noise will keep them on their toes.
I’m also bad at balancing things in general. It’s a flaw I discovered several years ago when tinkering with some abandoned RPG concepts. The sheer amount of monsters and items I had to balance was a nightmare. I can do it, but I don’t find that kind of spreadsheet work fun. That experience is probably why I focus so much on sandbox games now. It’s not that sandbox games don’t need balancing, by the way, but people are generally more accepting of balance issues due to its open-ended and ultimately unpredictable freeform nature.
Hence, the personality system. It removes the problem with automation. The agents can now individually decide what they care about. I don’t have to perfectly balance things to ensure they consider all the options. The end result is that some civilians will now prefer to take up arms instead of relying on the mercenaries. The system itself is pretty simple.
It’s just a bunch of random numbers. In fact, as of right now it’s just one random number that I currently refer to as aggression. The higher this aggression stat is the more likely an agent is to prefer more violent options. It works by multiplying the weight of compatible goals and actions by the personality stat. Example below.
woo more graphs
They’re still technically choosing the best option but now said options are tailored to each agents’ randomly generated preferences instead of them all sharing the same hard-coded universal response. I’ll still need to do some degree of balancing, of course, but now the line is kind of blurred and anything I add should at least get used by someone.
The visualization with civilian trigger points randomized.
I wanted to point out before moving on that personalities aren’t just random numbers. They used to be, but I foresaw a potential issue with that and tried to preemptively take care of it. They’re now gaussian numbers. The problem is that randomization, despite the sound of it, isn’t very random. It tends to have an averaging phenomenon where the random numbers land in the same general area. Unfortunately, I couldn’t show enough lines on the visualizer to show you this problem. It takes a massive sample size before any noticeable patterns emerge in the random numbers. This phenomenon might be due to how pythons pseudo-random number generator works but it doesn’t matter now. I’ve found a better method.
Here is an example of 10,000 rolls between 1-3. I saved each roll and tallied them for a total.
1 = 3259 rolls 2 = 3429 rolls 3 = 3312 rolls
See? They’re all in the three thousand range. The numbers are different, sure, but they’re too similar for my liking. It’s not just bad luck, either. I could roll the dice a billion more times and you would always notice some kind of pattern. If I were to use these rolls there wouldn’t be enough deviation. The personalities might be randomized but each agent would act so similarly that you probably wouldn’t notice any substantial differences. It’s like mixing several colors of paint together. Instead of something cool looking you just get generic old brown.
I fixed this by using a gauss based random number generator. In the above example, I was rolling a number from 1 to 3. This means the result will always be 1, 2 or 3. That’s not how it works with gauss, though! Instead of those two numbers controlling the min and max roll they instead control the mean and variance. The mean can be thought of as the starting point while the variance is how far you can wander from it.
Example random rolls. They stay within the supplied range. (1, 3) = 3 (1, 6) = 6 (1, 9) = 4 (1, 12) = 8
Example gauss rolls. The results can go beyond the supplied range. (1, 3) = 5 (1, 6) = 4 (1, 9) = 7 (1, 12) = 17
The visualizer using gauss. You might to open the image elsewhere and zoom in.
I’m going to stick with gauss because of that boundary-breaking ability. I like the idea of some personalities going beyond a strict 1-100 roll. There could be a civilian that gets an aggression stat of 320 or something like that which would make them absurdly violent. It’s especially interesting because that number has the potential to get legitimately out of control if the moon aligns correctly and the RNG god decides to bless a particular agent. This will hopefully allow for some more unique characters to stand out from the crowd that can have a more interesting impact on the setting. Heroes and villains, basically.
I’ll probably also apply this technique to whatever form attributes eventually take. This way you could encounter agents that are unusually strong since they’re gifted with a bunch of strength or intelligence. It’s the code equivalent of being born with good genes. If there’s an agent with a strategic personality and supporting attributes, for example, then they could end up becoming some great rebel general. Or maybe they’re blessed with a combat-oriented mindset and end up becoming a great bounty hunter that’s feared throughout the galaxy?
I might be incidentally creating a basic form of natural selection. Survival of the fittest agent!
I could also make personalities act like a gatekeeper. If an agent isn’t strong, for example, then they can’t use the action that lets them break down a door. It will limit their potential in regards to GOAP. Let me use the above bounty hunter for an even better example. If that bounty hunter is an idiot then they’ll just randomly explore the entire universe for their target. That’s obviously a horrible idea. They’ll die of old age before they find that needle in a galaxy sized haystack. If they were smart, though, then they’d have a lot more options!
help im becoming one of those annoying programmers that use graphs for everything
There’s also the possibility of inheriting bad genes. I haven’t talked about this yet, but gauss actually generates numbers that can be negative as well as positive. What does this mean? Attribute wise, it means agents can suck at things. They could end up with -200 strength!
Personality-wise, though, it means agents can be extremely for or against for something. If I take away the negatives then it means all the agents are neutral at worse. That’s because 0 is the minimum base-line, which just means they have no skill instead of negative skill. The inclusion of negatives, though, allows for qualities on the opposite end of the spectrum. If a civilian has -100 aggression then they’ll almost assuredly never do anything violent.
The above gif examples might not make sense since the agents have been abstracted to a graph, so here is an in-game example of gauss based personalities being turned on and off.
Anyway, a few paragraphs ago I started talking about civilians taking up arms. They do that now! Civilians with high aggression will take matters into their own hands and start attacking gangsters instead of looking for mercs to hire. That gives them two options now for dealing with out of control gangsters. They do it smoothly, too, due to the blurring effect personalities have in regards to their gang violence tolerance levels.
I’m going to go ahead and end the post here. There’s a lot more I want to talk about, but this post has been in the pipeline for months now. I had a lot of annoying things happen at once so it really messed up my schedule but things have finally normalized. Come back next time!
I’m going to continue adding more agents and maybe incorporate some basic gameplay.
I’ve been watching a lot of shows lately that involve high fantasy adventures – most of which involve some kind of power grab. They’re the kind of shows full of shady politics, tactical dealings, huge battles, and vast ambitions. I want to try and distill this into game format.
The most recent example of such a show is Game of Thrones. It has all sorts of characters going on all sorts of grand adventures. There’s dairy queen, for example, uniting a bunch of misfit armies, freeing the slaves, and taming dragons on her quest to claim the iron throne.
The best example of an epic adventure, though, is probably the Lord of the Rings. The sheer amount of stuff that Frodo gets up to on his quest to throw the one ring into Mount Doom is honestly quite ridiculous. I’d like to make a game that enables this kind of interesting quest.
Thus, long story short, I’m going to make an adventure generator!
Currently, my plan is to create a deeply simulated fantasy world. I want to fill the world with a bunch of different factions and let god sort them out.
The result should be a ton of chaos that I can exploit for procedural quest generation by using something similar to Stalkers A-Life or Bethesda’s radiant AI systems. I don’t know how these systems work, but it doesn’t matter. I’ll figure something out when needed.
I have to make the world super interactive in order to support maximum freedom of choice while also giving it enough depth that the player can get up to all sorts of zany antics.
Anyway, let’s get down to brass tacks. I’ve been pouring ungodly amounts of in-depth design analysis into my super project so for this series I’d rather focus on getting things done. I’ll go into excessive detail when it’s necessary instead of front-loading everything like I usually do.
The first thing I need to do is build the world. The game is going to focus on player-centric activities but without a world and its inhabitants, there’s no activities to be had! Thus, I need to create a basic simulation. I need to generate terrain, factions and who knows what else.
The first step is to generate noise. Lots of noise! It’s never actually that easy, though.
Let me show you what plain old noise looks like. It’s not very useful or pretty!
Here is some plain old simplex noise. The result would be largely the same even if I used perlin, wavelet or anything else. The problem is that noise is kind of worthless by itself. It needs to be treated like a worthless lump of clay and shaped into something more useful.
The brown tiles are what I’m currently using to represent land. The entire map defaults to being filled with land because I’m not applying a threshold. This means it doesn’t matter if a particular tile of noise is 0, 1, or something in-between. It considers everything land.
This is what happens if I apply a threshold of 0.2!
There are some blobs of water showing up now! This happens because increasing the threshold basically causes gaps to appear in the noise array. I’m only accepting values that are greater than the threshold – so anything below it doesn’t get carved to the map. I turn any tiles that aren’t land into water which is why more of it appears as the threshold rises.
As you can see, the higher I raise the threshold the less land there is.
You might also notice how each of the examples has a similar pattern. That’s because I’m using a seed number for the noise generator. I’m going to do that from now on for continuity purposes. This way, even a hundred posts from now, the map will still look familiar! I think it will be neat to compare an old version of the map to a fancier one a couple posts from now.
By the way, the map is actually far larger than I’ve led you to believe. The above images are only showing a small section of the world. This section is all I can fit in my 1280×720 game window! Even if I maxed out my game resolution to 1920×1080 or greater it still wouldn’t be enough to fit the whole world. The map is 200×200 which comes out to 40,000 tiles in total while each individual tile is 12×12. I’m only able to show 75 of these tiles at a time.
Let’s switch over to pixel scale. This means I basically draw every tile as an individual pixel instead of a 12×12 tile. If you take into consideration that every tile takes up 12 pixels then you can imagine the space-saving that occurs by compressing them to 1×1!
This is the result of switching over to pixel scale. I went ahead and included the rest of the map area just so you could really comprehend how much smaller things are. If you look closely you’ll notice the previous images pattern is now visible at the pixel scales center.
Anyway, since we can now see so much more it’s time to up the map size. Let’s go from 200×200 to 700×700. That brings us up to a grand total of 490,000 tiles from 40,000!
That’s better. I’m still using the same seed and threshold so due to how noise works, the previous image can be found in this images upper left corner.
Scroll up to look and then back down and you’ll see what I mean.
The next step is to make the world a little more interesting. I’m sure you’ve noticed how repetitive the noise looks. It was fine when we were zoomed in but now that we’re zoomed out a very obvious pattern has emerged. It doesn’t look like any kind of terrain I’ve ever seen! It comes off as some sort of bizarre planet covered in lakes.
This is another problem with noise. It’s very repetitive looking. This happens because the noise isn’t as random as you might think. If it was, then these images would look like static.
It’s beyond the scope of this blog to explain how and why the noise generates shapes instead of useless static, but this wiki entry about noise might help you a little bit.
Either way, static isn’t very useful in regards to terrain generation. The repetitive patterns, though, aren’t exactly ideal either. They look artificial and just plain weird.
The answer is more manipulation. I’ve found the best way to reduce this sameyness is to mix your noise with more noise. That’s what we’re going to do next. I’m going to generate some big and small noise and then evenly mix them together to see what happens.
Here is an animated version of the same images to try and better show the combination.
The end result is certainly more interesting visually but it’s still pretty samey. The only thing I really accomplished was replacing the old pattern with a new one. It’s rougher, sure, as if the world has been eroded over time, but the map still looks very repetitive from top to bottom.
It’s just less squiggly and more spikey.
To further improve this, I’m going to make both sets of noise bigger.
I’m pretty happy with this result! It also helps show off the whole noise combination thing a lot better since you can more clearly see how each set of noise influenced the final result.
This worked better because each set of noise had a bigger scale.
Previously, each set of noise was like static. Theirs shapes, sure, but they’re just a bunch of small patterns. The big noise, though, due to taking up so much space can’t repeat itself as much. This makes the end result more unique when it gets combined with other noise.
This is the map I’ll be using from now on so get used to it! The next thing I want to do is some noise maintenance. I’m going to nuke a few of those small islands from orbit.
Before and after small areas of land were turned into water.
Here is the end result. I turned any landmasses that were less than 30 tiles in total into water. The next step is basically the same thing but used on different terrain. I’m going to use my godly powers to erase any blobs of water that are too small now instead of land.
Before and after tiny bodies of water were turned into land.
I settled on a minimum water count of 50 after some trial and error. It gets rid of all the dumb puddles while retaining a few lakes and other interesting bodies of water.
What’s next? It’s time to give the world some actual terrain. Forests, mountains, deserts and other stuff like that! Believe it or not, I’m going to use more noise to accomplish this.
Here is our map with the addition of forests. It looks stupid because I need to add some new carving rules. I need to restrict the forests to only being carved over land tiles.
This is what it looks like after only letting the forests overwrite land. I also cleaned up any blobs of forest that were less than 20. I’m still using a seed for everything so if you compare this image and the previous one you’ll notice its the exact same noise distribution.
I think the forests might be too big, though, but I don’t care enough to mess with them further. I’ll probably come back to them later and fiddle with the noise values a bit more.
Let’s add some freshwater next. This doesn’t take any noise generation or anything! Instead, I’ll just be converting small bodies of landlocked water into freshwater.
This is what the map looks like with freshwater. I’m turning any water that is less than 10,000 tiles in size into it. That basically means everything but the ocean itself gets converted.
This isn’t a perfect solution. It’s possible for a landlocked blob of ocean tiles to exist that is greater than 10,000 tiles in size. This method wouldn’t detect and convert such a scenario into freshwater. That’s just how procedural generation is. There are infinite possibilities due to the nature of randomization which means theres too many edge cases to handle.
The mountains are next. These are a pain in the ass to make in a satisfying way. Originally, I wanted to create fault lines and simulate volcanic activity along them to create nice looking mountain ranges. This is the kind of appearance I was going for.
Satellite image of the Himalayan mountains. Credit: NASA.
I want nice long ridges like the above image and other curvy stringy mountain range shapes.
However, after several days of tinkering, I’ve decided to give up on that approach. I was making progress but it was slow and soon began to feel ridiculous. The terrain doesn’t really matter right now so every second spent perfecting it was largely a waste of time. I fell into that design trap of working on irrelevant things or optimizing when optimization isn’t needed.
I decided to take a less advanced approach. No geological modeling, unfortunately! Instead, I’m basically just generating a bunch of circles and then corrupting them with noise. There are too many steps involved to screenshot so I’m going to create a gif and then explain it.
Editing on wordpress is like stepping on legos.
I made the gif by just recording my screen. I built an in-game noise visualizer for debugging purposes. It’s a lot easier to figure out what you’re doing when you can see the results!
First, I create two arrays full of randomly positioned and sized circles. That’s Hills1 and Hills2 in the animation. Then, I feed these two circle arrays to a zany math function. It compares the two circle arrays and spits out a weird combination of the two. The combination seems to detect overlapping values and blends them into football-like shapes. The result is that Hills3 is now full of crescents and other vague mountain shapes instead of perfect circles. The first two hill arrays are purposely similar to one another to take advantage of this side effect.
Then I create two sets of small noise. That’s Small1 and Small 2. This noise is evenly mixed together to create Small3. The mixture is then eroded to rough it up even further. Finally, I mix Hills3 with Small3 and apply a gaussian filter to smooth things. The mountains are done!
Here is our familiar world with mountains.
Also, since this is the last dose of terrain generation for the time being, here are some other worlds. They’re made using the exact same noise settings. I just randomized the seed value.
The result isn’t perfect but it’s close enough. There’s some stringy mountain range shapes and other decently peaky looking things so I’m going to call it a wrap and move on.
Here is what the current world would look like if converted into an island if you’re curious.
This is accomplished by creating a map sized centered gradient circle and blending the landmass with it. It basically causes the land to taper off the further it gets from the center.
If you remember, I started adding terrain as a stepping stone towards supporting a basic simulation. I need a world to populate, of course, before I can do anything interesting. I’ve met that goal, so let’s move onto the next step! I’m going to start adding resources now.
I generated terrain first because resources are often tied to it. It’s possible to find ore in the middle of nowhere, for example, but it’s more likely to show up in the mountains. The same goes for wildlife resources like sheep. I guess they could be found in a swampy wasteland but they probably prefer grassy areas near fresh-water sources like natural springs or lakes.
There’s not enough biome variety to accurately simulate resource distribution yet but that’s alright. I’m not aiming for realism right now. I just wanted to build some kind of foundation to work off of instead of just throwing everything around randomly.
Why don’t I just throw it around randomly, though? I don’t literally need terrain. I could just as easily generate resources without it. The answer is that I want resources tied to terrain in preparation for faction generation. Towns, industries and entire civilizations have sprung up around useful resources. The best example I can think of is Egypt and the Nile river or the middle east and its oil. I want to say Rome and its bronze, too, but I’m not entirely sure.
Either way, I think an easy way to make factions more interesting is to give them unique access to certain resources. If one faction has access to lots of iron, for example, then they’ll be able to make some great equipment while everyone else is stuck with copper or stone. It then stands to reason that they’ll develop high-end blacksmithing as a result and potentially claim a good portion of the world due to their access to strong metals and talented smiths.
I could just randomly generate factions and give them access to random resources but then the world would have no weight to it. They would just be an intangible background element that can’t be interacted with. They’d be more like perks or upgrades than resources in this state. If iron is a real resource, though, then factions can trade, steal or even fight over it.
It has implications for the player, too, since resources are now a legitimate in-world thing.
The first iteration of this will be quite simple but should nevertheless help make the world a little more diverse at almost no cost to me complexity wise. I like the way the total war series of games handle resources. They’re just single tile objects on the map. I was originally going to generate fields of resources using noise, but have decided to go this way instead.
Medieval total war is the best total war.
I’m going to generate some resources, and then, if a faction is near said resources they’ll claim it. They’ll build a mine on diamonds, a farm on wheat or ranch on cows. This will be a real place the player can visit and people will staff. Traders will transport goods back and forth between them and whatever town the resource belongs to.
I think we’ll stop here, though. I’d like to put more thought into resources and factions before committing to anything. Come back next year when I add resources, factions and more!
Hello. It’s been awhile! I got completely fed up with the current state of things several weeks ago and had to perform some major code related surgery before continuing. My GOAP implementation, while technically functional, was a major pain in the ass to use.
I’m pleased to announce that the surgery was successful. I’ve not only greatly simplified it as a whole but it also runs faster as an unexpected plus. This simplification is a big deal because it brought a lot of clarity. I don’t need to sacrifice a goat and consult the oracle anymore when adding new goals/actions or otherwise making changes.
That’s enough talk, though. Let’s get down to business!
Last time I talked about not knowing where to go next. I’ve since decided to continue adding new agents or improve upon existing ones. More specifically I’m going to focus on deeper agent interactions. Less shoot and more think! This is to both leverage my recent GOAP improvements and give the player more interesting things to do.
This isn’t your typical game and as such, I don’t feel comfortable designing it in a vacuum. I want to get the player added as soon as possible for testing purposes. I’ve been talking about all sorts of systems and making all sorts of promises – but none of them are necessarily conducive to fun. I need in-game experience to ensure things feel right. I’m following my gut, after all, rather than some kind of detailed blueprint.
There’s no point adding the player yet, though. The only thing they’d be capable of doing is moving and fighting. I’ve tested these things to death in all my other projects so I know they work. I need to instead expand systems, add mechanics and otherwise just give the player more means of interaction. The easiest answer is more agents. They’re all so unique that with each addition the possibilities exponentially increase.
What do I add next, though? I got stuck on this question for quite a while. It’s harder than you think coming up with non-combat related AI. That’s why almost literally every game in the multiverse revolves around combat. Eventually, though, the concept of problem-solving came to mind. I’m going to give the agents problems and ways to solve them by interacting with other agents. There’s never going to be a dull moment with such a system because it’s inherently anti-balance. The agents will never stop working due to all the action and reaction going on. That’s because in order for one agent to be happy they’ll have to do something that will inherently make others unhappy.
What exactly is a problem, though? More importantly, how do I even represent such a thing to an agent? The answer is my previously mentioned history system. No, I’m not that much of a genius. I didn’t think of something before it was needed. The originally envisioned system was a different beast that I’m going to borrow and repurpose.
The original idea was to give the game a better way of doing behind the scenes things; such as deciding what agents to spawn or what random events to trigger. It would do so by analyzing a huge log of recorded stats and responding accordingly. The purpose of this isn’t realism, by the way. It’s to help build towards a more interesting setting by hopefully letting the player more readily see their or others impact on the world. I’m just mimicking realism because nature already has the answer to lots of design issues.
I’ll still use the above-described system at a later date, especially since talking about it got me excited about making it, but for now, the idea is going to be modified to serve a different purpose. The new idea is very similar but instead of a background system reacting to history its individual agents. I’m going to record all sorts of things that are happening across the city and make certain agent types respond to certain stats.
These stats are what the agents consider problems and they’ll solve said problems by modifying the stat. They do that by doing something in-game. Emphasis on doing! The agents must physically do something in the world. I settled on this extra step of complexity early on as it will make the world feel that much more alive. It will also help combat the issue of massive sandbox games (like daggerfall) feeling empty. If a crime stat threshold is reached, for example, then the police will start looking for criminals to arrest. The process of doing so will lower the crime stat by taking a big chunk out of it.
I say a big chunk because I speculate it’s necessary to have the solvers reduce the stat more than the causers increase it. This is to avoid a potential scenario where the solver is forever stuck trying to fix something that grows faster than they can reduce it. I don’t want endless problems. They need to be resolved so agents are free to do other things! I want it to function more like a back and forth tug of war rather than an infinite loop. If there’s a thousand criminals causing mischief but only one officer to reduce it then they’re obviously never going to get anything meaningful done. It’s not that big of a deal, though, because these kind of untenable situations happen in real life. It’s more of a personal preference right now. I’ll need to do some hard testing to see if it’s better gameplay wise to ensure problems can be resolved or to let some things fester.
The first-ever history stat I’ll be adding is gang violence. This stat increases whenever a gangster attacks another gangster. However, the new stat isn’t worth much on its own. I need to add a new agent that cares about it. This tripped me up for a while because the obvious answer is some kind of law enforcement but that’s the last thing you’ll find in this awful part of the city. They’re going to be corrupt at best or actively evil at worst.
The answer? Civilians. They’re only a indirect answer, though. The civilians themselves will not be taking up arms to fight the gangsters. This is a rough and tumble place so I’ll probably add that as a option sooner rather than later, but for now, I have something else in mind. Like I said near the beginning of this post I want to focus on more complex interactions so I’ll be adding yet another agent: mercenaries. I’m going to sprinkle a few of them around the map. The civilians will hire them to hunt gangsters once enough gang violence has happened. Each kill will reduce the stat by a few points. It might also damage their factions territory. This is free for now but in the future it will cost money.
Implementing this complex chain of agent interactions is what originally caused me to throw my hands up in the air and dedicate a few weeks (months?) to rewriting GOAP.
This is basically what happens. The gangsters fight which increases the gang violence stat. The civilians hire mercenary goal is triggered when said stat gets high enough. This causes them to start walking around the map in search of a mercenary. They’re not allowed to cheat so they have manually find one! Also, they can only hire mercenaries that aren’t already flagged as working. Upon finding a mercenary that’s open for business, they then path to it and flag them as hired once adjacent. Hiring the mercenary then activates the mercenaries hunt gangsters goal. This causes them to start wandering around the map in search of gangsters to blast. Each kill reduces the gang violence stat by 300. That sounds like a lot but every turn potentially hundreds of gangsters are fighting. Each attack from each gangster increases the stat by 1 so it can balloon really fast! The mercenary will keep doing this until they’ve reached 20 kills.
My shiny new rewrite of GOAP made creating this chain of goals/actions a snap. In fact, it was no more difficult than creating anything else despite containing significantly more steps. Even though there’s all this multi-agent interaction going on the goals/actions themselves are still independent. There’s basically no increase in complexity anymore where as it used to be almost exponential. Thus, tying two different agent goals/actions together is no more difficult than a thousand. That’s good news for the future! I can easily see situations where the depth of thought reaches hundreds of iterations deep.
Think about the amount of interactions that might be required to topple the empire, for example. There’s so many potential steps involved that I can’t even make up a number!
I’m going to stop here. This post is beyond late and I need to get some content up! I’ll have some examples to show you in the next post along with some new developments.
Hello! It’s time for miscellaneous Wednesday. I recently started the development of a new project that I think is pretty interesting. I can’t think of any roguelikes (or modern games in general) that go for this kind of thing anymore. I’m going to start documenting its progress before I get too far ahead. What is it, though? It’s a horrifying combination of my favorite elements from a million different games all shoved into one.
The core of the game is largely based on two games. I’ll focus on those. There’s galactic conquest mode from the Star Wars Battlefront line of games and Warfare mode from Arma 2. There’s a bunch of other Arma modes (and mods) that provide additional inspiration but talking about them is beyond the introductory scope of this post.
So, let’s start with galactic conquest. The name is pretty self explanatory!
Your goal is to conquer all the planets. To do this you move your fleet to worlds you don’t own yet. You can have more than one fleet but you can only move one of them per turn.
The neutral worlds are instantly claimed when your fleet arrives while enemy worlds require a fight. This is where the fun begins! Each planet can be thought of as a collection of maps.
To capture the planet you have to take control of all the maps by defeating the enemy on every single one of them. Each planet is a tug of war battle for total control.
Here is my attempt to peel back the layers a little bit more to help further explain things. This diagram was made in a free program called Dia. The red and blue planets represent the two different factions while the black one is neutral. The orange planet is contested which means they’re fighting over it. The rectangles connected to the contested planet are its maps. You can see how some of the maps belong to different factions. The orange one is where the current fight on the planet is located. If all those maps are captured by one of the factions then they capture the whole planet!
The maps are your standard control point based affair. If you’ve played any multiplayer FPS game before then you know what I mean. Even if you haven’t then you probably still know what I mean since it’s such a common mechanic. There’s also a ticket system. Tickets are basically respawn points. Every time a team member respawns one of those tickets gets taken away. This means that there are two ways to win. Either capture all the control points or kill so many of your enemies that they run out of tickets.
This is where my project begins to take on a form of its own. First, I plan to make planets and the maps on said planets more important. They’re going to be a source of bonuses instead of just territory. This will add a little more strategy to what you decide to attack and defend. Battlefront has bonuses but you just buy them with the credits you earn from fighting. It’s a pretty underdeveloped system that I forget to use most of the time. It’s unbalanced, too, since some bonuses are overwhelmingly better than others! I’ll always choose increased weapon damage over that stupid control point defense turret, for example. This is what a galaxy map in my game might instead look like.
I left faction ownership out of this example to avoid over-complicating things. You can see that planets and their maps now have bonuses tied to them. If you control a map then your faction gets the related bonus. If you control all the maps on a planet then you also get the planetary bonus. The bonuses hint at some of the fun stuff I plan to add later. I’m not going to talk about those yet, though!
I’m getting antsy with excitement and want to start working on the project so its time to move on! I’m going to start by making a map with control points. There’s also going to be two factions on the map that will be fighting over said control points. I’m not going to do any planet or galaxy stuff yet. There’s no point without the maps working.
To help keep things balanced for more sustainable testing purposes I’m also going to give each faction a headquarters. That’s a special type of control point that can’t be captured. This way, if one faction captures all the control points then the other faction will still have a place to spawn. This is an idea I got from Battlefield 2142. I forget what they’re called but that game has a few maps with the same mechanic.
The green base with the red crossed out circle cannot be captured. I don’t remember what the in game term is for these places but I’m going to continue calling them headquarters. Enough talk, though. Let’s go! I’m going to use the paint image to game map conversion method I’ve previously talked about in my super project series.
There’s not much to look at since everything is so simple right now. The red and green dots are each factions respective headquarters while the grey dots are neutral control points. The AI are finite state machines with two interests: capture control points and attack any enemies they come across. That’s it! I’m going to have each faction spawn an agent per turn at their HQ until a maximum of 100. Let’s see what happens.
Ah, yes. Truly flawless programming. There’s a ton of things going wrong! The agents aren’t attacking one another which probably means field of vision calculations are broken. They’re spawning near the top left corner instead of at their headquarters and for some inexplicable they’re pathfinding to their own headquarters? Mysteries abound.
Okay, I did some fixing! They’re now spawning at the proper location and targeting control points. The targeting system is still broken though so they’re not shooting each other yet. I’ve also now given them the code necessary to capture multiple control points whereas previously they would stop after getting the first one.
It looks weird. They move like flocks of birds. The agents tend to get all stacked up since they’re allowed to occupy the same tile. I need to get combat working.
I ripped my poor targeting code out since its not working and replaced it with a scummy brute force method. It’s slow but it works! Unfortunately, a problem I predicted might happen is actually happening. The pathfinder, due to being so efficient, is causing agents to move around the map in massive streams. This is due to the whole straight line between two points being the shortest path principle. I don’t like this because it means the player would be up against a never-ending line of enemies. The player needs to be capable of capturing points on their own and otherwise standing a chance in combat. That’s not going to be possible with how things currently are!
I need to spread the AI out a little bit more to reduce this wall of death phenomenon. First, I’ve randomized each agents sight radius. This helped a little bit when it comes to agents clumping up during combat since they detect each other at different ranges. The next thing I did was slow down the agent spawn rate. There’s now a spawn delay of 10.
It helped a little bit but also introduced a new problem: unbalance. If I let the simulation run for long enough then one of the factions always becomes the dominant force. This is because the units have a tendency to slowly form into groups and as a result they steamroll anyone they come across. This causes a scenario where the other faction cant replace their losses fast enough. It’s a death blow that can’t be recovered from. I guess that’s technically fine, though? If this was a full game rather than a prototype for testing then the faction being dominated would eventually run out of tickets and lose.
Let’s get back onto the pathfinding topic. I booted up Battlefront 2 classic and entered a random skirmish with the AI. The goal here was to just watch how things played out. Even though I can’t see the actual code I can sort of figure out what’s going on behind the scenes just by watching how things play out. I don’t know if this is a unique ability of mine or all developers in general but here’s a clip of what I was watching.
If you can set aside the obvious graphical differences between this game and mine then they look very similar! In regards to agent behavior, at-least. The agents go from control point to control point and attack any enemies they come across. I noticed a few major behavior differences in agents between my game and Battlefront while watching.
First, the agents seem a little more efficient when it comes to control point selection. In my game, the agents choose one at random whereas in Battlefront the agents seem to individually pick the one nearest to them. I’m going to go ahead and give my agents a targeting upgrade by implementing this feature in my game. This is what it looks like.
I think its better as a result. It’s kind of weird how similar my agents are to the Battlefront agents now. I turned my map into a crude representation of the Endor map so the similarities are a little more obvious. The majority of combat is focused on the center of the map while the occasional guy slips through and captures a rear point. Unfortunately, I didn’t capture a good video on this update and I’m too far ahead to make a better one.
The other thing I noticed is that Battlefronts agents, while going from control point to control point, aren’t doing so in perfectly straight lines. I’m not sure why but they seem to spread out a little bit more. I originally thought its because they were getting thrown off course due to combat but then I saw some AI spawn and take an inefficient path to a nearby control-point without them getting involved in combat.
I think instead of pathing directly to a control point they’re pathing to a random coord near said control point. This makes sense on further examination. The control points in Battlefront don’t work like mine do. To capture them you just need to be near them instead of directly on them. I’m going to make that change in my game. The control points will now have a radius and agents will path to a random coordinate within said radius instead of directly to the point itself.
It looks more like Battlefront but it didn’t do much to solve the snowball affect. In fact, the red faction really spirals out of control near the end. I’ll have to find a better fix.
I’ve now made some major performance improvements behind the scenes. The game now rarely goes below 50fps whereas previously it was struggling to stay above 20. I’ve increased the maximum amount of agents per faction to 200 to take advantage of the improved performance. I’m not sure why but 200 seems to be the sweet spot balance wise. The ball of death phenomenon seldom seems to happen at that specific number. I also turned off the respawn delay to more quickly test mass agent behavior. I’m pretty happy with the results now. The blob, while not properly fixed, now only shows up on occasion. I’m going to move onto other things until it becomes an issue again.
The next difference I noticed is how spawning works. In my game agents spawn one at a time. In Battlefront, though, multiple agents seem able to respawn simultaneously. That makes sense since its a multiplayer game. It would suck if players had to wait in a long que to respawn! I think theres a separate respawn counter for each agent rather than a single shared one. I’m going to implement that next!
I’m pretty happy with the result. It actually increased the pace of things since multiple agents can now respawn simultaneously and get right back into the action. I didn’t see anything even close to a wall of death form, either! What else can I do? I think the next thing I should add is the ability for agents to spawn at owned control points.
Looking good. I think I’ve reached the limit of what I can accomplish on this map, though. It’s so small that more advanced testing is out of the question. The agents are constantly in such close proximity that its hard to see any real patterns anymore.
Unfortunately, the game is already at the limit of what my 1920×1080 monitor can handle. I could increase the map size but then portions of it would be off screen. The game is setup for map scrolling but in order to properly test things I need to be able to see it all at once. It’s time to switch over to pixel scale rather than ascii representation.
This is the new map. The previous one was 101×101 or 10201 tiles and was being drawn with 8×8 ascii. This one is 301×301 which is 90601 tiles. I’m now drawing things at a 4×4 scale using boxes. I still have a good amount of wiggle room if I need to reduce the size further! I’ve come to realize, though, that enormous maps like this probably wont be very fun to play on due to all the traveling involved. I could add automated pathfinding for the player or transport options such as vehicles and teleporters but it would nevertheless be best to keep things small. For testing, though, this is just fine!
I’m going to go ahead and give the agents a new routine now. It’s a short range patrol that causes agents to occasionally path to a random nearby location. I’m doing this to help further spread agents out for the same reason I’ve done it previously.
I’m pretty happy with the result! Each agent has a patrol counter and once it hits a certain threshold they patrol to a random nearby location. They still prioritize combat above patrolling but patrolling comes before capturing control points. This should make combat a less frustrating scenario once the player finally gets involved. I didn’t record a video for it, unfortunately. I was on a programming binge and forgot. You can see it in the following videos, though!
What’s next? I’m going to make the map a little more interesting by adding obstacles. Then I’m going to finally add the player! Creating obstacles will make the map actually look like a map finally. There’s going to be corridors to navigate and all sorts of stuff.
Okay, I’ve added buildings. I was originally going to make it symmetrical but decided not to. In fact, I went haywire doing the exact opposite! I removed the corner control points and instead added a new ones near the top and middle bottom. The design is inspired by planetside 1 and 2 with all its interesting building layouts.
I think that’s enough for today, though. Come back next time for player gameplay!
In the last video update (viewable here if a refresher is needed) you might have noticed how the agents have a strong tendency to get stuck walking in looping patterns. This is because the agents aren’t aware of one another. The only thing they care about is spreading their territory. This means if two or more agents are close to one another they’ll just keep capturing one another’s territory as if they’re taking turns.
I fixed this by adding some new goals and actions that cause agents to search for and attack other agents. They do this with a quick field of vision check. If an enemy agent is detected they’ll attack until the threat is dead. The combat is super bare bones. There aren’t any calculations like damage rolls or hit chances going on yet. This means the first agent to attack will always win since they’ll have the health advantage. Eliminating other agents is prioritized above spreading territory so the moment a hostile comes into view they’ll attack. This means there’s no more weird dancing back and forth.
This is what combat looks like. The map starts with a stupid amount of agents present and they all kill one another until only a few remain. The red line between two agents means they’re fighting. I don’t think I ever explained the white line but it’s just an indicator of where the agent is pathing to. You can see that the agents don’t start claiming territory until all visible threats have been destroyed.
The next update was a new form of territory selection for the claim goal. The agent would previously analyze all the tiles that didn’t belong to their faction and choose the one that’s mathematically closest. This would lead to the agent sometimes picking a new tile to claim that was actually quite far away. That’s because the distance calculation didn’t take into account obstacles like walls.
The left image is how it previously worked while the right one is a closer approximation of how it now works. The green dot is the agent, red dot the target and grey line the path. The darker green tiles are claimed territory while white is unclaimed. The agent now selects a random neutral or enemy tile that borders their factions claimed tiles. This system isn’t perfect due to the random element but I actually prefer how it looks. It spreads the agents out and gets them expanding their territory in all directions.
What’s next? Groups! The agents are no longer going solo. The term faction now makes more sense since they’re working together.
The next thing I added was more goals and actions. The agents can now idle and patrol. Idling causes the agent to just stand where they are while patrol causes them to path to random friendly territory. The weights for these two goals are just counters which is code speak for a number that increments. It starts small but gets bigger over time and eventually it weighs enough to supersede claiming territory. The weight then gets reset back to zero at random which frees the agent to go back to claiming territory. I don’t feel like this shifting weight idea is the proper way to use GOAP but I’ve yet to think of a better way to handle things. If you’re wondering then combat has a high enough weight that idling and patrolling don’t ever overwhelm it.
The reason I added idling and patrolling is because I don’t always want the agents fighting over territory. It’d be kind of silly if there was a 24/7 gang war happening. I imagine them instead fighting in small unexpected bursts. The only time constant warfare should occur is when two or more factions have adjacent territory and their agents keep incidentally running into one another while patrolling. I’m not aiming for realism so much as I am the atmosphere. I think it would feel better if there was only the occasional skirmish instead of gangsters constantly shooting up the streets.
There have been no major changes at this point. I’ve been doing lots of minor behind the scene alterations to move things more towards my goal. Here are some of those changes. First, the maximum amount of agents a faction can have is now based on the amount of territory claimed. This means small factions have less and big factions have more. The current ratio is 1 agent for every 10 tiles with a maximum of 20 per faction. The agents spawn based on chance instead of a guarantee. This is why even factions with a ton of territory don’t have full agent counts. I did this so factions that are being constantly damaged will lose ground since it takes a while for reinforcements to spawn.
That’s about it. I’ve come to realize that I’m not using GOAP to it’s fullest yet. The agents have multiple goals, sure, but there’s only one path of actions available for them to accomplish each goal. The lack of multiple action paths kind of defeats the purpose of using it. Everything I’ve done so far would be much easier to implement as a finite state machine. That’s okay, though. I knew when adding GOAP that it would take a while to come into its own and be useful.
I think once more mechanics are in place things will get better. Having different kinds of equipment to use (guns, knives, cybernetics) and ways to get said equipment (buying, looting, stealing) will help. The games in such a simple state right now that there’s just not a lot for me to leverage yet.
I’m not sure what to do next. I want to start adding player interaction but there’s not anything for them to do aside from fight with the gangsters. Come back next Friday to see what I’ve decided to do next! Thanks for reading.
Hello! It’s time to get down to business. The last post was super wordy so I thought it would be nice to balance things out by filling this one with a bunch of serious progress.
I’m going to start by just spawning a bunch of different agent types. I’ll be focusing on stereotypical criminal archetypes for the time being. Gangsters, smugglers, assassins, thieves, pirates, spies, druggies, hackers, outlaws, slavers, fences and so on!
I’m making this city a sketchy place for more than just atmospheric purposes. The long term plan is to use it as a launching point for developing the whole rebellion thing. What better place for rebel sentiment to fester than one full of criminals?
The first thing I need to do is get some proper pathfinding working. The deer you saw moving around in previous videos weren’t doing anything too intelligent when it came to movement. They were just searching their neighboring tiles for the one closest to their target and then moving to it. This lead to them always moving in straight lines since that’s the quickest way between two points. This was fine for an environment with no obstacles but the city is full of obstacles. It’s probably one of the most cramped residential areas the game will ever see. The below video has updated pathfinding. The deer now have to navigate all sorts of complex paths to reach their precious berries.
The pathfinding issue is fixed so now it’s time to start adding new agents. It took me a while to figure out where to start, though. I eventually settled on gangsters since they’ll give me the most bang for my buck. The gangsters, due to how they fight over territory, means that by simply adding one agent I’ll get a city full of activity.
The gangsters will also drag others into their warfare since they’re messy fighters so it will have an accumulative effect as more agents are added. I actually need to do quite a bit of work to add them, though. I’ll need to get a combat, territory and a faction system up and running. Then I’ll have to create a bunch of new GOAP goals / actions for them.
The territory system is a two-dimensional array. That sound’s fancy, but it’s just the computer equivalent of a checkerboard. Each number in the array represents what faction owns it. The number 0 means nobody owns a tile. It’s neutral. Every other number is unique and belongs to a specific faction. I’m going to use Star Wars for some faction examples. I’d use my game, but there’s no official factions yet! The number 1 might belong to the Mandalorians while 2 belongs to the Hutt Cartel.
I couldn’t figure out how to make a grid of numbers to visualize things for you so I made one out of colors instead. It’s pretty ugly but there’s only so much you can do with paint! The left image is the city. You might not remember it, but I went over its creation and other related details in a previous post. The middle image is the city with the territory overlaid upon it and the last image is the territory array on its own. The color white is neutral while the other colors belong to various factions. Feel free to imagine green belonging to the Hutt Cartel, purple to the Mandalorians, cyan to the Trade Federation and red to the Meatlumps. The territory array is the same scale as the local map which means they’ll be fighting over every single inch (or tile, in this case) of land.
The previous example was pretty ugly so let me show you an in-game implementation. This is the city with a better looking color overlay showing who owns what. There’s no actual factions or anything added yet. I’m just using simplex noise to simulate it.
The above example ended up looking like a terrain relief map. It just doesn’t look like what you would imagine a territory control map to look like. I replaced the noise with flood fills instead and got a much better-looking result. The fake factions are now mostly spread into their own regions which is what you would expect. I imagine this is how things will look once I get the agents added and fighting for territory.
I made this on accident but it ended up looking pretty cool. I could use this to simulate clouds, smoke or some other weathery stuff in the far flung future.
Anyway, It’s time for the real deal. I don’t want to overly complicate things so for the time being each agent will be their own faction. I’m going to have them all fighting one another as they work to expand their personal territory. I’ll change this to be groups of agents working together under one banner once the gangster basics are functioning.
Okay, well, here is step one. I’ve spawned 800 agents (because why not) and turned each of them into their own little faction. The factions are visually represented by all the different colors. The colors are random but not unique. If you look close enough you’ll see some similarities and even exact matches. That’s okay, though, because the factions themselves are unique objects. Even if two agents are the same color they’ll still consider each other enemies. The next step is to get them claiming territory.
This is what the random spreading looks like. It’s not as cool as I thought it would be. The video has two examples. The first part is with 800 agents and the last is with 100.
Okay, now I’ve let GOAP take the wheel. I’m blown away by how easy this was. I just made a new goal for spreading territory and a new action for finding the closest valid tile to spread to. Then I passed those to the agent and that was that!
I think that’s enough for today. I have a good bit more to share but this post is becoming unreasonably long. Come back next time for more gangster stuff!
I spent the last couple of weeks getting accustomed to GOAP. The first version I managed to get running was pretty half-arsed. I was flying by the seat of my pants and as a result, many aspects of it were not properly implemented. I now have a better understanding of how it works, though, and as such have been steadily improving things as a whole! The code has been cleaned up and further generalized several times over and I’ve also got most (if not all) of the main features of GOAP fully implemented.
The last major feature I added is agents having multiple goals and the necessary logic to choose which one of them to work on. That logic revolves around costs. You can think of the costs as a representation of the agent’s decision-making ability.
In this video, the deer have both a hunger and an idle goal. The hunger goal starts at 1 while the idle cost is 10. This means the deer will choose to idle since it has the highest cost. However, once the deer gets hungry, that hunger cost shoots up to 15. This causes them to stop idling and instead work on finding something to eat.
However, that’s enough of that! It’s time to move away from deer simulator 2019. I was originally going to take the simulation further to continue ironing things out but have decided not to. The whole point of this detour, after all, was to get a functioning version of GOAP up and running. That goal has now been reached. Instead of wasting more time with continued debugging we’re going to move onto creating things that matter.
What matters, though? I thought about that for a good awhile. The answer I came up with is gameplay. That might seem like an obvious (and vague) answer but allow me to explain. The goal here isn’t to fake what I’ve been loosely referring to as civilization just for the heck of it. To me, these recent efforts with GOAP are just a means to an end. It’s the first of many complex but ultimately minor background systems that will eventually help bring us towards the goal of a world that doesn’t just feel alive but is alive.
The current plan is to breathe some life into my little hive of scum and villainy. The city already exists due to some previous work but it’s empty. I’m going to remedy that by spawning a variety of agents throughout the city and just letting them go crazy. I don’t want to spawn things in such a gamey way but I don’t have much choice right now. The foundation for more intelligent placement isn’t built yet but we’re getting there!
I don’t think I ever told you why I wanted to use GOAP, though! Its usage brings a whole bunch of neat bonuses but that’s all they are to me. These bonuses, such as the long term maintainability, while nice, isn’t that big of a deal in the grand scheme of things.
The thing I care about is the unpredictability that will come from the agents being given the ability to solve problems on their own. I plan to work with this unpredictability instead of against it. The long term plan is to take advantage of the chaos being caused all by these agents interacting with their surroundings and use it to drive the gameplay. The agents will inadvertently be acting like a bunch of little dynamic quest generators. I’ll be recording their activities and then pull from that history to generate content. This will help achieve my goal of a game full of meaningful content without relying on typical generation methods. Instead of generating missions out of thin air they’ll be made in response to genuine events that have or are happening throughout the galaxy.
This is, in my opinion, vital to the end goal of the player (or agents) being able to affect the galaxy in a meaningful way. Having action and reaction tightly woven into every part of the gameplay will help bring us towards that goal. I’m nowhere near accomplishing such a thing but with GOAP out of the way we’re a lot closer than before!
The reason for this obsession with an organic setting, by the way, is due to my lengthy back history playing all sorts of sandbox games. I’ve come to realize that most if not all of them are ultimately shallow and it’s something that annoys me. That freedom stops being interesting when you realize its only skin deep. It’s just not enough on its own.
Let me give you a better example to help drive my point home. My grand conquests in Terran Conflict started to feel pointless once I realized my actions don’t change the status quo. That’s because the state of the universe is set in stone. The sandbox is an illusion maintained by a bunch of AI pretending to do things that matter. There are factions waging war even though they never trade territory. There are traders trading even though the economy doesn’t matter. Pirates are pirating even though they don’t need the money and never use the things they steal. The player can’t capture sectors, defeat factions or even permanently destroy space stations. The most egregious offense is that space stations are respawned the moment you leave the sector! The game presses the reset button if you do anything that might interrupt the illusion.
I don’t think the factions even need resources to replace losses or do anything in general which further damages the simulation as it means the economic aspect of the game exists just for the player. This as a side effect now means that you can’t damage a faction by raiding it. They will continue to pump out ships if you destroy all their shipyards. Fleets can jump even if they don’t have any energy cells. I’m not specifically sure how much is faked so some of what I just said might be false – but enough of it is faked that it had a trickle-down effect that tempered my ability to enjoy it.
I want to avoid this kind of illusory sandbox which brings us back to my original point. The gameplay. I want to ensure it doesn’t get lost in the noise. I plan to accomplish this by creating a setting where things matter. The sandbox and all the bells and whistles that come with it are being built to support the gameplay rather than serve as it.
I have a lot of other things to talk about but it will have to wait until next time. Feel free to come back for part 7! I’ll actually have some stuff to show you.
Ah! Yes! I finally got a rough draft of GOAP up and running. It took a few days of banging my head against the wall but I finally got it! It wasn’t actually that difficult in the grand scheme of things. I probably spent most of the time just staring at the screen trying to wrap my head around this four dimensional non-sense. In order to create a GOAP system you have to think about AI from an entirely different angle. You can’t just go down a finite state machine style checklist of obvious choices anymore. Instead, it’s all abstracted to hell and back. Everything has to be decentralized but also compatible.
The current implementation isn’t very faithful, though. That’s why I’m only calling it a rough draft. I took a lot of short cuts in order to get where I am now. I did this to reduce the overall complexity of implementing something with such a foreign design concept. Instead of having to simultaneously develop new mechanics on multiple fronts I just focused on the most important one. The automated goal / action system!
I left out things like the cost / weights stuff or support for multiple goals and action paths. The deer only have one goal, which is to eat, and its always active. They’re basically being forced to gorge on those delicious berries non-stop! There’s also only one possible path of actions they can take in order to eat – which is find berries, path to berries and then eat berries. The important part, though, is that they’re figuring out how to do this all on their own. I’ve verified this by randomizing their actions prior to analysis. They figure out the right order of operations no matter how much I mess with them.
Anyway, here is the first ever video of it running! It’s just a dumb little deer eating dumb little berries. The white D is the deer and the pink bush looking things are berries.
The next step was to test its responsiveness. I added a respawn timer that adds new berries to the world once a timer is reached. It’s a good thing I did this because I noticed a problem. The agents aren’t analyzing their environment in real time. They get a path of actions and stick to it until completion even if a better path shows up. The deer will find a berry and move towards it as expected but if a new berry spawns that is closer than their currently targeted berry they wont change targets. This is a performance heavy feature but its kind of the whole point of GOAP. I’ll get it patched up soon.
I then took a risk and added another deer. Everything actually worked without issue! I was really expecting a crash or some kind of conflict to arise but nothing bad happened. However, as you may have noticed, their is something strange going on. It’s not a bug or anything, though. It’s more like a quirk.
That quirk is that both deer eventually get kind of stuck doing the exact same thing. This is happening due to how the berry search works. The game finds all the berries and directs the agent towards the closest one. This means, then, that the closer two agents are and the fewer berries their are the more likely they are to start going for the same berry. Eventually they’re on top of each other and moving in perfect unison. This would happen less if the map were bigger and I didn’t allow agents to occupy the same tile.
The below video has even more deer in it to help you see what I’m talking about. I also dramatically increased the berry respawn rate to try spreading them out more but it didn’t really help. Even with so many food options the dummies still get all stacked up! I’ll have to add some kind of randomization or something to prevent this. also cleaned up the debug stats and added a guide line that connects each agent to their debug stats. This is so we can tell which stats belong to which agent.
The earlier discussed issue is more noticeable in this test, by the way. If you pay close attention you’ll notice the agents walking towards coordinates where berries used to be but aren’t anymore. That shouldn’t be happening! Instead, if a targeted berry gets eaten then they should stop and search for a new one. This will hopefully be fixed next time.
That’s enough for today, though. I’ll see you guys next time in part 6! I will likely fix the above mentioned issues, add more goals / actions and who knows what else. This dumb deer/berry simulation stuff is to help me get used to using GOAP. It also helps with working out the kinks. It wont take long before we’re back to ‘real’ gameplay stuff.