forked from BattlesnakeOfficial/starter-snake-python
-
Notifications
You must be signed in to change notification settings - Fork 7
/
server.py
140 lines (115 loc) · 5.16 KB
/
server.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
import os
import io
from contextlib import redirect_stdout
import random
import time
from json import loads
import snakebrain
from tests.transform import transform_json
import cherrypy
import cProfile
"""
This is a Battlesnake server written in Python.
For instructions see https://github.com/BattlesnakeOfficial/starter-snake-python/README.md
"""
class Battlesnake(object):
game_id = ""
turn = -1
@cherrypy.expose
@cherrypy.tools.json_out()
def index(self):
# This function is called when you register your Battlesnake on play.battlesnake.com
# It controls your Battlesnake appearance and author permissions.
# TIP: If you open your Battlesnake URL in browser you should see this data
return {
"apiversion": "1",
"author": "altersaddle",
"color": "#306448", "head": "tongue", "tail": "sharp", # Untimely Neglected Wearable
#"color": "#ebae34", "head": "football", "tail": "coffee", # Hot Soup
"version": "unwinder",
}
@cherrypy.expose
@cherrypy.tools.json_in()
def start(self):
# This function is called everytime your snake is entered into a game.
# cherrypy.request.json contains information about the game that's about to be played.
# TODO: Use this function to decide how your snake is going to look on the board.
data = cherrypy.request.json
self.turn = data["turn"]
self.game_id = data["game"]["id"]
self.log("START")
return "ok"
@cherrypy.expose
@cherrypy.tools.json_in()
@cherrypy.tools.json_out()
def move(self):
# This function is called on every turn of a game. It's how your snake decides where to move.
# Valid moves are "up", "down", "left", or "right".
begin_time = time.perf_counter()
data = cherrypy.request.json
parse_time = time.perf_counter() - begin_time
self.turn = data["turn"]
self.game_id = data["game"]["id"]
body = data["you"]["body"]
snakes = data["board"]["snakes"]
# Choose a direction to move in
possible_moves = ["up", "down", "left", "right"]
snakebrain.set_globals(data['game'], data['board'])
safe_moves = snakebrain.get_safe_moves(possible_moves, body, data["board"])
safe_time = time.perf_counter() - begin_time
#pr = cProfile.Profile()
#pr.enable()
smart_moves = snakebrain.get_smart_moves(possible_moves, body, data["board"], data["you"])
#pr.disable()
#pr.print_stats()
smart_time = time.perf_counter() - begin_time
move = random.choice(possible_moves)
if smart_moves: #and random.uniform(0.0, 1.0) > 0.7 and self.turn < 10:
self.log (f"Smart! {smart_moves}")
move = random.choice(smart_moves)
elif safe_moves: #and random.uniform(0.0, 1.0) > 0.03:
self.log (f"Safe! {safe_moves}")
move = random.choice(safe_moves)
total_time = time.perf_counter() - begin_time
self.log(f"MOVE: {move} parse_time {parse_time} safe_time {safe_time} smart_time {smart_time} total_time {total_time}")
return {"move": move, "shout":f'wrap {snakebrain.is_wrapped()}'}
@cherrypy.expose
@cherrypy.tools.json_in()
def end(self):
# This function is called when a game your snake was in ends.
# It's purely for informational purposes, you don't have to make any decisions here.
data = cherrypy.request.json
self.log("END")
return "ok"
@cherrypy.expose
def debug(self, boardstate = None, boardwidth = "11", boardheight = "11"):
result = ""
output = ""
html_begin = f'<html><body><form method="POST">Width:<input type="text" name="boardwidth" value="{boardwidth}"> Height:<input type="text" name="boardheight" value="{boardheight}"><br>Boardstate:<br><textarea name="boardstate" rows="16" cols="120">'
html_middle = '</textarea><br><input type="submit"> <input type="reset"></form>'
html_end = '</body></html>'
if boardstate:
# get result and stdout
transform_output = io.StringIO()
with redirect_stdout(transform_output):
transform_json(boardstate, boardwidth, boardheight)
move_param = transform_output.getvalue()
request = cherrypy.serving.request
request.json = loads(move_param)
move_output = io.StringIO()
with redirect_stdout(move_output):
result = self.move()
output = move_output.getvalue()
return(f'{html_begin}{boardstate}{html_middle}<hr>{result}<br><textarea rows="16" cols="120">{output}</textarea>{html_end}')
def log(self, message):
# output message iwth globals
print(f"{self.game_id} [{self.turn}] {message}")
if __name__ == "__main__":
server = Battlesnake()
# cherrypy.config.update({"server.thread.pool": 11})
cherrypy.config.update({"server.socket_host": "0.0.0.0"})
cherrypy.config.update(
{"server.socket_port": int(os.environ.get("PORT", "8080")),}
)
print("Starting Battlesnake Server...")
cherrypy.quickstart(server)