You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
4.6 KiB
157 lines
4.6 KiB
use crate::game::{Move, Color, Roll};
|
|
use rustyline::error::ReadlineError;
|
|
use failure::{Fallible, format_err};
|
|
|
|
mod game;
|
|
|
|
fn main() {
|
|
let mut game = game::State::start(None);
|
|
|
|
let mut rl = rustyline::Editor::<()>::new();
|
|
|
|
let mut retry = false;
|
|
let mut filled = String::new();
|
|
'input: loop {
|
|
if !retry {
|
|
filled.clear();
|
|
}
|
|
|
|
println!("BOARD:\n{}", game);
|
|
|
|
let (sn, color) = game.turn();
|
|
let cmd = rl.readline_with_initial(&format!("{}> ", color), (&filled, ""));
|
|
retry = false;
|
|
match cmd {
|
|
Ok(line) => {
|
|
filled = line;
|
|
|
|
let line = filled.trim();
|
|
if line.is_empty() {
|
|
retry = true;
|
|
continue 'input;
|
|
}
|
|
|
|
match parse_input(line) {
|
|
Ok(moves) => {
|
|
println!("{:?}", moves);
|
|
let mut next = game.clone();
|
|
for m in moves {
|
|
match next.apply_move(color, m) {
|
|
Ok(n) => {
|
|
next = n;
|
|
println!("{}", next);
|
|
}
|
|
Err(e) => {
|
|
println!("Move failed: {:?}", e);
|
|
retry = true;
|
|
continue 'input;
|
|
}
|
|
}
|
|
}
|
|
if next.turn().0 != sn {
|
|
game = next;
|
|
} else {
|
|
println!("Move NOT complete, reverting.");
|
|
retry = true;
|
|
}
|
|
},
|
|
Err(e) => {
|
|
println!("Parsing failed: {}", e);
|
|
retry = true;
|
|
continue 'input;
|
|
},
|
|
}
|
|
},
|
|
// Err(ReadlineError::Interrupted) => {
|
|
// // just clear the line and retry
|
|
// retry = true;
|
|
// continue 'input;
|
|
// }
|
|
Err(_) => {
|
|
break 'input;
|
|
},
|
|
}
|
|
}
|
|
|
|
// let g = g.spoof_roll(Roll::from_dice((3, 5)));
|
|
//
|
|
// println!("{}", g);
|
|
//
|
|
// let g = g.apply_move(Color::Black, Move::InBoard { from: 0, to: 3 }).unwrap();
|
|
// let g = g.apply_move(Color::Black, Move::InBoard { from: 11, to: 16 }).unwrap();
|
|
//
|
|
// // White turn
|
|
// let g = g.spoof_roll(Roll::from_dice((4, 6)));
|
|
// println!("{}", g);
|
|
//
|
|
// let g = g.apply_move(Color::White, Move::InBoard { from: 23, to: 17 }).unwrap();
|
|
// let g = g.apply_move(Color::White, Move::InBoard { from: 7, to: 3 }).unwrap();
|
|
//
|
|
// // Black turn, need to place the hit stone
|
|
// let g = g.spoof_roll(Roll::from_dice((1, 2)));
|
|
// println!("{}", g);
|
|
//
|
|
// let g = g.apply_move(Color::Black, Move::Enter(1)).unwrap();
|
|
//
|
|
// let g = g.apply_move(Color::Black, Move::InBoard { from: 3, to: 4 }).unwrap();
|
|
//
|
|
// println!("{}", g);
|
|
}
|
|
|
|
|
|
fn parse_input(line : &str) -> Fallible<Vec<Move>> {
|
|
let line = line.trim();
|
|
|
|
let mut moves = vec![];
|
|
let fragments = line.split(',');
|
|
|
|
// let mut moves = vec![];
|
|
for f in fragments {
|
|
if !f.contains('/') {
|
|
return Err(format_err!("Bad syntax: \"{}\"", f));
|
|
}
|
|
|
|
let halves : Vec<&str> = f.split('/').collect();
|
|
|
|
if halves[0].is_empty() && halves[1].is_empty() {
|
|
return Err(format_err!("Bad syntax: \"{}\"", f));
|
|
}
|
|
|
|
if halves[0].is_empty() {
|
|
let to : u8 = halves[1].parse()?;
|
|
|
|
if to == 0 || to > 24 {
|
|
return Err(format_err!("Out of range: {}", to));
|
|
}
|
|
|
|
moves.push(Move::Enter(to - 1));
|
|
continue;
|
|
}
|
|
|
|
if halves[1].is_empty() {
|
|
let to : u8 = halves[0].parse()?;
|
|
|
|
if to == 0 || to > 24 {
|
|
return Err(format_err!("Out of range: {}", to));
|
|
}
|
|
|
|
moves.push(Move::BearOff(to - 1));
|
|
continue;
|
|
}
|
|
|
|
let from : u8 = halves[0].parse()?;
|
|
let to : u8 = halves[1].parse()?;
|
|
|
|
if from == 0 || from > 24 {
|
|
return Err(format_err!("Out of range: {}", to));
|
|
}
|
|
|
|
if to == 0 || to > 24 {
|
|
return Err(format_err!("Out of range: {}", to));
|
|
}
|
|
|
|
moves.push(Move::InBoard(from - 1, to - 1));
|
|
}
|
|
|
|
Ok(moves)
|
|
}
|
|
|