summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/board.rs50
-rw-r--r--src/main.rs243
2 files changed, 205 insertions, 88 deletions
diff --git a/src/board.rs b/src/board.rs
index eb8a638..578842c 100644
--- a/src/board.rs
+++ b/src/board.rs
@@ -94,7 +94,7 @@ impl fmt::Display for Action {
}
}
-type Stack = Vec<(Player, Stone)>;
+pub type Stack = Vec<(Player, Stone)>;
pub struct Board<L>
where
@@ -115,18 +115,22 @@ where
// TODO: Generate all legal actions for a given player
impl<L: Fn(String)> Board<L> {
- pub fn new(size: u8, log: L) -> Option<Board<L>> {
- if size >= 3 && size <= 8 {
- let (flats, caps) = match size {
- 3 => (10, 0),
- 4 => (15, 0),
- 5 => (21, 1),
- 6 => (30, 1),
- 7 => (40, 2),
- 8 => (50, 2),
- _ => return None,
- };
- Some(Board {
+ pub fn get_size(&self) -> u8 {
+ self.size
+ }
+
+ // Defaults to 5x5 if requested things are out of range
+ pub fn new(size: u8, log: L) -> (Board<L>, bool) {
+ let (flats, caps, correct) = match size {
+ 3 => (10, 0, true),
+ 4 => (15, 0, true),
+ 6 => (30, 1, true),
+ 7 => (40, 2, true),
+ 8 => (50, 2, true),
+ _ => (21, 1, false),
+ };
+ (
+ Board {
size: size,
black_flats: flats,
white_flats: flats,
@@ -135,19 +139,17 @@ impl<L: Fn(String)> Board<L> {
board: {
let mut v: Vec<Stack> = Vec::new();
for _i in 0..size * size {
- let t: Stack = Vec::new();
- v.push(t);
+ v.push(Vec::new());
}
v
},
log: log,
- })
- } else {
- None
- }
+ },
+ correct,
+ )
}
- fn remaining_pieces(&self, player: &Player, stone: &Stone) -> u8 {
+ pub fn remaining_pieces(&self, player: &Player, stone: &Stone) -> u8 {
match player {
Player::Black => {
if *stone == Stone::Capstone {
@@ -174,6 +176,14 @@ impl<L: Fn(String)> Board<L> {
}
}
+ pub fn query_square(&self, pos: &Position) -> Option<&Stack> {
+ if self.within_bounds(pos) {
+ self.board.get(self.pos_to_idx(pos))
+ } else {
+ None
+ }
+ }
+
fn pos_to_idx(&self, pos: &Position) -> usize {
let y: usize = pos.y as usize;
let x: usize = pos.x as usize;
diff --git a/src/main.rs b/src/main.rs
index 4528e96..6d110e1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -9,11 +9,15 @@ use crate::board::*;
struct BoardGui {
win: Window,
- size: i32,
- cell_height: i32,
- cell_width: i32,
+ cell_windows: Vec<Window>,
+ size: u8,
+ cell_height: u8,
+ cell_width: u8,
hoff: i32,
cur_cell: Position,
+ has_colours: bool,
+ white_colour: u8,
+ black_colour: u8,
}
#[derive(PartialEq)]
@@ -23,77 +27,129 @@ enum BGAction {
}
impl BoardGui {
- fn mv_to_cell(&self, pos: &Position) {
- let y: i32 = pos.y as i32;
- let x: i32 = pos.x as i32;
- if (y < self.size) && (x < self.size) {
- let y = (self.size - y) * self.cell_height + 1;
- let x = self.hoff + x * self.cell_width + 1;
- self.win.mv(y, x);
- self.win.refresh();
- }
- }
-
fn draw_grid(&self) {
- for y in 0..self.cell_height * self.size + 1 {
- for x in 0..self.cell_width * self.size + 1 {
- if y % self.cell_height == 0 {
- if x % self.cell_width == 0 {
+ let s: i32 = self.size as i32;
+ let h: i32 = self.cell_height as i32;
+ let w: i32 = self.cell_width as i32;
+ for y in 0..h * s + 1 {
+ for x in 0..w * s + 1 {
+ if y % h == 0 {
+ if x % w == 0 {
self.win.mvaddch(y, x + self.hoff, '+');
} else {
self.win.mvaddch(y, x + self.hoff, '-');
}
- } else if x % self.cell_width == 0 {
+ } else if x % w == 0 {
self.win.mvaddch(y, x + self.hoff, '|');
}
}
}
- for y in 0..self.size {
- self.win.mvaddstr(
- y * self.cell_height + self.cell_height / 2,
- 0,
- format!("{}.", self.size - y),
- );
+ for y in 0..s {
+ self.win.mvaddstr(y * h + h / 2, 0, format!("{}.", s - y));
}
- for x in 0..self.size {
+ for x in 0..s {
self.win.mvaddstr(
- self.size * self.cell_height + 1,
- self.cell_width * x + self.cell_width / 2 + self.hoff,
+ s * h + 1,
+ w * x + w / 2 + self.hoff,
format!("{:x}.", x + 10),
);
}
self.win.refresh();
}
+ fn pos_to_idx(&self, pos: &Position) -> usize {
+ let y = pos.y as usize;
+ let x = pos.x as usize;
+ x + y * (self.size as usize)
+ }
+
+ fn mv_to_cell(&self, pos: &Position, line: i32) {
+ if let Some(win) = self.cell_windows.get(self.pos_to_idx(pos)) {
+ win.mv(line, 0);
+ win.refresh();
+ }
+ }
+
+ fn draw_stone(&self, win: &Window, top: bool, player: &Player, stone: &Stone) {
+ if self.has_colours {
+ match player {
+ Player::Black => win.attrset(ColorPair(self.black_colour)),
+ Player::White => win.attrset(ColorPair(self.white_colour)),
+ };
+ if top {
+ win.addch(match stone {
+ Stone::Flat => '#',
+ Stone::Standing => '/',
+ Stone::Capstone => '*',
+ });
+ } else {
+ win.addstr(format!("{}", player));
+ }
+ } else {
+ win.addstr(format!("{}", player));
+ if top {
+ win.addstr(format!("{}", stone));
+ }
+ }
+ }
+
+ fn draw_stack(&self, pos: &Position, stack: &Stack) {
+ if let Some(win) = self.cell_windows.get(self.pos_to_idx(pos)) {
+ win.mv(0, 0);
+ let l = stack.len() as i32;
+ if l > 0 {
+ for i in 0..l {
+ let (player, stone) = &stack[i as usize];
+ self.draw_stone(win, i == l - 1, player, stone);
+ }
+ }
+ win.refresh();
+ }
+ }
+
+ // Is this really the best way to do this?
+ fn draw_board<L: Fn(String)>(&self, board: &Board<L>) {
+ // ????
+ assert!(board.get_size() == self.size);
+ let mut pos = Position { x: 0, y: 0 };
+ for y in 0..self.size {
+ pos.y = y;
+ for x in 0..self.size {
+ pos.x = x;
+ if let Some(stack) = board.query_square(&pos) {
+ self.draw_stack(&pos, stack);
+ }
+ }
+ }
+ }
+
fn handle_key(&mut self, key: Input) -> BGAction {
match key {
- KeyUp => {
+ KeyDown => {
if 0 < self.cur_cell.y {
self.cur_cell.y -= 1;
- self.mv_to_cell(&self.cur_cell);
+ self.mv_to_cell(&self.cur_cell, 0);
}
BGAction::None
}
- KeyDown => {
- let y: i32 = self.cur_cell.y as i32;
- if y + 1 < self.size {
+ KeyUp => {
+ if self.cur_cell.y + 1 < self.size {
self.cur_cell.y += 1;
- self.mv_to_cell(&self.cur_cell);
+ self.mv_to_cell(&self.cur_cell, 0);
}
BGAction::None
}
KeyLeft => {
if 0 < self.cur_cell.x {
self.cur_cell.x -= 1;
- self.mv_to_cell(&self.cur_cell);
+ self.mv_to_cell(&self.cur_cell, 0);
}
BGAction::None
}
KeyRight => {
- let x: i32 = self.cur_cell.x as i32;
- if x + 1 < self.size {
+ if self.cur_cell.x + 1 < self.size {
self.cur_cell.x += 1;
- self.mv_to_cell(&self.cur_cell);
+ self.mv_to_cell(&self.cur_cell, 0);
}
BGAction::None
}
@@ -106,9 +162,56 @@ impl BoardGui {
}
}
- fn init(&self) {
- self.draw_grid();
- self.mv_to_cell(&self.cur_cell);
+ fn new(
+ ypos: i32,
+ xpos: i32,
+ size: u8,
+ cell_height: u8,
+ cell_width: u8,
+ hoff: u8,
+ has_colours: bool,
+ white_colour: u8,
+ black_colour: u8,
+ ) -> BoardGui {
+ let mut cell_windows: Vec<Window> = Vec::new();
+
+ let hoff = hoff as i32;
+ let s: i32 = size as i32;
+ let h: i32 = cell_height as i32;
+ let w: i32 = cell_width as i32;
+ for i in 0..s * s {
+ let y: i32 = i / s;
+ let x: i32 = i % s;
+ cell_windows.push(newwin(h - 1, w - 1, (s - y - 1) * h + 1, hoff + x * w + 1));
+ }
+
+ let bg = BoardGui {
+ win: newwin(h * s + 3, w * s + 3 + hoff, ypos, xpos),
+ cell_windows: cell_windows,
+ size: size,
+ cell_height: cell_height,
+ cell_width: cell_width,
+ hoff: hoff,
+ cur_cell: Position { x: 0, y: 0 },
+ has_colours: has_colours,
+ black_colour: black_colour,
+ white_colour: white_colour,
+ };
+
+ bg.draw_grid();
+
+ // for i in 0..s * s {
+ // let y: i32 = i / s;
+ // let x: i32 = i % s;
+ // let y = (s - y - 1) * h + 1;
+ // let x = hoff + x * w + 1;
+ // bg.cell_windows[i as usize].addstr(format!("{}:({},{})", i, y, x));
+ // bg.cell_windows[i as usize].refresh();
+ // }
+
+ bg.mv_to_cell(&bg.cur_cell, 0);
+ bg.win.refresh();
+ bg
}
}
@@ -118,9 +221,8 @@ struct MoveEntry {
impl MoveEntry {
fn init(&self) {
- self.win.attrset(COLOR_PAIR(3) | A_BOLD); // ???? how
- self.win.mvaddstr(0, 0, "Enter move: ashtsaht");
- // self.win.mvchgat(0,12,10,A_NORMAL,COLOR_PAIR(1));
+ self.win.mvaddstr(0, 0, "Enter move: ");
+ // Make shaded box for entry
self.win.refresh();
}
@@ -131,61 +233,66 @@ impl MoveEntry {
struct MessageLog {
win: Window,
+ has_colours: bool,
+ red_colour: u8,
}
impl MessageLog {
fn init(&self) {}
fn log_error(&self, str: String) {
+ if self.has_colours {
+ self.win.attrset(ColorPair(self.red_colour));
+ }
// self.win.clear();
self.win.addstr(str);
+ self.win.attrset(Attribute::Normal);
self.win.refresh();
}
}
fn main() {
let screen = initscr();
- screen.nodelay(true);
+ // screen.nodelay(true);
screen.keypad(true);
-
- if has_colors() {
- start_color();
- }
-
cbreak();
noecho();
-
curs_set(2);
+ let has_colours = has_colors();
+ let (black_colour, white_colour, red_colour): (u8, u8, u8) = (1, 2, 3);
+
+ if has_colours {
+ start_color();
+ use_default_colors();
+ init_pair(black_colour as i16, -1, COLOR_RED);
+ init_pair(white_colour as i16, -1, COLOR_BLUE);
+ init_pair(red_colour as i16, COLOR_RED, -1);
+ }
+
screen.refresh();
- let bgw = newwin(25, 40, 0, 0);
let mew = newwin(1, 30, 25, 0);
let mlw = newwin(3, 70, 26, 0);
- let mut bg = BoardGui {
- win: bgw,
- size: 5,
- cell_height: 4,
- cell_width: 7,
- hoff: 3,
- cur_cell: Position { x: 0, y: 0 },
- };
+ let mut bg = BoardGui::new(0, 0, 5, 4, 8, 3, has_colours, white_colour, black_colour);
let me = MoveEntry { win: mew };
- let ml = MessageLog { win: mlw };
+ let ml = MessageLog {
+ win: mlw,
+ has_colours: has_colours,
+ red_colour: red_colour,
+ };
- bg.init();
me.init();
ml.init();
- let board_option = Board::new(5, |s| MessageLog::log_error(&ml, s));
- if let Some(mut board) = board_option {
- let pos = Position { x: 0, y: 0 };
- board.perform_action(Action::Place(Player::White, pos, Stone::Flat));
- board.is_legal_action(&Action::Move(Player::White, pos, Direction::Up, vec![0, 1]));
- }
+ let (mut board, _) = Board::new(5, |s| MessageLog::log_error(&ml, s));
+ let pos = Position { x: 0, y: 0 };
+ board.perform_action(Action::Place(Player::White, pos, Stone::Flat));
+ board.is_legal_action(&Action::Move(Player::White, pos, Direction::Up, vec![0, 1]));
+ bg.draw_board(&board);
loop {
if let Some(inp) = screen.getch() {