189 lines
5.8 KiB
Rust
189 lines
5.8 KiB
Rust
use crate::logic::*;
|
|
use rand::seq::SliceRandom;
|
|
use rand::{Rng, SeedableRng};
|
|
use rand_xoshiro::SplitMix64;
|
|
use xxhash_rust::xxh3::xxh3_64;
|
|
|
|
impl Board {
|
|
pub fn new(seed: &str) -> Board {
|
|
let mut rng = SplitMix64::seed_from_u64(xxh3_64(seed.as_bytes()));
|
|
let hexes = {
|
|
let mut arr = [[None; 7]; 7];
|
|
for h in Board::hexes(&mut rng) {
|
|
arr[h.position.0 as usize][h.position.1 as usize] = Some(h);
|
|
}
|
|
arr
|
|
};
|
|
let (edges, vertices) = {
|
|
let mut es = [[None; 15]; 15];
|
|
let mut vs = [[None; 15]; 15];
|
|
for hex in hexes.iter().flatten() {
|
|
match hex {
|
|
Some(Hex {
|
|
hextype: HexType::Resource | HexType::Desert,
|
|
position: p,
|
|
..
|
|
}) => {
|
|
let mut d = Position::new(1, 0);
|
|
for _ in 0..6 {
|
|
let e = p.edge(&d);
|
|
if es[e.0 as usize][e.1 as usize].is_none() {
|
|
es[e.0 as usize][e.1 as usize] = Some(Edge {
|
|
position: e,
|
|
road: None,
|
|
});
|
|
}
|
|
if vs[e.0 as usize][e.1 as usize].is_none() {
|
|
vs[e.0 as usize][e.1 as usize] = Some(Vertex {
|
|
position: e.vertex(&d),
|
|
settlement: None,
|
|
city: None,
|
|
});
|
|
}
|
|
d.rotate();
|
|
}
|
|
}
|
|
_ => (),
|
|
}
|
|
}
|
|
(es, vs)
|
|
};
|
|
|
|
let board = Board {
|
|
hexes,
|
|
edges,
|
|
vertices,
|
|
robber: hexes
|
|
.iter()
|
|
.flatten()
|
|
.find(|h| h.is_some() && h.unwrap().hextype == HexType::Desert)
|
|
.unwrap()
|
|
.unwrap()
|
|
.position,
|
|
};
|
|
board
|
|
}
|
|
|
|
fn hexes<R: Rng>(mut rng: &mut R) -> Vec<Hex> {
|
|
// get random direction
|
|
let direction = {
|
|
let mut d = Position::new(1, 0);
|
|
for _ in 0..rng.gen_range(0..6) {
|
|
d.rotate();
|
|
}
|
|
d
|
|
};
|
|
let ps = Board::spiral_order(&direction);
|
|
let mut hexes = Vec::new();
|
|
|
|
// randomize port resources
|
|
let mut port_resources = {
|
|
let mut v = vec![
|
|
None,
|
|
None,
|
|
None,
|
|
None,
|
|
Some(Resource::Wood),
|
|
Some(Resource::Brick),
|
|
Some(Resource::Sheep),
|
|
Some(Resource::Wheat),
|
|
Some(Resource::Ore),
|
|
];
|
|
v.shuffle(&mut rng);
|
|
v
|
|
};
|
|
let mut orientation = direction;
|
|
orientation.rotate().rotate();
|
|
for (i, p) in ps[0..18].iter().enumerate() {
|
|
if i % 2 == 0 {
|
|
//is a port
|
|
if i % 3 != 1 {
|
|
orientation.rotate();
|
|
}
|
|
hexes.push(Hex {
|
|
hextype: HexType::Port,
|
|
resource: port_resources.pop().unwrap(),
|
|
position: *p,
|
|
number: None,
|
|
orientation: Some(orientation),
|
|
});
|
|
} else {
|
|
hexes.push(Hex {
|
|
hextype: HexType::Ocean,
|
|
resource: None,
|
|
position: *p,
|
|
number: None,
|
|
orientation: None,
|
|
});
|
|
}
|
|
}
|
|
|
|
let mut numbers = {
|
|
let mut v = vec![5, 2, 6, 3, 8, 10, 9, 12, 11, 4, 8, 10, 9, 4, 5, 6, 3, 11];
|
|
v.reverse();
|
|
v
|
|
};
|
|
let mut hex_resources = {
|
|
let mut h = Vec::new();
|
|
for _ in 0..4 {
|
|
h.push(Resource::Wood);
|
|
h.push(Resource::Sheep);
|
|
h.push(Resource::Wheat);
|
|
}
|
|
for _ in 0..3 {
|
|
h.push(Resource::Brick);
|
|
h.push(Resource::Ore);
|
|
}
|
|
h.shuffle(&mut rng);
|
|
h
|
|
};
|
|
let desert_pos = rng.gen_range(0..18);
|
|
for (i, p) in ps[18..].iter().enumerate() {
|
|
if i == desert_pos {
|
|
hexes.push(Hex {
|
|
hextype: HexType::Desert,
|
|
resource: None,
|
|
position: *p,
|
|
number: None,
|
|
orientation: None,
|
|
});
|
|
} else {
|
|
hexes.push(Hex {
|
|
hextype: HexType::Resource,
|
|
resource: Some(hex_resources.pop().unwrap()),
|
|
position: *p,
|
|
number: Some(numbers.pop().unwrap()),
|
|
orientation: None,
|
|
});
|
|
};
|
|
}
|
|
hexes
|
|
}
|
|
|
|
fn spiral_order(direction: &Position) -> Vec<Position> {
|
|
let mut ps = Vec::new();
|
|
for r in (1..=3).rev() {
|
|
ps.extend(&Board::ring(&direction, r));
|
|
}
|
|
ps.push(Position::new(3, 3));
|
|
ps
|
|
}
|
|
|
|
fn ring(direction: &Position, radius: u32) -> Vec<Position> {
|
|
let mut ps = Vec::new();
|
|
let mut current = Position::new(3, 3);
|
|
for _ in 0..radius {
|
|
current.add(direction);
|
|
}
|
|
let mut d = *direction;
|
|
d.rotate().rotate();
|
|
for _ in 0..6 {
|
|
for _ in 0..radius {
|
|
ps.push(current);
|
|
current.add(&d);
|
|
}
|
|
d.rotate();
|
|
}
|
|
ps
|
|
}
|
|
}
|