Skip to content

Commit

Permalink
Refactor adversarial sim logic
Browse files Browse the repository at this point in the history
  • Loading branch information
KonaeAkira committed Aug 16, 2024
1 parent e055e2d commit b804bca
Show file tree
Hide file tree
Showing 16 changed files with 84 additions and 89 deletions.
49 changes: 18 additions & 31 deletions simulator/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ pub struct SimulationState {
pub cp: i16,
pub durability: i8,
pub progress: u16,
pub unreliable_quality: [u16; 2],
// This value represents the minimum additional quality achievable by the simulator
// 1 while allowing the previous un-Guarded action to be Poor
// 0 while forcing the previous un-Guarded action to be Normal
pub quality: u16, // previous unguarded action = Poor
pub unreliable_quality: u16, // previous unguarded action = Normal, diff with quality
pub effects: Effects,
pub combo: Combo,
}
Expand All @@ -19,7 +17,8 @@ impl SimulationState {
cp: settings.max_cp,
durability: settings.max_durability,
progress: 0,
unreliable_quality: [0; 2],
quality: 0,
unreliable_quality: 0,
effects: Effects::default().with_guard(if settings.adversarial { 2 } else { 0 }),
combo: Combo::SynthesisBegin,
}
Expand Down Expand Up @@ -54,12 +53,6 @@ impl SimulationState {
(state, errors)
}

pub fn get_quality(&self) -> u16 {
#[cfg(test)]
assert!(self.unreliable_quality[0] >= self.unreliable_quality[1]);
self.unreliable_quality[1]
}

pub fn is_final(&self, settings: &Settings) -> bool {
self.durability <= 0 || self.progress >= settings.max_progress
}
Expand Down Expand Up @@ -159,10 +152,22 @@ impl SimulationState {
state.effects.set_muscle_memory(0);
}

if state.effects.guard() == 0 && quality_increase == 0 {
state.unreliable_quality = 0;
} else if state.effects.guard() != 0 && quality_increase != 0 {
state.quality += quality_increase;
state.unreliable_quality = 0;
} else if quality_increase != 0 {
state.quality +=
quality_increase + std::cmp::min(state.unreliable_quality, quality_delta);
state.unreliable_quality = quality_delta.saturating_sub(state.unreliable_quality);
}

#[cfg(test)]
assert!(settings.adversarial || state.unreliable_quality == 0);

