-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtron_master.py
executable file
·551 lines (508 loc) · 21.1 KB
/
tron_master.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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
# tron master node
import pygame
from pygame.locals import *
import socket, struct, threading, sys
import cPickle, time
from pprint import pprint
from helper import draw_logic, load_images, construct_list
MONITOR_GRIDX = 3 # width
MONITOR_GRIDY = 3 # height
FULL_GRID_SIZE = (63, 51) # number of locations in full game
#WORKER_NODE_SIZE = (33,21)
WORKER_NODE_SIZE = (21,17)
PLAYER1_START = [0, FULL_GRID_SIZE[1]/2]
PLAYER2_START = [FULL_GRID_SIZE[0]-1, FULL_GRID_SIZE[1]/2]
SOCKET_DEL = '*ET*'
WIN_PAUSE = 3 # seconds
SPEED = 1 #.5
FPS = pygame.time.Clock()
NUM_OF_LEVELS = 8
LEVEL_INC = .5
LEVEL_MINUTES = []
last = 0
for x in range(0, NUM_OF_LEVELS+1):
LEVEL_MINUTES.append(last)
last += LEVEL_INC
LEVEL_TIMES = [x*1000*60 for x in LEVEL_MINUTES]
LEVEL_SPEED = [x*1 for x in range(1,NUM_OF_LEVELS+2)] #replaced x*15 with x*1
LEVEL_TUPLES = zip(LEVEL_TIMES, LEVEL_SPEED)
LEVELS = dict(zip([x for x in range(1, NUM_OF_LEVELS+2)], LEVEL_TUPLES))
END_TIME = LEVEL_TIMES[-1] * 60 * 1000 # minutes x seconds x miliseconds
class LightBike():
def __init__(self, startloc, start_orient, startvel, start_dir):
self.location = startloc[:]
self.velocity = startvel[:]
self.orientation = start_orient
self.score = 0
self.dir = start_dir
def movedown(self):
self.velocity[0] = 0
self.velocity[1] = 1
def moveup(self):
self.velocity[0] = 0
self.velocity[1] = -1
def moveleft(self):
self.velocity[0] = -1
self.velocity[1] = 0
def moveright(self):
self.velocity[0] = 1
self.velocity[1] = 0
def update(self):
self.location[0] += self.velocity[0]
self.location[1] += self.velocity[1]
class MasterTron(object):
"""The class for the MasterTron node"""
def __init__(self):
pygame.init()
self.player1 = LightBike(PLAYER1_START, 'hor', [1,0], 'left' )
self.player2 = LightBike(PLAYER2_START, 'hor', [-1,0], 'right' )
self.new_game_score()
self.init_locations()
self.window = pygame.display.set_mode((20,20))
self.image_dict = load_images()
self.sock_list = [[ [] for y in range(MONITOR_GRIDY)] for x in range(MONITOR_GRIDX)]
print self.sock_list
#ips = open('ip-list-one.txt', 'r')
ips = open('ip_list.txt','r').read()
ip_list = [ip for ip in ips.split('\n') if ip != '']
print(ip_list)
idx = 0
print(MONITOR_GRIDX, MONITOR_GRIDY)
for x in range(0, MONITOR_GRIDX):
for y in range(0, MONITOR_GRIDY):
print(ip_list[idx],idx)
self.sock_list[x][y] = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print(1)
self.sock_list[x][y].connect((ip_list[idx], 20000))
print(2)
idx += 1
print(3)
self.fliped_1x, self.fliped_1y, self.fliped_2x, self.fliped_2y = 4*[False]
self.flip_1x, self.flip_1y, self.flip_2x, self.flip_2y = 4*[False]
self.el_time = 0
self.current_level = 1
# pygame.mixer.init()
# pygame.mixer.music.set_volume(1.0)
# pygame.mixer.music.load("assets/backtrack.wav")
# pygame.mixer.music.play()
# self.explode = pygame.mixer.Sound('assets/explode.wav')
# self.backtrack = pygame.mixer.Sound('assets/backtrack.mp3')
# self.backtrack.play(-1)
def run(self):
"""loop to run the game and decide which state the game is in and call the
functions accordingly"""
data = ''
while True:
if self.state == 'play':
data, self.state = self.play_frame()
elif self.state == 'win':
# need to send win signal, reset locations and pause
self.win_signal(data)
elif self.state == 'draw':
self.win_signal(data)
elif self.state == 'over':
self.game_over_signal(data)
self.el_time += FPS.tick(LEVELS[self.current_level][1])
# print self.el_time
# print LEVELS[self.current_level][0]
if self.el_time > LEVELS[self.current_level][0]:
if self.current_level == len(LEVELS):
print "exiting at " + str(self.el_time)
print "current level is " + str(self.current_level)
self.state = 'over'
self.current_level += 1
def play_frame(self):
events = pygame.event.get()
self.handle_key_press(events)
self.handle_joy_stick(events)
self.last_2_loc_1 = self.last_loc_1[:]
self.last_loc_1[0] = [self.player1.location[0], self.player1.location[1]]
self.last_2_loc_2 = self.last_loc_2[:]
self.last_loc_2[0] = [self.player2.location[0], self.player2.location[1]]
self.player1.update()
self.player2.update()
player1_image_dict = draw_logic(self.last_2_loc_1, self.last_loc_1, self.player1,
self.fliped_1x, self.fliped_1y, 'c')
player2_image_dict = draw_logic(self.last_2_loc_2, self.last_loc_2, self.player2,
self.fliped_2x, self.fliped_2y, 'm')
self.fliped_1x, self.fliped_1y = self.adjust_periodic(self.player1)
self.fliped_2x, self.fliped_2y = self.adjust_periodic(self.player2)
# flip_1x, flip_1y = self.adjust_periodic(self.player1)
# flip_2x, flip_2y = self.adjust_periodic(self.player2)
# if loc_collision(self.player1):
# close_sockets(sock_list)
# if loc_collision(self.player2):
# close_sockets(sock_list)
self.location[self.player1.location[0]][self.player1.location[1]] = 1
self.location[self.player2.location[0]][self.player2.location[1]] = 1
send_struct = {'player1_images': player1_image_dict,
'player2_images':player2_image_dict,
'player1_locs':[self.player1.location, self.last_loc_1[0], self.last_2_loc_1[0]],
'player2_locs':[self.player2.location, self.last_loc_2[0], self.last_2_loc_2[0]],
'state': 'play'}
data = cPickle.dumps(send_struct, cPickle.HIGHEST_PROTOCOL) + '*ET*'
for x in range(0, len(self.sock_list)):
for y in range(0, len(self.sock_list[x])):
self.sock_list[x][y].sendall(data)
return_list = []
for x in range(0, len(self.sock_list)):
for y in range(0, len(self.sock_list[x])):
return_list.append(self.get_whole_packet(self.sock_list[x][y]))
num_of_wins = 0
win_states = []
for data in return_list:
if data['state'] != 'play':
if data['state'] == 'draw':
# draw happend on the same screen
print 'drew'
return data, 'draw'
if data['state'] == 'win':
num_of_wins += 1
win_states.append(data)
# return (data, 'win')
if num_of_wins > 1:
pprint(return_list)
print "NUM OF WINS IS LARGER THAN 1"
return win_states, 'draw'
elif num_of_wins == 1:
return (win_states[0], 'win')
if self.el_time > END_TIME:
return (data, 'over')
# return the state of the game
return (data, 'play')
def adjust_periodic(self, player):
"""Allows for periodic edges. Returns whether or not you need to flip the
corner piece."""
flipx = False
flipy = False
if player.location[0] >= FULL_GRID_SIZE[0]:
player.location[0] = 0
flipx = True
elif player.location[0] < 0:
player.location[0] = FULL_GRID_SIZE[0] - 1
flipx = True
if player.location[1] >= FULL_GRID_SIZE[1]:
player.location[1] = 0
flipy = True
elif player.location[1] < 0:
player.location[1] = FULL_GRID_SIZE[1] - 1
flipy = True
return flipx, flipy
def win_signal(self, data):
"""players scored, increment the score and send the win signal to all the nodes
"""
explod_loc_list = []
if isinstance(data, dict):
# not a draw, check who won then.
if data['which'] == 1:
self.player1.score += 1
msg = 'player 1 Scored'
else:
self.player2.score += 1
msg = 'player 2 Scored'
for loc in data['death_loc']:
# print "BEFORE CONVERTING" + str(loc)
explod_loc_list.append(self.convert_to_global(data['tile'],loc))
# print "AFTER CONVERTING" + str(self.convert_to_global(data['tile'],loc))
else:
# it's a list of states so there was a draw
print 'draw'
msg = 'DRAW!'
for x in data:
for loc in x['death_loc']:
explod_loc_list.append(self.convert_to_global(x['tile'],loc))
# the_time = LEVEL_TIMES[-1]- self.el_time
minutes, milliseconds = divmod(self.el_time, 60000)
seconds = float(milliseconds) / 1000
real_minutes = 3 - minutes
real_seconds = 60 - seconds
real_time = "%02i:%02.0f" % (real_minutes, real_seconds)
send_struct = {'state': 'win', 'death_loc':explod_loc_list,
'score':{'p1':self.player1.score, 'p2':self.player2.score},
'time':real_time, 'msg':msg}
#send to worker nodes
data = cPickle.dumps(send_struct, cPickle.HIGHEST_PROTOCOL) + SOCKET_DEL
for x in range(0, len(self.sock_list)):
for y in range(0, len(self.sock_list[x])):
self.sock_list[x][y].sendall(data)
# self.explode.play()
self.init_locations()
self.update_score_file()
time.sleep(WIN_PAUSE)
for x in range(0, len(self.sock_list)):
for y in range(0, len(self.sock_list[x])):
self.get_whole_packet(self.sock_list[x][y])
pygame.event.clear()
def game_over_signal(self, data):
send_struct = {'state': 'over','score':{'p1':self.player1.score,
'p2':self.player2.score},
'msg':'Game Over'}
# data = cPickle.dumps(send_struct, cPickle.HIGHEST_PROTOCOL) + SOCKET_DEL
self.handshake(send_struct)
reset = False
self.update_score_file()
# wait for rest key. TODO, add a kill key
while not reset:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == KEYDOWN:
if event.key == K_4:
reset = True
self.init_locations()
self.player1.score = 0
self.player2.score = 0
self.new_game_score()
for x in range(0, len(self.sock_list)):
for y in range(0, len(self.sock_list[x])):
self.sock_list[x][y].sendall('go' + SOCKET_DEL)
for x in range(0, len(self.sock_list)):
for y in range(0, len(self.sock_list[x])):
self.get_whole_packet(self.sock_list[x][y])
self.el_time = 0
self.current_level = 1
# reset the tick clock as fast as possible
FPS.tick(3000000)
# should be synced up for another game
def new_game_score(self):
"""appends the new players to the end of the score file"""
score_file = open('scores.txt', 'a')
last_line = 'player1 = 0 player2 = 0\n'
score_file.write(last_line)
score_file.close()
def update_score_file(self):
"""overwrites the last line of the score file with the changed scores"""
score_file = open('scores.txt', 'rw+')
last_line = score_file.readlines()[-1]
# score_file.write(' '*len(last_line))
score_file.seek(-len(last_line), 2)
last_line = 'player1 = ' + str(self.player1.score) + ' player2 = ' + str(self.player2.score) + '\n'
score_file.write(last_line)
score_file.close()
def handshake(self, data):
"""Passes data to the nodes then waits for there response to keep synchronization.
The data is first pickled as a string then sent"""
data = cPickle.dumps(data, cPickle.HIGHEST_PROTOCOL) + SOCKET_DEL
for x in range(0, len(self.sock_list)):
for y in range(0, len(self.sock_list[x])):
self.sock_list[x][y].sendall(data)
return_list = []
for x in range(0, len(self.sock_list)):
for y in range(0, len(self.sock_list[x])):
return_list.append(self.get_whole_packet(self.sock_list[x][y]))
return return_list
def handle_joy_stick(self, events):
"""handles the pygame keyboard events."""
# bug that you can go back on yourself if you register a lot of button presses
p1_moved = False
p2_moved = False
for event in events:
if event.type == pygame.QUIT:
sys.exit()
if event.type == KEYDOWN:
# check if trying to go back on themselves
if event.key == K_KP4 and self.player1.dir != 'left' and not p1_moved:
if self.player1.dir != 'right':
self.player1.moveleft()
self.player1.dir = 'left'
p1_moved = True
if event.key == K_KP6 and self.player1.dir != 'right' and not p1_moved:
if self.player1.dir != 'left':
self.player1.moveright()
self.player1.dir = 'right'
p1_moved = True
if event.key == K_KP8 and self.player1.dir != 'up' and not p1_moved:
if self.player1.dir != 'down':
self.player1.moveup()
self.player1.dir = 'up'
p1_moved = True
if event.key == K_KP2 and self.player1.dir != 'down' and not p1_moved:
if self.player1.dir != 'up':
self.player1.movedown()
self.player1.dir = 'down'
p1_moved = True
if event.key == K_d and self.player2.dir != 'left' and not p2_moved:
if self.player2.dir != 'right':
self.player2.moveleft()
self.player2.dir = 'left'
p2_moved = True
if event.key == K_g and self.player2.dir != 'right' and not p2_moved:
if self.player2.dir != 'left':
self.player2.moveright()
self.player2.dir = 'right'
p2_moved = True
if event.key == K_r and self.player2.dir != 'up' and not p2_moved:
if self.player2.dir != 'down':
self.player2.moveup()
self.player2.dir = 'up'
p2_moved = True
if event.key == K_f and self.player2.dir != 'down' and not p2_moved:
if self.player2.dir != 'up':
self.player2.movedown()
self.player2.dir = 'down'
p2_moved = True
# if event.key == K_2:
# self.close_sockets(self.sock_list)
if event.key == K_4:
self.game_over_signal('not_used')
def handle_key_press(self, events):
"""handles the pygame keyboard events."""
# bug that you can go back on yourself if you register a lot of button presses
p1_moved = False
p2_moved = False
for event in events:
if event.type == pygame.QUIT:
sys.exit()
if event.type == KEYDOWN:
# check if trying to go back on themselves
if event.key == K_a and self.player1.dir != 'left' and not p1_moved:
if self.player1.dir != 'right':
self.player1.moveleft()
self.player1.dir = 'left'
p1_moved = True
if event.key == K_d and self.player1.dir != 'right' and not p1_moved:
if self.player1.dir != 'left':
self.player1.moveright()
self.player1.dir = 'right'
p1_moved = True
if event.key == K_w and self.player1.dir != 'up' and not p1_moved:
if self.player1.dir != 'down':
self.player1.moveup()
self.player1.dir = 'up'
p1_moved = True
if event.key == K_s and self.player1.dir != 'down' and not p1_moved:
if self.player1.dir != 'up':
self.player1.movedown()
self.player1.dir = 'down'
p1_moved = True
if event.key == K_LEFT and self.player2.dir != 'left' and not p2_moved:
if self.player2.dir != 'right':
self.player2.moveleft()
self.player2.dir = 'left'
p2_moved = True
if event.key == K_RIGHT and self.player2.dir != 'right' and not p2_moved:
if self.player2.dir != 'left':
self.player2.moveright()
self.player2.dir = 'right'
p2_moved = True
if event.key == K_UP and self.player2.dir != 'up' and not p2_moved:
if self.player2.dir != 'down':
self.player2.moveup()
self.player2.dir = 'up'
p2_moved = True
if event.key == K_DOWN and self.player2.dir != 'down' and not p2_moved:
if self.player2.dir != 'up':
self.player2.movedown()
self.player2.dir = 'down'
p2_moved = True
if event.key == K_3:
self.close_sockets(self.sock_list)
def get_whole_packet(self, socket):
"""ensures that we receive the whole stream of data"""
data = ''
while True:
data += socket.recv(4024)
split = data.split(SOCKET_DEL) # split at newline, as per our custom protocol
if len(split) != 2: # it should be 2 elements big if it got the whole message
pass
else:
x = cPickle.loads(split[0])
return x
def close_sockets(self, sock_list):
"""kills and shutdown all the sockets. Despite adhering to exactly how it
should be done, seems to not work effectively"""
kill_struct = {'state': 'kill' }
kill_pickle = cPickle.dumps(kill_struct, cPickle.HIGHEST_PROTOCOL) + '*ET*'
for x in range(0, len(sock_list)):
for y in range(0, len(sock_list[x])):
sock_list[x][y].sendall(kill_pickle)
sock_list[x][y].shutdown(socket.SHUT_RDWR)
sock_list[x][y].close()
sys.exit()
def init_locations(self):
"""initilizes all of the location varibles and players"""
self.location = []
for x in range(0,FULL_GRID_SIZE[0] ):
self.location.append([])
for y in range(0,FULL_GRID_SIZE[1]):
self.location[x].append(0) # 0
self.player1.location = PLAYER1_START[:]
self.player1.velocity = [1,0]
self.player1.orientation = 'hor'
self.player1.dir = 'right'
self.player2.location = PLAYER2_START[:]
self.player2.velocity = [-1,0]
self.player2.orientation = 'hor'
self.player2.dir = 'left'
self.last_loc_1 = [[-1, FULL_GRID_SIZE[1]/2], 'off'] # initilize off screen, shouldn't affect anythin
self.last_2_loc_1 = [[-2, FULL_GRID_SIZE[1]/2], 'off']
self.last_loc_2 = [[ FULL_GRID_SIZE[0], FULL_GRID_SIZE[1]/2] , 'off'] # initilize off screen, shouldn't affect anythin
self.last_2_loc_2 = [[FULL_GRID_SIZE[0]+1, FULL_GRID_SIZE[1]/2], 'off']
self.state = 'play'
def convert_to_global(self, tile, location):
x_pos = location[0] + tile[0]*WORKER_NODE_SIZE[0]
y_pos = location[1] + tile[1]*WORKER_NODE_SIZE[1]
return x_pos, y_pos
# def loc_collision(bike):
# # check the location array to see if colided.
# if bike.location[0] < 0 or bike.location[0] > FULL_GRID_SIZE[0]:
# print "died of screen in x"
# return True
# if bike.location[1] < 0 or bike.location[1] > FULL_GRID_SIZE[1]:
# print "died off screen in y"
# return True
# def handle_move(self):
# """handles the pygame keyboard events."""
# # bug that you can go back on yourself if you register a lot of button presses
# p1_moved = False
# p2_moved = False
# for event in pygame.event.get():
# if event.type == pygame.QUIT:
# sys.exit()
# if event.type == KEYDOWN:
# # check if trying to go back on themselves
# if event.key == self.player1.left and not p1_moved:
# if self.player1.last_key != self.player1.right and self.player1.last_key != self.player1.left:
# self.player1.moveleft()
# self.player1.last_key = self.player1.left
# p1_moved = True
# if event.key == self.player1.right and self.player1.last_key != self.player1.right and not p1_moved:
# if self.player1.last_key != self.player1.left:
# self.player1.moveright()
# self.player1.last_key = self.player1.right
# p1_moved = True
# if event.key == self.player1.up and self.player1.last_key != self.player1.up and not p1_moved:
# if self.player1.last_key != self.player1.down:
# self.player1.moveup()
# self.player1.last_key = self.player1.up
# p1_moved = True
# if event.key == self.player1.down and self.player1.last_key != self.player1.down and not p1_moved:
# if self.player1.last_key != self.player1.up:
# self.player1.movedown()
# self.player1.last_key = self.player1.down
# p1_moved = True
# if event.key == self.player2.left and self.player2.last_key != self.player2.left and not p2_moved:
# if self.player2.last_key != self.player2.right:
# self.player2.moveleft()
# self.player2.last_key = self.player2.right
# p2_moved = True
# if event.key == self.player2.right and self.player2.last_key != self.player2.right and not p2_moved:
# if self.player2.last_key != self.player2.left:
# self.player2.moveright()
# self.player2.last_key = self.player2.left
# p2_moved = True
# if event.key == self.player2.up and self.player2.last_key != self.player2.up and not p2_moved:
# if self.player2.last_key != self.player2.down:
# self.player2.moveup()
# self.player2.last_key = self.player2.up
# p2_moved = True
# if event.key == self.player2.down and self.player2.last_key != self.player2.down and not p2_moved:
# if self.player2.last_key != self.player2.up:
# self.player2.movedown()
# self.player2.last_key = self.player2.down
# p2_moved = True
# if event.key == K_2:
# self.close_sockets(self.sock_list)
if __name__ == '__main__':
tron = MasterTron()
tron.run()