Skip to content

Commit

Permalink
Implement Tricks of the Trade
Browse files Browse the repository at this point in the history
  • Loading branch information
KonaeAkira committed Nov 20, 2024
1 parent 53e487c commit 46d6a72
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 13 deletions.
4 changes: 4 additions & 0 deletions game_data/src/locales.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ const fn action_name_en(action: Action) -> &'static str {
Action::BasicTouch => "Basic Touch",
Action::MasterMend => "Master's Mend",
Action::Observe => "Observe",
Action::TricksOfTheTrade => "Tricks of the Trade",
Action::WasteNot => "Waste Not",
Action::Veneration => "Veneration",
Action::StandardTouch => "Standard Touch",
Expand Down Expand Up @@ -127,6 +128,7 @@ const fn action_name_de(action: Action) -> &'static str {
Action::BasicTouch => "Veredelung",
Action::MasterMend => "Wiederherstellung",
Action::Observe => "Beobachten",
Action::TricksOfTheTrade => "Kunstgriff",
Action::WasteNot => "Nachhaltigkeit",
Action::Veneration => "Ehrfurcht",
Action::StandardTouch => "Solide Veredelung",
Expand Down Expand Up @@ -162,6 +164,7 @@ const fn action_name_fr(action: Action) -> &'static str {
Action::BasicTouch => "Ouvrage de base",
Action::MasterMend => "Réparation de maître",
Action::Observe => "Observation",
Action::TricksOfTheTrade => "Ficelles du métier",
Action::WasteNot => "Parcimonie",
Action::Veneration => "Vénération",
Action::StandardTouch => "Ouvrage standard",
Expand Down Expand Up @@ -197,6 +200,7 @@ const fn action_name_jp(action: Action) -> &'static str {
Action::BasicTouch => "加工",
Action::MasterMend => "マスターズメンド",
Action::Observe => "経過観察",
Action::TricksOfTheTrade => "秘訣",
Action::WasteNot => "倹約",
Action::Veneration => "ヴェネレーション",
Action::StandardTouch => "中級加工",
Expand Down
29 changes: 29 additions & 0 deletions simulator/src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,33 @@ impl ActionImpl for Observe {
}
}

pub struct TricksOfTheTrade {}
impl ActionImpl for TricksOfTheTrade {
const LEVEL_REQUIREMENT: u8 = 13;
const ACTION_MASK: ActionMask = ActionMask::none().add(Action::TricksOfTheTrade);
fn precondition(
state: &SimulationState,
_settings: &Settings,
condition: Condition,
) -> Result<(), &'static str> {
if state.effects.heart_and_soul() != SingleUse::Active
&& condition != Condition::Good
&& condition != Condition::Excellent
{
return Err(
"Tricks of the Trade can only be used when the condition is Good or Excellent.",
);
}
Ok(())
}
fn transform_post(state: &mut SimulationState, settings: &Settings, condition: Condition) {
state.cp = std::cmp::min(settings.max_cp, state.cp + 20);
if condition != Condition::Good && condition != Condition::Excellent {
state.effects.set_heart_and_soul(SingleUse::Unavailable);
}
}
}

