4
4
import pygame
5
5
import math
6
6
from render .colors import Color
7
+ from render .track import Track
7
8
8
9
9
10
# ------------------ GLOBAL VARIABLES ------------------
@@ -39,7 +40,7 @@ class Car:
39
40
DRAW_SENSORS = True
40
41
SENSORS_DRAW_DISTANCE = 1920
41
42
42
- def __init__ (self , start_position : list ):
43
+ def __init__ (self , start_position : list , track : Track ):
43
44
# The _sprite is the untouched sprite (not rotated) while the sprite is the one which will be moved around
44
45
self ._sprite = pygame .image .load (CAR_SPRITE_PATH ).convert_alpha ()
45
46
@@ -67,6 +68,15 @@ def __init__(self, start_position: list):
67
68
68
69
self .driven_distance = 0
69
70
self .speed_penalty = 0
71
+ track_width = track .width
72
+ track_height = track .height
73
+ self .track_diagonal = math .sqrt (track_width ** 2 + track_height ** 2 )
74
+
75
+ self .DISTANCE_NORMALIZER = self .track_diagonal / 2
76
+ self .MAX_EXPECTED_SPEED = self .track_diagonal / 100
77
+ self .minimum_speed = self .CAR_SIZE_X / 6
78
+ self .angle_increment = math .degrees (math .atan2 (self .CAR_SIZE_Y , self .speed * 10 ))
79
+ self .penalty_factor = self .track_diagonal / 1000
70
80
71
81
def draw (self , track : pygame .Surface ) -> None :
72
82
"""Draw the car on the track (and its sensors if enabled)
@@ -177,6 +187,13 @@ def check_sensor(self, degree: int, track: pygame.Surface) -> None:
177
187
distance = int (math .hypot (x - self .center [0 ], y - self .center [1 ]))
178
188
self .sensors .append ([(x , y ), distance ])
179
189
190
+ def update_adaptive_parameters (self ) -> None :
191
+ """Update the adaptive parameters of the car such as the angle increment, the minimum speed, etc."""
192
+ self .angle_increment = math .degrees (math .atan2 (self .CAR_SIZE_Y , self .speed * 10 ))
193
+
194
+ min_sensor_distance = min (sensor [1 ] for sensor in self .sensors ) if self .sensors else self .CAR_SIZE_X
195
+ self .minimum_speed = max (self .CAR_SIZE_X / 6 , min_sensor_distance / 20 )
196
+
180
197
def update_center (self ) -> None :
181
198
"""Update the center of the car after a rotation (when it turns left or right)"""
182
199
sprite_as_rect = self ._sprite .get_rect ()
@@ -205,7 +222,7 @@ def update_sprite(self, track: pygame.Surface) -> None:
205
222
self .position [1 ] += sin * self .speed
206
223
207
224
# Update the driven distance with the speed
208
- self .driven_distance += self . speed
225
+ self .update_adaptive_parameters ()
209
226
210
227
# Calculate Corners
211
228
self .refresh_corners_positions ()
@@ -242,17 +259,16 @@ def get_reward(self) -> float:
242
259
float: The calculated reward
243
260
"""
244
261
245
- # Reward for distance driven
246
- distance_reward = self .driven_distance / 10000
247
-
248
- MAX_EXPECTED_SPEED = 5000
249
- speed_reward = (self .speed / MAX_EXPECTED_SPEED ) ** 0.5 # Square root to apply diminishing returns
250
-
251
- malus = self .speed_penalty / 100
252
-
253
- # Calculate the final reward
254
- final_reward = distance_reward + speed_reward - malus
255
-
262
+ distance_reward = self .driven_distance / self .DISTANCE_NORMALIZER
263
+
264
+ speed_reward = (self .speed / self .MAX_EXPECTED_SPEED ) ** 0.5
265
+
266
+ malus = self .speed_penalty / self .penalty_factor
267
+
268
+ progress_factor = min (1.0 , self .driven_distance / (self .track_diagonal * 0.75 ))
269
+
270
+ final_reward = (distance_reward + speed_reward - malus ) * (1 + progress_factor )
271
+
256
272
return final_reward
257
273
258
274
@@ -266,7 +282,7 @@ def brake(self) -> None:
266
282
self .speed -= Car .SPEED_INCREMENT
267
283
else :
268
284
self .speed = Car .MINIMUM_SPEED
269
- self .speed_penalty += 1 # speed_penalty for going too slow
285
+ self .speed_penalty += 1
270
286
271
287
def turn_left (self ) -> None :
272
288
"""Turn the car to the left"""
0 commit comments