This commit is contained in:
parent
d91d0e0a82
commit
9c76df1f69
22
Cargo.lock
generated
22
Cargo.lock
generated
@ -173,8 +173,10 @@ version = "2.0.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"bitvec",
|
"bitvec",
|
||||||
|
"enum-iterator",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"log",
|
"log",
|
||||||
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
@ -299,6 +301,26 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "enum-iterator"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c280b9e6b3ae19e152d8e31cf47f18389781e119d4013a2a2bb0180e5facc635"
|
||||||
|
dependencies = [
|
||||||
|
"enum-iterator-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "enum-iterator-derive"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1ab991c1362ac86c61ab6f556cff143daa22e5a15e4e189df818b2fd19fe65b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "env_filter"
|
name = "env_filter"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
|
@ -27,3 +27,5 @@ env_logger = "0.11"
|
|||||||
|
|
||||||
# other
|
# other
|
||||||
bitvec = "1.0"
|
bitvec = "1.0"
|
||||||
|
enum-iterator = "2.1"
|
||||||
|
rand = "0.8"
|
||||||
|
@ -6,7 +6,8 @@ use axum::{
|
|||||||
routing::{get, post},
|
routing::{get, post},
|
||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use log::{debug, info};
|
use log::{debug, info, warn};
|
||||||
|
use rand::prelude::*;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
use types::{
|
use types::{
|
||||||
@ -62,8 +63,15 @@ async fn start(request: Json<Request>) {
|
|||||||
async fn get_move(request: Json<Request>) -> response::Json<Response> {
|
async fn get_move(request: Json<Request>) -> response::Json<Response> {
|
||||||
let board = Board::from(&*request);
|
let board = Board::from(&*request);
|
||||||
info!("got move request: {board}");
|
info!("got move request: {board}");
|
||||||
|
let actions = board.valid_actions(0).collect::<Vec<_>>();
|
||||||
|
info!("valid actions: {:?}", actions);
|
||||||
|
let action = actions.choose(&mut thread_rng()).copied();
|
||||||
|
if action.is_none() {
|
||||||
|
warn!("unable to find a valid action");
|
||||||
|
}
|
||||||
|
info!("chose {action:?}");
|
||||||
response::Json(Response {
|
response::Json(Response {
|
||||||
direction: Direction::Up,
|
direction: action.unwrap_or(Direction::Up),
|
||||||
shout: None,
|
shout: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use enum_iterator::Sequence;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub mod simulation;
|
pub mod simulation;
|
||||||
@ -9,7 +10,19 @@ pub struct Coord {
|
|||||||
y: u8,
|
y: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize)]
|
impl Coord {
|
||||||
|
pub fn apply(self, direction: Direction) -> Option<Self> {
|
||||||
|
match direction {
|
||||||
|
Direction::Up => self.y.checked_add(1).map(|y| Self { y, x: self.x }),
|
||||||
|
Direction::Down => self.y.checked_sub(1).map(|y| Self { y, x: self.x }),
|
||||||
|
Direction::Left => self.x.checked_sub(1).map(|x| Self { x, y: self.y }),
|
||||||
|
Direction::Right => self.x.checked_add(1).map(|x| Self { x, y: self.y }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Sequence)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
pub enum Direction {
|
pub enum Direction {
|
||||||
/// Move in positive y direction
|
/// Move in positive y direction
|
||||||
Up,
|
Up,
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use std::{collections::VecDeque, fmt::Display};
|
use std::{collections::VecDeque, fmt::Display};
|
||||||
|
|
||||||
use bitvec::prelude::*;
|
use bitvec::prelude::*;
|
||||||
use log::error;
|
use log::{error, warn};
|
||||||
|
|
||||||
use super::{wire::Request, Coord};
|
use super::{wire::Request, Coord, Direction};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct Board {
|
pub struct Board {
|
||||||
@ -123,9 +123,31 @@ impl Board {
|
|||||||
self.hazard[index]
|
self.hazard[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_blocked(&self, tile: Coord) -> bool {
|
pub fn is_free(&self, tile: Coord) -> bool {
|
||||||
let index = usize::from(self.coord_to_linear(tile));
|
let index = usize::from(self.coord_to_linear(tile));
|
||||||
!self.free[index]
|
self.free[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn valid_actions(&self, id: u8) -> impl Iterator<Item = Direction> + use<'_> {
|
||||||
|
let head = self
|
||||||
|
.snakes
|
||||||
|
.binary_search_by_key(&id, |snake| snake.id)
|
||||||
|
.ok()
|
||||||
|
.map(|index| self.snakes[index].head());
|
||||||
|
if head.is_none() {
|
||||||
|
warn!(
|
||||||
|
"Asked for an action for a snake that doesn't exist: {id} not in {:?}",
|
||||||
|
self.snakes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
enum_iterator::all::<Direction>()
|
||||||
|
.filter_map(move |direction| {
|
||||||
|
head.and_then(|head| head.apply(direction))
|
||||||
|
.map(|tile| (direction, tile))
|
||||||
|
})
|
||||||
|
.filter(|(_, tile)| tile.x < self.width && tile.y < self.height)
|
||||||
|
.filter(|(_, tile)| self.is_free(*tile))
|
||||||
|
.map(|(direction, _)| direction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn coord_to_linear(&self, coord: Coord) -> u16 {
|
fn coord_to_linear(&self, coord: Coord) -> u16 {
|
||||||
@ -140,18 +162,6 @@ struct Snake {
|
|||||||
body: VecDeque<Coord>,
|
body: VecDeque<Coord>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialOrd for Snake {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for Snake {
|
|
||||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
||||||
self.id.cmp(&other.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Snake {
|
impl Snake {
|
||||||
pub fn head(&self) -> Coord {
|
pub fn head(&self) -> Coord {
|
||||||
self.body.front().copied().unwrap_or_else(|| {
|
self.body.front().copied().unwrap_or_else(|| {
|
||||||
@ -161,7 +171,7 @@ impl Snake {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn tail(&self) -> Coord {
|
pub fn tail(&self) -> Coord {
|
||||||
self.body.front().copied().unwrap_or_else(|| {
|
self.body.back().copied().unwrap_or_else(|| {
|
||||||
error!("Snake without a tail: {self:?}");
|
error!("Snake without a tail: {self:?}");
|
||||||
Coord { x: 0, y: 0 }
|
Coord { x: 0, y: 0 }
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user