Level 10 and 11 are working now. For level 10, a crowd of people is (are?) crossing the street, and for level 11, you have to drive in between two stationary people. When I say people I mean the pedestrian model I discussed in my last post. I’m making myself finish a new level every week until I hit 16, so levels 12, 13, 14, 15, 16 should be done in the next five weeks assuming I don’t have like a vacation or something coming up. When that’s done I’ll focus on polishing the game up. There’s going to be a serious amount of work then, but for now it’s just fun.
I wanted to talk about another idea I’ve had that came from me learning that none of the really big rogue-like games that are popular right now are taking true advantage of multi-threaded application design. Specifically, Dwarf Fortress runs on a single thread and this just seems like a tragedy to me. I had to stare at the wall of my bathroom for a good two minutes after reading about this if you know what I mean (spoiler: I was pooping at the time) and fester on how it could be that the game considered to be the most complicated simulation in the world runs as a single threaded application. Someone pointed out that it does run things like rendering and sound on separate threads but the vast majority of the simulation does not take advantage of multi-core processing which becomes noticeable once the game has a lot happening right in front of the player. I’m guessing things off screen are just approximated which I get because we don’t have enough machine power to simulate everything in the world, but, I mean, really?
I was quite sure after reading this that the developers behind DF had very good reasons for doing this. Things have to happen sequentially for the simulation to make sense, and doing things all on the same thread ensures things happen in the order they should, but I am not able to accept this explanation because I have heard suppositions like this before and have seen them proven wrong, so I decided that I needed to take matters into my own hands and develop a massive simulation like DF while attempting to take advantage of
multi-threaded processing to see for myself why this is impossible. My theory is that I can break up the work if I set up everything using a layered approach (similar to the OSI networking model) and then pass this on to a thread pool for processing.
The most basic example I could think of was considering times when multiple creatures attempted to enter the same block (google rogue-like or dwarf fortress and read about how the map is setup if you’re not sure what I mean by this). If two threads checked that the block was empty at the same time, each would see an empty block, and then allow the creature to enter the block, which as far as I know isn’t allowed, or would at least signal an interaction between the two. However, if you broke this task up into a few different pieces, each creature could then create a request to enter the block which are placed in a block-specific queue, and are then dealt with by the thread pool once all the creatures have made their movement requests. Breaking up things into smaller and smaller chunks, you should be able to spread out the needed instructions across multiple CPUs (GPUs?)
One situation I keep thinking of works like this: two creatures want to move into a block, so some thread comes along and says, hey you both can’t move into the same block, do you want to attack instead? One may say yes, the other might say no. Who moves into the block? Additionally, lets says 10 CPU cycles later, turns out another creature wants to move into the same block, do we now go back and ask the first two creatures if they want to attack this third creature? Do we have to accumulate all the movement requests before they can be processed? Also, creatures can been in different states at different times, and even multiple states. Most animals and people can think and move at the same time, right? So, once a creature decides to do something, and they’ve made this decision before another creature does, shouldn’t they get to move into the block (assuming they’re faster) first? And once they’ve moved into that block, wouldn’t that influence the decision making process of any other creature within viewing distance?
There’s a lot of questions like this to answer, but even if you were to assign threads to groups of adjacent blocks, it would be a better design that using a single thread for the entire simulation. However, truth be told, the real question is, how in hell am I gonna find time to do this?! 😉