├── .gitignore
├── BattleSnakeStarter.sln
├── README.md
└── Starter.Api
├── Model
├── Board.cs
├── Coordinate.cs
├── Game.cs
├── Ruleset.cs
├── RulesetSettings.cs
└── Snake.cs
├── Program.cs
├── Properties
└── launchSettings.json
├── Requests
└── GameStatusRequest.cs
├── Responses
├── InitResponse.cs
└── MoveResponse.cs
├── Starter.Api.csproj
├── appsettings.Development.json
└── appsettings.json
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | *.*~
3 | project.lock.json
4 | .DS_Store
5 | *.pyc
6 | nupkg/
7 |
8 | # Visual Studio Code
9 | .vscode
10 |
11 | # Rider
12 | .idea
13 |
14 | # User-specific files
15 | *.suo
16 | *.user
17 | *.userosscache
18 | *.sln.docstates
19 |
20 | # Build results
21 | [Dd]ebug/
22 | [Dd]ebugPublic/
23 | [Rr]elease/
24 | [Rr]eleases/
25 | x64/
26 | x86/
27 | build/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Oo]ut/
32 | msbuild.log
33 | msbuild.err
34 | msbuild.wrn
35 |
36 | .vs/
--------------------------------------------------------------------------------
/BattleSnakeStarter.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Starter.Api", "Starter.Api\Starter.Api.csproj", "{A81484CB-5FE0-4F6C-8724-990FF2E05622}"
4 | EndProject
5 | Global
6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
7 | Debug|Any CPU = Debug|Any CPU
8 | Release|Any CPU = Release|Any CPU
9 | EndGlobalSection
10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
11 | {A81484CB-5FE0-4F6C-8724-990FF2E05622}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
12 | {A81484CB-5FE0-4F6C-8724-990FF2E05622}.Debug|Any CPU.Build.0 = Debug|Any CPU
13 | {A81484CB-5FE0-4F6C-8724-990FF2E05622}.Release|Any CPU.ActiveCfg = Release|Any CPU
14 | {A81484CB-5FE0-4F6C-8724-990FF2E05622}.Release|Any CPU.Build.0 = Release|Any CPU
15 | EndGlobalSection
16 | EndGlobal
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [Battlesnake](https://play.battlesnake.com) C# Starter
2 |
3 | This is a basic implementation of the Battlesnake API. It's a great starting point for anyone wanting to program their first Battlesnake using C#.
4 | It can also be deployed to Azure, or any other cloud provider you'd like.
5 |
6 | ### Technologies Used
7 |
8 | * [Asp Net Core](https://dotnet.microsoft.com/apps/aspnet)
9 |
10 | ## Prerequisites
11 |
12 | * [Battlesnake Account](https://play.battlesnake.com)
13 | * [Azure Account](https://azure.microsoft.com/en-us/)
14 | * [GitHub Account](https://github.com) (Optional)
15 |
16 | ## Running Your Battlesnake on [Azure](https://azure.microsoft.com/en-us/)
17 |
18 | For a quick setup you'll need a [Rider](https://www.jetbrains.com/rider/) or [Visual Studio](https://visualstudio.microsoft.com/)
19 |
20 | 1. Clone this repository and open it in any mentioned IDE
21 | ```
22 | https://github.com/neistow/battlesnake-starter-csharp.git
23 | ```
24 | ### Rider
25 | 2. You should install [Azure Toolkit](https://plugins.jetbrains.com/plugin/11220-azure-toolkit-for-rider).
26 | 3. Right click on Starter.Api and select "Publish" -> "Publish to Azure".
27 | 
28 | 
29 | 4. Choose subscription type,location of server etc. If you have login error go to "Tools" -> "Azure" and login to your account
30 | 
31 | 5. Click Publish and wait until a link to your app appears in console and/or opens in browser. At this point you've deployed your snake.
32 | 
33 | 6. If you need to update your snake simply click "publish" and select existing app, after confirmation your snake will be updated and deployed automatically.
34 |
35 | ### Visual Studio
36 | 2. Right click on Starter.Api and select "Publish" -> "App Service" -> "Create New".
37 | 
38 | 3. Choose subscription type,location of server etc.
39 | 
40 | 4. Click Publish and wait until a link to your app appears in console and/or opens in browser. At this point you've deployed your snake.
41 | 
42 | 5. If you need to update your snake simply click "publish" and select existing app, after confirmation your snake will be updated and deployed automatically.
43 |
44 |
--------------------------------------------------------------------------------
/Starter.Api/Model/Board.cs:
--------------------------------------------------------------------------------
1 | namespace Starter.Api;
2 |
3 | ///
4 | /// The game board is represented by a standard 2D grid, oriented with (0,0) in the bottom left.
5 | /// The Y-Axis is positive in the up direction, and X-Axis is positive to the right.
6 | /// Coordinates begin at zero, such that a board that is 12x12 will have coordinates ranging from [0, 11].
7 | ///
8 | public class Board
9 | {
10 | ///
11 | /// Height of the game board.
12 | /// Example: 11
13 | ///
14 | public int Height { get; set; }
15 |
16 |
17 | ///
18 | /// Width of the game board.
19 | /// Example: 11
20 | ///
21 | public int Width { get; set; }
22 |
23 |
24 | ///
25 | /// Array of s representing food locations on the game board.
26 | /// Example: [{"x": 5, "y": 5}, ..., {"x": 2, "y": 6}]
27 | ///
28 | public IEnumerable Food { get; set; } = new Coordinate[0];
29 |
30 |
31 | ///
32 | /// Array of s representing all Battlesnakes remaining on the game
33 | /// board (including yourself if you haven't been eliminated).
34 | /// Example: [{"id": "snake-one", ...}, ...]
35 | ///
36 | public IEnumerable Snakes { get; set; } = new Snake[0];
37 |
38 |
39 | ///
40 | /// Array of s representing hazardous locations on the game board. These
41 | /// will only appear in some game modes.
42 | /// Example: [{"x": 0, "y": 0}, ..., {"x": 0, "y": 1}]
43 | ///
44 | public IEnumerable Hazards { get; set; } = new Coordinate[0];
45 | }
--------------------------------------------------------------------------------
/Starter.Api/Model/Coordinate.cs:
--------------------------------------------------------------------------------
1 | namespace Starter.Api;
2 |
3 | ///
4 | /// Coordinate on the 2D grid game board.
5 | /// Coordinates begin at zero.
6 | ///
7 | public class Coordinate
8 | {
9 | public int X { get; set; }
10 | public int Y { get; set; }
11 |
12 | public Coordinate(int x, int y)
13 | {
14 | X = x;
15 | Y = y;
16 | }
17 | }
--------------------------------------------------------------------------------
/Starter.Api/Model/Game.cs:
--------------------------------------------------------------------------------
1 | namespace Starter.Api;
2 |
3 | ///
4 | /// Game Object
5 | ///
6 | public class Game
7 | {
8 | ///
9 | /// A unique identifier for this Game.
10 | ///
11 | public string Id { get; set; } = string.Empty;
12 |
13 | ///
14 | /// Information about the ruleset being used to run this game.
15 | /// Example: {"name": "standard", "version": "v1.2.3"}
16 | ///
17 | public Ruleset Ruleset { get; set; } = new Ruleset();
18 |
19 | ///
20 | /// The name of the map used to populate the game board with snakes, food, and hazards. Example: "standard" See Game Maps
21 | ///
22 | public string Map { get; set; } = string.Empty;
23 |
24 | ///
25 | /// How much time your snake has to respond to requests for this Game.
26 | /// Time is in milliseconds.
27 | /// Example: 500
28 | ///
29 | public int Timeout { get; set; }
30 |
31 | ///
32 | /// The source of this game. One of:
33 | /// tournament
34 | /// league (for League Arenas)
35 | /// arena (for all other Arenas)
36 | /// challenge
37 | /// custom (for all other games sources)
38 | /// The values for this field may change in the near future.
39 | ///
40 | public string Source { get; set; } = string.Empty;
41 | }
--------------------------------------------------------------------------------
/Starter.Api/Model/Ruleset.cs:
--------------------------------------------------------------------------------
1 | namespace Starter.Api;
2 |
3 | ///
4 | /// Information about the ruleset being used to run this game.
5 | ///
6 | public class Ruleset
7 | {
8 | ///
9 | /// Name of the ruleset being used to run this game.
10 | /// Possible values include: standard, solo, royale, squad, constrictor, wrapped.
11 | /// See Game Modes for more information on each ruleset.Example: "standard"
12 | ///
13 | public string Name { get; set; } = string.Empty;
14 |
15 | ///
16 | /// The release version of the Rules module used in this game.
17 | /// Example: "version": "v1.2.3"
18 | ///
19 | public string Version { get; set; } = string.Empty;
20 |
21 | ///
22 | /// A collection of specific settings being used by the current game that control how the rules are applied.
23 | ///
24 | public RulesetSettings Settings { get; set; } = new RulesetSettings();
25 | }
26 |
--------------------------------------------------------------------------------
/Starter.Api/Model/RulesetSettings.cs:
--------------------------------------------------------------------------------
1 | namespace Starter.Api;
2 |
3 | public class RulesetSettings
4 | {
5 | ///
6 | /// Percentage chance of spawning a new food every round.
7 | ///
8 | public int FoodSpawnChance { get; set; }
9 |
10 | ///
11 | /// Minimum food to keep on the board every turn.
12 | ///
13 | public int MinimumFood { get; set; }
14 |
15 | ///
16 | /// Health damage a snake will take when ending its turn in a hazard. This stacks on top of the regular 1 damage a snake takes per turn.
17 | ///
18 | public int HazardDamagePerTurn { get; set; }
19 |
20 | public RoyaleModeRulesetSettings Royale { get; set; } = new RoyaleModeRulesetSettings();
21 |
22 | public SquadModeRulesetSettings Squad { get; set; } = new SquadModeRulesetSettings();
23 |
24 | public class RoyaleModeRulesetSettings
25 | {
26 | ///
27 | /// In Royale mode, the number of turns between generating new hazards (shrinking the safe board space).
28 | ///
29 | public int ShrinkEveryNTurns { get; set; }
30 | }
31 |
32 | public class SquadModeRulesetSettings
33 | {
34 | ///
35 | /// In Squad mode, allow members of the same squad to move over each other without dying.
36 | ///
37 | public bool AllowBodyCollisions { get; set; }
38 |
39 | ///
40 | /// In Squad mode, all squad members are eliminated when one is eliminated.
41 | ///
42 | public bool SharedElimination { get; set; }
43 |
44 | ///
45 | /// In Squad mode, all squad members share health.
46 | ///
47 | public bool SharedHealth { get; set; }
48 |
49 | ///
50 | /// In Squad mode, all squad members share length.
51 | ///
52 | public bool SharedLength { get; set; }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Starter.Api/Model/Snake.cs:
--------------------------------------------------------------------------------
1 | namespace Starter.Api;
2 |
3 | ///
4 | /// The snake itself.
5 | ///
6 | public class Snake
7 | {
8 | ///
9 | /// Unique identifier for this Battlesnake in the context of the current Game.
10 | /// Example: "totally-unique-snake-id"
11 | ///
12 | public string Id { get; set; } = string.Empty;
13 |
14 | ///
15 | /// Name given to this Battlesnake by its author.
16 | /// Example: "Sneky McSnek Face"
17 | ///
18 | public string Name { get; set; } = string.Empty;
19 |
20 | ///
21 | /// Health value of this Battlesnake, between 0 and 100 inclusively.
22 | /// Example: 54
23 | ///
24 | public int Health { get; set; }
25 |
26 | ///
27 | /// Array of coordinates representing this Battlesnake's location on the game board.
28 | /// This array is ordered from head to tail.
29 | /// Example: [{"x": 0, "y": 0}, ..., {"x": 2, "y": 0}]
30 | ///
31 | public IEnumerable Body { get; set; } = new Coordinate[] { new Coordinate(0, 0) };
32 |
33 | ///
34 | /// Coordinates for this Battlesnake's head. Equivalent to the first element of the body array.
35 | /// Example: {"x": 0, "y": 0}
36 | ///
37 | public Coordinate Head { get; set; } = new Coordinate(0, 0);
38 |
39 | ///
40 | /// Length of this Battlesnake from head to tail. Equivalent to the length of the body
41 | /// array.
42 | /// Example: 3
43 | ///
44 | public int Length { get; set; }
45 |
46 | ///
47 | /// Message shouted by this Battlesnake on the previous turn.
48 | /// Example: "why are we shouting??"
49 | ///
50 | public string Shout { get; set; } = string.Empty;
51 |
52 | ///
53 | /// The previous response time of this Battlesnake, in milliseconds.
54 | /// If the Battlesnake timed out and failed to respond, the game timeout will be returned (game.timeout)
55 | /// Example: 500
56 | ///
57 | public string Latency { get; set; } = string.Empty;
58 |
59 | ///
60 | /// The squad that the Battlesnake belongs to. Used to identify squad members in Squad Mode games.
61 | /// Example: "1"
62 | ///
63 | public string Squad { get; set; } = string.Empty;
64 |
65 | ///
66 | /// The collection of customizations applied to this Battlesnake that represent how it is viewed.
67 | /// Follows the same rules as in the Info request.
68 | /// Example: {"color":"#888888", "head":"default", "tail":"default" }
69 | ///
70 | public SnakeCustomizations Customizations { get; set; } = new SnakeCustomizations();
71 |
72 | public class SnakeCustomizations
73 | {
74 | ///
75 | /// Hex color code used to display this Battlesnake. Must start with "#" and be 7 characters long.Example: "#888888"
76 | ///
77 | public string Color { get; set; } = string.Empty;
78 |
79 | ///
80 | /// Displayed head of this Battlesnake. See Customization Guide for available optionsExample: "default"
81 | ///
82 | public string Head { get; set; } = string.Empty;
83 |
84 | ///
85 | /// Displayed tail of this Battlesnake. See Customization Guide for available optionsExample: "default"
86 | ///
87 | public string Tail { get; set; } = string.Empty;
88 | }
89 | }
--------------------------------------------------------------------------------
/Starter.Api/Program.cs:
--------------------------------------------------------------------------------
1 | using Starter.Api.Requests;
2 | using Starter.Api.Responses;
3 |
4 | var builder = WebApplication.CreateBuilder(args);
5 | var app = builder.Build();
6 | app.UseHttpsRedirection();
7 |
8 | ///
9 | /// This request will be made periodically to retrieve information about your Battlesnake,
10 | /// including its display options, author, etc.
11 | ///
12 | app.MapGet("/", () =>
13 | {
14 | return new InitResponse
15 | {
16 | ApiVersion = "1",
17 | Author = "",
18 | Color = "#FFFFFF",
19 | Head = "default",
20 | Tail = "default"
21 | };
22 | });
23 |
24 | ///
25 | /// Your Battlesnake will receive this request when it has been entered into a new game.
26 | /// Every game has a unique ID that can be used to allocate resources or data you may need.
27 | /// Your response to this request will be ignored.
28 | ///
29 | app.MapPost("/start", (GameStatusRequest gameStatusRequest) =>
30 | {
31 | Results.Ok();
32 | });
33 |
34 | ///
35 | /// This request will be sent for every turn of the game.
36 | /// Use the information provided to determine how your
37 | /// Battlesnake will move on that turn, either up, down, left, or right.
38 | ///
39 | app.MapPost("/move", (GameStatusRequest gameStatusRequest) =>
40 | {
41 | var direction = new List { "down", "left", "right", "up" };
42 |
43 | return new MoveResponse
44 | {
45 | Move = direction[Random.Shared.Next(direction.Count)],
46 | Shout = "I am moving!"
47 | };
48 | });
49 |
50 | ///
51 | /// Your Battlesnake will receive this request whenever a game it was playing has ended.
52 | /// Use it to learn how your Battlesnake won or lost and deallocated any server-side resources.
53 | /// Your response to this request will be ignored.
54 | ///
55 | app.MapPost("/end", (GameStatusRequest gameStatusRequest) =>
56 | {
57 | Results.Ok();
58 | });
59 |
60 | app.Run();
--------------------------------------------------------------------------------
/Starter.Api/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:17832",
8 | "sslPort": 44325
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "Starter.Api": {
21 | "commandName": "Project",
22 | "launchBrowser": true,
23 | "launchUrl": "",
24 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Starter.Api/Requests/GameStatusRequest.cs:
--------------------------------------------------------------------------------
1 | namespace Starter.Api.Requests;
2 |
3 | public class GameStatusRequest
4 | {
5 |
6 | ///
7 | /// Object describing the game being played.
8 | ///
9 | public Game Game { get; set; } = new Game();
10 |
11 | ///
12 | /// start: Turn number of the game being played (0 for new games).
13 | /// move: Turn number for this move.
14 | /// end: Turn number for the last turn of the game.
15 | ///
16 | public int Turn { get; set; }
17 |
18 | ///
19 | /// start: Object describing the initial state of the game board.
20 | /// move: Object describing the game board on this turn.
21 | /// end: Object describing the final state of the game board.
22 | ///
23 | public Board Board { get; set; } = new Board();
24 |
25 | ///
26 | /// Object describing your Battlesnake.
27 | ///
28 | public Snake You { get; set; } = new Snake();
29 | }
--------------------------------------------------------------------------------
/Starter.Api/Responses/InitResponse.cs:
--------------------------------------------------------------------------------
1 | namespace Starter.Api.Responses;
2 |
3 | public class InitResponse
4 | {
5 | ///
6 | /// Version of the Battlesnake API implemented by this Battlesnake. Currently only API version 1 is valid. Example: "1"
7 | ///
8 | public string ApiVersion { get; set; } = "1";
9 |
10 | ///
11 | /// Username of the author of this Battlesnake. If provided, this will be used to verify ownership.Example: "BattlesnakeOfficial"
12 | ///
13 | public string? Author { get; set; }
14 |
15 | ///
16 | /// Hex color code used to display this Battlesnake. Must start with "#" and be 7 characters long.Example: "#888888"
17 | ///
18 | public string? Color { get; set; }
19 |
20 | ///
21 | /// Displayed head of this Battlesnake. See Customization Guide for available optionsExample: "default"
22 | ///
23 | public string? Head { get; set; }
24 |
25 | ///
26 | /// Displayed tail of this Battlesnake. See Customization Guide for available optionsExample: "default"
27 | ///
28 | public string? Tail { get; set; }
29 |
30 | ///
31 | /// A version number or tag for your snake.
32 | ///
33 | public string? Version { get; set; }
34 | }
--------------------------------------------------------------------------------
/Starter.Api/Responses/MoveResponse.cs:
--------------------------------------------------------------------------------
1 | namespace Starter.Api.Responses;
2 |
3 | public class MoveResponse
4 | {
5 | ///
6 | /// Your Battlesnake's move for this turn. Valid moves are up, down, left, or right.Example: "up"
7 | ///
8 | public string Move { get; set; } = "up";
9 |
10 | ///
11 | /// An optional message sent to all other Battlesnakes on the next turn. Must be 256 characters or less.Example: "I am moving up!"
12 | ///
13 | public string? Shout { get; set; }
14 | }
--------------------------------------------------------------------------------
/Starter.Api/Starter.Api.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net6.0
4 | enable
5 | enable
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Starter.Api/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Starter.Api/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*"
10 | }
11 |
--------------------------------------------------------------------------------