-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathhuman_vs_ai.py
More file actions
162 lines (133 loc) · 4.89 KB
/
human_vs_ai.py
File metadata and controls
162 lines (133 loc) · 4.89 KB
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import pygame as pyg
import sys
import train_ai_for_human as pc
import pong_twoPlayers as ai
import time
# Parameters used for training
TRAIN_TRAIL = 50000
Q_Dict = dict()
Action_Dict = dict()
# Frame per second that we set up and use in the GUI
FPS = 15
# Color setting
WHITE = [255, 255, 255]
RED = (255, 0, 0)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
# Viedo output setting
ZERO = 0
VIEW_HEIGHT = 480
VIEW_WIDTH = 640
MIDDLE = (int(VIEW_WIDTH/2), int(VIEW_HEIGHT/2))
WHOLE_WINDOW = ((ZERO, ZERO), (VIEW_WIDTH, VIEW_HEIGHT))
# Detail of the paddle
PAD_THICK = 5
L_PAD_LEN = VIEW_HEIGHT * pc.LP_HEIGHT
R_PAD_LEN = VIEW_HEIGHT * pc.RP_HEIGHT
# Detail of the ping-pong table
COURT_LINE = 2
RADIUS = 5
# init the screen
pyg.init()
SCREEN = pyg.display.set_mode((VIEW_WIDTH, VIEW_HEIGHT))
pyg.display.set_caption("Single Player Pong")
def showPaddle(paddle_area, position):
""" Function used to draw the paddle """
paddle_area.x, paddle_area.y = position
pyg.draw.rect(SCREEN, BLACK, paddle_area)
def showTable():
""" Function used to draw the game table """
# Fill in the background
SCREEN.fill(WHITE)
# Draw the boundary line
pyg.draw.rect(SCREEN, BLUE, WHOLE_WINDOW, COURT_LINE)
def showBall(position):
""" Function used to draw the ball on table """
pos = (int(position[0]), int(position[1]))
pyg.draw.circle(SCREEN, RED, pos, RADIUS)
def getUpdateValue(state):
# Unpackin the state tuple
ball_x, ball_y, velocity_x, velocity_y, left_pad_y, right_pad_y = state
new_ball_x = (VIEW_WIDTH - RADIUS - 2*PAD_THICK - COURT_LINE) * ball_x
new_ball_y = (VIEW_HEIGHT - RADIUS - COURT_LINE) * ball_y
new_right_pad = right_pad_y * VIEW_HEIGHT
new_left_pad = left_pad_y * VIEW_HEIGHT
return new_ball_x, new_ball_y, new_right_pad, new_left_pad
def displayState(state, l_pad, r_pad, round_count):
ball_x, ball_y, right_pad, left_pad = getUpdateValue(state)
# Start re-drawing the court
showTable()
showPaddle(l_pad, (l_pad.x, left_pad))
showPaddle(r_pad, (r_pad.x, right_pad))
showBall((ball_x, ball_y))
# Display game status
text = pyg.font.Font(None, 15)
surface = text.render('Round #: %s' % format(round_count), True, BLACK)
textbox = surface.get_rect()
textbox.topleft = (VIEW_WIDTH / 2, 28)
SCREEN.blit(surface, textbox)
clock = pyg.time.Clock()
# Right paddle sizing
right_pad_x = VIEW_WIDTH - COURT_LINE - PAD_THICK
right_pad_y = (VIEW_HEIGHT - R_PAD_LEN) / 2
# Start getting drawing unit for the right paddle
r_pad = pyg.Rect(right_pad_x, right_pad_y, PAD_THICK, R_PAD_LEN)
# Left paddle sizing
left_pad_x = COURT_LINE
left_pad_y = (VIEW_HEIGHT - L_PAD_LEN) / 2
l_pad = pyg.Rect(left_pad_x, left_pad_y, PAD_THICK, L_PAD_LEN)
# Start Training
start_t = time.clock() # Start recording training time
print("Start the training session, current set training trails: ", TRAIN_TRAIL, " times")
ai.simulated_training(TRAIN_TRAIL, Q_Dict, Action_Dict)
print("Time Spent: %.2f" % (time.clock() - start_t))
# Set up the initial state after the training to start testing
print("The training session has been completed.")
round_count = 1
init_state = (0.5, 0.5, 0.03, 0.01, 0.5 - (pc.LP_HEIGHT / 2), 0.5 - (pc.RP_HEIGHT / 2))
discrete_init = pc.to_discrete(init_state)
displayState(init_state, l_pad, r_pad, round_count)
right_action = max(Q_Dict[discrete_init], key=Q_Dict[discrete_init].get)
left_action = 'Nothing'
action = (left_action, right_action)
state = pc.action_state(init_state, action)
prev_state = init_state
bounce_count = 0
# Start looping this game
while 1:
# Make sure that the user doesn't want to quit
for event in pyg.event.get():
if event.type == pyg.QUIT:
pyg.quit()
sys.exit(status=None)
elif event.type == pyg.KEYDOWN:
if event.key == pyg.K_UP:
left_action = 'Up'
elif event.key == pyg.K_DOWN:
left_action = 'Down'
else:
left_action = 'Nothong'
else:
left_action = 'Nothing'
# Update the display
displayState(state, l_pad, r_pad, round_count)
state, prev_state, right_action = pc.update_pos(prev_state, left_action, right_action, state, Q_Dict, Action_Dict)
# Check if the AI lose the game
if right_action == "End":
# who wins?
if prev_state[0] < 0.2:
print("Right Paddle Wins")
elif prev_state[0] > 0.8:
print("Left Paddle Wins")
prev_state = init_state
displayState(prev_state, l_pad, r_pad, round_count)
round_count += 1
right_action = max(Q_Dict[discrete_init], key=Q_Dict[discrete_init].get)
left_action = pc.l_paddle_action(prev_state)
action = (left_action, right_action)
state = pc.action_state(prev_state, action)
bounce_count = 0
if pc.is_bounced(prev_state, state) and state[2] < 0:
bounce_count += 1
pyg.display.update()
clock.tick(FPS)