use enum for the direction

This commit is contained in:
Max Känner 2024-09-02 16:06:15 +02:00
parent fc123cbd2b
commit 565f2aefb5
2 changed files with 51 additions and 28 deletions

View File

@ -15,7 +15,7 @@ use rand::seq::SliceRandom;
use serde_json::{json, Value}; use serde_json::{json, Value};
use std::collections::HashMap; use std::collections::HashMap;
use crate::{Battlesnake, Board, Coord, Game}; use crate::{Battlesnake, Board, Coord, Direction, Game, Move};
// info is called when you create your Battlesnake on play.battlesnake.com // info is called when you create your Battlesnake on play.battlesnake.com
// and controls your Battlesnake's appearance // and controls your Battlesnake's appearance
@ -25,7 +25,7 @@ pub fn info() -> Value {
json!({ json!({
"apiversion": "1", "apiversion": "1",
"author": "Der Informatiker", "author": "der-informatiker",
"color": "#00FFEE", "color": "#00FFEE",
"head": "smart-caterpillar", "head": "smart-caterpillar",
"tail": "mouse", "tail": "mouse",
@ -45,15 +45,12 @@ pub fn end(_game: &Game, _turn: i32, _board: &Board, _you: &Battlesnake) {
// move is called on every turn and returns your next move // move is called on every turn and returns your next move
// Valid moves are "up", "down", "left", or "right" // Valid moves are "up", "down", "left", or "right"
// See https://docs.battlesnake.com/api/example-move for available data // See https://docs.battlesnake.com/api/example-move for available data
pub fn get_move(_game: &Game, turn: i32, board: &Board, you: &Battlesnake) -> Value { pub fn get_move(_game: &Game, turn: i32, board: &Board, you: &Battlesnake) -> Move {
let mut is_move_safe: HashMap<_, _> = vec![ use Direction::{Down, Left, Right, Up};
("up", true), let mut is_move_safe: HashMap<_, _> =
("down", true), vec![(Up, true), (Down, true), (Left, true), (Right, true)]
("left", true), .into_iter()
("right", true), .collect();
]
.into_iter()
.collect();
// We've included code to prevent your Battlesnake from moving backwards // We've included code to prevent your Battlesnake from moving backwards
let my_head = &you.body[0]; // Coordinates of your head let my_head = &you.body[0]; // Coordinates of your head
@ -61,30 +58,30 @@ pub fn get_move(_game: &Game, turn: i32, board: &Board, you: &Battlesnake) -> Va
if my_neck.x < my_head.x { if my_neck.x < my_head.x {
// Neck is left of head, don't move left // Neck is left of head, don't move left
is_move_safe.insert("left", false); is_move_safe.insert(Left, false);
} else if my_neck.x > my_head.x { } else if my_neck.x > my_head.x {
// Neck is right of head, don't move right // Neck is right of head, don't move right
is_move_safe.insert("right", false); is_move_safe.insert(Right, false);
} else if my_neck.y < my_head.y { } else if my_neck.y < my_head.y {
// Neck is below head, don't move down // Neck is below head, don't move down
is_move_safe.insert("down", false); is_move_safe.insert(Down, false);
} else if my_neck.y > my_head.y { } else if my_neck.y > my_head.y {
// Neck is above head, don't move up // Neck is above head, don't move up
is_move_safe.insert("up", false); is_move_safe.insert(Up, false);
} }
// TODO: Step 1 - Prevent your Battlesnake from moving out of bounds // TODO: Step 1 - Prevent your Battlesnake from moving out of bounds
if my_head.x == 0 { if my_head.x == 0 {
is_move_safe.insert("left", false); is_move_safe.insert(Left, false);
} }
if my_head.x == board.width - 1 { if my_head.x == board.width - 1 {
is_move_safe.insert("right", false); is_move_safe.insert(Right, false);
} }
if my_head.y == 0 { if my_head.y == 0 {
is_move_safe.insert("down", false); is_move_safe.insert(Down, false);
} }
if my_head.y == board.height - 1 { if my_head.y == board.height - 1 {
is_move_safe.insert("up", false); is_move_safe.insert(Up, false);
} }
// TODO: Step 2 - Prevent your Battlesnake from colliding with itself // TODO: Step 2 - Prevent your Battlesnake from colliding with itself
@ -92,25 +89,25 @@ pub fn get_move(_game: &Game, turn: i32, board: &Board, you: &Battlesnake) -> Va
x: my_head.x - 1, x: my_head.x - 1,
y: my_head.y, y: my_head.y,
}) { }) {
is_move_safe.insert("left", false); is_move_safe.insert(Left, false);
} }
if you.body.contains(&Coord { if you.body.contains(&Coord {
x: my_head.x + 1, x: my_head.x + 1,
y: my_head.y, y: my_head.y,
}) { }) {
is_move_safe.insert("right", false); is_move_safe.insert(Right, false);
} }
if you.body.contains(&Coord { if you.body.contains(&Coord {
x: my_head.x, x: my_head.x,
y: my_head.y - 1, y: my_head.y - 1,
}) { }) {
is_move_safe.insert("down", false); is_move_safe.insert(Down, false);
} }
if you.body.contains(&Coord { if you.body.contains(&Coord {
x: my_head.x, x: my_head.x,
y: my_head.y + 1, y: my_head.y + 1,
}) { }) {
is_move_safe.insert("up", false); is_move_safe.insert(Up, false);
} }
// TODO: Step 3 - Prevent your Battlesnake from colliding with other Battlesnakes // TODO: Step 3 - Prevent your Battlesnake from colliding with other Battlesnakes
@ -124,11 +121,14 @@ pub fn get_move(_game: &Game, turn: i32, board: &Board, you: &Battlesnake) -> Va
.collect::<Vec<_>>(); .collect::<Vec<_>>();
// Choose a random move from the safe ones // Choose a random move from the safe ones
let chosen = safe_moves.choose(&mut rand::thread_rng()).unwrap(); let chosen = safe_moves.choose(&mut rand::thread_rng()).unwrap_or(&Up);
// TODO: Step 4 - Move towards food instead of random, to regain health and survive longer // TODO: Step 4 - Move towards food instead of random, to regain health and survive longer
// let food = &board.food; // let food = &board.food;
info!("MOVE {}: {}", turn, chosen); info!("MOVE {}: {:?}", turn, chosen);
json!({ "move": chosen }) Move {
r#move: *chosen,
shout: None,
}
} }

View File

@ -15,6 +15,29 @@ mod logic;
// API and Response Objects // API and Response Objects
// See https://docs.battlesnake.com/api // See https://docs.battlesnake.com/api
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, Deserialize, Serialize)]
pub enum Direction {
#[serde(rename = "left")]
Left,
#[serde(rename = "up")]
Up,
#[serde(rename = "right")]
Right,
#[serde(rename = "down")]
Down,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Move {
r#move: Direction,
#[serde(default, skip_serializing_if = "is_default")]
shout: Option<String>,
}
fn is_default<T: Default + PartialEq>(value: &T) -> bool {
*value == T::default()
}
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
pub struct Game { pub struct Game {
id: String, id: String,
@ -43,7 +66,7 @@ pub struct Battlesnake {
shout: Option<String>, shout: Option<String>,
} }
#[derive(Debug, PartialEq, Eq, Clone, Copy,Deserialize, Serialize)] #[derive(Debug, PartialEq, Eq, Clone, Copy, Deserialize, Serialize)]
pub struct Coord { pub struct Coord {
x: i32, x: i32,
y: i32, y: i32,
@ -75,7 +98,7 @@ fn handle_start(start_req: Json<GameState>) -> Status {
} }
#[post("/move", format = "json", data = "<move_req>")] #[post("/move", format = "json", data = "<move_req>")]
fn handle_move(move_req: Json<GameState>) -> Json<Value> { fn handle_move(move_req: Json<GameState>) -> Json<Move> {
let response = logic::get_move( let response = logic::get_move(
&move_req.game, &move_req.game,
move_req.turn, move_req.turn,