Skip to content

Commit

Permalink
Addition of forts for each turn (#5)
Browse files Browse the repository at this point in the history
* Addition of forts for each turn

* Addition of forts for each turn

* Addition of forts for each turn

* Addition of forts for each turn

* Addition of forts for each turn

* Addition of forts for each turn

* Addition of death due to starvation
  • Loading branch information
quantifex authored Jul 25, 2021
1 parent a0fb987 commit 8d2146a
Show file tree
Hide file tree
Showing 13 changed files with 560 additions and 146 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
uses: actions/checkout@v2
- name: Unit test
id: unit_test
uses: quantifex/rust_oregontrail_1978@v1
uses: quantifex/rust_oregontrail_1978@b1f654613c5e17b3c72a402ee32e15183b3082af
- name: Archive code coverage
uses: actions/upload-artifact@v2
with:
Expand Down
7 changes: 1 addition & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
FROM rust:1.53

RUN apt-get update && apt-get install -y jq
RUN cargo install grcov
RUN rustup component add llvm-tools-preview
RUN rustup toolchain install nightly
FROM quantifex/rust_devtest:1_53

CMD ["/bin/bash"]
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ graph TD
Turn ---->|Traveled > 40 Weeks| Death[You have died];
Turn -->|Need Food| Hunt[Hunt];
Turn -->|Stop at a Fort| Fort[Fort];
Turn -->|Stop at a Fort| Fort[Fort<br>Buy Supplies<br>Buying 33% more expensive];
Turn --> E[Eat];
E -->|Travel| R[Riders Ahead];
R --> Turn;
Expand Down
167 changes: 167 additions & 0 deletions src/ask.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
use std::io::{Cursor, Write, BufRead, Seek, SeekFrom};
use crate::marksman::*;

#[derive(PartialEq)]
#[derive(Debug)]
pub enum TurnAction {
Fort,
Hunt,
Continue,
}

#[macro_export]
macro_rules! ask {
Expand All @@ -18,6 +27,25 @@ macro_rules! ask {
};
}

/// Ask the user to answer a Yes/No question (default to Yes)
#[macro_export]
macro_rules! ask_yn {
( $question: expr, $out: expr, $input: expr ) => {
{
$out.write($question.as_bytes()).unwrap();
$out.flush().unwrap();

let mut buffer = String::new();
$input.read_line(&mut buffer).unwrap();
buffer.retain(|buffer| !buffer.is_whitespace());
match buffer.chars().next().unwrap() {
'n' => false,
_ => true,
}
}
};
}

#[macro_export]
macro_rules! ask_ok {
( $ask: expr ) => {
Expand All @@ -32,6 +60,42 @@ macro_rules! ask_ok {
};
}

pub fn ask_marksman<W: Write, R: BufRead>(out: &mut W, input: &mut R) -> MarksmanQuality {
loop {
let marksman = MarksmanQuality::from_u32(ask!(include_str!("../strings/ask_marksman.txt"), out, input));
if marksman != MarksmanQuality::Unknown { return marksman; }
}
}

pub fn ask_continue<W: Write, R: BufRead>(out: &mut W, input: &mut R) -> TurnAction {
loop {
let action = ask!("Do you want to 1) Continue? ", out, input);
if action == 1 { return TurnAction::Continue; }
}
}

pub fn ask_hunt_continue<W: Write, R: BufRead>(out: &mut W, input: &mut R) -> TurnAction {
loop {
let action = ask!("Do you want to 1) Hunt or 2) Continue? ", out, input);
match action {
1 => return TurnAction::Hunt,
2 => return TurnAction::Continue,
_ => continue,
}
}
}

pub fn ask_fort_hunt_continue<W: Write, R: BufRead>(out: &mut W, input: &mut R) -> TurnAction {
loop {
let action = ask!("Do you want to 1) Stop at a Fort, 2) Hunt or 3) Continue? ", out, input);
match action {
1 => return TurnAction::Fort,
2 => return TurnAction::Hunt,
3 => return TurnAction::Continue,
_ => continue,
}
}
}

#[test]
fn test_ask_value_1() {
Expand Down Expand Up @@ -67,6 +131,39 @@ fn test_ask_value_999_with_return() {
assert_eq!(999, value);
}

#[test]
fn test_ask_yn_value_y() {
let mut cout = Cursor::new(Vec::new());
let mut cin = Cursor::new(Vec::new());
cin.write(b"y").unwrap();
cin.seek(SeekFrom::Start(0)).unwrap();
// Assert
let value = ask_yn!("test? ", cout, cin);
assert_eq!(true, value);
}

#[test]
fn test_ask_yn_value_n() {
let mut cout = Cursor::new(Vec::new());
let mut cin = Cursor::new(Vec::new());
cin.write(b"n").unwrap();
cin.seek(SeekFrom::Start(0)).unwrap();
// Assert
let value = ask_yn!("test? ", cout, cin);
assert_eq!(false, value);
}

#[test]
fn test_ask_yn_value_test() {
let mut cout = Cursor::new(Vec::new());
let mut cin = Cursor::new(Vec::new());
cin.write(b"test").unwrap();
cin.seek(SeekFrom::Start(0)).unwrap();
// Assert
let value = ask_yn!("test? ", cout, cin);
assert_eq!(true, value);
}

#[test]
fn test_ask_ok_success() {
let mut okay_result: bool = false;
Expand All @@ -78,3 +175,73 @@ fn test_ask_ok_success() {
ask_ok!(func());
assert!(okay_result);
}

#[test]
fn test_ask_marksman() {
let mut cout = Cursor::new(Vec::new());
let mut cin = Cursor::new(Vec::new());
cin.write(b"1").unwrap();
cin.seek(SeekFrom::Start(0)).unwrap();
let action = ask_marksman(&mut cout, &mut cin);
assert_eq!(MarksmanQuality::Ace, action);
}

#[test]
fn test_ask_continue() {
let mut cout = Cursor::new(Vec::new());
let mut cin = Cursor::new(Vec::new());
cin.write(b"1").unwrap();
cin.seek(SeekFrom::Start(0)).unwrap();
let action = ask_continue(&mut cout, &mut cin);
assert_eq!(TurnAction::Continue, action);
}

#[test]
fn test_ask_hunt_continue_hunt() {
let mut cout = Cursor::new(Vec::new());
let mut cin = Cursor::new(Vec::new());
cin.write(b"1").unwrap();
cin.seek(SeekFrom::Start(0)).unwrap();
let action = ask_hunt_continue(&mut cout, &mut cin);
assert_eq!(TurnAction::Hunt, action);
}

#[test]
fn test_ask_hunt_continue_continue() {
let mut cout = Cursor::new(Vec::new());
let mut cin = Cursor::new(Vec::new());
cin.write(b"2").unwrap();
cin.seek(SeekFrom::Start(0)).unwrap();
let action = ask_hunt_continue(&mut cout, &mut cin);
assert_eq!(TurnAction::Continue, action);
}

#[test]
fn test_ask_fort_hunt_continue_fort() {
let mut cout = Cursor::new(Vec::new());
let mut cin = Cursor::new(Vec::new());
cin.write(b"1").unwrap();
cin.seek(SeekFrom::Start(0)).unwrap();
let action = ask_fort_hunt_continue(&mut cout, &mut cin);
assert_eq!(TurnAction::Fort, action);
}

#[test]
fn test_ask_fort_hunt_continue_hunt() {
let mut cout = Cursor::new(Vec::new());
let mut cin = Cursor::new(Vec::new());
cin.write(b"2").unwrap();
cin.seek(SeekFrom::Start(0)).unwrap();
let action = ask_fort_hunt_continue(&mut cout, &mut cin);
assert_eq!(TurnAction::Hunt, action);
}

#[test]
fn test_ask_fort_hunt_continue_continue() {
let mut cout = Cursor::new(Vec::new());
let mut cin = Cursor::new(Vec::new());
cin.write(b"3").unwrap();
cin.seek(SeekFrom::Start(0)).unwrap();
let action = ask_fort_hunt_continue(&mut cout, &mut cin);
assert_eq!(TurnAction::Continue, action);
}
29 changes: 1 addition & 28 deletions src/banner.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,12 @@
use std::str;
use std::io::{Cursor, Read, Seek, SeekFrom};
use crate::*;
use std::io::{Cursor, Write, Read, Seek, SeekFrom};

pub fn print_banner<W: Write>(out: &mut W) {
let banner = include_str!("../strings/banner.txt");
out.write(banner.as_bytes()).unwrap();
out.flush().unwrap();
}

pub fn complete_trip<W: Write>(out: &mut W, supplies: &mut Supplies) {
let prefix = include_str!("../strings/complete_prefix.txt");
let suffix = include_str!("../strings/complete_suffix.txt");
let supplies_status = format!("Supplies left:\n{}\n", supplies);
out.write(prefix.as_bytes()).unwrap();
out.write(supplies_status.as_bytes()).unwrap();
out.write(suffix.as_bytes()).unwrap();
out.flush().unwrap();
}

#[test]
fn test_banner() {
let banner = include_str!("../strings/banner.txt");
Expand All @@ -30,19 +19,3 @@ fn test_banner() {

assert_eq!(banner, str::from_utf8(&banner_out).unwrap());
}

#[test]
fn test_complete_trip() {
let mut supplies = Supplies::new();
let prefix = include_str!("../strings/complete_prefix.txt");
let suffix = include_str!("../strings/complete_suffix.txt");
let trip_message = format!("{}Supplies left:\n{}\n{}", prefix, supplies, suffix);
let mut c = Cursor::new(Vec::new());

complete_trip(&mut c, &mut supplies);
c.seek(SeekFrom::Start(0)).unwrap();
let mut trip_out = Vec::new();
c.read_to_end(&mut trip_out).unwrap();

assert_eq!(trip_message, str::from_utf8(&trip_out).unwrap());
}
90 changes: 90 additions & 0 deletions src/finish.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use std::str;
use std::io::{Cursor, Read, Seek, SeekFrom};
use crate::*;

const ASK_FINISH_MINISTER: &str = "Would you like a minister (y/n)? ";
const ASK_FINISH_FUNERAL: &str = "Would you like a fancy funeral (y/n)? ";
const ASK_FINISH_NOTIFY_KIN: &str = "Would you like to inform your next of kin (y/n)? ";

const NOTIFY_TELEGRAPH_CHARGE: &str = "That will be $4.50 for the telegraph charge.\n\n";
const NOTIFY_SADIE_WORRIED: &str = "Your Aunt Sadie in St. Louis is really worried about you...\n\n";

pub fn complete_trip<W: Write>(out: &mut W, supplies: &mut Supplies) {
let prefix = include_str!("../strings/complete_prefix.txt");
let suffix = include_str!("../strings/complete_suffix.txt");
let supplies_status = format!("Supplies left:\n{}\n", supplies);
out.write(prefix.as_bytes()).unwrap();
out.write(supplies_status.as_bytes()).unwrap();
out.write(suffix.as_bytes()).unwrap();
out.flush().unwrap();
}

pub fn handle_death<W: Write, R: BufRead>(out: &mut W, input: &mut R) {
out.write(include_str!("../strings/death_prefix.txt").as_bytes()).unwrap();
let _ = ask_yn!(ASK_FINISH_MINISTER, out, input);
let _ = ask_yn!(ASK_FINISH_FUNERAL, out, input);
let notify_sadie = ask_yn!(ASK_FINISH_NOTIFY_KIN, out, input);

if notify_sadie {
out.write(NOTIFY_TELEGRAPH_CHARGE.as_bytes()).unwrap();
} else {
out.write(NOTIFY_SADIE_WORRIED.as_bytes()).unwrap();
}
out.write(include_str!("../strings/death_suffix.txt").as_bytes()).unwrap();
}

#[test]
fn test_complete_trip() {
let mut supplies = Supplies::new();
let prefix = include_str!("../strings/complete_prefix.txt");
let suffix = include_str!("../strings/complete_suffix.txt");
let trip_message = format!("{}Supplies left:\n{}\n{}", prefix, supplies, suffix);
let mut c = Cursor::new(Vec::new());

complete_trip(&mut c, &mut supplies);
c.seek(SeekFrom::Start(0)).unwrap();
let mut trip_out = Vec::new();
c.read_to_end(&mut trip_out).unwrap();

assert_eq!(trip_message, str::from_utf8(&trip_out).unwrap());
}

#[test]
fn test_handle_death_notify() {
let prefix = include_str!("../strings/death_prefix.txt");
let suffix = include_str!("../strings/death_suffix.txt");
let trip_message = format!("{}{}{}{}{}{}",
prefix, ASK_FINISH_MINISTER, ASK_FINISH_FUNERAL, ASK_FINISH_NOTIFY_KIN, NOTIFY_TELEGRAPH_CHARGE, suffix);

let mut cout = Cursor::new(Vec::new());
let mut cin = Cursor::new(Vec::new());
cin.write(b"y\r\ny\r\ny").unwrap();
cin.seek(SeekFrom::Start(0)).unwrap();
// Assert
handle_death(&mut cout, &mut cin);
cout.seek(SeekFrom::Start(0)).unwrap();
let mut trip_out = Vec::new();
cout.read_to_end(&mut trip_out).unwrap();

assert_eq!(trip_message, str::from_utf8(&trip_out).unwrap());
}

#[test]
fn test_handle_death_no_notify() {
let prefix = include_str!("../strings/death_prefix.txt");
let suffix = include_str!("../strings/death_suffix.txt");
let trip_message = format!("{}{}{}{}{}{}",
prefix, ASK_FINISH_MINISTER, ASK_FINISH_FUNERAL, ASK_FINISH_NOTIFY_KIN, NOTIFY_SADIE_WORRIED, suffix);

let mut cout = Cursor::new(Vec::new());
let mut cin = Cursor::new(Vec::new());
cin.write(b"y\r\ny\r\nn").unwrap();
cin.seek(SeekFrom::Start(0)).unwrap();
// Assert
handle_death(&mut cout, &mut cin);
cout.seek(SeekFrom::Start(0)).unwrap();
let mut trip_out = Vec::new();
cout.read_to_end(&mut trip_out).unwrap();

assert_eq!(trip_message, str::from_utf8(&trip_out).unwrap());
}
Loading

0 comments on commit 8d2146a

Please sign in to comment.