Greasy Fork

来自缓存

Greasy Fork is available in English.

Slither Full Auto Bot (Responsive Overlay)

Slither.io bot with enhanced overlay. Automatically collects food and avoids nearby enemies using strategic pathfinding.

目前为 2025-03-28 提交的版本。查看 最新版本

// ==UserScript==
// @name         Slither Full Auto Bot (Responsive Overlay)
// @namespace    http://slither.com/io
// @version      1.4
// @description  Slither.io bot with enhanced overlay. Automatically collects food and avoids nearby enemies using strategic pathfinding.
// @author       EliottValette
// @match        http://slither.com/io
// @grant        none
// @license      MIT
// ==/UserScript==

/*
===================================================
Section 1: Utility Functions and Debugging
===================================================
*/

// Custom log function (only displays if "logDebugging" is enabled)
window.log = (...args) => window.logDebugging && console.log(...args);

// Functions to save and load preferences in localStorage
const savePreference = (key, value) => localStorage.setItem(key, value);
const loadPreference = (key, def) => JSON.parse(localStorage.getItem(key)) ?? def;

let Logger = 0;
let IsBotActive = true;
let targetFood = null;
let targetFoodTimestamp = 0;
let blacklistedFoods = {};
let criticDanger = false;

// Add listener to memorize real mouse position
window.mousePos = { x: 0, y: 0 };
document.addEventListener('mousemove', function(e) {
    window.mousePos = { x: e.clientX, y: e.clientY };
});

// Variable to memorize bot target position (the "bot mouse pose")
window.botTargetPos = null;

console.log('Bot Starting');

/*
===================================================
Section 2: Window Object Debug Scan
===================================================
After 5 seconds, scans the window object to find
potential snake objects (presence of xx and yy)
*/
setTimeout(() => {
    for (let key in window) {
        try {
            let val = window[key];
            if (val && typeof val === 'object') {
                // Checks if the object has coordinates
                if ('xx' in val && 'yy' in val) {
                    console.log(`🟢 Snake? -> window.${key}`, val);
                }
                // Checks if the object is an array of objects with coordinates
                if (Array.isArray(val) && val.length > 0 && val[0] && 'xx' in val[0] && 'yy' in val[0]) {
                    console.log(`🍏 Array of objects with coords? -> window.${key}`, val);
                }
            }
        } catch (e) {
            // In case of error, move to next property
        }
    }
}, 5000);

