From 7d83efe953c84cc5b0b52eaf2f836369c1a07409 Mon Sep 17 00:00:00 2001 From: dece Date: Mon, 1 Jun 2020 00:43:05 +0200 Subject: [PATCH] cli: basic games over the command-line --- Cargo.lock | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 + src/board.rs | 3 +- src/cli.rs | 66 +++++++++++++++++++ src/game.rs | 2 + src/main.rs | 38 ++++++++++- src/rules.rs | 7 +- 7 files changed, 294 insertions(+), 4 deletions(-) create mode 100644 src/cli.rs create mode 100644 src/game.rs diff --git a/Cargo.lock b/Cargo.lock index 7a58565..243d1fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,186 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hermit-abi 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clap" +version = "2.33.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "getrandom" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hermit-abi" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.71" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ppv-lite86" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vatu" version = "0.1.0" +dependencies = [ + "clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", +] +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129" +"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +"checksum hermit-abi 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71" +"checksum libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)" = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" +"checksum ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" +"checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +"checksum rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" +"checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index c5100cb..c22b3a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,3 +5,5 @@ authors = ["dece "] edition = "2018" [dependencies] +clap = "2.33" +rand = "0.7" diff --git a/src/board.rs b/src/board.rs index 323a1ec..351e987 100644 --- a/src/board.rs +++ b/src/board.rs @@ -168,8 +168,9 @@ pub fn draw(board: &Board) { let piece = if is_color(s, SQ_WH) { piece.to_ascii_uppercase() } else { piece }; rank.push(piece); } - println!("{}", rank); + println!("{} {}", r + 1, rank); } + println!(" abcdefgh"); } #[cfg(test)] diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..667ce17 --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,66 @@ +//! Functions to play games over the command-line. + +use std::io::{self, Write}; + +use rand::seq::IteratorRandom; + +use crate::board; +use crate::rules; + +pub fn start_game(player_color: u8) { + println!("Starting new game."); + println!("Player is {}.", if player_color == board::SQ_WH { "white" } else { "black" }); + println!(""); + let ai_color = board::opposite(player_color); + let mut rng = rand::thread_rng(); + let mut b = board::new(); + let mut turn = board::SQ_WH; + loop { + board::draw(&b); + println!(""); + let m = if turn == player_color { + println!("Player turn."); + let legal_moves = rules::get_player_legal_moves(&b, player_color); + let mut m; + loop { + m = get_player_move(); + if legal_moves.contains(&m) { + break + } else { + println!("Illegal move."); + } + } + m + } else { + println!("Computer turn."); + let moves = rules::get_player_legal_moves(&b, ai_color); + *moves.iter().choose(&mut rng).unwrap() + }; + println!("Move: {:?}", m); + board::apply_into(&mut b, &m); + println!(""); + turn = board::opposite(turn); + } +} + +fn get_player_move() -> board::Move { + loop { + let from = if let Some(s) = get_input("From: ") { board::pos(&s) } else { continue }; + let to = if let Some(s) = get_input("To: ") { board::pos(&s) } else { continue }; + if board::is_valid_pos(from) && board::is_valid_pos(to) { + return (from, to) + } + println!("Bad input."); + } + +} + +fn get_input(message: &str) -> Option { + print!("{}", message); + io::stdout().flush().unwrap(); + let mut input = String::new(); + if io::stdin().read_line(&mut input).is_err() { + return None + } + Some(input) +} diff --git a/src/game.rs b/src/game.rs new file mode 100644 index 0000000..cde4fa0 --- /dev/null +++ b/src/game.rs @@ -0,0 +1,2 @@ +//! Function to actually play games. + diff --git a/src/main.rs b/src/main.rs index 5245eac..7b2d237 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,41 @@ +use std::process; + +use clap::{App, AppSettings, Arg, ArgMatches, SubCommand}; + pub mod board; +pub mod cli; pub mod rules; fn main() { - let b = board::new(); - board::draw(&b); + let matches = App::new("Vatu") + .setting(AppSettings::ArgRequiredElseHelp) + .subcommand(SubCommand::with_name("cli") + .about("Start a game in command-line") + .arg(Arg::with_name("color") + .help("Color for the player") + .short("c").long("color").takes_value(true).required(false) + .possible_values(&["w", "white", "b", "black"]))) + .get_matches(); + + process::exit(match matches.subcommand() { + ("cli", Some(a)) => cmd_cli(a), + _ => 0, + }) +} + +fn cmd_cli(args: &ArgMatches) -> i32 { + let color = if let Some(c) = args.value_of("color") { + match c { + s if ["w", "white"].contains(&s) => board::SQ_WH, + s if ["b", "black"].contains(&s) => board::SQ_BL, + _ => { eprintln!("Choose white or black as color."); return 1 } + } + } else if rand::random() { + board::SQ_WH + } else { + board::SQ_BL + }; + + cli::start_game(color); + 0 } diff --git a/src/rules.rs b/src/rules.rs index 54a5767..a77fe12 100644 --- a/src/rules.rs +++ b/src/rules.rs @@ -2,7 +2,12 @@ use crate::board::*; -/// Get a list of moves for all pieces of either white or black. +/// Get a list of legal moves for all pieces of this color. +pub fn get_player_legal_moves(board: &Board, color: u8) -> Vec { + filter_illegal_moves(board, color, get_player_moves(board, color)) +} + +/// Get a list of moves for all pieces of this color. pub fn get_player_moves(board: &Board, color: u8) -> Vec { let mut moves = vec!(); for r in 0..8 {