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