# Dynamic 2024 (Mothblocks)
## Problems of Dynamic
- Several changes made it simpler, but is still complex to the point of odd behavior not being obvious if it's a bug or design issue.
- Configuration is far too complex, and has not gotten simpler
- It is especially too difficult to easily lower/raise chaos levels without very large knock on effects (e.g. just moving median threat up will not just add more traitors, but will also bring in more cults/nuke ops)
## What is Dynamic trying to *do*?
For as complex as Dynamic is, it ultimately is not very hard to explain what we want from it.
- Rounds have varying levels of chaos, ranging from "none" to "you were dead the moment you stepped foot onto the station"
- Most rounds should have a decent amount of chaos, because it's fun
- The start of a round (first 20 minutes) shouldn't be boring, but also not be chaotic to the point of most rounds ending quickly
- Chaos should be interspersed throughout a round
- This should roughly scale to population, such that low pop is playable without being regularly swarmed with antagonists
These are the core wishes from Dynamic. Several other desires, such as 90 minute rounds and diverse antagonists, will stem from this, but this is the foundation we must build upon.
### How does Dynamic currently try to do this?
Dynamic starts out with a threat level. Antagonists, in the form of rulesets, each have their own weight, threat, as well as an amount of threat required at all in order to roll. For example, for Blood Cult to spawn at lowpop, there might need to be 80 threat in the round, even though it will cost only around 10. This helps separate levels of chaos.
In order to maintain that chaos throughout the round, the initial budget of threat is split between roundstart and midround. Dynamic then tries to evenly split that midround threat across the remaining time. Midround rulesets are also either "light" (more likely to happen earlier), or "heavy" (vice-versa).
Finally, Dynamic has an extra mechanism for handling low-pop by capping the maximum amount of threat a round can have up to 20 pop.
This system has a decent amount of problems though.
- Cost of rulesets is hard to rationalize for anyone trying to configure the system (admins or contributors). Increasing a ruleset's threat cost does *not* necessarily correlate to it being more rare, but will instead take *away* from other antagonists, making less enjoyable rounds overall.
- This confusion leads to a lot of misconceptions from players about how antagonist selection actually happens. See Thieves being accused of wasting an antagonist roll even when they were a lone ruleset with extremely low threat cost.
- The midround split only works if every midround ruleset cooperates, in the sense that an early ruleset being too expensive will take away later threats that are meant to maintain chaos levels.
- Distribution of threat is done on a [Lorentz distribution](https://en.m.wikipedia.org/wiki/Cauchy_distribution). We have found that it is hard to adjust the probable chaos of rounds with this formula.
---
Dynamic can accomplish its same goals more precisely, accurately, and comprehensibly by following the requirements to the letter.
Firstly, we remove threat as it exists today. The difference between something like 40 and 50 threat is very minimal as a player, but large in terms of code. Instead, we will refer to **tiers** of threat. If it helps, you can think of these in terms of the existing advisory levels ("Red Star" etc) which we already use to abstract threat levels to something players can more easily comprehend.
In essence, we have four tiers. 1 is considered low threat (not greenshifts, we will discuss those later), 2 is considered low-medium, 3 is considered medium-high, and 4 is considered very high.
A tier is represented as a set of simple knobs. Primarily:
- Weight
- Range of roundstart rulesets to roll
- Range of light midround rulesets to roll
- Range of heavy midround rulesets to roll
- Range of latejoin rulesets to roll
Other knobs, such as light/heavy timers (when to start guaranteeing heavies, etc) are optional but ought to be generally unnecessary, and will derive from some global parameters.
Some sample numbers (not set in stone, but simply to give you an idea of the thinking):
1. Tier 1 (Low threat)
- 8% chance
- 1 roundstart
- 1-2 light midrounds
- 0-1 heavy midrounds
- Heavy ruleset takes 60 minutes before starting
- 1 latejoin
2. Tier 2 (low-med threat)
- 24% chance
- 1-2 roundstart
- 1-2 light midrounds
- 1 heavy midround
- 1-2 latejoin
3. Tier 3 (med-high threat)
- 52% chance
- 2-3 roundstart
- 2-3 light midrounds
- 0-2 heavy midrounds
- 1-3 latejoins
4. Tier 4 (high threat)
- 16% chance
- 3-4 roundstart
- 1-2 light midrounds
- 1-2 heavy midrounds
- Heavy rulesets take 30 miuntes before starting
- 2-3 latejoins
The benefits of this over the current threat system is that we have precise control over how often chaos happens, and what it means. If midrounds are happening too often, we can trivially lower the number of midrounds, rather than putzing around with other numbers that will correlate to the same effect, while potentially affecting other unrelated systems.
From this system, we can now also dramatically simplify ruleset configuration and requirements. For substantial antagonists like Blood Cult or Revolution, we can give them different weights at different tiers, or even lock them out of some tiers completely. This might look like...
```dm=
/datum/dynamic_ruleset/roundstart/blood_cult
name = "Blood Cult"
// weight is either a flat number, or a list keyed by tier
weight = list(
DYNAMIC_TIER_2 = 0, // We don't need to specify DYNAMIC_TIER_1,
// it's assumed lowest. Same goes for vice versa:
// if we didn't specify the highest tier, it would
// copy the closest one.
DYNAMIC_TIER_3 = 2,
DYNAMIC_TIER_4 = 10, // These weights may still confuse you.
// Don't worry, read "Unnecessary but coming...".
)
```
## Adjusting for population
Most rulesets already handle their own impact on population through the `antag_cap` variable. This determines how many antagonists it will create depending on the population. For example, the roundstart "Traitors" ruleset will roll 1 traitor for every 38 players. However, with the removal of the `requirements` variable (which controls necessary threat per population), we face a problem where we want rulesets like Malfunctioning AI to still be possible on low-pop, but be more likely on high-pop. Malfunctioning AI in specific, for example, only becomes possible at around 21 pop, but only becomes its likeliest around 60.
This desire complicates things. We must acknowledge that "2-4 midround rulesets" can be significantly more impactful to a 20 pop round than an 80 pop one. The current proposed solution is to try to work with the existing system by applying a few caveats.
1. A tier can specify a minimum population requirement. Tier 4 will likely require 25 population or so before being available.
- You probably ought to be able to configure the weights per population as well.
3. The minimum amount of rulesets is favored correlated to how low the population is. For example, if a tier specifies 1-3 roundstart rulesets, then at something like 20 pop, it'll overwhelmingly favor 1. This may be implemented in something like steps: "at 25 pop, you can now be up to half your max range, at 35 pop, you can now have all of it", etc.
- This is likely the most complicated part of the new Dynamic calculations.
## Green shifts
Green shifts work intuitively in this system as an added tier with zero of any kind of ruleset.
## The command report
Today, the command report is based on threat level. Every advisory level carries a range to it. The threat level it shows is the precise threat level, +/- some fudge, with a chance to be completely wrong. The intent of the report is to give you a ballpark estimate of what the round is going to be like, but not with enough certainty to truly rely on.
With this in mind, we can approximate the same system. Each tier will associate itself with an advisory level (e.g. tier 3 is "orange star"). The tier shown on the paper will have a 75% chance to be correct, a 15% chance to choose a tier above/below the current one, and a 10% chance to be a completely random, incorrect tier. Numbers not set in stone.
If this is not satisfactory enough, advisory levels can also be dependent on the number of rulesets rolled. For instance, we could have one "star" level for less than 50% of potential rulesets rolled, and one for more than 50% rolled. I suspect this will not be necessary, but welcome.
## Random events
Currently, Dynamic cancels rulesets if a random event has happened too recently, or is going to happen too soon. We can improve this existing hijacking system by reversing the control--the random event system can pick something else if it knows Dynamic is going to create an antagonist soon.
There is a possibility we can have specific tiers increase likelihood of random events as well.
---
## Unnecessary, but coming...
But alongside these changes, a panel in moth.fans will be created to immediately simulate Dynamic rounds with a given configuration/addition. At the same time, you will be able to adjust configurations through the panel in order to see how they would affect gameplay, while exporting any changes you make back into config. This helps the complexity problems, as well as making it impossible to make broken changes, which happens frequently. These simulations could also be shown to players in the Dynamic changelog thread.
For example, if you want to make Blood Cult less common, you would be able to simulate and get a rough % chance of how common it is now, lower the weight, and see how it adjusts.