|
@@ -25,23 +25,35 @@ const DEFAULT_COLS: usize = 24;
|
|
const TERMINAL_PRINTING_SPEED: time::Duration = time::Duration::from_millis(20);
|
|
const TERMINAL_PRINTING_SPEED: time::Duration = time::Duration::from_millis(20);
|
|
const TYPING_SPEED: time::Duration = time::Duration::from_millis(70);
|
|
const TYPING_SPEED: time::Duration = time::Duration::from_millis(70);
|
|
|
|
|
|
|
|
+// Everything displayed to the player, + a reference to the curses window.
|
|
|
|
+#[derive(Debug)]
|
|
pub struct Screen {
|
|
pub struct Screen {
|
|
pub w: Window,
|
|
pub w: Window,
|
|
attempts_left: u8,
|
|
attempts_left: u8,
|
|
b: Board
|
|
b: Board
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// The game board.
|
|
|
|
+#[derive(Debug)]
|
|
struct Board {
|
|
struct Board {
|
|
rows: usize,
|
|
rows: usize,
|
|
cols: usize,
|
|
cols: usize,
|
|
c: Vec<char>
|
|
c: Vec<char>
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// The position of a word on the game board.
|
|
|
|
+#[derive(Debug)]
|
|
struct Coord {
|
|
struct Coord {
|
|
start: usize,
|
|
start: usize,
|
|
end: usize
|
|
end: usize
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+impl Coord {
|
|
|
|
+ fn new(start: usize, len: usize) -> Coord {
|
|
|
|
+ Coord{start:start, end:start+len-1}
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
impl Board {
|
|
impl Board {
|
|
fn new(rows: Option<usize>, cols: Option<usize>) -> Board {
|
|
fn new(rows: Option<usize>, cols: Option<usize>) -> Board {
|
|
let r = match rows {
|
|
let r = match rows {
|
|
@@ -71,6 +83,10 @@ impl Board {
|
|
b
|
|
b
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ fn capacity(&self) -> usize {
|
|
|
|
+ self.c.len()
|
|
|
|
+ }
|
|
|
|
+
|
|
fn get(&self, i: usize) -> char {
|
|
fn get(&self, i: usize) -> char {
|
|
self.c[i]
|
|
self.c[i]
|
|
}
|
|
}
|
|
@@ -86,6 +102,73 @@ impl Board {
|
|
fn setxy(&mut self, x: usize, y: usize, c: char) {
|
|
fn setxy(&mut self, x: usize, y: usize, c: char) {
|
|
self.c[x*y] = c;
|
|
self.c[x*y] = c;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // Think of the board in word_len "chunks": place a slot for a word in each chunk
|
|
|
|
+ fn place_words(&self, num_of_words: usize, word_len: usize) -> Vec<Coord> {
|
|
|
|
+ let chunk_len = self.capacity() / num_of_words;
|
|
|
|
+ if chunk_len < word_len+1 {
|
|
|
|
+ panic!("Can't fill board");
|
|
|
|
+ }
|
|
|
|
+ let mut coords: Vec<Coord> = Vec::with_capacity(num_of_words);
|
|
|
|
+ let mut starting_coord = 0;
|
|
|
|
+ for _ in 0..num_of_words {
|
|
|
|
+ let coord = Coord::new(starting_coord, word_len);
|
|
|
|
+ coords.push(coord);
|
|
|
|
+ starting_coord+=chunk_len;
|
|
|
|
+ }
|
|
|
|
+ coords
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // "shake" each word slot around, in a random order, 3 times/word.
|
|
|
|
+ fn shake_words(&self, word_coords: &mut Vec<Coord>) {
|
|
|
|
+ let mut rng = rand::thread_rng();
|
|
|
|
+
|
|
|
|
+ for _ in 0..3 {
|
|
|
|
+ let mut positions: Vec<usize> = (0..word_coords.len()).collect();
|
|
|
|
+ positions.shuffle(&mut rng);
|
|
|
|
+ for i in positions {
|
|
|
|
+ let coord = &word_coords[i];
|
|
|
|
+ // Where can this coord move (leaving at least 1 space between words)?
|
|
|
|
+ let mut movement_options = Vec::with_capacity(2);
|
|
|
|
+
|
|
|
|
+ let mut start = coord.start as i32;
|
|
|
|
+ let mut end = -2;
|
|
|
|
+ if i > 0 {
|
|
|
|
+ let prev_coord = &word_coords[i-1];
|
|
|
|
+ end = prev_coord.end as i32;
|
|
|
|
+ }
|
|
|
|
+ if start - end > 1 {
|
|
|
|
+ // It can move backwards
|
|
|
|
+ movement_options.push((start-end-1) * -1);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ start = self.capacity() as i32;
|
|
|
|
+ end = coord.end as i32;
|
|
|
|
+ if i < word_coords.len()-1 {
|
|
|
|
+ let next_coord = &word_coords[i+1];
|
|
|
|
+ start = next_coord.start as i32;
|
|
|
|
+ }
|
|
|
|
+ if start - end > 1 {
|
|
|
|
+ // It can move forwards
|
|
|
|
+ movement_options.push(start-end-1);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Pick a movement option, & pick some amount to move
|
|
|
|
+ let mv = match movement_options.choose(&mut rng) {
|
|
|
|
+ None => continue,
|
|
|
|
+ Some(m) => if *m > 0 {
|
|
|
|
+ rng.gen_range(0, *m)
|
|
|
|
+ } else {
|
|
|
|
+ rng.gen_range(*m, 1)
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ word_coords[i] = Coord{
|
|
|
|
+ start: (coord.start as i32+mv) as usize,
|
|
|
|
+ end: (coord.end as i32+mv) as usize,
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
impl Screen {
|
|
impl Screen {
|
|
@@ -123,17 +206,21 @@ impl Screen {
|
|
let border_hex = border_hex_gen(self.b.rows);
|
|
let border_hex = border_hex_gen(self.b.rows);
|
|
|
|
|
|
let shuffled_words = copy_shuffle(&conf.words);
|
|
let shuffled_words = copy_shuffle(&conf.words);
|
|
|
|
+ let words = &shuffled_words[..conf.choose];
|
|
|
|
|
|
- let word_len = conf.words[0].len();
|
|
|
|
// Assumes validate() ensured `words` is not empty, and each word is the same length
|
|
// Assumes validate() ensured `words` is not empty, and each word is the same length
|
|
- let required_tiles = word_len * conf.words.len() + (conf.words.len() - 1);
|
|
|
|
- let board_tiles = self.b.rows * self.b.cols;
|
|
|
|
|
|
+ let word_len = words[0].len();
|
|
|
|
+ let required_tiles = word_len * words.len() + (words.len() - 1);
|
|
|
|
+ let board_tiles = self.b.capacity();
|
|
if required_tiles > board_tiles {
|
|
if required_tiles > board_tiles {
|
|
panic!("{} words of length {} requires {} tiles, but an {}x{} board only allows for {} tiles", conf.words.len(), word_len, required_tiles, self.b.cols, self.b.rows, board_tiles);
|
|
panic!("{} words of length {} requires {} tiles, but an {}x{} board only allows for {} tiles", conf.words.len(), word_len, required_tiles, self.b.cols, self.b.rows, board_tiles);
|
|
}
|
|
}
|
|
|
|
|
|
- name_this(&self.b);
|
|
|
|
- // TODO: insert each word, of size N, into the array, with at least 1 character between each
|
|
|
|
|
|
+ let mut coords = self.b.place_words(words.len(), word_len);
|
|
|
|
+ self.b.shake_words(&mut coords);
|
|
|
|
+
|
|
|
|
+ println!("{:?}", coords);
|
|
|
|
+ println!("{:?}", self.b);
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@@ -179,16 +266,10 @@ fn border_hex_gen(rows: usize) -> Vec<u32> {
|
|
let mut hex = rng.gen_range(0,200) + 63744;
|
|
let mut hex = rng.gen_range(0,200) + 63744;
|
|
|
|
|
|
let mut ls = Vec::with_capacity(rows * 2);
|
|
let mut ls = Vec::with_capacity(rows * 2);
|
|
- for i in 0..rows * 2 {
|
|
|
|
- ls[i] = hex;
|
|
|
|
|
|
+ for _ in 0..rows * 2 {
|
|
|
|
+ ls.push(hex);
|
|
hex += 12;
|
|
hex += 12;
|
|
}
|
|
}
|
|
|
|
|
|
ls
|
|
ls
|
|
}
|
|
}
|
|
-
|
|
|
|
-// Think of the board in word_len "chunks": place a word in each chunk. Then "shake" each one around a bit, in a random order, 3 times/word.
|
|
|
|
-fn name_this(b: &Board) -> Vec<Coord> {
|
|
|
|
- // TODO
|
|
|
|
- return Vec::new();
|
|
|
|
-}
|
|
|