pub struct WasteNot {}
impl ActionImpl for WasteNot {
const LEVEL_REQUIREMENT: u8 = 15;
Expand Down Expand Up @@ -716,6 +743,7 @@ pub enum Action {
BasicTouch,
MasterMend,
Observe,
TricksOfTheTrade,
WasteNot,
Veneration,
StandardTouch,
Expand Down Expand Up @@ -779,6 +807,7 @@ impl Action {
Action::BasicTouch => 3,
Action::MasterMend => 3,
Action::Observe => 3,
Action::TricksOfTheTrade => 3,
Action::WasteNot => 2,
Action::Veneration => 2,
Action::StandardTouch => 3,
Expand Down
1 change: 1 addition & 0 deletions simulator/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ const ALL_ACTIONS: &[Action] = &[
Action::BasicTouch,
Action::MasterMend,
Action::Observe,
Action::TricksOfTheTrade,
Action::WasteNot,
Action::Veneration,
Action::StandardTouch,
Expand Down
18 changes: 6 additions & 12 deletions simulator/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
use crate::{
actions::{
ActionImpl, AdvancedTouch, BasicSynthesis, BasicTouch, ByregotsBlessing, CarefulSynthesis,
DelicateSynthesis, GreatStrides, Groundwork, HeartAndSoul, ImmaculateMend, Innovation,
IntensiveSynthesis, Manipulation, MasterMend, MuscleMemory, Observe, PreciseTouch,
PreparatoryTouch, PrudentSynthesis, PrudentTouch, QuickInnovation, RefinedTouch, Reflect,
StandardTouch, TrainedEye, TrainedFinesse, TrainedPerfection, Veneration, WasteNot,
WasteNot2,
},
effects::SingleUse,
Action, Combo, Condition, Effects, Settings,
};
use crate::actions::*;
use crate::effects::*;
use crate::{Condition, Settings};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SimulationState {
Expand Down Expand Up @@ -175,6 +166,9 @@ impl SimulationState {
Action::BasicTouch => self.use_action_impl::<BasicTouch>(settings, condition),
Action::MasterMend => self.use_action_impl::<MasterMend>(settings, condition),
Action::Observe => self.use_action_impl::<Observe>(settings, condition),
Action::TricksOfTheTrade => {
self.use_action_impl::<TricksOfTheTrade>(settings, condition)
}
Action::WasteNot => self.use_action_impl::<WasteNot>(settings, condition),
Action::Veneration => self.use_action_impl::<Veneration>(settings, condition),
Action::StandardTouch => self.use_action_impl::<StandardTouch>(settings, condition),
Expand Down
42 changes: 42 additions & 0 deletions simulator/tests/action_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,48 @@ fn test_observe() {
assert_eq!(state.combo, Combo::StandardTouch);
}

#[test]
fn test_tricks_of_the_trade() {
// Precondition not fulfilled
let error = SimulationState::new(&SETTINGS)
.use_action(Action::TricksOfTheTrade, Condition::Normal, &SETTINGS)
.unwrap_err();
assert_eq!(
error,
"Tricks of the Trade can only be used when the condition is Good or Excellent."
);
// Can use when condition is Good or Excellent
let initial_state = SimulationState {
cp: SETTINGS.max_cp - 25, // test maximum restored CP
..SimulationState::new(&SETTINGS)
};
let state = initial_state
.use_action(Action::TricksOfTheTrade, Condition::Good, &SETTINGS)
.unwrap();
assert_eq!(primary_stats(&state, &SETTINGS), (0, 0, 0, 5));
// Can use when Heart and Soul is active
let initial_state = SimulationState {
cp: SETTINGS.max_cp - 5, // test that restored CP is capped at max_cp
effects: Effects::new().with_heart_and_soul(SingleUse::Active),
..SimulationState::new(&SETTINGS)
};
let state = initial_state
.use_action(Action::TricksOfTheTrade, Condition::Normal, &SETTINGS)
.unwrap();
assert_eq!(primary_stats(&state, &SETTINGS), (0, 0, 0, 0));
assert_eq!(state.effects.heart_and_soul(), SingleUse::Unavailable);
// Heart and Soul effect isn't consumed when condition is Good or Excellent
let initial_state = SimulationState {
effects: Effects::new().with_heart_and_soul(SingleUse::Active),
..SimulationState::new(&SETTINGS)
};
let state = initial_state
.use_action(Action::TricksOfTheTrade, Condition::Good, &SETTINGS)
.unwrap();
assert_eq!(primary_stats(&state, &SETTINGS), (0, 0, 0, 0));
assert_eq!(state.effects.heart_and_soul(), SingleUse::Active);
}

#[test]
fn test_waste_not() {
let state = SimulationState::new(&SETTINGS)
Expand Down
1 change: 1 addition & 0 deletions solvers/src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub const QUALITY_ACTIONS: ActionMask = action_mask!(

pub const DURABILITY_ACTIONS: ActionMask = action_mask!(
Action::MasterMend,
Action::TricksOfTheTrade,
Action::WasteNot,
Action::WasteNot2,
Action::Manipulation,
Expand Down
3 changes: 2 additions & 1 deletion solvers/src/finish_solver.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use simulator::{Action, ActionMask, Combo, Condition, Effects, Settings, SimulationState};
use simulator::*;

use rustc_hash::FxHashMap as HashMap;

use super::actions::{DURABILITY_ACTIONS, PROGRESS_ACTIONS};

const SEARCH_ACTIONS: ActionMask = PROGRESS_ACTIONS
.union(DURABILITY_ACTIONS)
.remove(Action::TricksOfTheTrade)
.remove(Action::DelicateSynthesis);

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
Expand Down
7 changes: 7 additions & 0 deletions solvers/src/quality_upper_bound_solver/solver.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::i16;

use crate::{
actions::{PROGRESS_ACTIONS, QUALITY_ACTIONS},
utils::{ParetoFrontBuilder, ParetoFrontId, ParetoValue},
Expand Down Expand Up @@ -42,6 +44,11 @@ impl QualityUpperBoundSolver {
std::mem::align_of::<ReducedState>()
);

let settings = Settings {
max_cp: i16::MAX,
..settings
};

let initial_state = SimulationState::new(&settings);
let mut durability_cost = 100;
if settings.is_action_allowed::<MasterMend>() {
Expand Down
1 change: 1 addition & 0 deletions solvers/src/step_lower_bound_solver/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ impl ReducedState {
settings.allowed_actions = settings
.allowed_actions
.remove(Action::Observe)
.remove(Action::TricksOfTheTrade)
.remove(Action::Manipulation)
.remove(Action::TrainedPerfection)
.remove(Action::ImmaculateMend);
Expand Down

0 comments on commit 46d6a72

Please sign in to comment.