I'm really new to neural networks. I'm trying to make a neural network with genetics algorithms which will make a snake learn to look for the food and avoid hitting his tail.
The thing is that I think that I've done it, but as there's no walls the snake learns to go one direction only without making a 180 turn [GIF HERE].
I've tried to incentivate mutations that make them turn by decreasing the score of the snakes that always takes the same directions, but it don't works. I've only made them dumber, needing more breeds to reach another "smart" linear snake.
I've made a network with 5 inputs:
- Food position relative to my position and direction (2 inputs. x and y)
- Nearest wall (my tail) if I turn left
- Nearest wall (my tail) if I do not turn
- Nearest wall (my tail) if I turn right
The output are 3, being the first one turning left, the second do not turn and the third going right. I make the snake go the highest one of the 3 outputs.
I've added 1 hidden layer of 8 neurons (inputs + outputs premise).
The way I calculate the score is:
- Each step, 1 point.
- Each food eaten, 10 points.
- If the snake lasts too much time without eating food, dies.
- If hits his tail, dies.
Then I save each time the direction this snake has gone (up, right, down, left) and increment them by one. When the snake dies, I weight the final score by the difference between the lowest and highest values. If the difference is high, they receive a big penalty (down to 0.25 of their score). This way if a snake is pretty much linear gets a high penalty and if a snake does a cool pattern, gets a low penalty.
Also, I keep a record of each time a direction change happens compared to the last direction change, so if a snake keeps going in circles don't gets a high score because of "cool pattern method" for going all 4 directions.
With all this, I don't understand why my best snakes are always the linear ones :-/
I spawn 20 snakes and get the best 4 of each generation when everyone dies.
For generations I use neataptics.js and for neural networks I use synaptics.js. I have a Fiddle here: http://jsfiddle.net/Llorx/gunsct5r/
At line 10
you can see the network definition. At 211
you can see the snake "view" (food position and walls. Where it gets the inputs) and at 164
you can see the score weight calculation depending on steps taken that I mentioned before.
All inputs are normalized from 0 to 1.
I'm sure that I'm doing, not one, but a lot of things pretty bad, as I'm a newbie on this, but some light on this will be really cool.