Skip to content

Commit

Permalink
prerelease
Browse files Browse the repository at this point in the history
  • Loading branch information
ondras committed Apr 7, 2020
1 parent 77a2dcc commit 625614b
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 18 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
# rustymind

![CI](https://github.com/ondras/rustymind/workflows/CI/badge.svg)

This is a hobby project to learn Rust. It is an implementation of the *Mastermind* game, including a game-solving AI.

![screenshot](https://i.imgur.com/SXachN1.png)

## Running

```sh
$ git clone https://github.com/ondras/rustymind.git && cd rustymind
$ cargo run
```

With an explicit code length:

```sh
$ cargo run -- 5
```

Tests:

```sh
$ cargo test
```

## TODO

- [X] GH Actions to lint, test, and release
- [ ] the `--i-guess` option
5 changes: 0 additions & 5 deletions src/ai/defender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ impl crate::Defender for Defender {
Style::new().bold().paint("secret code"),
code
);
print!("======================");
for _ in 0..(3 * code.data.len()) {
print!("=");
}
println!();

Self { code }
}
Expand Down
39 changes: 39 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use std::env;

pub struct Config {
pub code_length: u8,
pub ai: bool,
}

impl Config {
pub fn parse() -> Result<Self, String> {
let mut code_length = 4;
let mut ai = true;
let mut args: Vec<String> = env::args().skip(1).collect();

let iguess_idx = args.iter().position(|x| x == "--i-guess");
if let Some(idx) = iguess_idx {
args.remove(idx);
ai = false;
}

if let Some(last) = args.pop() {
if let Ok(parsed) = last.parse::<u8>() {
let range = 2..6 + 1;
if range.contains(&parsed) {
code_length = parsed;
} else {
return Err(format!(
"Pick a value from {} to {} for code length",
range.start,
range.end - 1
));
}
} else {
return Err(format!("Cannot parse '{}' as a code length", last));
}
}

Ok(Self { code_length, ai })
}
}
41 changes: 28 additions & 13 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
mod ai;
mod config;
mod guess;
mod score;
mod util;

use config::Config;
use guess::Guess;
use score::Score;

Expand All @@ -21,7 +23,15 @@ trait Defender {
fn score(&self, attempt: &Guess) -> Score;
}

fn game(mut attacker: impl Attacker, defender: impl Defender) {
fn print_line(code_length: u8) {
let count = 22 + code_length * 3;
for _ in 0..count {
print!("=");
}
println!();
}

fn game(mut attacker: impl Attacker, defender: impl Defender) -> String {
let mut rounds = 0;
let mut previous: Option<History> = None;

Expand All @@ -36,28 +46,33 @@ fn game(mut attacker: impl Attacker, defender: impl Defender) {
);

let score = defender.score(&attempt);
println!("Round #{}\n {} | {}", rounds, score, attempt);
println!(
"Round #{} |\n {} | {}",
rounds, score, attempt
);

if score.is_won() {
println!("The code was found in {} rounds.", rounds);
break;
}

if rounds == 10 {
println!("Not found in {} rounds", rounds);
break;
return format!("The code was found in {} rounds.", rounds);
}

previous = Some((attempt, score));
} else {
println!("Code was not found");
break;
return "Code was not found".to_string();
}
}
}

fn main() {
let defender = ai::defender::Defender::new(4);
let config = Config::parse().unwrap_or_else(|e| {
println!("{}", e);
std::process::exit(1);
});

let defender = ai::defender::Defender::new(config.code_length);
let attacker = ai::attacker::Attacker::new(defender.code_length());
game(attacker, defender);

print_line(config.code_length);
let result = game(attacker, defender);
print_line(config.code_length);
println!("{}", result);
}

0 comments on commit 625614b

Please sign in to comment.