Skip to content

Commit

Permalink
"Reduce observation vector size and refocus AI on key game metrics"
Browse files Browse the repository at this point in the history
Reduced the VectorObservationSize in Prefabs/SnakeAgent.prefab from 71 to 5. This change fine-tunes the AI's attention towards the most important information for decision-making in the game. The Observation Vector will now only include data on the direction to the food and immediate dangers for the snake - front, left, and right positions relative to the snake's heading. This will help in optimising the performance of the AI.

Also adapted AI_timers.json and SnakeAgent.cs files to reflect these changes.
  • Loading branch information
Pristar4 committed Jul 11, 2023
1 parent 88f850b commit d17612f
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 19 deletions.
2 changes: 1 addition & 1 deletion Assets/ML-Agents/Timers/AI_timers.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"count":1,"self":40.0425568,"total":40.238061599999995,"children":{"InitializeActuators":{"count":16,"self":0.0020276,"total":0.0020276,"children":null},"InitializeSensors":{"count":16,"self":0.0005068,"total":0.0005068,"children":null},"AgentSendState":{"count":60,"self":0.0030371,"total":0.070967099999999991,"children":{"CollectObservations":{"count":480,"self":0.0035174,"total":0.0035174,"children":null},"WriteActionMask":{"count":480,"self":0,"total":0,"children":null},"RequestDecision":{"count":480,"self":0.0644126,"total":0.0644126,"children":null}}},"DecideAction":{"count":60,"self":0.045922,"total":0.045922,"children":null},"AgentAct":{"count":60,"self":0.076081799999999991,"total":0.076081799999999991,"children":null}},"gauges":{"SnakeAi.CumulativeReward":{"count":106,"max":-0.003001213,"min":-10.008,"runningAverage":-9.815557,"value":-10.005,"weightedAverage":-10.0048523}},"metadata":{"timer_format_version":"0.1.0","start_time_seconds":"1689087858","unity_version":"2023.1.3f1","command_line_arguments":"C:\\Program Files\\Unity\\Hub\\Editor\\2023.1.3f1\\Editor\\Unity.exe -projectpath C:\\Users\\felix\\SnakeGame -useHub -hubIPC -cloudEnvironment production","communication_protocol_version":"1.5.0","com.unity.ml-agents_version":"2.3.0-exp.3","scene_name":"AI","end_time_seconds":"1689087899"}}
{"count":1,"self":312.13376,"total":578.49973879999993,"children":{"InitializeActuators":{"count":16,"self":0.0010077999999999999,"total":0.0010077999999999999,"children":null},"InitializeSensors":{"count":16,"self":0,"total":0,"children":null},"AgentSendState":{"count":31843,"self":0.5999386,"total":2.4476492999999997,"children":{"CollectObservations":{"count":238033,"self":0.3295816,"total":0.3295816,"children":null},"WriteActionMask":{"count":238033,"self":0.11404349999999999,"total":0.11404349999999999,"children":null},"RequestDecision":{"count":238033,"self":0.3964431,"total":1.4040856,"children":{"AgentInfo.ToProto":{"count":237905,"self":0.37333649999999996,"total":1.0076425,"children":{"GenerateSensorData":{"count":237905,"self":0.63430599999999993,"total":0.63430599999999993,"children":null}}}}}}},"DecideAction":{"count":31843,"self":255.17744639999998,"total":255.1774481,"children":null},"AgentAct":{"count":31843,"self":8.7121871999999989,"total":8.739863999999999,"children":{"AgentInfo.ToProto":{"count":4018,"self":0.0145954,"total":0.027676899999999997,"children":{"GenerateSensorData":{"count":4018,"self":0.0130815,"total":0.0130815,"children":null}}}}}},"gauges":{"SnakeAi.CumulativeReward":{"count":4042,"max":109.316093,"min":-10.4399977,"runningAverage":-2.30997682,"value":39.7010956,"weightedAverage":48.6735573}},"metadata":{"timer_format_version":"0.1.0","start_time_seconds":"1689089519","unity_version":"2023.1.3f1","command_line_arguments":"C:\\Program Files\\Unity\\Hub\\Editor\\2023.1.3f1\\Editor\\Unity.exe -projectpath C:\\Users\\felix\\SnakeGame -useHub -hubIPC -cloudEnvironment production","communication_protocol_version":"1.5.0","com.unity.ml-agents_version":"2.3.0-exp.3","scene_name":"AI","end_time_seconds":"1689090097"}}
2 changes: 1 addition & 1 deletion Assets/SnakeGame/Prefabs/SnakeAgent.prefab
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
m_BrainParameters:
VectorObservationSize: 71
VectorObservationSize: 5
NumStackedVectorObservations: 1
m_ActionSpec:
m_NumContinuousActions: 0
Expand Down
57 changes: 40 additions & 17 deletions Assets/SnakeGame/Scripts/SnakeAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using System;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using Unity.MLAgents;
using Unity.MLAgents.Actuators;
Expand Down Expand Up @@ -125,27 +126,49 @@ private static bool IsSnakeAlive(Snake snake) {


public override void CollectObservations(VectorSensor sensor) {
if (board.Snakes.Length > 0) {
sensor.AddObservation(board.Snakes[0].Direction);
sensor.AddObservation(board.Snakes[0].Position);
sensor.AddObservation(PreviousDistance);
sensor.AddObservation(board.FoodPositions[0]);
int[] array = board.GetBoardAsArray();

for (int i = 0; i < array.Length; i++) {
sensor.AddObservation(array[i]);
}
} else {
sensor.AddObservation(Vector2.zero);
sensor.AddObservation(Vector2.zero);
sensor.AddObservation(Vector2.zero);
// Assuming that there is always at least one snake and one food in the game
var snake = board.Snakes[0];
var food = board.FoodPositions[0];

// Calculate direction to the food relative to the snake's heading
Vector2 directionToFood = (food - snake.Position);
// Normalize directionToFood
directionToFood = directionToFood.normalized;


int[] array = board.GetBoardAsArray();
// Add the direction to the food (2 floats)
sensor.AddObservation(directionToFood);

for (int i = 0; i < array.Length; i++) {
sensor.AddObservation(-1);
// Check for immediate dangers: front, left, right relative to the snake's current direction
var forwardPosition = snake.Position + snake.Direction;
var leftPosition = snake.Position + RotateCounterClockwise(snake.Direction);
var rightPosition = snake.Position + RotateClockwise(snake.Direction);

// Check if next positions are inside the board and not occupied by the snake's body
sensor.AddObservation(IsPositionSafe(forwardPosition));
sensor.AddObservation(IsPositionSafe(leftPosition));
sensor.AddObservation(IsPositionSafe(rightPosition));
}

private bool IsPositionSafe(Vector2Int position) {
// Define the condition for the position to be safe. The following is just a basic example.
// You might need to add more conditions or modify it according to your game rules.

// Check if out of bounds
if (position.x < 0 || position.y < 0 || position.x >= width || position.y >= height)
return false;

// Check if would collide with the snake
foreach (var snake in board.Snakes)
{
if (snake.Body.Contains(position)) {

return false;
}
}

// If passed both conditions, the position is safe.
return true;
}

private Vector2Int RotateClockwise(Vector2Int direction) {
Expand Down

0 comments on commit d17612f

Please sign in to comment.