From d6dfd431588624510574c2386a563af890c4adc1 Mon Sep 17 00:00:00 2001 From: Nguyễn Gia Phong Date: Sun, 5 Aug 2018 18:21:48 +0700 Subject: Add HTML5 record player and update hit-and-run client --- client-examples/hit-and-run.py | 61 +++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 13 deletions(-) (limited to 'client-examples') diff --git a/client-examples/hit-and-run.py b/client-examples/hit-and-run.py index 925a3a6..7bbf5a1 100755 --- a/client-examples/hit-and-run.py +++ b/client-examples/hit-and-run.py @@ -1,38 +1,73 @@ #!/usr/bin/env python3 from math import inf, atan2, degrees +from random import randrange, shuffle from socket import socket +AROUND = [5, 2, 1, 0, 3, 6, 7, 8] + + +def get_moves(y, x): + """Return tuple of encoded moves.""" + return ((y - 1, x - 1), (y - 1, x), (y - 1, x + 1), + (y, x - 1), (y, x), (y, x + 1), + (y + 1, x - 1), (y + 1, x), (y + 1, x + 1)) + + +def is_wall(maze, y, x): + """Return weather the cell (x, y) is wall.""" + return maze[y][x] != '0' + + clientsocket = socket() clientsocket.connect(('localhost', 8089)) +corners, sides = [0, 2, 6, 8], [1, 3, 5, 7] +around, move = [0, 1, 2, 3, 5, 6, 7, 8], 4 while True: length = clientsocket.recv(7).decode() if length in ('', '0000000'): break # connection closed or game over l = clientsocket.recv(int(length)).decode().split() data = iter(l) nh, ne, nb, score = (int(next(data)) for _ in range(4)) - maze = [[bool(int(i)) for i in next(data)] for _ in range(nh)] + maze = [list(next(data)) for _ in range(nh)] hp = (lambda c: 0 if c == 48 else 123 - c)(ord(next(data))) hx, hy, ha = (int(next(data)) for _ in range(3)) - attackable, mobility = (bool(int(next(data))) for _ in range(2)) + attackable, heal = (bool(int(next(data))) for _ in range(2)) - shortest = angle = inf + if nh: + moves = get_moves(len(maze) // 2, len(maze[0]) // 2) + if move == 4 or is_wall(maze, *moves[move]): + try: + idx = AROUND.index(move) + except ValueError: + pass + else: + around.sort(key=(lambda i: (lambda x: min(x, 8 - x))( + abs(AROUND.index(i) - idx)))) + for move in around: + idx = AROUND.index(move) + if all(map( + (lambda i: not is_wall(maze, *moves[i])), + (move, AROUND[idx - 1], AROUND[idx - 7]))): + break + else: + move = 4 + + angle, shortest = ha, inf for _ in range(ne): - p = (lambda c: 0 if c == 48 else 3 - (c-97)%3)(ord(next(data))) + p = 3 - (ord(next(data)) - 97)%3 x, y, a = (int(next(data)) for _ in range(3)) d = ((x - hx)**2 + (y - hy)**2)**0.5 if d < shortest: shortest = d b = degrees(atan2(y - hy, x - hx)) angle = round(b + 360 if b < 0 else b) - # calculate to dodge from bullets is a bit too much for an example - - move = 4 if ne and hp > 2 else 0 - if angle == inf: - angle, attack = ha, 0 - elif not attackable: - attack = 0 - elif shortest < 160 or hp < 3: - move, angle, attack = 8, ha, 2 + + if hp <= 2 and heal: + move, attack = 4, 2 + elif not ne: + attack = randrange(3) * (attackable and hp > 2) + elif shortest < 160: + move, angle, attack = AROUND[round(angle/45 - 0.5) - 4], ha, 2 else: attack = 1 clientsocket.send('{} {} {}'.format(move, angle, attack).encode()) -- cgit 1.4.1