Skip to content

Commit

Permalink
impl name guessing for dropping items; mod stats
Browse files Browse the repository at this point in the history
  • Loading branch information
Zaechus committed Sep 30, 2019
1 parent b1806f2 commit 2a8d2db
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 92 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "kingslayer"
version = "0.4.1"
version = "0.4.2"
authors = ["Maxwell Anderson <[email protected]>"]
edition = "2018"
license = "MIT"
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![Build status](https://ci.appveyor.com/api/projects/status/b5p7b1efiy9t0fm7/branch/master?svg=true)](https://ci.appveyor.com/project/Maxgy/kingslayer/branch/master)
[![Current Crates.io Version](https://img.shields.io/crates/v/kingslayer)](https://crates.io/crates/kingslayer)

Kingslayer is a text adventure dungeon crawler game written in Rust. It is a rewrite and continuation of [thekinggame](https://github.com/Maxgy/thekinggame).
Kingslayer is a text-based dungeon crawler written in Rust. It is a rewrite and continuation of [thekinggame](https://github.com/Maxgy/thekinggame).

You can find the WASM package at [github.com/Maxgy/kingslayer-wasm](https://github.com/Maxgy/kingslayer-wasm)

Expand All @@ -19,7 +19,7 @@ $ cargo run --release

### Creating and Running your own World

Worlds are defined with JSON. An example can be found on the [wiki](https://github.com/Maxgy/kingslayer/wiki/Example-world-JSON-file). Deploying the world to the command line looks like this:
Worlds are defined with JSON. An example can be found on the [wiki](https://github.com/Maxgy/kingslayer/wiki/). Deploying the world to the command line looks like this:
```rust
use kingslayer::Cli;

Expand Down
30 changes: 1 addition & 29 deletions data/test_world.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,35 +96,7 @@
"inspection": "The path expands into a larger room."
}
},
"enemies": {
"ogre": {
"hp": 7,
"xp": 15,
"damage": 4,
"name": "ogre",
"desc": "The ogre stands there menacingly with a club.",
"inspection": "The ogre is holding a long club made of wood. He is wearing nothing but a loincloth and a leather jerkin.",
"is_angry": false,
"loot": {
"club": {
"name": "club",
"desc": "There is a club on the ground.",
"inspection": "The club is very thick and heavy.",
"damage": 4
}
}
},
"goblin": {
"hp": 5,
"xp": 10,
"damage": 2,
"name": "goblin",
"desc": "The goblin cowers in a corner holding a knife.",
"inspection": "The goblin is small, grey-green, and skinny. He is brandishing a knife.",
"is_angry": false,
"loot": {}
}
},
"enemies": {},
"allies": {},
"items": {}
},
Expand Down
4 changes: 2 additions & 2 deletions data/world.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
},
"enemies": {
"ogre": {
"hp": 7,
"hp": 10,
"xp": 15,
"damage": 4,
"name": "ogre",
Expand All @@ -115,7 +115,7 @@
}
},
"goblin": {
"hp": 5,
"hp": 7,
"xp": 10,
"damage": 2,
"name": "goblin",
Expand Down
3 changes: 0 additions & 3 deletions justfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
run:
cargo run --release

build:
cargo build

test:
cargo clippy
cargo bench
Expand Down
2 changes: 1 addition & 1 deletion src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Some available commands:
Manage your character
heal replenish some HP
increase increase a chosen ability score by 1 if stat points are available
status display information on the state of your character"
c | stats display information on the state of your character"
.to_owned(),
)
}
Expand Down
7 changes: 1 addition & 6 deletions src/input/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,6 @@ impl Parser {
}
}

fn parse_stats(player: &mut Player) -> CmdResult {
player.stats()
}

fn parse_take(words: CmdTokens, world: &mut World, player: &mut Player) -> CmdResult {
if words.num_words() > 1 {
if words.prep() == "from" || words.prep() == "out" || words.prep() == "in" {
Expand Down Expand Up @@ -196,7 +192,7 @@ impl Parser {
Parser::parse_attack(words, world, player)
}
"close" => Parser::parse_close(words, player, world),
"diagno" | "status" => player.status(),
"c" | "stats" => player.info(),
"don" => Parser::parse_don(words, player),
"draw" | "equip" | "hold" | "use" => Parser::parse_equip(words, player),
"drop" | "remove" | "throw" => Parser::parse_drop(words, world, player),
Expand All @@ -211,7 +207,6 @@ impl Parser {
"l" | "look" => world.look(),
"open" => Parser::parse_open(words, world, player),
"insert" | "place" | "put" => Parser::parse_put(words, world, player),
"stats" => Parser::parse_stats(player),
"wait" | "z" => Player::wait(),
_ => CmdResult::new(
false,
Expand Down
101 changes: 74 additions & 27 deletions src/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ impl Player {
fn ac(&self) -> u32 {
if let Some(armor) = &self.armor {
if let Some(ac) = armor.armor_class() {
ac + self.stats.dex
ac + ((self.stats.dex - 10) as f64 / 2.0).floor() as u32
} else {
10 + self.stats.dex
10 + ((self.stats.dex - 10) as f64 / 2.0).floor() as u32
}
} else {
10 + self.stats.dex
Expand Down Expand Up @@ -86,7 +86,7 @@ impl Player {
}

fn deal_damage(&self, weapon_damage: u32) -> u32 {
weapon_damage + self.stats.strngth
weapon_damage + ((self.stats.strngth - 10) as f64 / 2.0).floor() as u32
}

pub fn disengage_combat(&mut self) {
Expand Down Expand Up @@ -253,9 +253,32 @@ impl Player {
}
}

pub fn info(&self) -> CmdResult {
CmdResult::new(
false,
format!(
"Level: {}\
\nHP: ({} / {})\
\nAC: {}\
\nXP: ({} / {})\
\nStat points: {}\
\n\n{}",
self.lvl,
self.hp(),
self.hp_cap(),
self.ac(),
self.xp.0,
self.xp.1,
self.stats.pts,
self.stats.print_stats()
),
)
}

pub fn inspect(&self, name: &str) -> Option<CmdResult> {
if name == "me" || name == "self" || name == "myself" {
Some(self.status())
Some(self.info())
} else if let Some(item) = self.inventory.get(name) {
Some(CmdResult::new(true, item.inspection().to_owned()))
} else if let Some(item) = &self.main_hand {
Expand Down Expand Up @@ -317,13 +340,56 @@ impl Player {
CmdResult::new(true, items_carried)
}

fn remove_item(&mut self, name: &str) -> Option<Box<Item>> {
if let Some(item) = self.inventory.remove(name) {
Some(item)
} else {
let similar_name = if let Some(similar_name) = self
.inventory
.keys()
.find(|key| key.split_whitespace().any(|word| word == name))
{
similar_name.clone()
} else {
return None;
};
self.inventory.remove(&similar_name)
}
}

fn remove_main_hand(&mut self, name: &str) -> Option<Box<Item>> {
if let Some(item) = self.main_hand.take() {
if item.name() == name || item.name().split_whitespace().any(|word| word == name) {
Some(item)
} else {
self.main_hand = Some(item);
None
}
} else {
None
}
}

fn remove_armor(&mut self, name: &str) -> Option<Box<Item>> {
if let Some(item) = self.armor.take() {
if item.name() == name || item.name().split_whitespace().any(|word| word == name) {
Some(item)
} else {
self.armor = Some(item);
None
}
} else {
None
}
}

// remove an item from inventory and into the current Room
pub fn remove(&mut self, name: &str) -> Option<Box<Item>> {
if let Some(item) = self.inventory.remove(name) {
if let Some(item) = self.remove_item(name) {
Some(item)
} else if let Some(item) = self.main_hand.take() {
} else if let Some(item) = self.remove_main_hand(name) {
Some(item)
} else if let Some(item) = self.armor.take() {
} else if let Some(item) = self.remove_armor(name) {
Some(item)
} else {
None
Expand Down Expand Up @@ -358,26 +424,6 @@ impl Player {
}
}

pub fn stats(&self) -> CmdResult {
CmdResult::new(true, self.stats.print_stats())
}

pub fn status(&self) -> CmdResult {
CmdResult::new(
false,
format!(
"Level: {}\nHP: ({} / {})\nAC: {}\nXP: ({} / {})\nStat points: {}",
self.lvl,
self.hp(),
self.hp_cap(),
self.ac(),
self.xp.0,
self.xp.1,
self.stats.pts
),
)
}

pub fn take_damage(&mut self, enemy_name: &str, damage: u32) -> String {
if rand::thread_rng().gen_range(1, 21) > self.ac() {
self.hp = (self.hp.0 - damage as i32, self.hp.1);
Expand Down Expand Up @@ -446,6 +492,7 @@ impl Player {
} else {
return dont_have(container_name);
};

if is_closed == Some(true) {
CmdResult::new(false, format!("The {} is closed.", container_name))
} else if let Some(container) = self.inventory.get_mut(container_name) {
Expand Down
25 changes: 13 additions & 12 deletions src/types/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,24 @@ impl Stats {
pub fn new() -> Self {
Self {
pts: 4,
strngth: 0,
dex: 0,
con: 0,
int: 0,
wis: 0,
cha: 0,
strngth: 14,
dex: 13,
con: 15,
int: 12,
wis: 10,
cha: 8,
}
}

pub fn print_stats(&self) -> String {
format!(
"Strength: {},
Dexterity: {},
Constitution: {},
Intellect: {},
Wisdom: {},
Charisma: {}",
"\
Strength: {}\
\nDexterity: {}\
\nConstitution: {}\
\nIntellect: {}\
\nWisdom: {}\
\nCharisma: {} ",
self.strngth, self.dex, self.con, self.int, self.wis, self.cha
)
}
Expand Down
18 changes: 9 additions & 9 deletions tests/increase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,27 @@ mod tests {
fn increase_stat_pts() {
let cli = Cli::from_json_file("data/test_world.json");

assert!(cli.ask("status").contains("Stat points: 4"));
assert!(cli.ask("c").contains("Stat points: 4"));
assert!(cli
.ask("increase dex")
.contains("Ability score increased by one."));
assert!(cli.ask("status").contains("Stat points: 3"));
assert!(cli.ask("stats").contains("Dexterity: 1"));
assert!(cli.ask("c").contains("Stat points: 3"));
assert!(cli.ask("stats").contains("Dexterity: 14\n"));
assert!(cli
.ask("increase charisma")
.contains("Ability score increased by one."));
assert!(cli.ask("status").contains("Stat points: 2"));
assert!(cli.ask("stats").contains("Charisma: 1"));
assert!(cli.ask("c").contains("Stat points: 2"));
assert!(cli.ask("c").contains("Charisma: 9 "));
assert!(cli
.ask("increase cha")
.contains("Ability score increased by one."));
assert!(cli.ask("status").contains("Stat points: 1"));
assert!(cli.ask("stats").contains("Charisma: 2"));
assert!(cli.ask("c").contains("Stat points: 1"));
assert!(cli.ask("c").contains("Charisma: 10 "));
assert!(cli
.ask("increase wisdom")
.contains("Ability score increased by one."));
assert!(cli.ask("status").contains("Stat points: 0"));
assert!(cli.ask("stats").contains("Wisdom: 1"));
assert!(cli.ask("c").contains("Stat points: 0"));
assert!(cli.ask("c").contains("Wisdom: 11\n"));
assert!(cli
.ask("increase wisdom")
.contains("You do not have any stat points."));
Expand Down

0 comments on commit 2a8d2db

Please sign in to comment.