summary refs log tree commit diff homepage
path: root/client-examples/hit-and-run.py
diff options
context:
space:
mode:
Diffstat (limited to 'client-examples/hit-and-run.py')
-rwxr-xr-xclient-examples/hit-and-run.py61
1 files changed, 48 insertions, 13 deletions
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())