servicepoint-idle/src/unlocks.rs
2025-07-06 11:46:32 +02:00

120 lines
3.7 KiB
Rust

use crate::Currency;
use crate::game::{Game, State};
use std::collections::VecDeque;
use std::fmt::{Debug, Formatter, format};
use std::ops::Mul;
#[derive(Debug)]
pub(crate) struct UnlockSystem {
bought: usize,
last_unlock: Option<String>,
unlock_queue: VecDeque<Unlock>,
}
pub(crate) struct Unlock {
pub(crate) name: String,
pub(crate) cost: Currency,
pub(crate) apply: Box<dyn Fn(&mut State)>,
}
impl Debug for Unlock {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!(
"Upgrade {{ name: {:?}, cost: {:?} }}",
self.name, self.cost
))
}
}
impl UnlockSystem {
pub(crate) fn new(start_state: &State) -> Self {
let mut upgrades = start_state
.bars
.iter()
.enumerate()
.flat_map(|(index, bar)| {
let initial_cost = 10usize.pow(index as u32);
[
Unlock {
name: format!("Start {}", bar.name()),
cost: initial_cost as f64,
apply: Box::new(move |game| {
game.bars[index].enabled = true;
}),
},
Unlock {
name: format!("{} productivity", bar.name()),
cost: initial_cost.mul(2) as f64,
apply: Box::new(move |game| {
game.bars[index].productivity *= 2.0;
}),
},
Unlock {
name: format!("{} speed", bar.name()),
cost: initial_cost.mul(20) as f64,
apply: Box::new(move |game| {
game.bars[index].speed *= 1.5;
}),
},
]
})
.chain(
(1..10).map(|level|
Unlock {
name: format!("The answer {}", level),
cost: (42usize * 10usize.pow(level)) as f64,
apply: Box::new(move |game| {
game.speed *= 1.1;
}),
}
)
)
.chain(
(1..10).map(|level|
Unlock {
name: format!("??? {}", level),
cost: (23usize * 10usize.pow(level)) as f64,
apply: Box::new(move |game| {
game.productivity *= 1.1;
}),
},
)
)
.collect::<Vec<_>>();
upgrades.sort_by(|l, r| l.cost.total_cmp(&r.cost));
let unlock_queue = upgrades.into();
Self {
unlock_queue,
bought: 0,
last_unlock: None
}
}
pub(crate) fn peek_next(&self) -> Option<&Unlock> {
self.unlock_queue.front()
}
pub(crate) fn check_next(&mut self, state: &mut State) {
if let Some(next_upgrade) = self.peek_next() {
if next_upgrade.cost <= state.currency {
log::info!("Applying upgrade {:?}", next_upgrade);
let next_upgrade = self.unlock_queue.pop_front().unwrap();
state.currency -= next_upgrade.cost;
(next_upgrade.apply)(state);
self.last_unlock = Some(next_upgrade.name);
self.bought += 1;
}
}
}
pub(crate) fn bought(&self) -> usize {
self.bought
}
pub(crate) fn previous(&self) -> Option<&String> {
self.last_unlock.as_ref()
}
}