Tribal Wars Bot with GUI and Start/Stop Buttons

Tribal wars bot with GUI and Start/Stop buttons

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Tribal Wars Bot with GUI and Start/Stop Buttons
// @namespace    http://tampermonkey.net/
// @version      1.4.5
// @license      MIT
// @icon         https://us72.tribalwars.us/favicon.ico
// @description  Tribal wars bot with GUI and Start/Stop buttons
// @author       sharmanhall
// @match        https://enXX.tribalwars.net/*
// @match        https://*.tribalwars.us/*
// @match        https://*.tribalwars.net/*
// @grant        none
// ==/UserScript==
//
// Description:
// This userscript is designed to automate certain actions in the Tribal Wars game. It includes a graphical user interface (GUI) for configuring settings and starting/stopping the bot. The bot has two main phases:
//
// Phase 1: Automatically queues buildings.
// Phase 2: Automatically queues buildings and farms villages.
//
// Features:
// GUI (Graphical User Interface):
// - Min Wait Time (ms): Input field to set the minimum wait time between actions in milliseconds.
// - Max Wait Time (ms): Input field to set the maximum wait time between actions in milliseconds.
// - Phase: Dropdown menu to select between PHASE_1 (building queue) and PHASE_2 (building queue and farming).
// - Wait For Order Buildings: Checkbox to decide whether the bot should wait for buildings to be queued in a specific order or build as soon as possible.
// - Farm Coordinates: Text area to input the coordinates of villages you want to farm.
// - Farm Troop Set: Dropdown menu to select the set of troops used for farming.
// - Log Area: Text area to view detailed logs of the bot's actions.
//
// Start and Stop Buttons:
// - Start Bot: Button to start the bot.
// - Stop Bot: Button to stop the bot.
//
// Bot Actions:
// - Phase 1: Automatically queues the next available building.
// - Phase 2: Queues the next available building and sends farming attacks to specified coordinates.
//
// Interval Management:
// - Uses intervals to repeatedly check and execute actions at regular intervals (10 seconds by default).
//
// Dynamic Configuration:
// - Allows for changing settings through the GUI, which are applied immediately during the bot's operation.
//
// How It Works:
// Initialization:
// - The script creates a GUI on the game page when enabled.
//
// Configuration:
// - Users can configure wait times, phases, building queue order, farm coordinates, and troop sets through the GUI.
//
// Bot Execution:
// - When the "Start Bot" button is clicked, the bot begins operating based on the selected phase.
//   - Phase 1: The bot navigates to the headquarters view and queues buildings in the specified order or as soon as possible.
//   - Phase 2: The bot navigates to the rally point view and sends farming attacks to the specified coordinates using the chosen troop set.
//
// Stopping the Bot:
// - Clicking the "Stop Bot" button will stop the bot from executing further actions.
//
// Potential Improvements:
// - Error Handling: Enhance error handling to manage scenarios where certain actions fail or specific elements are not found.
// - Logging and Notifications: Add more detailed logging and in-game notifications to inform the user of the bot's actions and status.
// - Advanced Strategies: Implement more sophisticated strategies for farming, such as prioritizing targets based on resources or defensive strength.
// - Dynamic Adaptation: Allow the bot to dynamically adapt to changing game conditions, such as troop availability and resource levels.
// - Customization: Provide more customization options for troop compositions and building priorities.
// - Multi-Village Support: Extend support for managing multiple villages, automating tasks across all user-owned villages.

//*************************** SETUP ***************************//
// Choose Minimum and maximum wait time between actions (in milliseconds)
let MIN_WAIT_TIME = 20000;
let MAX_WAIT_TIME = 40000;
// Choose the bot's actions
// PHASE_1: The bot automatically queues buildings
// PHASE_2: The bot automatically queues buildings and farms villages
let PHASE = "PHASE_1";
// Choose whether you want the bot to queue buildings in the defined order (= true) or
// as soon as a building is available for the building queue (= false)
let WAIT_FOR_ORDER_BUILDINGS = false;
// Enter the coordinates of the villages you want to farm
let FARM_COORDINATES = [
    '000|000', '000|000', '000|000'
];
// Choose your farming troops template
let FARM_TROOP_SET = "FARM_TROOP_SET_3";
// Define your farming troops template
let farmTroopSets = {
    "FARM_TROOP_SET_1": {
        "spear": 10,
        "sword": 10
    },
    "FARM_TROOP_SET_2": {
        "spear": 15,
        "axe": 3
    },
    "FARM_TROOP_SET_3": {
        "lc": 8
    }
};
//*************************** /SETUP ***************************//

