-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgame_functions.py
248 lines (209 loc) · 8.73 KB
/
game_functions.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
import pygame
import torch
import numpy as np
from player_functions import get_random_position, get_random_gap
from player_functions import move_players, get_winner
from display_functions import display_text, draw_players, display_winner, draw_screen
from items import render_items, power_down
import config as cfg
def reset_game(players, win_counts, player_keys=None, screen=None):
# Set all players to be alive and reset their positions and directions
gap = False
for player in players:
player["alive"] = True
start_pos, start_dir = get_random_position()
start_gap, start_line = get_random_gap()
game_state_pos = np.array(
[
np.arange(
int(round(start_pos[0], 0)) - int(cfg.player_size / 2),
int(round(start_pos[0], 0)) + int(cfg.player_size / 2),
),
np.arange(
int(round(start_pos[1], 0)) - int(cfg.player_size / 2),
int(round(start_pos[1], 0)) + int(cfg.player_size / 2),
),
]
)
player["game_state_pos"] = game_state_pos
player["speed"] = cfg.speed
if player["ai"] == False:
player["left"] = player_keys[player["id"] - cfg.num_ai_players]["left"]
player["right"] = player_keys[player["id"] - cfg.num_ai_players]["right"]
player["pos"] = start_pos
player["dir"] = start_dir
player["gap_timer"] = start_gap
player["line_timer"] = start_line
player["pos_history"] = [start_pos]
player["del_angle"] = 5
player["gap"] = gap
player["gap_history"] = [gap]
player["items"] = []
player["item_timer"] = []
if player["ai"]:
player["outcomes"] = torch.tensor([0])
player["pred_actions"] = torch.tensor(data=[])
player["actions"] = torch.tensor(data=[], dtype=torch.int64)
# Reset winner
winner = None
items = []
# Refresh the screen
if screen:
draw_screen(screen, win_counts)
pygame.display.flip()
# Pause briefly to give players time to reposition
pygame.time.wait(1000)
game_state = init_game_state()
return winner, items, game_state
def game_loop(players, player_keys, screen, win_counts, last_spawn_time):
# set up game variables
game_over = False
running = True
winner = None
items = []
game_state = init_game_state()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE and game_over:
winner, items, game_state = reset_game(
players, win_counts, player_keys, screen
)
game_over = False
elif event.key == pygame.K_ESCAPE and game_over:
# Save nn models
for i in range(cfg.num_ai_players):
if cfg.training:
player_iter = players[i]["iteration"]
torch.save(
players[i]["model"].state_dict(),
f"{cfg.save_model_path}\model_checkpoint_iter_{player_iter}_player_{i}.pth",
)
running = False
# Get current time in milliseconds
current_time = pygame.time.get_ticks()
# Check if it's time to spawn a new item (every 10 seconds)
if current_time - last_spawn_time >= 1000:
if len(items) <= cfg.max_items:
items, game_state = render_items(items, game_state, screen)
# Update the last spawn time
last_spawn_time = current_time
# move all players and check for collisions
players, game_state = move_players(players, items, game_state)
# check if any players are alive
alive_players = [player for player in players if player["alive"]]
if len(alive_players) <= 1:
# Set game over to true
game_over = True
# Stop all players when the game is over
for player in players:
player["dir"] = "stop"
# Get winning player
if len(alive_players) == 1:
if winner == None:
winner = get_winner(players, win_counts)
display_winner(screen, win_counts)
# Display options to restart or quit
display_text(
screen,
"Game Over",
font=cfg.font,
color=cfg.white,
x=(cfg.screen_width - cfg.score_section_width) / 2,
y=cfg.screen_height / 2 - 50,
)
display_text(
screen,
"Press Space to Restart",
font=cfg.font,
color=cfg.white,
x=(cfg.screen_width - cfg.score_section_width) / 2,
y=cfg.screen_height / 2 + 10,
)
display_text(
screen,
"Press Esc to Quit",
font=cfg.font,
color=cfg.white,
x=(cfg.screen_width - cfg.score_section_width) / 2,
y=cfg.screen_height / 2 + 50,
)
# Event handling for options
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
for player, player_key in zip(players, player_keys):
for i in range(len(player["items"])):
player, player_key = power_down(
player["items"][i],
player["item_timer"][i],
player,
)
winner, items, game_state = reset_game(
players, win_counts, player_keys, screen
)
elif event.key == pygame.K_ESCAPE:
running = False
# Draw players
draw_players(players, screen)
pygame.display.update()
cfg.clock.tick(60)
pygame.quit()
def init_game_state():
game_state = np.zeros(shape=(cfg.play_screen_width - 10, cfg.screen_height - 10))
game_state = np.pad(game_state, 5, constant_values=-1)
return game_state
def simulation_game_loop(players, win_counts, last_spawn_time, iteration):
# set up game variables
game_over = False
winner = None
items = []
game_state = init_game_state()
steps = 0
while iteration < cfg.max_iter:
# Get current time in milliseconds
current_time = pygame.time.get_ticks()
# Check if it's time to spawn a new item (every 10 seconds)
if current_time - last_spawn_time >= 1000:
if len(items) <= cfg.max_items:
items, game_state = render_items(items, game_state)
# Update the last spawn time
last_spawn_time = current_time
# move all players and check for collisions
players, game_state = move_players(players, items, game_state)
steps += 1
# check if any players are alive
alive_players = [player for player in players if player["alive"]]
if len(alive_players) <= 1:
# Set game over to true
game_over = True
# Stop all players when the game is over
for player in players:
player["dir"] = "stop"
# Get winning player, update training iteration and reset game
if len(alive_players) == 1:
if winner == None:
winner = get_winner(players, win_counts)
iteration += 1
print(iteration, steps, current_time)
steps = 0
for player in players:
for i in range(len(player["items"])):
player = power_down(
player["items"][i],
player["item_timer"][i],
player,
)
winner, items, game_state = reset_game(players, win_counts)
cfg.clock.tick(60)
# If max iteration is reached: Save nn state for all players
for i in range(cfg.num_ai_players):
torch.save(
players[i]["model"].state_dict(),
f"{cfg.save_model_path}model_checkpoint_iter_{iteration}_player_{i}.pth",
)
pygame.quit()