-
Notifications
You must be signed in to change notification settings - Fork 0
/
box_car.py
141 lines (107 loc) · 3.94 KB
/
box_car.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import arcade
import pymunk
import math
from ga import Chromosome
from car_parts import Chassis, Wheel
from constants import START_POSITION, SIZE, REWARD
class BoxCar:
'''
The BoxCar class.
It contains chassis and wheels.
It is characterised based on the chromosome it received.
'''
def __init__(self, space, chromosome=None):
self.lifespan = 1000
self.is_alive = True
self.checkpoint_index = 0
# Generate the chromosome for the car.
self.chromosome = chromosome
if self.chromosome is None:
self.chromosome = Chromosome.generate_inital_chromosome()
# Create a chassis.
position_main = pymunk.Vec2d(START_POSITION)
vs = self.chromosome.get_vertices()
self.chassis = Chassis(space, position_main, vs)
self.position = self.chassis.body.position
# Create the wheels.
self.wheels = []
genes = self.chromosome.get_genes()
for position, [radius, speed] in genes:
if radius == -1 or speed == -1:
continue
position = pymunk.Vec2d(position) + position_main
wheel = Wheel(space, position, radius)
c = pymunk.constraint.PivotJoint(self.chassis.body, wheel.body, position)
c.collide_bodies = False
m = pymunk.SimpleMotor(self.chassis.body, wheel.body, speed)
space.add(c, m)
self.wheels.append(wheel)
self.__setup_draw()
def __setup_draw(self):
'''
Setting up the inital body of the chassis and wheels to be rendered.
'''
# Drawing Wheels
for wheel in self.wheels:
wheel.setup_draw()
# Drawing Chassis
self.chassis.setup_draw()
def draw(self):
'''
To render on screen.
'''
self.__update_visuals()
if self.is_alive:
for wheel in self.wheels:
wheel.draw()
self.chassis.draw()
def __update_visuals(self):
'''
To update the visuals after every step.
'''
if self.is_alive:
for wheel in self.wheels:
wheel.update_visuals()
self.chassis.update_visuals()
def get_position(self):
'''
Returns the current position of the car.
'''
return self.position
def update_lifespan(self, checkpoints):
'''
Updates the lifespan based on the checkpoints crossed.
Returns the status of the car.
'''
if self.is_alive:
car_position = self.chassis.body.position
check_position = checkpoints[self.checkpoint_index]
if checkpoints[self.checkpoint_index] == checkpoints[-1]:
self.is_alive = False
if abs(check_position - car_position).length < SIZE and self.is_alive:
self.checkpoint_index += 1
self.lifespan += REWARD
self.lifespan -= 1
if self.lifespan <= 0 and self.is_alive:
self.is_alive = False
self.__set_bodies_to_sleep()
return self.is_alive
def get_chromosome_and_score(self):
'''
Returns a dictionary of the genes and the score of the car.
'''
return {'gene': self.chromosome.get_genes(), 'score': self.checkpoint_index + self.lifespan + 2}
def get_checkpoint_index(self):
'''
Returns the current checkpoint index of the car.
'''
return self.checkpoint_index
def __set_bodies_to_sleep(self):
'''
Sets the bodies and shapes to sleep to prevent extra computations during simulations.
'''
if not self.chassis.body.is_sleeping:
self.chassis.body.sleep()
for wheel in self.wheels:
if not wheel.body.is_sleeping:
wheel.body.sleep()