// Constants
const OVERVIEW_VIEW = "OVERVIEW_VIEW";
const HEADQUARTERS_VIEW = "HEADQUARTERS_VIEW";
const RALLY_POINT_VIEW = "RALLY_POINT_VIEW";
const ATTACK_CONFIRM_VIEW = "ATTACK_CONFIRM_VIEW";

let isBotRunning = false;
let botInterval;

(function () {
    'use strict';

    console.log("-- Tribal Wars script enabled --");

    createGUI();

})();

// GUI Creation
function createGUI() {
    const guiContainer = document.createElement('div');
    guiContainer.id = 'twBotGUI';
    guiContainer.style.position = 'fixed';
    guiContainer.style.bottom = '10px';
    guiContainer.style.left = '10px';
    guiContainer.style.backgroundColor = '#fff';
    guiContainer.style.border = '1px solid #000';
    guiContainer.style.padding = '10px';
    guiContainer.style.zIndex = '10000';
    guiContainer.style.cursor = 'move';

    const header = document.createElement('div');
    header.innerText = 'Tribal Wars Bot';
    header.style.fontWeight = 'bold';
    header.style.cursor = 'move';
    header.style.backgroundColor = '#ddd';
    header.style.padding = '5px';
    header.onmousedown = dragMouseDown;
    guiContainer.appendChild(header);

    const minButton = document.createElement('button');
    minButton.innerText = 'Minimize';
    minButton.onclick = toggleMinimize;
    guiContainer.appendChild(minButton);

    const content = document.createElement('div');
    content.id = 'twBotGUIContent';

    const minWaitInput = createInput('Min Wait Time (ms)', MIN_WAIT_TIME, (e) => MIN_WAIT_TIME = parseInt(e.target.value));
    const maxWaitInput = createInput('Max Wait Time (ms)', MAX_WAIT_TIME, (e) => MAX_WAIT_TIME = parseInt(e.target.value));
    const phaseInput = createSelect('Phase', ['PHASE_1', 'PHASE_2'], PHASE, (e) => PHASE = e.target.value);
    const waitForOrderInput = createCheckbox('Wait For Order Buildings', WAIT_FOR_ORDER_BUILDINGS, (e) => WAIT_FOR_ORDER_BUILDINGS = e.target.checked);
    const farmCoordsInput = createTextArea('Farm Coordinates', FARM_COORDINATES.join('\n'), (e) => FARM_COORDINATES = e.target.value.split('\n'));
    const farmTroopSetInput = createSelect('Farm Troop Set', Object.keys(farmTroopSets), FARM_TROOP_SET, (e) => FARM_TROOP_SET = e.target.value);

    const startButton = document.createElement('button');
    startButton.innerText = 'Start Bot';
    startButton.onclick = startBot;

    const stopButton = document.createElement('button');
    stopButton.innerText = 'Stop Bot';
    stopButton.onclick = stopBot;

    const logArea = createTextArea('Log', '', () => {});
    logArea.children[1].id = 'logArea';
    logArea.children[1].disabled = true;

    const buildingSelect = createSelect('Select Building', [
        'Headquarters', 'Barracks', 'Stable', 'First church', 'Smithy', 'Rally point', 'Statue', 'Market',
        'Timber camp', 'Clay pit', 'Iron mine', 'Farm', 'Warehouse', 'Hiding place', 'Wall', 'Workshop', 'Academy'
    ], '', (e) => queueBuilding(e.target.value));

    content.appendChild(minWaitInput);
    content.appendChild(maxWaitInput);
    content.appendChild(phaseInput);
    content.appendChild(waitForOrderInput);
    content.appendChild(farmCoordsInput);
    content.appendChild(farmTroopSetInput);
    content.appendChild(startButton);
    content.appendChild(stopButton);
    content.appendChild(buildingSelect);
    content.appendChild(logArea);

    guiContainer.appendChild(content);
    document.body.appendChild(guiContainer);

    function dragMouseDown(e) {
        e.preventDefault();
        document.onmouseup = closeDragElement;
        document.onmousemove = elementDrag;

        let pos3 = e.clientX;
        let pos4 = e.clientY;

        function elementDrag(e) {
            e.preventDefault();
            let pos1 = pos3 - e.clientX;
            let pos2 = pos4 - e.clientY;
            pos3 = e.clientX;
            pos4 = e.clientY;
            guiContainer.style.top = (guiContainer.offsetTop - pos2) + "px";
            guiContainer.style.left = (guiContainer.offsetLeft - pos1) + "px";
        }

        function closeDragElement() {
            document.onmouseup = null;
            document.onmousemove = null;
        }
    }

    function toggleMinimize() {
        if (content.style.display === 'none') {
            content.style.display = 'block';
            minButton.innerText = 'Minimize';
        } else {
            content.style.display = 'none';
            minButton.innerText = 'Maximize';
        }
    }
}