/*
===================================================
Section 3: Improved Interface Overlay
===================================================
Creation of a unique container that displays bot status,
coordinates and enemy count in real-time.
*/
(function setupOverlayUI() {
    // Creation of main container with semi-transparent background
    const overlayContainer = document.createElement('div');
    overlayContainer.id = 'bot-overlay-container';
    overlayContainer.style.cssText = `
        position: fixed;
        top: 10px;
        left: 10px;
        background: rgba(0, 0, 0, 0.5);
        padding: 10px;
        border-radius: 5px;
        z-index: 9999;
        font-family: Arial, sans-serif;
        color: #FFF;
        font-size: 14px;
    `;
    document.body.appendChild(overlayContainer);

    // Creation of sub-elements for status, coordinates and enemy count
    const statusDiv = document.createElement('div');
    statusDiv.id = 'bot_status_overlay';
    statusDiv.textContent = 'Status: BOT ON (To Toggle - Press t)';
    overlayContainer.appendChild(statusDiv);

    const coordsDiv = document.createElement('div');
    coordsDiv.id = 'bot_coords_overlay';
    coordsDiv.textContent = 'Coords: loading...';
    overlayContainer.appendChild(coordsDiv);

    const enemyDiv = document.createElement('div');
    enemyDiv.id = 'bot_enemies_overlay';
    enemyDiv.textContent = 'Enemies: loading...';
    overlayContainer.appendChild(enemyDiv);

    const nearEnemiesDiv = document.createElement('div');
    nearEnemiesDiv.id = 'bot_enemies_near_overlay';
    nearEnemiesDiv.textContent = 'Enemies (Near): loading...';
    overlayContainer.appendChild(nearEnemiesDiv);

    const midEnemiesDiv = document.createElement('div');
    midEnemiesDiv.id = 'bot_enemies_mid_overlay';
    midEnemiesDiv.textContent = 'Enemies (Mid): loading...';
    overlayContainer.appendChild(midEnemiesDiv);

    const farEnemiesDiv = document.createElement('div');
    farEnemiesDiv.id = 'bot_enemies_far_overlay';
    farEnemiesDiv.textContent = 'Enemies (Far): loading...';
    overlayContainer.appendChild(farEnemiesDiv);

    const criticDangerDiv = document.createElement('div');
    criticDangerDiv.id = 'bot_critic_danger_overlay';
    criticDangerDiv.textContent = 'Danger: loading...';
    overlayContainer.appendChild(criticDangerDiv);

    // Continuous overlay update via requestAnimationFrame
    function updateOverlay() {
        if (window.slither && typeof window.slither.xx === 'number') {
            statusDiv.textContent = IsBotActive ? 'Status: BOT ON (To Turn OFF - Press t)' : 'Status: BOT OFF (To Turn ON - Press t)';
            coordsDiv.textContent = `Coords: ${Math.round(window.slither.xx)} / ${Math.round(window.slither.yy)}`;
            criticDangerDiv.textContent = `Danger: ${criticDanger}`;
        }
        if (Array.isArray(window.slithers) && window.slither) {
            const self = window.slither;
            // Building enemy lists based on distance from their body points
            const nearEnemies = [];
            const midEnemies = [];
            const farEnemies = [];
            window.slithers.forEach(e => {
                if (!e || typeof e.xx !== 'number' || typeof e.yy !== 'number' || e.xx === self.xx)
                    return;
                const bodyPoints = getEnemyBodyPoints(e);
                let minDistance = Infinity;
                let closestPoint = null;
                bodyPoints.forEach(p => {
                    const dx = p.xx - self.xx;
                    const dy = p.yy - self.yy;
                    const dist = Math.sqrt(dx * dx + dy * dy);
                    if (dist < minDistance) {
                        minDistance = dist;
                        closestPoint = p;
                    }
                });
                if (closestPoint) {
                    if (minDistance < 300) {
                        nearEnemies.push({ enemy: e, dist: minDistance, point: closestPoint });
                    } else if (minDistance >= 300 && minDistance <= 700) {
                        midEnemies.push({ enemy: e, dist: minDistance, point: closestPoint });
                    } else if (minDistance > 700) {
                        farEnemies.push({ enemy: e, dist: minDistance, point: closestPoint });
                    }
                }
            });
            enemyDiv.textContent = 'Enemies: ' + window.slithers.length;
            nearEnemiesDiv.textContent = 'Enemies (Near): ' + nearEnemies.map(e => e.enemy.id || `(${Math.round(e.point.xx)},${Math.round(e.point.yy)})`).join(', ');
            midEnemiesDiv.textContent = 'Enemies (Mid): ' + midEnemies.map(e => e.enemy.id || `(${Math.round(e.point.xx)},${Math.round(e.point.yy)})`).join(', ');
            farEnemiesDiv.textContent = 'Enemies (Far): ' + farEnemies.map(e => e.enemy.id || `(${Math.round(e.point.xx)},${Math.round(e.point.yy)})`).join(', ');
        }
        requestAnimationFrame(updateOverlay);
    }
    requestAnimationFrame(updateOverlay);
})();

/*
===================================================
Section 4: World to Screen Coordinate Conversion
===================================================
Utility function to convert game coordinates
(in "world") to screen coordinates.
*/
const worldToScreen = (xx, yy) => {
    const mapX = (xx - window.view_xx) * window.gsc + window.mww2;
    const mapY = (yy - window.view_yy) * window.gsc + window.mhh2;
    return { x: mapX, y: mapY };
};

/*
===================================================
Section 5: Enemy Processing
===================================================
Functions to extract enemy body points and
calculate line color based on distance.
*/

