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.
gammon/src/main.rs

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)
}