function createInput(labelText, defaultValue, onChange) {
    const label = document.createElement('label');
    label.innerText = labelText;

    const input = document.createElement('input');
    input.type = 'number';
    input.value = defaultValue;
    input.addEventListener('input', onChange);

    const container = document.createElement('div');
    container.appendChild(label);
    container.appendChild(input);

    return container;
}

function createSelect(labelText, options, defaultValue, onChange) {
    const label = document.createElement('label');
    label.innerText = labelText;

    const select = document.createElement('select');
    options.forEach(option => {
        const opt = document.createElement('option');
        opt.value = option;
        opt.innerText = option;
        select.appendChild(opt);
    });
    select.value = defaultValue;
    select.addEventListener('change', onChange);

    const container = document.createElement('div');
    container.appendChild(label);
    container.appendChild(select);

    return container;
}

function createCheckbox(labelText, defaultChecked, onChange) {
    const label = document.createElement('label');
    label.innerText = labelText;

    const checkbox = document.createElement('input');
    checkbox.type = 'checkbox';
    checkbox.checked = defaultChecked;
    checkbox.addEventListener('change', onChange);

    const container = document.createElement('div');
    container.appendChild(label);
    container.appendChild(checkbox);

    return container;
}

function createTextArea(labelText, defaultValue, onChange) {
    const label = document.createElement('label');
    label.innerText = labelText;

    const textarea = document.createElement('textarea');
    textarea.value = defaultValue;
    textarea.addEventListener('input', onChange);

    const container = document.createElement('div');
    container.appendChild(label);
    container.appendChild(textarea);

    return container;
}

function log(message) {
    const logArea = document.getElementById('logArea');
    logArea.value += message + '\n';
    logArea.scrollTop = logArea.scrollHeight;
}

function startBot() {
    if (isBotRunning) return;
    isBotRunning = true;

    if (PHASE == "PHASE_1") {
        botInterval = setInterval(executePhase1, 10000);
    }
    else if (PHASE == "PHASE_2") {
        botInterval = setInterval(executePhase2, 10000);
    }

    log("Bot started");
}

function stopBot() {
    if (!isBotRunning) return;
    isBotRunning = false;

    clearInterval(botInterval);

    log("Bot stopped");
}

function queueBuilding(buildingName) {
    const buildingMap = {
        'Headquarters': 'main_buildlink_main',
        'Barracks': 'main_buildlink_barracks',
        'Stable': 'main_buildlink_stable',
        'First church': 'main_buildlink_church_f',
        'Smithy': 'main_buildlink_smith',
        'Rally point': 'main_buildlink_place',
        'Statue': 'main_buildlink_statue',
        'Market': 'main_buildlink_market',
        'Timber camp': 'main_buildlink_wood',
        'Clay pit': 'main_buildlink_stone',
        'Iron mine': 'main_buildlink_iron',
        'Farm': 'main_buildlink_farm',
        'Warehouse': 'main_buildlink_storage',
        'Hiding place': 'main_buildlink_hide',
        'Wall': 'main_buildlink_wall',
        'Workshop': 'main_buildlink_workshop',
        'Academy': 'main_buildlink_academy'
    };

    const buildLink = document.getElementById(buildingMap[buildingName]);
    if (buildLink) {
        buildLink.click();
        log(`Queued building: ${buildingName}`);
    } else {
        log(`Failed to queue building: ${buildingName}`);
    }
}

// Phase 1: Building
function executePhase1() {
    let currentView = getCurrentView();
    log(currentView);
    if (currentView == HEADQUARTERS_VIEW) {
        buildNextBuilding();
    }
    else if (currentView == OVERVIEW_VIEW) {
        // Open headquarters view
        document.getElementById("l_main").children[0].children[0].click();
    }
}