// Gets enemy body points by traversing its segments
function getEnemyBodyPoints(enemy) {
    const points = [];
    if (!enemy.pts) return points;

    for (const segment of enemy.pts) {
        if (!segment.fxs || !segment.fys) continue;

        // Sampling: we get about 10% of the segment points
        const step = Math.max(1, Math.floor(segment.fxs.length / 10));
        for (let i = 0; i < segment.fxs.length; i += step) {
            const x = segment.xx + segment.fxs[i];
            const y = segment.yy + segment.fys[i];

            if (isFinite(x) && isFinite(y)) {
                points.push({ xx: x, yy: y });
            }
        }
    }
    return points;
}

// Calculates a color transitioning from red (close) to green (far)
function DangerColor(start, end) {
    const dx = end.x - start.x;
    const dy = end.y - start.y;
    const dist = Math.sqrt(dx * dx + dy * dy);
    const maxDist = 3000; // Maximum distance to fully transition to green
    const dangerRatio = Math.max(0, Math.min(1, 1 - dist / maxDist));
    const r = Math.floor(255 * dangerRatio);
    const g = Math.floor(255 * (1 - dangerRatio));
    return `rgb(${r},${g},0)`;
}

/*
===================================================
Section 6: Drawing Lines to Enemies and Food
===================================================
Two functions to draw lines between the player and:
- Enemies (by choosing the closest point of each enemy)
- Food (with a custom color)
*/
// Draws lines connecting the player to enemies
function drawAllEnemyLines(start, enemyList) {
    let canvas = document.getElementById('bot-line-overlay');
    if (!canvas) {
        canvas = document.createElement('canvas');
        canvas.id = 'bot-line-overlay';
        canvas.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            pointer-events: none;
            z-index: 9998;
        `;
        document.body.appendChild(canvas);

        // Resize canvas when window is resized
        window.addEventListener('resize', () => {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
        });
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
    }

    const ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Si le bot est OFF, on trie les ennemis par distance et on garde les 5 plus proches
    let enemiesToDraw = enemyList;
    if (!IsBotActive) {
        enemiesToDraw = enemyList
            .map(enemy => {
                const body_points = getEnemyBodyPoints(enemy);
                let min_dist = Infinity;
                body_points.forEach(p => {
                    const dx = p.xx - window.slither.xx;
                    const dy = p.yy - window.slither.yy;
                    const d = dx * dx + dy * dy;
                    if (d < min_dist) min_dist = d;
                });
                return { enemy, min_dist };
            })
            .sort((a, b) => a.min_dist - b.min_dist)
            .slice(0, 5)
            .map(obj => obj.enemy);
    }

    enemiesToDraw.forEach(enemy => {
        const body_points = getEnemyBodyPoints(enemy);
        let min_dist = Infinity;
        let min_dist_point = null;
        body_points.forEach(p => {
            const screenPoint = worldToScreen(p.xx, p.yy);
            const dx = screenPoint.x - start.x;
            const dy = screenPoint.y - start.y;
            const d = dx * dx + dy * dy;
            if (d < min_dist && d > 0) {
                min_dist = d;
                min_dist_point = screenPoint;
            }
        });
        if (Logger < 100) {
            console.log('min_dist', min_dist);
            Logger++;
        }
        if (min_dist_point) {
            ctx.beginPath();
            ctx.moveTo(start.x, start.y);
            ctx.lineTo(min_dist_point.x, min_dist_point.y);
            ctx.strokeStyle = DangerColor(start, min_dist_point);
            ctx.lineWidth = 1.5;
            ctx.stroke();
        }
    });
}


// Draws lines connecting the player to food particles
function drawAllFoodLines(start, foodList) {
    let canvas = document.getElementById('bot-line-overlay-food');
    if (!canvas) {
        canvas = document.createElement('canvas');
        canvas.id = 'bot-line-overlay-food';
        canvas.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            pointer-events: none;
            z-index: 9997;
        `;
        document.body.appendChild(canvas);

        window.addEventListener('resize', () => {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
        });
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
    }

    const ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    foodList.forEach(food => {
        const end = worldToScreen(food.xx, food.yy);
        ctx.beginPath();
        ctx.moveTo(start.x, start.y);
        ctx.lineTo(end.x, end.y);
        ctx.strokeStyle = 'cyan';
        ctx.lineWidth = 1;
        ctx.stroke();
    });
}

