#### 73 lines 2.5 KiB Python Executable File Raw Permalink Blame History

 ```#!/usr/bin/env python3 ``` ```from contextlib import closing, suppress ``` ```from math import atan2, degrees, inf ``` ```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), # noqa ``` ``` (y, x - 1), (y, x), (y, x + 1), # noqa ``` ``` (y + 1, x - 1), (y + 1, x), (y + 1, x + 1)) # noqa ``` ``` ``` ``` ``` ```def is_wall(maze, y, x): ``` ``` """Return weather the cell (x, y) is wall.""" ``` ``` return maze[y][x] != '0' ``` ``` ``` ``` ``` ```def get_move(maze, move): ``` ``` """Return an outstanding move.""" ``` ``` moves, around = get_moves(len(maze) // 2, len(maze[0]) // 2), AROUND[:] ``` ``` if move != 4 and not is_wall(maze, *moves[move]): return move ``` ``` if move == 4: ``` ``` shuffle(around) ``` ``` else: ``` ``` idx = AROUND.index(move) ``` ``` around.sort(key=lambda i: abs(abs(abs(AROUND.index(i)-idx)-4)-4)) ``` ``` for move in around: ``` ``` idx = AROUND.index(move) ``` ``` if all(not is_wall(maze, *moves[i]) ``` ``` for i in (move, AROUND[idx - 1], AROUND[idx - 7])): ``` ``` return move ``` ``` return 4 ``` ``` ``` ``` ``` ```with suppress(KeyboardInterrupt), closing(socket()) as sock: ``` ``` sock.connect(('localhost', 42069)) ``` ``` move = 4 ``` ``` while True: ``` ``` length = sock.recv(7).decode() ``` ``` # connection closed or game over ``` ``` if length in ('', '0000000'): break ``` ``` data = iter(sock.recv(int(length)).decode().split()) ``` ``` nh, ne, nb, score = (int(next(data)) for i in range(4)) ``` ``` maze = [list(next(data)) for i in range(nh)] ``` ``` hp = (lambda c: 0 if c == 48 else 123 - c)(ord(next(data))) ``` ``` hx, hy, ha = (int(next(data)) for i in range(3)) ``` ``` attackable, heal = (bool(int(next(data))) for i in range(2)) ``` ``` ``` ``` if nh: move = get_move(maze, move) ``` ``` angle, shortest = ha, inf ``` ``` for i in range(ne): ``` ``` p = 3 - (ord(next(data)) - 97)%3 ``` ``` x, y, a = (int(next(data)) for j 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) ``` ``` ``` ``` 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 ``` ``` sock.send(f'{move} {angle} {attack}'.encode()) ```