Battlesnake Challenge #1 - Python
Rob van der Leek
Posted on May 15, 2024
In this series I'll share my progress with my self-imposed programming challenge: build a Battlesnake in as many different programming languages as possible.
Check the first post for a short intro to this series.
You can also follow my progress on GitHub.
Python
For the first post in this series I picked an easy start: Python.
Python is a beautiful language. Readability was one of the language’s core design principles, and that feature still makes Python stand out from other contemporary programming languages. Open a Python project, any Python project, and the code immediately has a familiar feel to it.
Also, the Python Standard Library is very versatile, the language comes with batteries included for many things.
Let's see how these language features help in building Battlesnakes...
Hello, world!
The obligatory "Hello, world!" does not become more idiomatic than it looks in Python:
print("Hello, world!")
This is the Dockerfile for the runtime environment:
FROM python:3.11
RUN mkdir /app
WORKDIR /app
COPY snake.py .
CMD ["python", "snake.py"]
And here's the development setup in action:
A basic web server
Python comes with a simple HTTPServer as part of its Standard Library. There's a threaded and a non-threaded version. For my implementation, the non-threaded server will do.
This is the full code for the web server that implements the GET /
endpoint:
import os
import json
from http.server import HTTPServer, BaseHTTPRequestHandler
class RequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
handle_get_meta_data(self)
def handle_get_meta_data(request_handler):
content = json.dumps({
'apiversion': '1',
'author': 'robvanderleek',
'version': '1.0',
'color': '#3776ab',
'head': 'safe',
'tail': 'sharp'
})
request_handler.send_response(200)
request_handler.end_headers()
request_handler.wfile.write(content.encode('utf-8'))
PORT=int(os.getenv('PORT', 3000))
print(f'Starting Battlesnake server on port: {PORT}')
server = HTTPServer(('0.0.0.0', PORT), RequestHandler)
server.serve_forever()
Game logic
The game logic is spread out over a number of short, and IMHO very readable Python functions.
Below is one of the core game logic functions that returns a prioritized list of directions based on the position of the snake's head and the position of the nearest food on the board:
def preferred_directions(board, head):
food = nearest_food(head, board['food'])
result = []
if head['x'] != food['x']:
result.append('right' if head['x'] < food['x'] else 'left')
if head['y'] != food['y']:
result.append('up' if head['y'] < food['y'] else 'down')
for d in ['right', 'down', 'left', 'up']:
if not d in result:
result.append(d)
return result
And this is the complete code in action:
The full code for the Python Battlesnake can be found here on GitHub.
Feedback appreciated!
I hope you like reading along with my coding adventures.
Let me know in the comments below what you think about the code above, or what programming languages you are looking forward to in this series.
Until the next language!
Posted on May 15, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.