/*
===================================================
Section 7: Animation Loop for Line Drawing
===================================================
Uses requestAnimationFrame for smooth animation.
*/
(function updateEnemyLines() {
    function update() {
        if (
            window.slither &&
            window.slither.xx !== undefined &&
            window.view_xx !== undefined &&
            Array.isArray(window.slithers)
        ) {
            const selfScreen = worldToScreen(window.slither.xx, window.slither.yy);
            const validEnemies = window.slithers.filter(e =>
                e &&
                typeof e.xx === 'number' &&
                typeof e.yy === 'number' &&
                window.slither.xx !== e.xx
            );
            drawAllEnemyLines(selfScreen, validEnemies);
        }
        requestAnimationFrame(update);
    }
    requestAnimationFrame(update);
})();

(function updateFoodTargetLine() {
    let canvas = document.getElementById('bot-line-overlay-food');
    if (!canvas) {
        canvas = document.createElement('canvas');
        canvas.id = 'bot-line-overlay-food';
        canvas.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            pointer-events: none;
            z-index: 9997;
        `;
        document.body.appendChild(canvas);
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        window.addEventListener('resize', () => {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
        });
    }

    function update() {
        const ctx = canvas.getContext('2d');
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        if (window.slither && typeof window.slither.xx === 'number' && targetFood) {
            const selfScreen = worldToScreen(window.slither.xx, window.slither.yy);
            const end = worldToScreen(targetFood.xx, targetFood.yy);
            ctx.beginPath();
            ctx.moveTo(selfScreen.x, selfScreen.y);
            ctx.lineTo(end.x, end.y);
            ctx.strokeStyle = 'cyan';
            ctx.lineWidth = 1;
            ctx.stroke();
        }
        requestAnimationFrame(update);
    }
    requestAnimationFrame(update);
})();

/*
===================================================
Section 8: Line between Snake and Real Mouse
===================================================
Draws a magenta line between the snake and the real mouse position.
*/
(function updateMouseLine() {
    let canvas = document.getElementById('bot-line-mouse');
    if (!canvas) {
        canvas = document.createElement('canvas');
        canvas.id = 'bot-line-mouse';
        canvas.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            pointer-events: none;
            z-index: 9996;
        `;
        document.body.appendChild(canvas);
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        window.addEventListener('resize', () => {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
        });
    }
    function update() {
        const ctx = canvas.getContext('2d');
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        if (window.slither && typeof window.slither.xx === 'number' && window.mousePos) {
            const selfScreen = worldToScreen(window.slither.xx, window.slither.yy);
            ctx.beginPath();
            ctx.moveTo(selfScreen.x, selfScreen.y);
            ctx.lineTo(window.mousePos.x, window.mousePos.y);
            ctx.strokeStyle = 'magenta';
            ctx.lineWidth = 2;
            ctx.stroke();
        }
        requestAnimationFrame(update);
    }
    requestAnimationFrame(update);
})();

