{"id":13691572,"url":"https://github.com/nbw/battlesnake_crystal","last_synced_at":"2026-02-28T08:07:17.374Z","repository":{"id":73291642,"uuid":"120967715","full_name":"nbw/battlesnake_crystal","owner":"nbw","description":"A bounty battlesnake written in Crystal. ","archived":false,"fork":false,"pushed_at":"2020-01-14T03:43:00.000Z","size":1497,"stargazers_count":7,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-11-14T08:03:43.719Z","etag":null,"topics":["battlesnake","crystal-language","programming-competitions"],"latest_commit_sha":null,"homepage":"https://crystal-battlesnake.herokuapp.com/","language":"Crystal","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nbw.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-02-09T23:43:16.000Z","updated_at":"2023-06-14T04:15:18.000Z","dependencies_parsed_at":"2024-01-14T19:13:27.397Z","dependency_job_id":"4c96c61f-f3ca-4bf0-8cc1-bbc2802d2467","html_url":"https://github.com/nbw/battlesnake_crystal","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/nbw/battlesnake_crystal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nbw%2Fbattlesnake_crystal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nbw%2Fbattlesnake_crystal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nbw%2Fbattlesnake_crystal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nbw%2Fbattlesnake_crystal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nbw","download_url":"https://codeload.github.com/nbw/battlesnake_crystal/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nbw%2Fbattlesnake_crystal/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29928024,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T19:37:42.220Z","status":"online","status_checked_at":"2026-02-28T02:00:07.010Z","response_time":90,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["battlesnake","crystal-language","programming-competitions"],"created_at":"2024-08-02T17:00:46.684Z","updated_at":"2026-02-28T08:07:17.336Z","avatar_url":"https://github.com/nbw.png","language":"Crystal","funding_links":[],"categories":["Battlesnakes","Examples and funny stuff"],"sub_categories":[],"readme":"# Battlesnake in Crystal\n\nTron-style [Battlesnake](https://www.battlesnake.io/) written in [Crystal](https://crystal-lang.org/).\n\n![example game](extra/3.gif)\n\n***Blue**: Crystal snake using Voronoi; **Red**: Ruby snake using DFS*\n\n# Challenge\n\nAs a sponsor in the [Battlesnake](https://www.battlesnake.io/) event, each company is tasked with creating a _bounty snake_ that participants can challenge for a potential prize. The variant we chose was a _tron-styled game_ where the tail of the snake remains stationary and no food is available.\n\n# Why Crystal?\n\nIt's compiled! It's typed! It's fast! Also my background is in Ruby and Elixir. This was my first time using Crystal.\n\n---\n\n# Strategy\n\nThere are two phases:\n\n1. **Voronoi Analysis**: maxmizing the area controlled by my snake\n\n2. **Survival Mode**: using remaining space as efficiently and compactly as possible\n\n**Survival mode** is triggered once my snake is in a closed area, which was determined using [Two Pass Connected Component](https://en.wikipedia.org/wiki/Connected-component_labeling#Two-pass) analysis. Code [here](src/battlesnake_crystal/connected_components.cr).\n\n## 1. Voronoi Analysis\n\n### Voronoi Heuristic\n\nThe [voronoi heuristic](https://en.wikipedia.org/wiki/Voronoi_diagram) is useful for determining _how much area a user controls_. The basic premise is to use a flood fill algorithm (or however you want to do it) to find the minimum distance required for a snake to reach a point on the grid. In the case of two snakes, a border will exist between them (where the snakes reach a point on the grid at the same time).\n\n**Voronoi for two snakes (white is shared distances):**\n![voronoi color](extra/voronoi_color.png)\n\n**Visualization of the area controlled by each snake:**\n![voronoi area](extra/voronoi_area.png)\n\n### Using Voronoi\n\nApplying the voronoi heuristic once isn't actually that useful. Here's the recipie for the magic sauce:\n\n1. From the head of my snake, determine all the farthest paths it can take. In practice, there are too many possible paths to compute in a reasonable time. Instead find all paths up to distance X away. In my case, X=3 but can be changed via an environment variable. So to rephrase, **find all paths up to 3 steps away from my snake's head**.\n\n2. **Reapply the voronoi heuristic for each of the possibe paths that my snake can take (from step 1).**\n\n3. **Choose the path that results with my snake having the most controlled area.**\n\nNote: It's worth acknowledging that I'm only accounting for where my snake moves, without considering the movements of other snakes on the grid.\n\n## 2. Survival Mode\n\nSurvival mode is super simple. Check all the points around my snake's head and go in the direction of the one that has the fewest open spaces next to it. This basically forces the snake to hug it's body and/or hug walls. Code [here](src/battlesnake_crystal/survival_snake.cr).\n\n## Optimizations\n\n* Instead of using a 2-D array ( [] of Array(T)) to represent the grid, I opted for using a 1-D array instead ([] of T). The end result was around a 20-30 percent increase in speed I'd say.\n\n* Reducing iterations over the grid at any point was key.\n\n* Being conscious of memory allocation and creation of classes with identical states.\n\n* Reducing intermediary variables while leaving the code relatively verbose.\n\n---\n\n# Usage\n\nThis part is for me.\n\n## Installation\n\nInstall Crystal off the website or just use:\n\n```\nbrew update\nbrew install crystal-lang\n```\n\nThen to install deps run:\n\n`shards install`\n\nFor hotcode reloading, install [sentry](https://github.com/samueleaton/sentry).\n\nThen call: `./sentry` from the project directory to run it with hot reloading.\n\nOtherwise, to run the server, run:\n\n`crystal src/battlesnake_crystal.cr`\n\n## Battlesnake stuff:\n\nThere is an example start request in: start.json\n\nThere is an example move request in: move.json\n\n## Issues\n\nIf you run into a libssl issue, try:\n`https://github.com/crystal-lang/crystal/issues/4745#issuecomment-332553374`\n\n---\n\n# Thanks\n\nThanks to my coworkers, especially Ian Clarkson for being a soundboard for ideas and feedback.\n\nThanks to AppColony for the chance to participate in the event as a sponsor (thanks Aaron!).\n\nSpecial thanks to [A1k0n](https://www.a1k0n.net/2010/03/04/google-ai-postmortem.html) who's article was the inspiration to use a [Voronoi diagram](https://en.wikipedia.org/wiki/Voronoi_diagram) approach.\n\n# More screenshots\n\n![example game](extra/2.gif)\n\n![example game](extra/1.gif)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnbw%2Fbattlesnake_crystal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnbw%2Fbattlesnake_crystal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnbw%2Fbattlesnake_crystal/lists"}