// reset great strides and increase inner quiet if quality increased
if quality_increase != 0 {
state.unreliable_quality[0] += quality_increase;
state.unreliable_quality[1] += quality_increase;
state.effects.set_great_strides(0);
if settings.job_level >= 11 {
let inner_quiet_bonus = match action {
Expand All @@ -179,24 +184,6 @@ impl SimulationState {
}
}

// calculate guard effects
if settings.adversarial {
if (state.effects.guard() == 0 && quality_increase == 0)
|| (state.effects.guard() != 0 && quality_increase != 0)
{
// commit the current value
state.unreliable_quality = [state.get_quality(); 2];
} else if quality_increase != 0 {
// append new info
let saved = state.unreliable_quality[0];
state.unreliable_quality[0] =
std::cmp::min(state.unreliable_quality[1], state.unreliable_quality[0])
+ quality_delta;
state.unreliable_quality[1] =
std::cmp::min(saved, state.unreliable_quality[1] + quality_delta);
}
}

if state.is_final(settings) {
return Ok(state);
}
Expand Down
8 changes: 4 additions & 4 deletions simulator/tests/action_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ fn test_trained_eye_opener() {
let state = SimulationState::from_macro(&SETTINGS, &[Action::TrainedEye]);
assert!(matches!(state, Ok(_)));
let state = state.unwrap();
assert_eq!(state.get_quality(), SETTINGS.max_quality);
assert_eq!(state.quality, SETTINGS.max_quality);
assert_eq!(state.effects.inner_quiet(), 1);
let state =
SimulationState::from_macro(&SETTINGS, &[Action::BasicSynthesis, Action::TrainedEye]);
Expand Down Expand Up @@ -231,7 +231,7 @@ fn test_delicate_synthesis() {
match state {
Ok(state) => {
assert_eq!(state.progress, 100);
assert_eq!(state.get_quality(), 100);
assert_eq!(state.quality, 100);
}
Err(e) => panic!("Unexpected error: {}", e),
}
Expand All @@ -243,7 +243,7 @@ fn test_delicate_synthesis() {
match state {
Ok(state) => {
assert_eq!(state.progress, 150);
assert_eq!(state.get_quality(), 100);
assert_eq!(state.quality, 100);
}
Err(e) => panic!("Unexpected error: {}", e),
}
Expand Down Expand Up @@ -275,7 +275,7 @@ fn test_precise_touch() {
SimulationState::from_macro(&SETTINGS, &[Action::HeartAndSoul, Action::PreciseTouch]);
match state {
Ok(state) => {
assert_eq!(state.get_quality(), 150);
assert_eq!(state.quality, 150);
assert_eq!(state.effects.inner_quiet(), 2);
assert_eq!(state.effects.heart_and_soul(), SingleUse::Unavailable);
}
Expand Down
22 changes: 11 additions & 11 deletions simulator/tests/adversarial_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fn guaranteed_quality(mut settings: Settings, actions: &[Action]) -> Result<u16,
};
state = state.use_action(*action, condition, &settings)?;
}
min_quality = std::cmp::min(min_quality, state.get_quality());
min_quality = std::cmp::min(min_quality, state.quality);
}
Ok(min_quality)
}
Expand All @@ -65,7 +65,7 @@ fn test_simple() {
let state = SimulationState::from_macro(&SETTINGS, &actions);
if let Ok(state) = state {
assert_eq!(guaranteed_quality(SETTINGS, &actions).unwrap(), 100);
assert_eq!(state.get_quality(), 100);
assert_eq!(state.quality, 100);
} else {
panic!("Unexpected err: {}", state.err().unwrap());
}
Expand All @@ -77,7 +77,7 @@ fn test_short_quality_opener() {
let state = SimulationState::from_macro(&SETTINGS, &actions);
if let Ok(state) = state {
assert_eq!(guaranteed_quality(SETTINGS, &actions).unwrap(), 300);
assert_eq!(state.get_quality(), 300);
assert_eq!(state.quality, 300);
} else {
panic!("Unexpected err: {}", state.err().unwrap());
}
Expand All @@ -94,7 +94,7 @@ fn test_long_quality_opener() {
let state = SimulationState::from_macro(&SETTINGS, &actions);
if let Ok(state) = state {
assert_eq!(guaranteed_quality(SETTINGS, &actions).unwrap(), 1140);
assert_eq!(state.get_quality(), 1140);
assert_eq!(state.quality, 1140);
} else {
panic!("Unexpected err: {}", state.err().unwrap());
}
Expand All @@ -114,7 +114,7 @@ fn test_alternating_quality_actions() {
let state = SimulationState::from_macro(&SETTINGS, &actions);
if let Ok(state) = state {
assert_eq!(guaranteed_quality(SETTINGS, &actions).unwrap(), 440);
assert_eq!(state.get_quality(), 440);
assert_eq!(state.quality, 440);
} else {
panic!("Unexpected err: {}", state.err().unwrap());
}
Expand All @@ -135,7 +135,7 @@ fn test_double_status_drops() {
let state = SimulationState::from_macro(&SETTINGS, &actions);
if let Ok(state) = state {
assert_eq!(guaranteed_quality(SETTINGS, &actions).unwrap(), 525);
assert_eq!(state.get_quality(), 525);
assert_eq!(state.quality, 525);
} else {
panic!("Unexpected err: {}", state.err().unwrap());
}
Expand All @@ -156,7 +156,7 @@ fn test_two_action_drops() {
let state = SimulationState::from_macro(&SETTINGS, &actions);
if let Ok(state) = state {
assert_eq!(guaranteed_quality(SETTINGS, &actions).unwrap(), 607);
assert_eq!(state.get_quality(), 607);
assert_eq!(state.quality, 607);
} else {
panic!("Unexpected err: {}", state.err().unwrap());
}
Expand All @@ -178,7 +178,7 @@ fn test_dp() {
let state = SimulationState::from_macro(&SETTINGS, &actions);
if let Ok(state) = state {
assert_eq!(guaranteed_quality(SETTINGS, &actions).unwrap(), 952);
assert_eq!(state.get_quality(), 952);
assert_eq!(state.quality, 952);
} else {
panic!("Unexpected err: {}", state.err().unwrap());
}
Expand Down Expand Up @@ -209,7 +209,7 @@ fn test_long_sequence() {
let state = SimulationState::from_macro(&SETTINGS, &actions);
if let Ok(state) = state {
assert_eq!(guaranteed_quality(SETTINGS, &actions).unwrap(), 2924);
assert_eq!(state.get_quality(), 2924);
assert_eq!(state.quality, 2924);
} else {
panic!("Unexpected err: {}", state.err().unwrap());
}
Expand All @@ -230,7 +230,7 @@ fn test_exhaustive() {
if let Ok(state) = state {
dbg!(&actions);
assert_eq!(
state.get_quality(),
state.quality,
guaranteed_quality(SETTINGS, &actions).unwrap()
);
} else {
Expand Down Expand Up @@ -261,7 +261,7 @@ fn test_fuzz() {
if let Ok(state) = SimulationState::from_macro(&SETTINGS, &actions) {
dbg!(&actions);
assert_eq!(
state.get_quality(),
state.quality,
guaranteed_quality(SETTINGS, &actions).unwrap()
);
}
Expand Down
14 changes: 7 additions & 7 deletions simulator/tests/simulator_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ fn test_random_926ae85b() {
assert_eq!(state.cp, 14);
assert_eq!(state.durability, 30);
assert_eq!(state.progress, 4);
assert_eq!(state.get_quality(), 76);
assert_eq!(state.quality, 76);
assert_eq!(state.effects.inner_quiet(), 0);
}

Expand Down Expand Up @@ -82,7 +82,7 @@ fn test_random_3c721e47() {
assert_eq!(state.cp, 223);
assert_eq!(state.durability, 60);
assert_eq!(state.progress, 2520);
assert_eq!(state.get_quality(), 1473);
assert_eq!(state.quality, 1473);
}

#[test]
Expand Down Expand Up @@ -121,7 +121,7 @@ fn test_random_3ba90d3a() {
assert_eq!(state.cp, 188);
assert_eq!(state.durability, 25);
assert_eq!(state.progress, 918);
assert_eq!(state.get_quality(), 2118);
assert_eq!(state.quality, 2118);
assert_eq!(state.effects.inner_quiet(), 5);
assert_eq!(state.effects.innovation(), 1);
}
Expand Down Expand Up @@ -179,7 +179,7 @@ fn test_random_bce2650c() {
assert_eq!(state.cp, 1);
assert_eq!(state.durability, 5);
assert_eq!(state.progress, 6323);
assert_eq!(state.get_quality(), 11475);
assert_eq!(state.quality, 11475);
}

#[test]
Expand Down Expand Up @@ -224,7 +224,7 @@ fn test_ingame_be9fc5c2() {
)
.unwrap()
.into_iter()
.map(|state| (state.progress, state.get_quality()))
.map(|state| (state.progress, state.quality))
.collect();
let expected = [
(0, 795),
Expand Down Expand Up @@ -288,7 +288,7 @@ fn test_ingame_d11d9c68() {
)
.unwrap()
.into_iter()
.map(|state| (state.progress, state.get_quality()))
.map(|state| (state.progress, state.quality))
.collect();
let expected = [
(0, 900),
Expand Down Expand Up @@ -362,7 +362,7 @@ fn test_ingame_f9f0dac7() {
)
.unwrap()
.into_iter()
.map(|state| (state.progress, state.get_quality()))
.map(|state| (state.progress, state.quality))
.collect();
let expected = [
(0, 720),
Expand Down
2 changes: 1 addition & 1 deletion solvers/examples/macro_solver_example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fn main() {

let quality = SimulationState::from_macro(&settings, &actions)
.unwrap()
.get_quality();
.quality;
let steps = actions.len();
let duration: i16 = actions.iter().map(|action| action.time_cost()).sum();
dbg!(quality, steps, duration);
Expand Down
3 changes: 2 additions & 1 deletion solvers/src/finish_solver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ impl ReducedState {
durability: self.durability,
cp: self.cp,
progress: 0,
unreliable_quality: [0; 2],
quality: 0,
unreliable_quality: 0,
effects: self.effects,
combo: self.combo,
}
Expand Down
2 changes: 1 addition & 1 deletion solvers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ pub mod test_utils {
.unwrap();
}
assert!(state.progress >= settings.max_progress);
state.get_quality()
state.quality
}
}
2 changes: 1 addition & 1 deletion solvers/src/macro_solver/fast_lower_bound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub fn fast_lower_bound(
if !finish_solver.can_finish(&state) {
continue;
}
quality_lower_bound = std::cmp::max(quality_lower_bound, state.get_quality());
quality_lower_bound = std::cmp::max(quality_lower_bound, state.quality);
if action == Action::ByregotsBlessing {
continue;
}
Expand Down
12 changes: 7 additions & 5 deletions solvers/src/macro_solver/pareto_front/quality_pareto_front.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ use super::{Dominate, ParetoFront};
#[derive(Clone, Copy, PartialEq, Eq)]
struct Value {
cp: i16,
quality: [u16; 2],
quality: u16,
unreliable_quality: u16,
inner_quiet: u8,
}

impl Value {
pub fn new(state: SimulationState) -> Self {
Self {
cp: state.cp,
quality: state.unreliable_quality,
quality: state.quality,
unreliable_quality: state.unreliable_quality,
inner_quiet: state.effects.inner_quiet(),
}
}
Expand All @@ -23,8 +25,8 @@ impl Value {
impl Dominate for Value {
fn dominate(&self, other: &Self) -> bool {
self.cp >= other.cp
&& self.quality[0] >= other.quality[0]
&& self.quality[1] >= other.quality[1]
&& self.quality >= other.quality
&& self.unreliable_quality >= other.unreliable_quality
&& self.inner_quiet >= other.inner_quiet
}
}
Expand All @@ -39,7 +41,7 @@ struct Key {

impl Key {
pub fn new(state: SimulationState, settings: &Settings) -> Self {
let effects = if state.get_quality() >= settings.max_quality {
let effects = if state.quality >= settings.max_quality {
state
.effects
.with_inner_quiet(0)
Expand Down
8 changes: 5 additions & 3 deletions solvers/src/macro_solver/search_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,14 @@ impl SearchQueue {
return;
}
self.minimum_score = score;
let mut dropped = 0;
while let Some((bucket_score, _)) = self.buckets.first_key_value() {
if *bucket_score >= self.minimum_score {
break;
}
self.buckets.pop_first();
dropped += self.buckets.pop_first().unwrap().1.len();
}
dbg!(self.minimum_score, dropped);
}

pub fn push(
Expand Down Expand Up @@ -159,8 +161,8 @@ impl SearchQueue {
fn pareto_weight(state: &SimulationState) -> u32 {
state.cp as u32
+ state.durability as u32
+ state.unreliable_quality[0] as u32
+ state.unreliable_quality[1] as u32
+ state.quality as u32
+ state.unreliable_quality as u32
+ state.effects.into_bits()
+ state.combo.into_bits() as u32
}
Loading

0 comments on commit b804bca

Please sign in to comment.