diff --git a/.gitignore b/.gitignore index ea8c4bf..d81f12e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +/.idea diff --git a/Cargo.lock b/Cargo.lock index a483ee8..cc86c5c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,47 +3,17 @@ version = 4 [[package]] -name = "byteorder" -version = "1.5.0" +name = "fastrand" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "color-print" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3aa954171903797d5623e047d9ab69d91b493657917bdfb8c2c80ecaf9cdb6f4" -dependencies = [ - "color-print-proc-macro", -] - -[[package]] -name = "color-print-proc-macro" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692186b5ebe54007e45a59aea47ece9eb4108e141326c304cdc91699a7118a22" -dependencies = [ - "nom", - "proc-macro2", - "quote", - "syn", -] +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fiars" version = "0.1.0" dependencies = [ - "color-print", + "fastrand", "getch", - "lazy_static", - "rand", - "strum", ] [[package]] @@ -56,153 +26,12 @@ dependencies = [ "termios", ] -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - [[package]] name = "libc" version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "proc-macro2" -version = "1.0.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rustversion" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" - -[[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn", -] - -[[package]] -name = "syn" -version = "2.0.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "termios" version = "0.3.3" @@ -211,36 +40,3 @@ checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b" dependencies = [ "libc", ] - -[[package]] -name = "unicode-ident" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/Cargo.toml b/Cargo.toml index 8e2afe5..195f433 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,11 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -color-print = "0.3.7" -getch = "0.3.1" -lazy_static = "1.5.0" -rand = "0.8.5" -strum = { version = "0.26.3", features = ["derive"] } +getch = "0.3" +fastrand = "2.3" [profile.release] opt-level = 3 diff --git a/src/bot.rs b/src/bot.rs index 182b068..67adc72 100644 --- a/src/bot.rs +++ b/src/bot.rs @@ -1,5 +1,4 @@ use crate::{game, Board, BotDifficulty, CellState, WIDTH}; -use rand::prelude::*; pub(crate) fn bot_move(board: &mut Board, difficulty: &BotDifficulty) -> usize { let best_move = get_best_move(&board, &difficulty); @@ -39,16 +38,17 @@ fn get_best_move(board: &Board, difficulty: &BotDifficulty) -> usize { return scores[0].0; }; - let mut rng = rand::thread_rng(); let length = scores.len(); match difficulty { - BotDifficulty::Easy => scores[rng.gen_range(0..length)].0, + BotDifficulty::Easy => scores[fastrand::usize(0..length)].0, BotDifficulty::Normal => { - scores[rng.gen_range(0..(length.saturating_sub(length / 2).max(1)))].0 + let number = fastrand::usize(0..(length.saturating_sub(length / 2).max(1))); + scores[number].0 } BotDifficulty::Difficult => { - scores[rng.gen_range(0..(length.saturating_sub(length / 4).max(1)))].0 + let number = fastrand::usize(0..(length.saturating_sub(length / 4).max(1))); + scores[number].0 } BotDifficulty::Expert => scores[0].0, BotDifficulty::Off => unreachable!(), diff --git a/src/game.rs b/src/game.rs index 5a7501d..df59a4b 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,5 +1,3 @@ -use color_print::cprintln; - use crate::{ bot, tui, Board, BotDifficulty, CellState, Command, GameOver, DIRECTIONS, I_HEIGHT, I_WIDTH, SIZE, WIDTH, @@ -16,8 +14,7 @@ pub fn start_game() { match tui::get_command() { Command::Quit => break, Command::Bot => { - bot_difficulty = - BotDifficulty::from_repr(bot_difficulty as u8 + 1).unwrap_or_default() + bot_difficulty = change_difficulty(bot_difficulty) } Command::Reset => reset_game(&mut board, &mut turn), Command::Move(row) => match make_move(&mut board, turn, row) { @@ -57,7 +54,7 @@ pub fn start_game() { }; } Err(message) => { - cprintln!("{}", message); + println!("\x1b[31m{}\x1b[0m", message); println!("Press any key to continue..."); tui::pause(); } @@ -66,6 +63,16 @@ pub fn start_game() { } } +fn change_difficulty(bot_difficulty: BotDifficulty) -> BotDifficulty { + match bot_difficulty { + BotDifficulty::Off => BotDifficulty::Easy, + BotDifficulty::Easy => BotDifficulty::Normal, + BotDifficulty::Normal => BotDifficulty::Difficult, + BotDifficulty::Difficult => BotDifficulty::Expert, + BotDifficulty::Expert => BotDifficulty::Off + } +} + fn transform_to_index(row: usize, column: usize) -> usize { column * WIDTH + row } diff --git a/src/lib.rs b/src/lib.rs index 570feb5..b09a431 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ -use color_print::cstr; -use std::fmt::Display; +use std::fmt; +use std::fmt::{Display, Formatter}; pub(crate) mod bot; pub mod game; @@ -40,22 +40,33 @@ pub(crate) enum Command { Move(usize), } -#[derive(Default, PartialEq, Eq, strum::AsRefStr, strum::FromRepr)] +#[derive(Default, PartialEq, Eq)] #[repr(u8)] pub(crate) enum BotDifficulty { - #[strum(serialize = "off")] #[default] Off = 0, - #[strum(serialize = "easy")] Easy = 1, - #[strum(serialize = "normal")] Normal = 2, - #[strum(serialize = "difficult")] Difficult = 3, - #[strum(serialize = "expert")] Expert = 4, } +impl Display for BotDifficulty { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!( + f, + "{}", + match self { + BotDifficulty::Off => "off", + BotDifficulty::Easy => "easy", + BotDifficulty::Normal => "normal", + BotDifficulty::Difficult => "difficult", + BotDifficulty::Expert => "expert" + } + ) + } +} + impl Display for CellState { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( @@ -63,8 +74,8 @@ impl Display for CellState { "{}", match self { CellState::Empty => " ", - CellState::PlayerOne => cstr!("X"), - CellState::PlayerTwo => cstr!("O"), + CellState::PlayerOne => "\x1b[32mX\x1b[0m", + CellState::PlayerTwo => "\x1b[31mO\x1b[0m", } ) } diff --git a/src/tui.rs b/src/tui.rs index ce67b53..941c1b1 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -1,14 +1,9 @@ use crate::{Board, BotDifficulty, Command, WIDTH}; -use color_print::cprintln; use getch::Getch; -lazy_static::lazy_static! { - static ref GETCH: Getch = Getch::new(); -} - pub(crate) fn get_command() -> Command { loop { - let input = GETCH.getch().unwrap(); + let input = read_key(); match input.to_ascii_lowercase() { b'q' => return Command::Quit, b'b' => return Command::Bot, @@ -20,13 +15,17 @@ pub(crate) fn get_command() -> Command { } pub(crate) fn confirm() -> bool { - let input = GETCH.getch().unwrap(); + let input = read_key(); match input.to_ascii_lowercase() { b'n' => return false, _ => return true, } } +fn read_key() -> u8 { + Getch::new().getch().unwrap() +} + fn clear_ui() { // clear screen and place cursor on 1,1 print!("\x1B[2J\x1B[1;1H"); @@ -53,12 +52,12 @@ pub(crate) fn print_ui(board: &Board, bot: &BotDifficulty) { println!(); println!("{}", "=".repeat(WIDTH * 2 + 1)); - cprintln!( - "quit reset bot={}", - bot.as_ref() + println!( + "\x1b[1;31mq\x1b[0muit \x1b[1;32mr\x1b[0meset \x1b[1;34mb\x1b[0mot={}", + bot ); } pub(crate) fn pause() { - GETCH.getch().ok(); + Getch::new().getch().ok(); }