Level 10 & 11 With Some Other Stuff

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?

The Layers Of The OSI Networking Model

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?! 😉

Level 9 (Now With Pedestrians!)

You can’t have the old trolley problem without taking a few innocent lives, so the game needs pedestrians!
Unity offers many prebuilt assets for this, but because I’m still in the initial development phase focusing on the real content of the game is more important than wasting valuable time and willpower dealing with complicated 3D models of humans. While I was trying to get to sleep a few nights ago, I realized that I just needed to make the cardboard cutout (used in a previous level) mobile, so why not just put wheels on it so it can roll around in whatever direction I need. Here’s what I ended up with last week after wasting a few hours with blender (I ended up just using unity’s primitives because I’m too impatient for a real modeling app):

The Wheelbase Prefab

My modeling skills are embarrassing at best, but it works. I want to make the wheels more like bicycle wheels that spin when it moves so it looks like somebody made it in their garage at 3am. It’s only able to move in one direction, but you can specify the speed. I also want the pedestrian image itself to be an actual cutout not just a textured plane, but that will have to happen later when I have all sixteen levels working.

Bad as it looks, it works, and I was able to do the first real level where the trolley problem is implemented in the game. I’m hoping to have a playable demo on here soon. The neat thing was adding this to the game as an obstacle attached all the behaviors the previous obstacles have as well, so colliding with it causes a failure and so forth without any additional coding on my part. Maybe you can OOP correctly?