From 7ddfddb3a8cf3cb5e0f30aa6b84b24f615a68af1 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 15 May 2023 23:10:59 -0400 Subject: [PATCH 1/6] Bots: Modify friction changes with gamespeed --- src/k_kart.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 91b2802ee..7d9ec7ed3 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10270,7 +10270,10 @@ static void K_AirFailsafe(player_t *player) // fixed_t K_PlayerBaseFriction(player_t *player, fixed_t original) { - const fixed_t factor = FixedDiv(FRACUNIT - original, FRACUNIT - ORIG_FRICTION); + const fixed_t factor = FixedMul( + FixedDiv(FRACUNIT - original, FRACUNIT - ORIG_FRICTION), + K_GetKartGameSpeedScalar(gamespeed) + ); fixed_t frict = original; if (K_PodiumSequence() == true) From 5b5323226f45923530e73c9e9a4fd449f5d4d870 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 15 May 2023 23:53:32 -0400 Subject: [PATCH 2/6] Bots: Rebalance rubberband speeds - Lv.1 has a significanty lower minimum top speed (from 75% -> 50%) - Lv.MAX has a significantly higher minimum top speed (from 112.5% -> 125%) - Every bot level has a slightly lower maximum top speed (Lv.1: 100% -> 80%, Lv.MAX: 220% -> 200%) - Uses easing functions now to make the distance rubberbanding applies to, and the rubberbanding curves, much more customizable. --- src/k_bot.c | 52 +++++++++++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index 7756c7fe6..39cf55ec5 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -30,6 +30,7 @@ #include "m_perfstats.h" #include "k_podium.h" #include "k_respawn.h" +#include "m_easing.h" /*-------------------------------------------------- boolean K_AddBot(UINT8 skin, UINT8 difficulty, UINT8 *p) @@ -486,8 +487,9 @@ static UINT32 K_BotRubberbandDistance(player_t *player) --------------------------------------------------*/ fixed_t K_BotRubberband(player_t *player) { - fixed_t rubberband = FRACUNIT; - fixed_t rubbermax, rubbermin; + fixed_t rubberband = FRACUNIT >> 1; + fixed_t rubbermin = FRACUNIT; + fixed_t rubbermax = FRACUNIT; player_t *firstplace = NULL; UINT8 i; @@ -511,6 +513,18 @@ fixed_t K_BotRubberband(player_t *player) } } + // Lv. 1: x0.5 min + // Lv. 5: x0.75 min + // Lv. 9: x1.0 min + // Lv. MAX: x1.25 min + rubbermin = FRACUNIT - (((FRACUNIT/2) * (DIFFICULTBOT - player->botvars.difficulty)) / (DIFFICULTBOT - 1)); + + // Lv. 1: x0.8 max + // Lv. 5: x1.2 max + // Lv. 9: x1.4 max + // Lv. MAX: x2.0 max + rubbermax = FRACUNIT + ((FRACUNIT * (player->botvars.difficulty - 3)) / 10); + for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i] || players[i].spectator) @@ -534,43 +548,23 @@ fixed_t K_BotRubberband(player_t *player) if (firstplace != NULL) { + const UINT32 spacing = FixedDiv(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT; const UINT32 wanteddist = firstplace->distancetofinish + K_BotRubberbandDistance(player); const INT32 distdiff = player->distancetofinish - wanteddist; - if (wanteddist > player->distancetofinish) - { - // Whoa, you're too far ahead! Slow back down a little. - rubberband += (DIFFICULTBOT - min(DIFFICULTBOT, player->botvars.difficulty)) * (distdiff / 3); - } - else - { - // Catch up to your position! - rubberband += player->botvars.difficulty * distdiff; - } + rubberband += (distdiff * (FRACUNIT >> 1)) / spacing; } - // Lv. 1: x1.0 max - // Lv. 5: x1.4 max - // Lv. 9: x1.8 max - // Lv. MAX: x2.2 max - rubbermax = FRACUNIT + ((FRACUNIT * (player->botvars.difficulty - 1)) / 10); - - // Lv. 1: x0.75 min - // Lv. 5: x0.875 min - // Lv. 9: x1.0 min - // Lv. MAX: x1.125 min - rubbermin = FRACUNIT - (((FRACUNIT/4) * (DIFFICULTBOT - player->botvars.difficulty)) / (DIFFICULTBOT - 1)); - - if (rubberband > rubbermax) + if (rubberband > FRACUNIT) { - rubberband = rubbermax; + rubberband = FRACUNIT; } - else if (rubberband < rubbermin) + else if (rubberband < 0) { - rubberband = rubbermin; + rubberband = 0; } - return rubberband; + return Easing_Linear(rubberband, rubbermin, rubbermax); } /*-------------------------------------------------- From 724beb0ffe87f35ee6949db4dd04c63a6d2979e3 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 19 May 2023 01:00:55 -0400 Subject: [PATCH 3/6] Bots: Improve rubberbanding further - Use easing functions for the rubberbanding values themselves, for more fine-control over the end-points and the curves. - Fixed K_UpdateRubberband being broken from using shift instead of divide. - Rename `debugbotpredict` to `debugbots`, it now displays some of the bots' botvars values as well. If the player isn't a bot, it will show them from the first place bot (for inspecting the rubberband value). - Bot turning buff was increased, from x1.25 to x2.0. Noticed that Tails bots were failing turns on Popcorn Workshop. I personally think that Tails bots shouldn't be failing very many turns unless if they're finding objects, and constant wall-bumping should be reserved for Eggman and Metal :P --- src/d_netcmd.c | 2 +- src/d_netcmd.h | 2 +- src/k_bot.c | 58 ++++++++++++++++++++++-------------------- src/k_hud.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/k_kart.c | 4 +-- 5 files changed, 103 insertions(+), 31 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a9e7afa28..380a3e609 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -449,7 +449,7 @@ consvar_t cv_kartdebugdistribution = CVAR_INIT ("debugitemodds", "Off", CV_NETVA consvar_t cv_kartdebughuddrop = CVAR_INIT ("debugitemdrop", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); static CV_PossibleValue_t kartdebugwaypoint_cons_t[] = {{0, "Off"}, {1, "Forwards"}, {2, "Backwards"}, {0, NULL}}; consvar_t cv_kartdebugwaypoints = CVAR_INIT ("debugwaypoints", "Off", CV_NETVAR|CV_CHEAT, kartdebugwaypoint_cons_t, NULL); -consvar_t cv_kartdebugbotpredict = CVAR_INIT ("debugbotpredict", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); +consvar_t cv_kartdebugbots = CVAR_INIT ("debugbots", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); consvar_t cv_kartdebugnodes = CVAR_INIT ("debugnodes", "Off", CV_CHEAT, CV_OnOff, NULL); consvar_t cv_kartdebugcolorize = CVAR_INIT ("debugcolorize", "Off", CV_CHEAT, CV_OnOff, NULL); consvar_t cv_kartdebugdirector = CVAR_INIT ("debugdirector", "Off", CV_CHEAT, CV_OnOff, NULL); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 5428d3c04..c9938b4e5 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -96,7 +96,7 @@ extern consvar_t cv_botscanvote; extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartdebugdistribution, cv_kartdebughuddrop; extern consvar_t cv_kartdebugnodes, cv_kartdebugcolorize, cv_kartdebugdirector; extern consvar_t cv_spbtest, cv_reducevfx; -extern consvar_t cv_kartdebugwaypoints, cv_kartdebugbotpredict; +extern consvar_t cv_kartdebugwaypoints, cv_kartdebugbots; extern consvar_t cv_debugrank; extern consvar_t cv_battletest; diff --git a/src/k_bot.c b/src/k_bot.c index 39cf55ec5..d9533ceb4 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -487,11 +487,19 @@ static UINT32 K_BotRubberbandDistance(player_t *player) --------------------------------------------------*/ fixed_t K_BotRubberband(player_t *player) { + const fixed_t difficultyEase = ((player->botvars.difficulty - 1) * FRACUNIT) / (DIFFICULTBOT - 1); + + // Lv. 1: x0.35 min + // Lv. 9: x1.35 min + const fixed_t rubbermin = Easing_Linear(difficultyEase, FRACUNIT * 35 / 100, FRACUNIT * 135 / 100); + + // Lv. 1: x1.0 max + // Lv. 9: x1.65 max + const fixed_t rubbermax = Easing_Linear(difficultyEase, FRACUNIT, FRACUNIT * 165 / 100); + fixed_t rubberband = FRACUNIT >> 1; - fixed_t rubbermin = FRACUNIT; - fixed_t rubbermax = FRACUNIT; player_t *firstplace = NULL; - UINT8 i; + size_t i = SIZE_MAX; if (player->exiting) { @@ -513,18 +521,6 @@ fixed_t K_BotRubberband(player_t *player) } } - // Lv. 1: x0.5 min - // Lv. 5: x0.75 min - // Lv. 9: x1.0 min - // Lv. MAX: x1.25 min - rubbermin = FRACUNIT - (((FRACUNIT/2) * (DIFFICULTBOT - player->botvars.difficulty)) / (DIFFICULTBOT - 1)); - - // Lv. 1: x0.8 max - // Lv. 5: x1.2 max - // Lv. 9: x1.4 max - // Lv. MAX: x2.0 max - rubbermax = FRACUNIT + ((FRACUNIT * (player->botvars.difficulty - 3)) / 10); - for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i] || players[i].spectator) @@ -548,20 +544,28 @@ fixed_t K_BotRubberband(player_t *player) if (firstplace != NULL) { - const UINT32 spacing = FixedDiv(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT; + // Lv. 1: 5120 units + // Lv. 9: 320 units + const fixed_t spacing = FixedDiv( + max( + 80 * mapobjectscale, + Easing_Linear(difficultyEase, 5120 * mapobjectscale, 320 * mapobjectscale) + ), + K_GetKartGameSpeedScalar(gamespeed) + ) / FRACUNIT; const UINT32 wanteddist = firstplace->distancetofinish + K_BotRubberbandDistance(player); const INT32 distdiff = player->distancetofinish - wanteddist; - rubberband += (distdiff * (FRACUNIT >> 1)) / spacing; - } + rubberband = FixedDiv(distdiff + spacing, spacing * 2); - if (rubberband > FRACUNIT) - { - rubberband = FRACUNIT; - } - else if (rubberband < 0) - { - rubberband = 0; + if (rubberband > FRACUNIT) + { + rubberband = FRACUNIT; + } + else if (rubberband < 0) + { + rubberband = 0; + } } return Easing_Linear(rubberband, rubbermin, rubbermax); @@ -578,7 +582,7 @@ fixed_t K_UpdateRubberband(player_t *player) fixed_t ret = player->botvars.rubberband; // Ease into the new value. - ret += (dest - player->botvars.rubberband) >> 3; + ret += (dest - player->botvars.rubberband) / 8; return ret; } @@ -1732,7 +1736,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) // Free the prediction we made earlier if (predict != NULL) { - if (cv_kartdebugbotpredict.value != 0 && player - players == displayplayers[0]) + if (cv_kartdebugbots.value != 0 && player - players == displayplayers[0]) { K_DrawPredictionDebug(predict, player); } diff --git a/src/k_hud.c b/src/k_hud.c index a278225dc..b0351baf1 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -4994,6 +4994,73 @@ static void K_DrawWaypointDebugger(void) } } +static void K_DrawBotDebugger(void) +{ + player_t *bot = NULL; + + if (cv_kartdebugbots.value == 0) + { + return; + } + + if (stplyr != &players[displayplayers[0]]) // only for p1 + { + return; + } + + if (stplyr->bot == true) + { + // we ARE the bot + bot = stplyr; + } + else + { + // get winning bot + size_t i; + for (i = 0; i < MAXPLAYERS; i++) + { + player_t *p = NULL; + + if (playeringame[i] == false) + { + continue; + } + + p = &players[i]; + if (p->spectator == true || p->bot == false) + { + continue; + } + + if (bot == NULL || p->distancetofinish < bot->distancetofinish) + { + bot = p; + } + } + } + + if (bot == NULL) + { + // no bot exists? + return; + } + + V_DrawSmallString(8, 8, 0, va("Difficulty: %d / %d", bot->botvars.difficulty, MAXBOTDIFFICULTY)); + V_DrawSmallString(8, 12, 0, va("Difficulty increase: %d", bot->botvars.diffincrease)); + V_DrawSmallString(8, 16, 0, va("Rival: %d", (UINT8)(bot->botvars.rival == true))); + V_DrawSmallString(8, 20, 0, va("Rubberbanding: %.02f", FIXED_TO_FLOAT(bot->botvars.rubberband) * 100.0f)); + + V_DrawSmallString(8, 26, 0, va("Item delay: %d", bot->botvars.itemdelay)); + V_DrawSmallString(8, 30, 0, va("Item confirm: %d", bot->botvars.itemconfirm)); + + V_DrawSmallString(8, 36, 0, va("Turn: %d / %d / %d", -BOTTURNCONFIRM, bot->botvars.turnconfirm, BOTTURNCONFIRM)); + V_DrawSmallString(8, 40, 0, va("Spindash: %d / %d", bot->botvars.spindashconfirm, BOTSPINDASHCONFIRM)); + V_DrawSmallString(8, 44, 0, va("Respawn: %d / %d", bot->botvars.respawnconfirm, BOTRESPAWNCONFIRM)); + + V_DrawSmallString(8, 50, 0, va("Item priority: %d", bot->botvars.roulettePriority)); + V_DrawSmallString(8, 54, 0, va("Item timeout: %d", bot->botvars.rouletteTimeout)); +} + static void K_DrawGPRankDebugger(void) { gp_rank_e grade = GRADE_E; @@ -5321,6 +5388,7 @@ void K_drawKartHUD(void) } K_DrawWaypointDebugger(); + K_DrawBotDebugger(); K_DrawDirectorDebugger(); K_DrawGPRankDebugger(); } diff --git a/src/k_kart.c b/src/k_kart.c index 7d9ec7ed3..6339b9e02 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -311,7 +311,7 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartdebugdistribution); CV_RegisterVar(&cv_kartdebughuddrop); CV_RegisterVar(&cv_kartdebugwaypoints); - CV_RegisterVar(&cv_kartdebugbotpredict); + CV_RegisterVar(&cv_kartdebugbots); CV_RegisterVar(&cv_kartdebugnodes); CV_RegisterVar(&cv_kartdebugcolorize); @@ -9004,7 +9004,7 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) if (K_PlayerUsesBotMovement(player)) { - turnfixed = FixedMul(turnfixed, 5*FRACUNIT/4); // Base increase to turning + turnfixed = FixedMul(turnfixed, 2*FRACUNIT); // Base increase to turning } if (player->drift != 0 && P_IsObjectOnGround(player->mo)) From cbb684cd251dd6631cf51fbe2161fe5520c645bb Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 19 May 2023 01:29:46 -0400 Subject: [PATCH 4/6] Bots: Add bot name to debugbots For the frontrunner behavior --- src/k_hud.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index b0351baf1..74a35da30 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -5045,20 +5045,22 @@ static void K_DrawBotDebugger(void) return; } - V_DrawSmallString(8, 8, 0, va("Difficulty: %d / %d", bot->botvars.difficulty, MAXBOTDIFFICULTY)); - V_DrawSmallString(8, 12, 0, va("Difficulty increase: %d", bot->botvars.diffincrease)); - V_DrawSmallString(8, 16, 0, va("Rival: %d", (UINT8)(bot->botvars.rival == true))); - V_DrawSmallString(8, 20, 0, va("Rubberbanding: %.02f", FIXED_TO_FLOAT(bot->botvars.rubberband) * 100.0f)); + V_DrawSmallString(16, 8, V_YELLOWMAP, va("Bot: %s", player_names[bot - players])); - V_DrawSmallString(8, 26, 0, va("Item delay: %d", bot->botvars.itemdelay)); - V_DrawSmallString(8, 30, 0, va("Item confirm: %d", bot->botvars.itemconfirm)); + V_DrawSmallString(8, 14, 0, va("Difficulty: %d / %d", bot->botvars.difficulty, MAXBOTDIFFICULTY)); + V_DrawSmallString(8, 18, 0, va("Difficulty increase: %d", bot->botvars.diffincrease)); + V_DrawSmallString(8, 22, 0, va("Rival: %d", (UINT8)(bot->botvars.rival == true))); + V_DrawSmallString(8, 26, 0, va("Rubberbanding: %.02f", FIXED_TO_FLOAT(bot->botvars.rubberband) * 100.0f)); - V_DrawSmallString(8, 36, 0, va("Turn: %d / %d / %d", -BOTTURNCONFIRM, bot->botvars.turnconfirm, BOTTURNCONFIRM)); - V_DrawSmallString(8, 40, 0, va("Spindash: %d / %d", bot->botvars.spindashconfirm, BOTSPINDASHCONFIRM)); - V_DrawSmallString(8, 44, 0, va("Respawn: %d / %d", bot->botvars.respawnconfirm, BOTRESPAWNCONFIRM)); + V_DrawSmallString(8, 32, 0, va("Item delay: %d", bot->botvars.itemdelay)); + V_DrawSmallString(8, 36, 0, va("Item confirm: %d", bot->botvars.itemconfirm)); - V_DrawSmallString(8, 50, 0, va("Item priority: %d", bot->botvars.roulettePriority)); - V_DrawSmallString(8, 54, 0, va("Item timeout: %d", bot->botvars.rouletteTimeout)); + V_DrawSmallString(8, 42, 0, va("Turn: %d / %d / %d", -BOTTURNCONFIRM, bot->botvars.turnconfirm, BOTTURNCONFIRM)); + V_DrawSmallString(8, 46, 0, va("Spindash: %d / %d", bot->botvars.spindashconfirm, BOTSPINDASHCONFIRM)); + V_DrawSmallString(8, 50, 0, va("Respawn: %d / %d", bot->botvars.respawnconfirm, BOTRESPAWNCONFIRM)); + + V_DrawSmallString(8, 56, 0, va("Item priority: %d", bot->botvars.roulettePriority)); + V_DrawSmallString(8, 60, 0, va("Item timeout: %d", bot->botvars.rouletteTimeout)); } static void K_DrawGPRankDebugger(void) From 2eff6d7fb54d111fa564cc4d19a6754fdce986c1 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 19 May 2023 06:08:37 -0400 Subject: [PATCH 5/6] Bots: Make them stay farther from the beam --- src/k_bot.c | 4 ++-- src/k_botsearch.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index d9533ceb4..1bbe92c28 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -1557,8 +1557,8 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if (leveltime <= starttime && finishBeamLine != NULL) { // Handle POSITION!! - const fixed_t distBase = 384*mapobjectscale; - const fixed_t distAdjust = 64*mapobjectscale; + const fixed_t distBase = 480*mapobjectscale; + const fixed_t distAdjust = 128*mapobjectscale; const fixed_t closeDist = distBase + (distAdjust * (9 - player->kartweight)); const fixed_t farDist = closeDist + (distAdjust * 2); diff --git a/src/k_botsearch.c b/src/k_botsearch.c index 4d5088aa7..88f61b90b 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -989,7 +989,7 @@ INT32 K_PositionBully(player_t *player) anglediff = 360-(AngleFixed(angle)>>FRACBITS); } - if (anglediff < 30) + if (abs(anglediff) < 30) return 0; if (anglediff < 0) From f1d5867877f7c11cb0c8935b97c0a66507314291 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 19 May 2023 06:09:29 -0400 Subject: [PATCH 6/6] Bots: Make Lv.1 end worse at timing items --- src/k_botitem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_botitem.c b/src/k_botitem.c index 8758db8dc..dc69cc058 100644 --- a/src/k_botitem.c +++ b/src/k_botitem.c @@ -1394,8 +1394,8 @@ static void K_BotItemRings(player_t *player, ticcmd_t *cmd) --------------------------------------------------*/ static void K_BotItemRouletteMash(player_t *player, ticcmd_t *cmd) { - // 12 tics late for Lv.1, frame-perfect for Lv.MAX - const tic_t confirmTime = (MAXBOTDIFFICULTY - player->botvars.difficulty); + // 24 tics late for Lv.1, frame-perfect for Lv.MAX + const tic_t confirmTime = (MAXBOTDIFFICULTY - player->botvars.difficulty) * 2; if (K_ItemButtonWasDown(player) == true) {