diff --git a/src/bar.rs b/src/bar.rs index d6f1cfe..e4ddaac 100644 --- a/src/bar.rs +++ b/src/bar.rs @@ -1,12 +1,12 @@ -use crate::{Currency, Progressable}; +use crate::Currency; use servicepoint::{CharGridMutExt, GridMut, WindowMut}; use std::time::Duration; #[derive(Debug, Clone, Copy)] pub struct Bar { name: &'static str, - pub(crate) enabled: bool, progress: f64, + pub(crate) enabled: bool, pub(crate) speed: f64, pub(crate) productivity: f64, } @@ -15,10 +15,10 @@ impl Bar { pub(crate) fn new(productivity: f64, speed: f64, name: &'static str) -> Self { Self { name, - enabled: false, productivity, - progress: 0f64, speed, + enabled: false, + progress: 0f64, } } } diff --git a/src/game.rs b/src/game.rs index 9d1aa79..e07d752 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,65 +1,62 @@ -use crate::upgrades::{Upgrade, get_upgrades}; -use crate::{Currency, Progressable, bar::Bar}; -use log::log; +use crate::unlocks::UnlockSystem; +use crate::{Currency, bar::Bar}; use servicepoint::{Bitmap, CharGrid, CharGridMutExt, TILE_SIZE, WindowMut}; -use std::collections::VecDeque; use std::time::Duration; #[derive(Debug)] -pub struct Game { - pub(crate) currency: Currency, - pub(crate) bars: [Bar; STEP_COUNT], - unlocks: usize, - unlock_queue: VecDeque, +pub struct Game { total_currency: Currency, - pub(crate) global_speed: f64, - pub(crate) global_productivity: f64, + unlocks: UnlockSystem, + state: State, +} + +#[derive(Debug)] +pub struct State { + pub(crate) currency: Currency, + pub(crate) speed: f64, + pub(crate) productivity: f64, + pub(crate) bars: [Bar; STEP_COUNT], } impl Game { pub fn new() -> Self { Self { - currency: 0f64, total_currency: 0f64, - global_speed: 1f64, - global_productivity: 1f64, - unlocks: 0, - unlock_queue: get_upgrades(), - bars: [ - Bar::new(1f64, 1.0, "Powering infrastructure"), - Bar::new(2f64, 0.5, "Dusting ServicePoint"), - Bar::new(4f64, 0.25, "Activating colorful lights"), - Bar::new(8f64, 0.125, "Dimming darkroom"), - Bar::new(16f64, 0.0625, "Refilling Matemat"), - Bar::new(32f64, 0.03125, "Pre-heating convectiomat"), - Bar::new(64f64, 0.015625, "Resetting chair heights"), - Bar::new(128f64, 0.0078125, "Untangling 'block chain'"), - Bar::new(256f64, 0.00390625, "Refilling sticker box"), - Bar::new(512f64, 0.001953125, "Setting room to public"), - Bar::new(1024f64, 0.000976562, "Welcoming creatures"), - ], + unlocks: UnlockSystem::new(), + state: State { + currency: 0f64, + speed: 1f64, + productivity: 1f64, + bars: [ + Bar::new(1f64, 1.0, "Powering infrastructure"), + Bar::new(2f64, 0.5, "Dusting ServicePoint"), + Bar::new(4f64, 0.25, "Activating colorful lights"), + Bar::new(8f64, 0.125, "Dimming darkroom"), + Bar::new(16f64, 0.0625, "Refilling Matemat"), + Bar::new(32f64, 0.03125, "Pre-heating convectiomat"), + Bar::new(64f64, 0.015625, "Resetting chair heights"), + Bar::new(128f64, 0.0078125, "Untangling 'block chain'"), + Bar::new(256f64, 0.00390625, "Refilling sticker box"), + Bar::new(512f64, 0.001953125, "Setting room to public"), + Bar::new(1024f64, 0.000976562, "Welcoming creatures"), + ], + }, } } pub(crate) fn progress(&mut self, delta: Duration) { - let adjusted_delta = delta.mul_f64(self.global_speed); + let adjusted_delta = delta.mul_f64(self.state.speed); - self.currency += self.global_productivity + let extra_currency = self.state.productivity * self + .state .bars .iter_mut() .map(|bar| bar.progress(adjusted_delta)) .sum::(); - - if let Some(next_upgrade) = self.unlock_queue.front() { - if next_upgrade.cost <= self.currency { - log::info!("Applying upgrade {:?}", next_upgrade); - let next_upgrade = self.unlock_queue.pop_front().unwrap(); - self.currency -= next_upgrade.cost; - (next_upgrade.apply)(self); - self.unlocks += 1; - } - } + self.state.currency += extra_currency; + self.total_currency += extra_currency; + self.unlocks.check_next(&mut self.state); } pub(crate) fn draw( @@ -74,10 +71,10 @@ impl Game { text_layer .window_mut(middle, 0, middle, 1) .unwrap() - .set_row_str(0, &format!(" Completions: {}", self.currency.floor())) + .set_row_str(0, &format!(" Hacks: {}", self.state.currency.floor())) .unwrap(); - for (index, bar) in self.bars.iter().enumerate() { + for (index, bar) in self.state.bars.iter().enumerate() { let row = 2 + index; let mut bar_window = pixel_layer .window_mut(0, row * TILE_SIZE, pixel_layer.width(), TILE_SIZE) @@ -88,24 +85,21 @@ impl Game { bar.draw(&mut label_window, &mut bar_window); } - if let Some(next_upgrade) = self.unlock_queue.front() { + if let Some(next_upgrade) = self.unlocks.peek_next() { text_layer .window_mut(0, text_layer.height() - 2, text_layer.width(), 1) .unwrap() - .set_row_str( - 0, - &format!("Next unlock: {} {}", next_upgrade.cost, next_upgrade.name), - ) + .set_row_str(0, &format!("Next unlock for {} Hacks", next_upgrade.cost)) .unwrap(); } text_layer .window_mut(0, text_layer.height() - 1, text_layer.width() / 2, 1) .unwrap() - .set_row_str(0, &format!("Score: {}", self.total_currency)) + .set_row_str(0, &format!("Hack Score: {:.2}", self.total_currency)) .unwrap(); - if self.unlocks > 0 { + if self.unlocks.bought() > 0 { text_layer .window_mut( text_layer.width() / 2, @@ -114,7 +108,7 @@ impl Game { 1, ) .unwrap() - .set_row_str(0, &format!(" Unlocks: {}", self.unlocks)) + .set_row_str(0, &format!(" Unlocks: {}", self.unlocks.bought())) .unwrap(); } } diff --git a/src/main.rs b/src/main.rs index 80587fe..447ed05 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,23 +3,14 @@ use servicepoint::{ BinaryOperation, BitVecCommand, Bitmap, CharGrid, CharGridCommand, ClearCommand, CompressionCode, FRAME_PACING, TILE_HEIGHT, TILE_WIDTH, UdpSocketExt, }; -use std::{ - net::UdpSocket, - thread::sleep, - time::{Duration, Instant}, -}; +use std::{net::UdpSocket, thread::sleep, time::Instant}; mod bar; mod game; -mod upgrades; +mod unlocks; type Currency = f64; -trait Progressable: Sized { - #[must_use] - fn progress(&self, delta: Duration) -> (Self, Currency); -} - const DESTINATION: &str = "127.0.0.1:2342"; //const DESTINATION: &str = "172.23.42.29:2342"; diff --git a/src/unlocks.rs b/src/unlocks.rs new file mode 100644 index 0000000..bbf5497 --- /dev/null +++ b/src/unlocks.rs @@ -0,0 +1,168 @@ +use crate::Currency; +use crate::game::{Game, State}; +use std::collections::VecDeque; +use std::fmt::{Debug, Formatter}; + +#[derive(Debug)] +pub(crate) struct UnlockSystem { + bought: usize, + unlock_queue: VecDeque, +} + +pub(crate) struct Unlock { + pub(crate) name: &'static str, + pub(crate) cost: Currency, + pub(crate) apply: 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() -> Self { + Self { + bought: 0, + unlock_queue: vec![ + Unlock { + name: "Start Powering infrastructure", + cost: 0f64, + apply: |game| { + game.bars[0].enabled = true; + }, + }, + Unlock { + name: "More power", + cost: 10f64, + apply: |game| { + game.bars[0].productivity *= 2.0; + }, + }, + Unlock { + name: "", + cost: 23f64, + apply: |game| { + game.productivity *= 1.1; + }, + }, + Unlock { + name: "The answer", + cost: 42f64, + apply: |game| { + game.speed *= 1.1; + }, + }, + Unlock { + name: "Start Dusting ServicePoint", + cost: 64f64, + apply: |game| { + game.bars[1].enabled = true; + }, + }, + Unlock { + name: "Dust filters", + cost: 100f64, + apply: |game| { + game.bars[1].productivity *= 2.0; + }, + }, + Unlock { + name: "HASS automation", + cost: 128f64, + apply: |game| { + game.bars[0].speed *= 1.5; + }, + }, + Unlock { + name: "Start Activating colorful lights", + cost: 256f64, + apply: |game| { + game.bars[2].enabled = true; + }, + }, + Unlock { + name: "Start Dimming darkroom", + cost: 1024f64, + apply: |game| { + game.bars[3].enabled = true; + }, + }, + Unlock { + name: "Start Refilling Matemat", + cost: 4096f64, + apply: |game| { + game.bars[4].enabled = true; + }, + }, + Unlock { + name: "Start Pre-heating convectiomat", + cost: 16384f64, + apply: |game| { + game.bars[5].enabled = true; + }, + }, + Unlock { + name: "Start Resetting chair heights", + cost: 65536f64, + apply: |game| { + game.bars[6].enabled = true; + }, + }, + Unlock { + name: "Start Untangling 'block chain'", + cost: 262144f64, + apply: |game| { + game.bars[7].enabled = true; + }, + }, + Unlock { + name: "Start Refilling sticker box", + cost: 1048576f64, + apply: |game| { + game.bars[8].enabled = true; + }, + }, + Unlock { + name: "Start Setting room to public", + cost: 4194304f64, + apply: |game| { + game.bars[9].enabled = true; + }, + }, + Unlock { + name: "Start Welcoming creatures", + cost: 16777216f64, + apply: |game| { + game.bars[10].enabled = true; + }, + }, + ] + .into(), + } + } + + 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.bought += 1; + } + } + } + + pub(crate) fn bought(&self) -> usize { + self.bought + } +} diff --git a/src/upgrades.rs b/src/upgrades.rs deleted file mode 100644 index 6b408b4..0000000 --- a/src/upgrades.rs +++ /dev/null @@ -1,123 +0,0 @@ -use crate::Currency; -use crate::game::Game; -use std::collections::VecDeque; -use std::fmt::{Debug, Formatter, Write}; - -pub(crate) struct Upgrade { - pub(crate) name: &'static str, - pub(crate) cost: Currency, - pub(crate) apply: Box, -} - -impl Debug for Upgrade { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.write_fmt(format_args!( - "Upgrade {{ name: {:?}, cost: {:?} }}", - self.name, self.cost - )) - } -} - -pub(crate) fn get_upgrades() -> VecDeque { - vec![ - Upgrade { - name: "Start Powering infrastructure", - cost: 0f64, - apply: Box::new(|game| { - game.bars[0].enabled = true; - }), - }, - Upgrade { - name: "More power", - cost: 10f64, - apply: Box::new(|game| { - game.bars[0].productivity *= 2.0; - }), - }, - Upgrade { - name: "", - cost: 23f64, - apply: Box::new(|game| { - game.global_productivity *= 1.1; - }), - }, - Upgrade { - name: "The answer", - cost: 42f64, - apply: Box::new(|game| { - game.global_speed *= 1.1; - }), - }, - Upgrade { - name: "Start Dusting ServicePoint", - cost: 64f64, - apply: Box::new(|game| { - game.bars[1].enabled = true; - }), - }, - Upgrade { - name: "Start Activating colorful lights", - cost: 256f64, - apply: Box::new(|game| { - game.bars[2].enabled = true; - }), - }, - Upgrade { - name: "Start Dimming darkroom", - cost: 1024f64, - apply: Box::new(|game| { - game.bars[3].enabled = true; - }), - }, - Upgrade { - name: "Start Refilling Matemat", - cost: 4096f64, - apply: Box::new(|game| { - game.bars[4].enabled = true; - }), - }, - Upgrade { - name: "Start Pre-heating convectiomat", - cost: 16384f64, - apply: Box::new(|game| { - game.bars[5].enabled = true; - }), - }, - Upgrade { - name: "Start Resetting chair heights", - cost: 65536f64, - apply: Box::new(|game| { - game.bars[6].enabled = true; - }), - }, - Upgrade { - name: "Start Untangling 'block chain'", - cost: 262144f64, - apply: Box::new(|game| { - game.bars[7].enabled = true; - }), - }, - Upgrade { - name: "Start Refilling sticker box", - cost: 1048576f64, - apply: Box::new(|game| { - game.bars[8].enabled = true; - }), - }, - Upgrade { - name: "Start Setting room to public", - cost: 4194304f64, - apply: Box::new(|game| { - game.bars[9].enabled = true; - }), - }, - Upgrade { - name: "Start Welcoming creatures", - cost: 16777216f64, - apply: Box::new(|game| { - game.bars[10].enabled = true; - }), - }, - ] - .into() -}