From 73de62794ac14a19a6bba9b4626c922c189d5b69 Mon Sep 17 00:00:00 2001 From: WiseDev <83840010+wisedevik@users.noreply.github.com> Date: Sun, 23 Aug 2026 15:28:52 +0300 Subject: [PATCH] let the bot borrow the player's deck to split the model question the account ids check out end to end: the player's avatar carries the profile account, the bot carries 0-0, LogicBattle::account_ids takes both from the avatars, and the client's getAccountIndex therefore finds the player at index 0 and makes them the bottom avatar. so isOwnedByBottomPlayer is right, and it is right in a way that matters: the player's units take the blue export names in Character::Character and the bot's take the red ones. red draws, blue does not. that leaves two candidates - an empty blue prefix on the row, or a data reference pointing at the wrong row whose blue prefix happens to be empty - and one run tells them apart. SCROLL_BOT_MIRRORS_DECK=1 hands the bot the player's cards; if its knight draws and ours does not, the rows are fine and the blue branch is the fault. --- crates/game-service/src/bot.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crates/game-service/src/bot.rs b/crates/game-service/src/bot.rs index 0802b6c..e496185 100644 --- a/crates/game-service/src/bot.rs +++ b/crates/game-service/src/bot.rs @@ -64,7 +64,16 @@ impl BotPlayer { avatar.name_change_state = -1; Self { avatar, deck } } + pub fn mirrors_deck() -> bool { + std::env::var("SCROLL_BOT_MIRRORS_DECK") + .map(|value| value == "1") + .unwrap_or(false) + } pub fn against(player: &LogicClientAvatar, fallback: &LogicSpellDeck) -> Self { + if Self::mirrors_deck() { + tracing::info!("the bot is playing the player's deck for this battle"); + return Self::matching(player.arena.clone(), player.score, fallback.clone()); + } let deck = predefined_deck() .filter(|deck| deck.filled_slot_count() == DECK_SLOT_COUNT) .unwrap_or_else(|| fallback.clone());