/*
===================================================
Section 9: Line between Snake and Bot Mouse Position
===================================================
Draws a yellow line between the snake and the bot's target position.
*/
(function updateBotMouseLine() {
    let canvas = document.getElementById('bot-line-botmouse');
    if (!canvas) {
        canvas = document.createElement('canvas');
        canvas.id = 'bot-line-botmouse';
        canvas.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            pointer-events: none;
            z-index: 9995;
        `;
        document.body.appendChild(canvas);
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        window.addEventListener('resize', () => {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
        });
    }
    function update() {
        const ctx = canvas.getContext('2d');
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        if (window.slither && typeof window.slither.xx === 'number' && window.botTargetPos) {
            const selfScreen = worldToScreen(window.slither.xx, window.slither.yy);
            const targetScreen = worldToScreen(window.botTargetPos.x, window.botTargetPos.y);
            ctx.beginPath();
            ctx.moveTo(selfScreen.x, selfScreen.y);
            ctx.lineTo(targetScreen.x, targetScreen.y);
            ctx.strokeStyle = 'yellow';
            ctx.lineWidth = 2;
            ctx.stroke();
        }
        requestAnimationFrame(update);
    }
    requestAnimationFrame(update);
})();

/*
===================================================
Section 10: FoodBot - Automatic Movement Towards Food
===================================================
Detects the closest enemy and chooses a food particle
located in the opposite direction to move the mouse (and thus the snake).
*/

// Simulates a mouse movement event towards a given position in the world
function moveMouseToward(worldX, worldY) {
    // Updates the bot's target position
    window.botTargetPos = { x: worldX, y: worldY };

    const screenX = (worldX - window.view_xx) * window.gsc + window.mww2;
    const screenY = (worldY - window.view_yy) * window.gsc + window.mhh2;

    const event = new MouseEvent('mousemove', {
        clientX: screenX,
        clientY: screenY,
        bubbles: true
    });
    window.dispatchEvent(event);
}

// Declare a variable for the FoodBot interval
let foodBotInterval = null;

// The function containing the FoodBot update code
function foodBotUpdate() {
    if (
        window.slither &&
        typeof window.slither.xx === 'number' &&
        Array.isArray(window.foods)
    ) {
        const self = window.slither;
        const now = Date.now();

        // Building the list of enemies with their closest body point
        let enemyList = [];
        if (Array.isArray(window.slithers)) {
            window.slithers.forEach(enemy => {
                if (!enemy || typeof enemy.xx !== 'number' || typeof enemy.yy !== 'number' || enemy.xx === self.xx)
                    return;
                const bodyPoints = getEnemyBodyPoints(enemy);
                if (bodyPoints.length === 0) return;
                let bestPoint = null;
                let bestDistance = Infinity;
                let bestDx = 0, bestDy = 0;
                bodyPoints.forEach(p => {
                    const dx = p.xx - self.xx;
                    const dy = p.yy - self.yy;
                    const d = Math.sqrt(dx * dx + dy * dy);
                    if (d < bestDistance) {
                        bestDistance = d;
                        bestPoint = p;
                        bestDx = dx;
                        bestDy = dy;
                    }
                });
                if (bestPoint) {
                    enemyList.push({ point: bestPoint, distance: bestDistance, dx: bestDx, dy: bestDy });
                }
            });
        }

        // Utility function to choose the nearest food
        function chooseNearestFood(foods) {
            let bestFood = null;
            let bestFoodDist = Infinity;
            foods.forEach(f => {
                if (!f || typeof f.xx !== 'number' || typeof f.yy !== 'number') return;
                const dx = f.xx - self.xx;
                const dy = f.yy - self.yy;
                const d = Math.sqrt(dx * dx + dy * dy);
                if (d < bestFoodDist) {
                    bestFoodDist = d;
                    bestFood = f;
                }
            });
            return bestFood;
        }

        // Utility function to choose the best food in SAFE mode
        // This targets foods with the largest size and high local density (grouping)
        function chooseBestFood(foods) {
            let bestFood = null;
            let bestScore = -Infinity;
            const groupRadius = 100; // radius to determine grouping
            foods.forEach(f => {
                if (!f || typeof f.xx !== 'number' || typeof f.yy !== 'number' || typeof f.sz !== 'number') return;
                let groupCount = 0;
                foods.forEach(other => {
                    if (other === f) return;
                    const dx = other.xx - f.xx;
                    const dy = other.yy - f.yy;
                    const d = Math.sqrt(dx * dx + dy * dy);
                    if (d < groupRadius) {
                        groupCount++;
                    }
                });
                const score = f.sz + groupCount; // combines size and density
                if (score > bestScore) {
                    bestScore = score;
                    bestFood = f;
                }
            });
            return bestFood;
        }

        // Filter the food list to exclude blacklisted ones
        let availableFoods = window.foods.filter(f => {
            return (
                f &&
                typeof f.xx === 'number' &&
                typeof f.yy === 'number' &&
                !(blacklistedFoods[`${f.xx}_${f.yy}`] && now < blacklistedFoods[`${f.xx}_${f.yy}`])
            );
        });

        let target = null;

        if (enemyList.length === 0) {
            // No nearby enemies (safe mode): target food with highest value (size + grouping)
            target = chooseBestFood(availableFoods);
        } else {
            // Separate enemies by distance
            const enemiesWithin300 = enemyList.filter(e => e.distance < 300);
            const enemiesBetween300And700 = enemyList.filter(e => e.distance >= 300 && e.distance <= 700);
            // Case 3: If there are one or more enemies in the <300 range, run away
            if (enemiesWithin300.length > 0) {
                let totalWeight = 0;
                let avgX = 0;
                let avgY = 0;

                enemiesWithin300.forEach(e => {
                    const weight = 1 / (e.distance + 1e-5); // Closer = more weight
                    const normX = e.dx / e.distance;
                    const normY = e.dy / e.distance;
                    avgX += normX * weight;
                    avgY += normY * weight;
                    totalWeight += weight;
                });

                if (totalWeight > 0) {
                    avgX /= totalWeight;
                    avgY /= totalWeight;
                }

                const scale = 150;
                const runAwayX = self.xx - avgX * scale;
                const runAwayY = self.yy - avgY * scale;
                moveMouseToward(runAwayX, runAwayY);
                targetFood = null;
                return;
            }

            // Case 2: No critical enemies (<300) but at least one between 300 and 700
            if (enemiesBetween300And700.length > 0) {
                enemiesBetween300And700.sort((a, b) => a.distance - b.distance);
                const closest = enemiesBetween300And700[0];
                // Calculate opposite vector from enemy body point
                const vecX = self.xx - closest.point.xx;
                const vecY = self.yy - closest.point.yy;
                const vecLength = Math.sqrt(vecX * vecX + vecY * vecY);
                const normX = vecLength ? vecX / vecLength : 0;
                const normY = vecLength ? vecY / vecLength : 0;
                // Only keep foods in the opposite direction
                const filteredFoods = availableFoods.filter(f => {
                    const foodVecX = f.xx - self.xx;
                    const foodVecY = f.yy - self.yy;
                    const dot = foodVecX * normX + foodVecY * normY;
                    return dot > 0;
                });
                target = filteredFoods.length ? chooseNearestFood(filteredFoods) : chooseNearestFood(availableFoods);
            } else {
                // Case 1: All enemies are beyond 700: choose nearest food
                target = chooseNearestFood(availableFoods);
            }
        }

        // Blacklist mechanism if the same target is aimed at for more than 2 seconds
        if (
            target &&
            targetFood &&
            target.xx === targetFood.xx &&
            target.yy === targetFood.yy
        ) {
            if (now - targetFoodTimestamp >= 2000) {
                const key = `${targetFood.xx}_${targetFood.yy}`;
                blacklistedFoods[key] = now + 2000;
                const alternatives = availableFoods.filter(
                    f => !(f.xx === targetFood.xx && f.yy === targetFood.yy)
                );
                if (alternatives.length > 0) {
                    target = chooseNearestFood(alternatives);
                    targetFoodTimestamp = now;
                } else {
                    target = null;
                }
            }
        } else {
            targetFoodTimestamp = now;
        }

        if (target) {
            moveMouseToward(target.xx, target.yy);
            targetFood = target;
        }
    }
}

// Start FoodBot by launching the setInterval
function startFoodBot() {
    if (!foodBotInterval) {
        foodBotInterval = setInterval(foodBotUpdate, 20);
    }
}

// Stop FoodBot
function stopFoodBot() {
    if (foodBotInterval) {
        clearInterval(foodBotInterval);
        foodBotInterval = null;
    }
}

// On startup, if bot is enabled, launch FoodBot
if (IsBotActive) {
    startFoodBot();
}

document.addEventListener('keydown', (e) => {
    // Here we use the "t" key to toggle the bot (you can modify according to your needs)
    if (e.key.toLowerCase() === 't') {
        IsBotActive = !IsBotActive;
        if (IsBotActive) {
            startFoodBot();
        } else {
            stopFoodBot();
        }
    }
});