aboutsummaryrefslogtreecommitdiff
path: root/src/stats.rs
blob: 99340f2989dcb62b1c74b0a10c130daffb67ac73 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
//! This file contains balancing data
//!
//! Each type of node and packet is being balanced for different
//! factors.  The stats are just returned by these functions.
//! Whenever there is some effect that can happen in the game, it's
//! value (strength) will be derived from here.

pub type Money = u16;

/// The cost of doing business
pub mod costs {
    use super::Money;
    use crate::data::{Level, PacketType, Upgrade};

    /// Takes the current node and desired upgrade level
    pub fn upgrade(curr: &Upgrade, want: &Upgrade) -> Money {
        use self::{Level::*, Upgrade::*};
        match (curr, want) {
            // Base upgrades
            (Base, Guard(One)) => 30,
            (Base, Compute(One)) => 25,
            (Base, Relay(One)) => 20,

            // Guards
            (Guard(One), Guard(Two)) => 50,
            (Guard(Two), Guard(Three)) => 75,

            // Compute is expensive
            (Compute(One), Compute(Two)) => 50,
            (Compute(Two), Compute(Three)) => 95,

            // Relays
            (Relay(One), Relay(Two)) => 35,
            (Relay(Two), Relay(Three)) => 55,

            // Can't touch this
            (_, _) => unreachable!(),
        }
    }

    /// Sending certain packets costs money, let's find out how much
    pub fn packets(node: &Upgrade, packet: &PacketType) -> Money {
        use {
            Level::*,
            PacketType::*,
            Upgrade::{Base, Compute as Cc, Guard, Relay},
        };
        match (node, packet) {
            // Sending pings is free forever
            (_, Ping) => 0,
            // Capture packets always cost the same
            (_, Capture) => 15,

            // The cost of compute packets increases with levels
            // because their efficiency increases more dramatically
            (Cc(One), Compute { .. }) => 7,
            (Cc(Two), Compute { .. }) => 14,
            (Cc(Three), Compute { .. }) => 21,

            // Payloads can only be sent from guards
            (Guard(_), Payload { .. }) => 12,

            // Resets are relatively cheap
            (Guard(One), Reset) => 16,
            (Guard(Two), Reset) => 32,
            (Guard(Three), Reset) => 48,

            (Guard(One), CNS) => 22,
            (Guard(Two), CNS) => 40,
            (Guard(Three), CNS) => 82,

            (Guard(Two), Nitm) => 64,
            (Guard(Three), Nitm) => 148,

            (Guard(Two), Virus) => 40,
            (Guard(Three), Virus) => 60,

            // Only level 3 guards can send takeovers
            (Guard(Three), TakeOver) => 256,

            // Can't touch this
            (_, _) => unreachable!(),
        }
    }
}

/// This is what capitalists are all the rage about
pub mod gains {
    use super::Money;
    use crate::data::{Level, PacketType, Upgrade};
    use std::sync::atomic::Ordering;

    /// This will tell you if you'll receive any money this week
    pub fn parse_packet(node: &Upgrade, packet: &PacketType) -> Money {
        use {
            Level::*,
            PacketType::*,
            Upgrade::{Base, Compute as Cc, Guard, Relay},
        };

        /// A utility function which increments the packet progress
        ///
        /// Depending on the node that is processing the incoming
        /// packet, progress is either stepped by 1, 1.5, or 2 times
        /// the advertised step rate, which is set by the spawning
        /// node of the compute job.  This means that stronger compute
        /// nodes have a positive impact even in mostly low-level
        /// systems.
        ///
        /// This function returns if it reached or overflowed the max
        fn incr_compute(l: &Level, packet: &PacketType) -> bool {
            match (l, packet) {
                (lvl, Compute { max, curr, step }) => {
                    if curr.load(Ordering::Relaxed) < *max {
                        curr.fetch_add(
                            match lvl {
                                One => *step,
                                Two => (*step as f32 * 1.5) as u16,
                                Three => *step * 2,
                            },
                            Ordering::Relaxed,
                        );
                    }

                    // Did we reach the target?
                    curr.load(Ordering::Relaxed) >= *max
                }
                (_, _) => unreachable!(),
            }
        }

        match (node, packet) {
            // A basic income for all node and packets
            (Base, Ping) => 4,
            (Guard(One), Ping) | (Cc(One), Ping) | (Relay(One), Ping) => 6,
            (Guard(Two), Ping) | (Cc(Two), Ping) | (Relay(Two), Ping) => 11,
            (Guard(Three), Ping) | (Cc(Three), Ping) | (Relay(Three), Ping) => 17,

            // A compute node will always increment the packet
            // reference.  If it made it to "max", it will then also
            // return an amount of money that can be gained
            (Cc(ref lvl), Compute { ref max, .. }) if incr_compute(lvl, packet) => match lvl {
                One => *max,
                Two => max * 2,
                Three => max * 3,
            },

            // If in doubt, nada!
            (_, _) => 0,
        }
    }
}

pub mod strengths {
    use crate::data::Level::{self, *};

    /// Determine the maximum amount of resources for a compute packet
    pub fn compute_max(lvl: Level) -> u16 {
        match lvl {
            One => 65,
            Two => 120,
            Three => 250,
        }
    }

    /// Determine the step size by which a computation advances
    pub fn compute_step(lvl: Level) -> u16 {
        match lvl {
            One => 7,
            Two => 20,
            Three => 32,
        }
    }

    /// Determine the reward gained from processing a payload packet
    pub fn payload_reward(lvl: Level) -> u16 {
        match lvl {
            One => 70,
            Two => 150,
            Three => 275,
        }
    }
}