// Phase 2: Farm
function executePhase2() {
    let delay = Math.floor(Math.random() * (MAX_WAIT_TIME - MIN_WAIT_TIME) + MIN_WAIT_TIME);

    // Process action
    let currentView = getCurrentView();
    log(currentView);
    setTimeout(function () {
        if (currentView == HEADQUARTERS_VIEW) {
            buildNextBuilding();
            document.getElementById("main_buildrow_place").children[0].children[0].click();
        }
        else if (currentView == RALLY_POINT_VIEW) {
            sendFarmAttacks();
        }
        else if (currentView == OVERVIEW_VIEW) {
            document.getElementById("l_main").children[0].children[0].click();
        }
        else if (currentView == ATTACK_CONFIRM_VIEW) {
            document.getElementById("troop_confirm_go").click();
        }
    }, delay);
}

function getCurrentView() {
    let currentUrl = window.location.href;
    if (currentUrl.endsWith('overview')) {
        return OVERVIEW_VIEW;
    }
    else if (currentUrl.endsWith('main')) {
        return HEADQUARTERS_VIEW;
    }
    else if (currentUrl.endsWith('place')) {
        return RALLY_POINT_VIEW;
    }
    else if (currentUrl.endsWith('confirm')) {
        return ATTACK_CONFIRM_VIEW;
    }
}

function buildNextBuilding() {
    let nextBuildingElement = getNextBuildingElement();
    if (nextBuildingElement !== undefined) {
        nextBuildingElement.click();
        log("Clicked on " + nextBuildingElement);
    }
}

function getNextBuildingElement() {
    let buildableBuildings = document.getElementsByClassName("btn btn-build");
    let buildingElementsQueue = getBuildingElementsQueue();
    let found;
    while (found === undefined && buildingElementsQueue.length > 0) {
        var next = buildingElementsQueue.shift();
        if (buildableBuildings.hasOwnProperty(next)) {
            let nextBuilding = document.getElementById(next);
            var isVisible = nextBuilding.offsetWidth > 0 || nextBuilding.offsetHeight > 0;
            if (isVisible) {
                found = nextBuilding;
            }
            if (WAIT_FOR_ORDER_BUILDINGS) {
                break;
            }
        }
    }
    return found;
}

function sendFarmAttacks() {
    let availableInputs = getAvailableInputs();
    if (availableInputs === undefined) {
        log("Not enough troops available");
        goToOverviewViewFromRallyPointView();
        return;
    }

    let currentlyAttackingCoordinates = getCurrentlyAttackingCoordinates();
    let choice = Math.floor(Math.random() * FARM_COORDINATES.length);

    for (let i = 0; i < FARM_COORDINATES.length; i++) {
        if (choice >= FARM_COORDINATES.length) {
            choice -= FARM_COORDINATES.length;
        }
        if (!currentlyAttackingCoordinates.includes(FARM_COORDINATES[choice])) {
            sendAttackToCoordinate(FARM_COORDINATES[choice], availableInputs);
            return;
        }
        choice++;
    }
    goToOverviewViewFromRallyPointView();
}

function goToOverviewViewFromRallyPointView() {
    document.getElementById("menu_row").children[1].children[0].click();
}

function sendAttackToCoordinate(coordinates, inputAmounts) {
    log("Sending attack to: " + coordinates);
    for (var prop in inputAmounts) {
        inputAmounts[prop].input.value = inputAmounts[prop].amount;
    }
    let coordinatesInput = document.getElementById("place_target").children[1];
    coordinatesInput.value = coordinates;
    document.getElementById("target_attack").click();
}

