DEV Community

Cover image for Battlesnake Challenge #1 - Python
Rob van der Leek
Rob van der Leek

Posted on • Edited on

Battlesnake Challenge #1 - Python

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!")
Enter fullscreen mode Exit fullscreen mode

This is the Dockerfile for the runtime environment:

FROM python:3.11
RUN mkdir /app
WORKDIR /app
COPY snake.py .
CMD ["python", "snake.py"]
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

And this is the complete code in action:

Image description

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!

Top comments (0)