The first thing I did was to set up the structures for objects on the screen. I then made subclasses of these objects for animals and food. I stored all the objects in a list, and the python garbage collector took care of the rest.
The objects on the screen eat smaller objects and animals move forward when updated. They slowly die unless they eat food or animals. Something important to note is that animals won't each other if they are similar enough.
Here I talk about rays as inputs for the eyes of the neural nets. My first approach for ray casting was very naive. I had the program take small steps in the ray's direction until it hit something or it reached its max length. If I had kept an updated 2d matrix, the size of the screen in pixels notating which objects were at each location, this method could have worked. I won't be taking that approach, so the first time I loaded up the script with this naive ray casting/marching, my computer did not enjoy itself.
My next approach was to use the circle line formula for each object on the screen, skipping any circles outside of the sight range. This lead to a significant speedup. You can see below that the rays aren't drawn if nothing is close to an animal.
Then I quickly checked if collisions were working by only drawing ray hits.
The last step is to add a neural network for each of these animals. Each animal uses a Pytorch sequential neural net with two times its number of rays as inputs: the ratio between the hit distance and the ray length, and the ratio between the target size and the animal size.
This line of code seals the deal: self.vel += self.brain(self.get_inputs()).item()
"vel" in this case is a value between 0 and 359 representing the direction the neural net should face.
Now they're definitely taking actions based on what they see, but 90% of them are just spinning around. Let's let them train for a little bit:
Now the zoo is getting a bit smarter.
I added a scoreboard that the program will automatically fill with the animals who survive the longest. When repopulating the screen it chooses 2/3 of new animals from that scoreboard, the rest are randomly created. You can also save the scoreboard with pickle so you don't have to lose training progress.
The large turquoise animals look like they have promise