function getAvailableInputs() {
    let availableInputs = {};
    let farmTroopSet = farmTroopSets[FARM_TROOP_SET];

    if (farmTroopSet.spear !== undefined) {
        let currentInput = document.getElementById("unit_input_spear");
        let currentInputAvailableCount = currentInput.getAttribute("data-all-count");
        if (farmTroopSet.spear > currentInputAvailableCount) {
            return;
        }
        availableInputs.spear = { "input": currentInput, "amount": farmTroopSet.spear };
    }
    if (farmTroopSet.sword !== undefined) {
        let currentInput = document.getElementById("unit_input_sword");
        let currentInputAvailableCount = currentInput.getAttribute("data-all-count");
        if (farmTroopSet.sword > currentInputAvailableCount) {
            return;
        }
        availableInputs.sword = { "input": currentInput, "amount": farmTroopSet.sword };
    }
    if (farmTroopSet.axe !== undefined) {
        let currentInput = document.getElementById("unit_input_axe");
        let currentInputAvailableCount = currentInput.getAttribute("data-all-count");
        if (farmTroopSet.axe > currentInputAvailableCount) {
            return;
        }
        availableInputs.axe = { "input": currentInput, "amount": farmTroopSet.axe };
    }
    if (farmTroopSet.lc !== undefined) {
        let currentInput = document.getElementById("unit_input_light");
        let currentInputAvailableCount = currentInput.getAttribute("data-all-count");
        if (farmTroopSet.lc > currentInputAvailableCount) {
            return;
        }
        availableInputs.lc = { "input": currentInput, "amount": farmTroopSet.lc };
    }
    return availableInputs;
}

function getCurrentlyAttackingCoordinates() {
    let currentlyAttackingElements = document.getElementsByClassName("quickedit-label");
    let currentlyAttackingCoordinates = [];
    for (var i = 0, len = currentlyAttackingElements.length; i < len; i++) {
        let coordinatesString = currentlyAttackingElements[i].innerHTML.split(")")[0].split("(")[1];
        currentlyAttackingCoordinates.push(coordinatesString);
    }
    return currentlyAttackingCoordinates;
}

