"""Behavioral pattern randomization for anti-detection. Varies bot behavior to avoid detectable patterns like identical farming routes, consistent timing, or perfect execution. """ import random import logging from typing import List, Tuple, Callable, Any logger = logging.getLogger(__name__) class RouteRandomizer: """Randomizes farming routes and action sequences.""" def __init__(self, variation_factor: float = 0.15): self.variation_factor = variation_factor def shuffle_optional_steps( self, steps: List[Any], required_indices: List[int] = None, ) -> List[Any]: """Shuffle non-required steps while keeping required ones in order.""" required_indices = set(required_indices or []) required = [(i, s) for i, s in enumerate(steps) if i in required_indices] optional = [s for i, s in enumerate(steps) if i not in required_indices] random.shuffle(optional) result = [] opt_iter = iter(optional) req_iter = iter(required) next_req = next(req_iter, None) for i in range(len(steps)): if next_req and next_req[0] == i: result.append(next_req[1]) next_req = next(req_iter, None) else: result.append(next(opt_iter)) return result def vary_route( self, waypoints: List[Tuple[int, int]], ) -> List[Tuple[int, int]]: """Add slight variations to a route's waypoints.""" varied = [] for x, y in waypoints: offset_x = int(x * self.variation_factor * random.uniform(-1, 1)) offset_y = int(y * self.variation_factor * random.uniform(-1, 1)) varied.append((x + offset_x, y + offset_y)) return varied def should_skip_optional(self, skip_chance: float = 0.1) -> bool: """Randomly decide to skip an optional action.""" return random.random() < skip_chance class ActionVariator: """Varies how actions are performed.""" @staticmethod def vary_count(target: int, variance: int = 1) -> int: """Vary a repeat count (e.g., click 2-4 times instead of always 3).""" return max(1, target + random.randint(-variance, variance)) @staticmethod def random_order(actions: List[Callable]) -> List[Callable]: """Randomize the order of independent actions.""" shuffled = actions.copy() random.shuffle(shuffled) return shuffled