From 9d227fe4aa83a762dba18e3742f966a162fdaba3 Mon Sep 17 00:00:00 2001 From: Charlie Nolan Date: Sun, 16 Feb 2025 00:02:22 -0800 Subject: [PATCH] Reduced dynamic budget at low player count (#28300) * Reduced dynamic budget at low player count * Tests * One linty boy * I was, uh, making sure the test worked. That definitely wasn't a typo. <.< --- code/game/gamemodes/dynamic/dynamic.dm | 22 ++++++++++++++++++++-- code/tests/game_tests.dm | 1 + code/tests/test_dynamic_budget.dm | 15 +++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 code/tests/test_dynamic_budget.dm diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index b75cdc5fca9..e72612c3c7e 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -3,7 +3,7 @@ GLOBAL_LIST_EMPTY(dynamic_forced_rulesets) /datum/game_mode/dynamic name = "Dynamic" config_tag = "dynamic" - required_players = 10 + required_players = 0 /// Non-implied rulesets in play var/list/datum/ruleset/rulesets = list() /// Implied rulesets that are in play @@ -26,9 +26,27 @@ GLOBAL_LIST_EMPTY(dynamic_forced_rulesets) possible_rulesets |= ruleset.implied_ruleset_type.name to_chat(world, "Possible Rulesets: [english_list(possible_rulesets)]") +/// Calculates the dynamic budget based on the number of players in the round +/datum/game_mode/dynamic/proc/calculate_budget(players) + switch(players) + if(0 to 4) + // Flat budget of 7 + return 7 + if(5 to 20) + // +0.5 budget each for players 5-20 + // Cumulative total at 20 players: 15 + return 7 + 0.5 * (players - 4) + if(21 to 30) + // +1.5 budget each for players 21 to 30 + // Cumulative total at 30 players: 30 + return 15 + 1.5 * (players - 20) + else + // +1 budget each for players 31+, so just player count. + return players + /datum/game_mode/dynamic/proc/allocate_ruleset_budget() var/ruleset_budget = text2num(GLOB.dynamic_forced_rulesets["budget"] || pickweight(list("0" = 3, "1" = 8, "2" = 12, "3" = 3))) - antag_budget = num_players() + antag_budget = calculate_budget(num_players()) log_dynamic("Allocated gamemode budget: [ruleset_budget]") var/list/possible_rulesets = list() for(var/datum/ruleset/ruleset as anything in subtypesof(/datum/ruleset)) diff --git a/code/tests/game_tests.dm b/code/tests/game_tests.dm index 81b45121d88..ff155d0c96f 100644 --- a/code/tests/game_tests.dm +++ b/code/tests/game_tests.dm @@ -21,6 +21,7 @@ #include "test_components.dm" #include "test_config_sanity.dm" #include "test_crafting_lists.dm" +#include "test_dynamic_budget.dm" #include "test_elements.dm" #include "test_emotes.dm" #include "test_init_sanity.dm" diff --git a/code/tests/test_dynamic_budget.dm b/code/tests/test_dynamic_budget.dm new file mode 100644 index 00000000000..924b3090514 --- /dev/null +++ b/code/tests/test_dynamic_budget.dm @@ -0,0 +1,15 @@ +/datum/game_test/dynamic_budget/Run() + var/datum/game_mode/dynamic/dynamic = new() + + // If calculate_budgets updates, and these need to change to match, the pattern is to put an assert at the beginning and end of each distinct range of players (with 100 here standing in for a non-existent upper limit). + TEST_ASSERT_EQUAL(dynamic.calculate_budget(0), 7, "Flat budget incorrect.") + TEST_ASSERT_EQUAL(dynamic.calculate_budget(4), 7, "Flat budget incorrect.") + + TEST_ASSERT_EQUAL(dynamic.calculate_budget(5), 7.5, "Lowpop budget incorrect.") + TEST_ASSERT_EQUAL(dynamic.calculate_budget(20), 15, "Lowpop budget incorrect.") + + TEST_ASSERT_EQUAL(dynamic.calculate_budget(21), 16.5, "Midpop budget incorrect.") + TEST_ASSERT_EQUAL(dynamic.calculate_budget(30), 30, "Midpop budget incorrect.") + + TEST_ASSERT_EQUAL(dynamic.calculate_budget(31), 31, "Highpop budget incorrect.") + TEST_ASSERT_EQUAL(dynamic.calculate_budget(100), 100, "Highpop budget incorrect.")