function getBuildingElementsQueue() {
    var queue = [];
    queue.push("main_buildlink_stone_1");
    queue.push("main_buildlink_wood_1");
    queue.push("main_buildlink_iron_1");
    queue.push("main_buildlink_stone_2");
    queue.push("main_buildlink_wood_2");
    queue.push("main_buildlink_stone_3");
    queue.push("main_buildlink_wood_3");
    queue.push("main_buildlink_iron_2");
    queue.push("main_buildlink_stone_4");
    queue.push("main_buildlink_stone_5");
    queue.push("main_buildlink_wood_4");
    queue.push("main_buildlink_wood_5");
    queue.push("main_buildlink_wood_6");
    queue.push("main_buildlink_wood_7");
    queue.push("main_buildlink_main_2");
    queue.push("main_buildlink_main_3");
    queue.push("main_buildlink_barracks_1");
    queue.push("main_buildlink_wood_8");
    queue.push("main_buildlink_storage_2");
    queue.push("main_buildlink_market_1");
    queue.push("main_buildlink_wood_9");
    queue.push("main_buildlink_storage_3");
    queue.push("main_buildlink_wood_10");
    queue.push("main_buildlink_stone_6");
    queue.push("main_buildlink_market_2");
    queue.push("main_buildlink_stone_7");
    queue.push("main_buildlink_iron_3");
    queue.push("main_buildlink_main_4");
    queue.push("main_buildlink_main_5");
    queue.push("main_buildlink_smith_1");
    queue.push("main_buildlink_smith_2");
    queue.push("main_buildlink_iron_4");
    queue.push("main_buildlink_iron_5");
    queue.push("main_buildlink_market_3");
    queue.push("main_buildlink_iron_6");
    queue.push("main_buildlink_iron_7");
    queue.push("main_buildlink_farm_2");
    queue.push("main_buildlink_farm_3");
    queue.push("main_buildlink_storage_3");
    queue.push("main_buildlink_farm_4");
    queue.push("main_buildlink_storage_4");
    queue.push("main_buildlink_barracks_2");
    queue.push("main_buildlink_barracks_3");
    queue.push("main_buildlink_barracks_4");
    queue.push("main_buildlink_barracks_5");
    queue.push("main_buildlink_main_6");
    queue.push("main_buildlink_main_7");
    queue.push("main_buildlink_farm_5");
    queue.push("main_buildlink_storage_5");
    queue.push("main_buildlink_smith_3");
    queue.push("main_buildlink_main_8");
    queue.push("main_buildlink_main_9");
    queue.push("main_buildlink_main_10");
    queue.push("main_buildlink_smith_4");
    queue.push("main_buildlink_farm_6");
    queue.push("main_buildlink_storage_6");
    queue.push("main_buildlink_smith_5");
    queue.push("main_buildlink_iron_8");
    queue.push("main_buildlink_iron_9");
    queue.push("main_buildlink_iron_10");
    queue.push("main_buildlink_stable_1");
    queue.push("main_buildlink_stable_2");
    queue.push("main_buildlink_stable_3");
    queue.push("main_buildlink_wall_1");
    queue.push("main_buildlink_stone_8");
    queue.push("main_buildlink_stone_9");
    queue.push("main_buildlink_storage_7");
    queue.push("main_buildlink_farm_7");
    queue.push("main_buildlink_market_4");
    queue.push("main_buildlink_market_5");
    queue.push("main_buildlink_barracks_6");
    queue.push("main_buildlink_barracks_7");
    queue.push("main_buildlink_iron_11");
    queue.push("main_buildlink_iron_12");
    queue.push("main_buildlink_iron_13");
    queue.push("main_buildlink_farm_8");
    queue.push("main_buildlink_farm_9");
    queue.push("main_buildlink_iron_14");
    queue.push("main_buildlink_iron_15");
    queue.push("main_buildlink_stone_10");
    queue.push("main_buildlink_stone_11");
    queue.push("main_buildlink_storage_8");
    queue.push("main_buildlink_farm_10");
    queue.push("main_buildlink_wood_11");
    queue.push("main_buildlink_wood_12");
    queue.push("main_buildlink_wood_13");
    queue.push("main_buildlink_main_11");
    queue.push("main_buildlink_main_12");
    queue.push("main_buildlink_farm_11");
    queue.push("main_buildlink_farm_12");
    queue.push("main_buildlink_farm_13");
    queue.push("main_buildlink_storage_9");
    queue.push("main_buildlink_iron_16");
    queue.push("main_buildlink_stone_12");
    queue.push("main_buildlink_stone_13");
    queue.push("main_buildlink_stone_14");
    queue.push("main_buildlink_wood_14");
    queue.push("main_buildlink_wood_15");
    queue.push("main_buildlink_stone_15");
    queue.push("main_buildlink_wall_2");
    queue.push("main_buildlink_wall_3");
    queue.push("main_buildlink_wall_4");
    queue.push("main_buildlink_wall_5");
    queue.push("main_buildlink_wall_6");
    queue.push("main_buildlink_wall_7");
    queue.push("main_buildlink_wall_8");
    queue.push("main_buildlink_storage_10");
    queue.push("main_buildlink_wall_9");
    queue.push("main_buildlink_wall_10");
    queue.push("main_buildlink_stable_4");
    queue.push("main_buildlink_stable_5");
    queue.push("main_buildlink_main_13");
    queue.push("main_buildlink_main_14");
    queue.push("main_buildlink_main_15");
    queue.push("main_buildlink_wood_16");
    queue.push("main_buildlink_stone_16");
    queue.push("main_buildlink_storage_11");
    queue.push("main_buildlink_storage_12");
    queue.push("main_buildlink_storage_13");
    queue.push("main_buildlink_storage_14");
    queue.push("main_buildlink_farm_14");
    queue.push("main_buildlink_farm_15");
    queue.push("main_buildlink_farm_16");
    queue.push("main_buildlink_wood_17");
    queue.push("main_buildlink_stone_17");
    queue.push("main_buildlink_iron_17");
    queue.push("main_buildlink_storage_15");
    queue.push("main_buildlink_wood_18");
    queue.push("main_buildlink_stone_18");
    queue.push("main_buildlink_iron_18");
    queue.push("main_buildlink_storage_16");
    queue.push("main_buildlink_storage_17");
    queue.push("main_buildlink_storage_18");
    queue.push("main_buildlink_main_16");
    queue.push("main_buildlink_main_17");
    queue.push("main_buildlink_main_18");
    queue.push("main_buildlink_main_19");
    queue.push("main_buildlink_main_20");
    queue.push("main_buildlink_farm_17");
    queue.push("main_buildlink_farm_18");
    queue.push("main_buildlink_farm_19");
    queue.push("main_buildlink_farm_20");
    queue.push("main_buildlink_wood_19");
    queue.push("main_buildlink_wood_20");
    queue.push("main_buildlink_stone_19");
    queue.push("main_buildlink_stone_20");
    queue.push("main_buildlink_iron_19");
    queue.push("main_buildlink_iron_20");
    queue.push("main_buildlink_stable_6");
    queue.push("main_buildlink_stable_7");
    queue.push("main_buildlink_stable_8");
    queue.push("main_buildlink_stable_9");
    queue.push("main_buildlink_stable_10");

    return queue;
}