Skip to content

Commit 287ed0b

Browse files
committed
New track in racing ai
Impossible difficulty added, which switches between tracks randomly! Also readjusted the tracks to fit better on screen
1 parent 9ebbcfe commit 287ed0b

File tree

1 file changed

+66
-15
lines changed

1 file changed

+66
-15
lines changed

Racing AI.py

Lines changed: 66 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ def generate_square_track(center, size, track_width):
238238
# Create checkpoints - perpendicular lines across track at regular intervals
239239
checkpoints = []
240240
total_points = len(outer_points)
241-
checkpoint_spacing = total_points // 25 # Changed from 16 to 25 for more frequent checkpoints
241+
checkpoint_spacing = total_points // 25 # Changed from 16 to 24 for more frequent checkpoints
242242

243243
for i in range(0, total_points, checkpoint_spacing):
244244
checkpoints.append([inner_points[i], outer_points[i]])
@@ -256,8 +256,8 @@ def generate_square_track(center, size, track_width):
256256

257257
def set_track(track_type):
258258
global center, walls, checkpoints, road_polygons, start_pos, start_angle
259-
center = (SIM_WIDTH // 2, SIM_HEIGHT // 2)
260259
if track_type == "easy":
260+
center = (SIM_WIDTH // 2 + 50, SIM_HEIGHT // 2) # Shifted right to (475, 300)
261261
outer_radius = 250
262262
inner_radius = 150
263263
num_segments = 40
@@ -269,14 +269,15 @@ def set_track(track_type):
269269
track_points = outer_points + inner_points[::-1]
270270
road_polygons = [track_points]
271271
checkpoints.clear()
272-
for i in range(20): # Increased from 10 to 20 checkpoints
272+
for i in range(20):
273273
angle = 2 * math.pi * i / 20
274274
p_inner = (center[0] + inner_radius * math.cos(angle), center[1] + inner_radius * math.sin(angle))
275275
p_outer = (center[0] + outer_radius * math.cos(angle), center[1] + outer_radius * math.sin(angle))
276276
checkpoints.append([p_inner, p_outer])
277277
start_pos = (center[0] + (inner_radius + outer_radius) / 2, center[1])
278278
start_angle = math.pi / 2
279279
elif track_type == "medium":
280+
center = (SIM_WIDTH // 2 + 50, SIM_HEIGHT // 2) # Shifted right to (475, 300)
280281
outer_a = 250
281282
outer_b = 200
282283
inner_a = 170
@@ -290,15 +291,15 @@ def set_track(track_type):
290291
track_points = outer_points + inner_points[::-1]
291292
road_polygons = [track_points]
292293
checkpoints.clear()
293-
for i in range(20): # Increased from 10 to 20 checkpoints
294+
for i in range(20):
294295
angle = 2 * math.pi * i / 20
295296
p_inner = (center[0] + inner_a * math.cos(angle), center[1] + inner_b * math.sin(angle))
296297
p_outer = (center[0] + outer_a * math.cos(angle), center[1] + outer_b * math.sin(angle))
297298
checkpoints.append([p_inner, p_outer])
298299
start_pos = (center[0] + (inner_a + outer_a) / 2, center[1])
299300
start_angle = math.pi / 2
300301
elif track_type == "hard":
301-
hard_center = (center[0] + 50, center[1] + 50) # New center: (475, 350)
302+
hard_center = (SIM_WIDTH // 2 + 50, SIM_HEIGHT // 2 + 50) # Remains at (475, 350)
302303
square_size = 175
303304
track_width = 70
304305
walls, road_polygons, checkpoints, start_pos, start_angle = generate_square_track(
@@ -319,15 +320,19 @@ def menu():
319320
return "medium"
320321
elif event.key == pygame.K_3:
321322
return "hard"
323+
elif event.key == pygame.K_4: # New option
324+
return "impossible"
322325
screen.fill(WHITE)
323326
title_text = FONT_MEDIUM.render("Select Track Difficulty", True, BLACK)
324327
screen.blit(title_text, (SIM_WIDTH / 2 - title_text.get_width() / 2, 100))
325328
option1 = FONT_SMALL.render("1 - Easy (Circle Track)", True, BLACK)
326329
option2 = FONT_SMALL.render("2 - Medium (Oval Track)", True, BLACK)
327-
option3 = FONT_SMALL.render("3 - Hard (Square Track)", True, BLACK) # Updated description
330+
option3 = FONT_SMALL.render("3 - Hard (Square Track)", True, BLACK)
331+
option4 = FONT_SMALL.render("4 - Impossible (Random Track Each Generation)", True, BLACK)
328332
screen.blit(option1, (SIM_WIDTH / 2 - option1.get_width() / 2, 200))
329333
screen.blit(option2, (SIM_WIDTH / 2 - option2.get_width() / 2, 240))
330334
screen.blit(option3, (SIM_WIDTH / 2 - option3.get_width() / 2, 280))
335+
screen.blit(option4, (SIM_WIDTH / 2 - option4.get_width() / 2, 320))
331336
pygame.display.flip()
332337
clock.tick(60)
333338

@@ -874,9 +879,21 @@ def run_simulation():
874879
global walls, checkpoints, road_polygons, start_pos, start_angle
875880
generation_frame_count = 0
876881

877-
# Select track from menu
882+
# Select difficulty from menu
878883
track_type = menu()
879-
set_track(track_type)
884+
885+
# Define track options based on difficulty
886+
if track_type == "impossible":
887+
track_options = ["easy", "medium", "hard"]
888+
current_track = random.choice(track_options) # Initial random track
889+
previous_track = current_track # Track the previous track
890+
else:
891+
track_options = [track_type]
892+
current_track = track_type
893+
previous_track = None # No need to track for fixed tracks
894+
895+
# Set up the initial track
896+
set_track(current_track)
880897

881898
# Initialize first generation of cars with random NNs
882899
cars = [Car(NeuralNetwork()) for _ in range(NUM_CARS)]
@@ -972,6 +989,9 @@ def run_simulation():
972989
f"Checkpoint: {best_car.current_checkpoint}/{len(checkpoints)}",
973990
f"Distance: {best_car.distance_traveled:.1f}"
974991
])
992+
if track_type == "impossible":
993+
stats.append(f"Current Track: {current_track}")
994+
975995
for i, text in enumerate(stats):
976996
text_surface = FONT_SMALL.render(text, True, BLACK)
977997
screen.blit(text_surface, (10, 10 + i * 24))
@@ -989,21 +1009,31 @@ def run_simulation():
9891009
'alive_count': alive_count
9901010
})
9911011

1012+
# Randomize track for impossible mode, ensuring no consecutive repeats
1013+
if track_type == "impossible":
1014+
available_tracks = [t for t in track_options if t != previous_track]
1015+
new_track = random.choice(available_tracks)
1016+
current_track = new_track
1017+
previous_track = current_track
1018+
set_track(current_track)
1019+
else:
1020+
set_track(current_track) # Re-set the track, though it's the same
1021+
9921022
# Create next generation
9931023
new_generation = []
9941024

9951025
# Elitism: keep the best performers
996-
elite_count = max(3, NUM_CARS // 10) # 10% or at least 3
1026+
elite_count = max(3, NUM_CARS // 10)
9971027
elite_nns = elitism(cars, elite_count)
9981028
for nn in elite_nns:
9991029
new_generation.append(Car(nn))
10001030

10011031
# Add mutants of the top cars
10021032
top_cars = sorted(cars, key=lambda x: x.fitness, reverse=True)[:5]
10031033
for i, top_car in enumerate(top_cars):
1004-
num_mutants = 2 # Default number of mutants per top car
1005-
if i == 0: # For the best car (index 0)
1006-
num_mutants += 2 # Add 2 more mutants, making it 4 total
1034+
num_mutants = 2
1035+
if i == 0:
1036+
num_mutants += 2
10071037
for _ in range(num_mutants):
10081038
mutant_nn = top_car.nn.mutate()
10091039
new_generation.append(Car(mutant_nn))
@@ -1013,19 +1043,40 @@ def run_simulation():
10131043
parent1 = select_parents(cars, "tournament")
10141044
parent2 = select_parents(cars, "tournament")
10151045

1016-
# Crossover with increased probability
1017-
if random.random() < 0.85: # Probability of crossover
1046+
if random.random() < 0.85:
10181047
child_nn = parent1.nn.crossover(parent2.nn)
10191048
else:
10201049
child_nn = parent1.nn.clone() if random.random() < 0.5 else parent2.nn.clone()
10211050

1022-
# Mutation with dynamic rate
10231051
mutation_rate = MUTATION_RATE * (1.0 - min(0.5, generation / 100))
10241052
child_nn = child_nn.mutate(mutation_rate=mutation_rate)
10251053

10261054
new_generation.append(Car(child_nn))
10271055

1056+
# Reset cars for the new generation and track
10281057
cars = new_generation
1058+
for car in cars:
1059+
car.x, car.y = start_pos
1060+
car.angle = start_angle
1061+
car.alive = True
1062+
car.fitness = 0
1063+
car.raw_fitness = 0
1064+
car.distance_traveled = 0
1065+
car.current_checkpoint = 0
1066+
car.prev_checkpoint = 0
1067+
car.lap_count = 0
1068+
car.prev_x = car.x
1069+
car.prev_y = car.y
1070+
car.idle_time = 0
1071+
car.wrong_way = False
1072+
car.crashes = 0
1073+
car.start_time = pygame.time.get_ticks()
1074+
car.checkpoint_times.clear()
1075+
car.position_history.clear()
1076+
car.avg_speed.clear()
1077+
for _ in range(10):
1078+
car.position_history.append((car.x, car.y))
1079+
10291080
generation += 1
10301081
generation_frame_count = 0
10311082
is_first_frame = True

0 commit comments

Comments
 (0)