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 = [
|
||||
"axum",
|
||||
"bitvec",
|
||||
"enum-iterator",
|
||||
"env_logger",
|
||||
"log",
|
||||
"rand",
|
||||
"serde",
|
||||
"tokio",
|
||||
]
|
||||
@ -299,6 +301,26 @@ dependencies = [
|
||||
"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]]
|
||||
name = "env_filter"
|
||||
version = "0.1.3"
|
||||
|
@ -27,3 +27,5 @@ env_logger = "0.11"
|
||||
|
||||
# other
|
||||
bitvec = "1.0"
|
||||
enum-iterator = "2.1"
|
||||
rand = "0.8"
|
||||
|
@ -6,7 +6,8 @@ use axum::{
|
||||
routing::{get, post},
|
||||
Router,
|
||||
};
|
||||
use log::{debug, info};
|
||||
use log::{debug, info, warn};
|
||||
use rand::prelude::*;
|
||||
use serde::Serialize;
|
||||
use tokio::net::TcpListener;
|
||||
use types::{
|
||||
@ -62,8 +63,15 @@ async fn start(request: Json<Request>) {
|
||||
async fn get_move(request: Json<Request>) -> response::Json<Response> {
|
||||
let board = Board::from(&*request);
|
||||
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 {
|
||||
direction: Direction::Up,
|
||||
direction: action.unwrap_or(Direction::Up),
|
||||
shout: None,
|
||||
})
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use enum_iterator::Sequence;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub mod simulation;
|
||||
@ -9,7 +10,19 @@ pub struct Coord {
|
||||
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 {
|
||||
/// Move in positive y direction
|
||||
Up,
|
||||
|
@ -1,9 +1,9 @@
|
||||
use std::{collections::VecDeque, fmt::Display};
|
||||
|
||||
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)]
|
||||
pub struct Board {
|
||||
@ -123,9 +123,31 @@ impl Board {
|
||||
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));
|
||||
!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 {
|
||||
@ -140,18 +162,6 @@ struct Snake {
|
||||
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 {
|
||||
pub fn head(&self) -> Coord {
|
||||
self.body.front().copied().unwrap_or_else(|| {
|
||||
@ -161,7 +171,7 @@ impl Snake {
|
||||
}
|
||||
|
||||
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:?}");
|
||||
Coord { x: 0, y: 0 }
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user