The start
I had the idea for this project a long time ago. It's a mix of different inspirations:
- Dwarf Fortress for the output,
- videos where AI learns to perform tasks alone or in groups,
- and more recently, an episode of Black Mirror (Thronglets).
The main idea is to simulate a world and have digital creatures learn to live in it.
To get started, I had to build a world and create both creatures and food (plants). At first, the creatures didn’t have any AI they could train. Instead, they used a simple state machine to switch between different actions: eat, sleep, move, and reproduce. The creatures had to eat in order to survive, but they would also die of 'old age' after a certain number of in-world ticks. This ensured that the world wouldn't become overpopulated. I also created a plant that the creatures could eat, which itself would die and reproduce, making the world more dynamic.
Adding the recurrent neural network
Once that was done, I asked ChatGPT to help me build a simple RNN (Recurrent Neural Network) class. I didn’t want to use an existing library because I wouldn’t be able to modify it as needed. Doing it from scratch also helped me better understand how an RNN works, which was one of my main goals for the project. Implementing this class was quite difficult, as I had to rewrite a lot of the existing code.
Each creature has its own “brain,” which learns after each tick based on whether its actions were successful or not. For example, if a creature tries to eat but no plant is nearby, it gets a reward of '-1'. If a plant is nearby but the creature isn’t hungry, it also gets a '-1'. But if a plant is nearby and the creature is hungry, the reward is '1'. In this way, the creatures slowly learn what to do based on their observations.
Providing the right input to the RNN was another important step. I had to decide what information would be given to the network to help it choose the next action. Right now, the input includes basic information about the creature’s surroundings and internal state—like hunger level, the presence of nearby plants or other creatures, etc. All inputs had to be normalized between 0 and 1 to help the RNN process them more effectively. For hunger, for example, the input becomes 'hunger / maxHunger.
To ensure the RNN continues to evolve, it is passed on to the offspring of each creature. This means that the creatures with the most adaptive 'brains' are more likely to reproduce and pass on their neural networks, while poorly adapted ones die out.
What's next ?
- Add carnivorous and omnivorous creatures to introduce more dynamics to the ecosystem.
- Add more types of plants, including toxic ones, so that creatures will need to learn which are safe and which aren’t.
- Introduce terrain features like water, adding a thirst meter, so that creatures have to manage two survival needs.
- Possibly expand the UI using a proper GUI library.
- Save / Load for the best brains to use them in other runs.