🎮ArcadeLab

资源战争

by LuckyFlame48
1180 lines46.6 KB
▶ Play
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <title>资源战争</title>
    <style>
        * { box-sizing: border-box; font-family: system-ui, sans-serif; }
        body {
            background: #1a1a2e;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            margin: 0;
            padding: 8px;
        }
        .game {
            max-width: 720px;
            width: 100%;
            background: #16213e;
            padding: 12px;
            border-radius: 28px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.6);
            color: #eee;
        }
        h1 { text-align: center; font-weight: 400; font-size: 1.6rem; margin: 0 0 4px; color: #f9d371; }
        .turn { text-align: center; font-size: 1rem; color: #f9d371; margin-bottom: 4px; }
        .row {
            display: flex;
            flex-wrap: wrap;
            gap: 4px;
            justify-content: center;
            margin-bottom: 4px;
        }
        .card {
            background: #0f3460;
            padding: 4px 6px;
            border-radius: 12px;
            min-width: 44px;
            text-align: center;
            flex: 1 0 auto;
            max-width: 72px;
        }
        .card .label { font-size: 0.55rem; opacity: 0.7; }
        .card .value { font-size: 1.1rem; font-weight: bold; }
        .gold { color: #f9d371; }
        .green { color: #6fcf97; }
        .blue { color: #4fc3f7; }
        .red { color: #f05454; }
        .log {
            background: #0a0a1a;
            padding: 8px 12px;
            border-radius: 12px;
            min-height: 50px;
            margin: 4px 0 8px;
            font-size: 0.85rem;
            line-height: 1.5;
            white-space: pre-wrap;
            border: 1px solid #2a2a4a;
            max-height: 160px;
            overflow-y: auto;
        }
        .main-buttons {
            display: flex;
            gap: 6px;
            margin-bottom: 4px;
        }
        .main-btn {
            flex: 1;
            padding: 8px 0;
            border: none;
            border-radius: 40px;
            font-size: 0.9rem;
            font-weight: 600;
            cursor: pointer;
            background: #1a3a5e;
            color: #fff;
            transition: 0.2s;
        }
        .main-btn:hover:not(:disabled) { transform: scale(1.02); filter: brightness(1.2); }
        .main-btn:disabled { opacity: 0.4; cursor: not-allowed; }
        .main-btn.active { background: #3a5a7e; box-shadow: 0 0 10px #4fc3f7; }

        .sub-panel {
            background: #0a1a2e;
            border-radius: 16px;
            padding: 10px;
            margin-bottom: 6px;
            display: none;
            flex-direction: column;
            gap: 6px;
        }
        .sub-panel.show { display: flex; }

        .panel-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            font-weight: bold;
            font-size: 0.9rem;
        }
        .panel-header .idle {
            font-size: 0.85rem;
            color: #6fcf97;
        }
        .panel-header .back-btn {
            background: #444;
            border: none;
            border-radius: 20px;
            padding: 2px 12px;
            color: #fff;
            cursor: pointer;
            font-size: 0.8rem;
        }
        .panel-header .back-btn:hover { background: #666; }

        .resource-grid {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            justify-content: center;
        }
        .resource-btn {
            padding: 8px 14px;
            border: none;
            border-radius: 20px;
            font-size: 0.85rem;
            font-weight: 600;
            cursor: pointer;
            background: #2a4a6e;
            color: #fff;
            transition: 0.2s;
            flex: 1 0 auto;
            min-width: 70px;
        }
        .resource-btn:hover:not(:disabled) { filter: brightness(1.2); }
        .resource-btn:disabled { opacity: 0.4; cursor: not-allowed; }
        .resource-btn.green { background: #2d6a4f; }
        .resource-btn.orange { background: #b38b3b; }
        .resource-btn.diamond { background: #4a9bb5; }

        .zone-grid {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            justify-content: center;
            margin-top: 4px;
        }
        .zone-btn {
            padding: 8px 16px;
            border: none;
            border-radius: 16px;
            font-size: 0.85rem;
            font-weight: 600;
            cursor: pointer;
            background: #1a3a5e;
            color: #fff;
            transition: 0.2s;
            min-width: 80px;
            text-align: center;
        }
        .zone-btn:hover:not(:disabled) { background: #2a5a7e; }
        .zone-btn:disabled { opacity: 0.4; cursor: not-allowed; background: #333; }
        .zone-btn .sub { font-size: 0.65rem; opacity: 0.7; display: block; }

        .steal-panel {
            margin-top: 6px;
            border-top: 1px solid #2a2a4a;
            padding-top: 6px;
            display: flex;
            flex-wrap: wrap;
            gap: 4px;
            justify-content: center;
        }
        .steal-btn {
            padding: 4px 14px;
            border: none;
            border-radius: 30px;
            font-size: 0.8rem;
            font-weight: 600;
            cursor: pointer;
            background: #b35a3b;
            color: #fff;
            transition: 0.2s;
        }
        .steal-btn:hover:not(:disabled) { filter: brightness(1.2); }
        .steal-btn:disabled { opacity: 0.4; cursor: not-allowed; }

        .build-grid {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 6px;
        }
        .build-btn {
            padding: 8px 0;
            border: none;
            border-radius: 16px;
            font-size: 0.8rem;
            font-weight: 600;
            cursor: pointer;
            color: #fff;
            transition: 0.2s;
            background: #2a4a6e;
        }
        .build-btn:hover:not(:disabled) { filter: brightness(1.2); }
        .build-btn:disabled { opacity: 0.4; cursor: not-allowed; }
        .build-btn.wood { background: #2d6a4f; }
        .build-btn.stone { background: #b38b3b; }
        .build-btn.turret { background: #7d3c98; }
        .build-btn.knight { background: #2b6b8e; }
        .build-btn.alloy { background: #e94560; }
        .build-btn.castle { background: #d4a373; }

        .order-grid {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 6px;
        }
        .order-btn {
            padding: 10px 0;
            border: none;
            border-radius: 16px;
            font-size: 0.85rem;
            font-weight: 600;
            cursor: pointer;
            color: #fff;
            transition: 0.2s;
        }
        .order-btn:hover:not(:disabled) { filter: brightness(1.2); }
        .order-btn:disabled { opacity: 0.4; cursor: not-allowed; }
        .order-btn.attack { background: #b33b3b; }
        .order-btn.diamond { background: #4a9bb5; }
        .order-btn.siege { background: #d4a373; }

        .end-btn {
            width: 100%;
            padding: 10px;
            border: none;
            border-radius: 40px;
            font-size: 1rem;
            font-weight: bold;
            background: #e94560;
            color: #fff;
            cursor: pointer;
            transition: 0.2s;
            margin-top: 4px;
        }
        .end-btn:hover:not(:disabled) { filter: brightness(1.1); transform: scale(1.02); }
        .end-btn:disabled { opacity: 0.4; cursor: not-allowed; }

        .reset-btn {
            width: 100%;
            padding: 6px;
            border: none;
            border-radius: 40px;
            background: #444;
            color: #fff;
            cursor: pointer;
            margin-top: 4px;
            font-size: 0.85rem;
        }
        .reset-btn:hover { background: #666; }
        .footer { text-align: center; font-size: 0.65rem; opacity: 0.5; margin-top: 4px; }
        .status-row {
            display: flex;
            flex-wrap: wrap;
            gap: 3px;
            justify-content: center;
            margin-bottom: 4px;
        }
        .status-item {
            background: #0a0a1a;
            padding: 2px 8px;
            border-radius: 20px;
            font-size: 0.7rem;
        }
        .status-item span { font-weight: bold; }
        @media (max-width: 480px) {
            .card { min-width: 36px; padding: 2px 4px; }
            .card .value { font-size: 0.95rem; }
            .main-btn { font-size: 0.8rem; padding: 6px 0; }
            .build-grid { grid-template-columns: repeat(2, 1fr); }
            .order-grid { grid-template-columns: 1fr 1fr; }
        }
    </style>
</head>
<body>
<div class="game" id="app">
    <h1>⚔️ 资源战争</h1>
    <div class="turn" id="turnDisplay">回合 0</div>

    <!-- 资源 -->
    <div class="row" id="resourceRow">
        <div class="card"><div class="label">🪵 木</div><div class="value gold" id="wood">0</div></div>
        <div class="card"><div class="label">🪨 石</div><div class="value gold" id="stone">0</div></div>
        <div class="card"><div class="label">⛏️ 铁</div><div class="value gold" id="iron">0</div></div>
        <div class="card"><div class="label">🔥 碳</div><div class="value gold" id="carbon">0</div></div>
        <div class="card"><div class="label">💎 钻</div><div class="value gold" id="diamond">0</div></div>
    </div>

    <!-- 状态 -->
    <div class="status-row">
        <div class="status-item">👨‍🌾 农民 <span id="peasants">3</span></div>
        <div class="status-item">⚔️ 骑士 <span id="knights">0</span></div>
        <div class="status-item">🏹 城下 <span id="knightsSieging">0</span></div>
        <div class="status-item">🛡️ 炮台 <span id="turrets">0</span></div>
        <div class="status-item">🏰 我方 <span id="baseHp">50</span></div>
        <div class="status-item">🏰 敌方 <span id="enemyBaseHp">50</span></div>
        <div class="status-item">🪚 伐木机 <span id="woodMachines">0</span></div>
        <div class="status-item">⛏️ 钻头 <span id="stoneMachines">0</span></div>
    </div>

    <!-- 日志 -->
    <div class="log" id="log">开局!先获取物资,再建造设施,最后调遣骑士。</div>

    <!-- 主按钮 -->
    <div class="main-buttons">
        <button class="main-btn" id="btnCollect">📦 获取物资</button>
        <button class="main-btn" id="btnBuild">🏗️ 建造设施</button>
        <button class="main-btn" id="btnOrder">⚔️ 调遣骑士</button>
    </div>

    <!-- 子面板:获取物资 -->
    <div class="sub-panel" id="panelCollect">
        <div class="panel-header">
            <span class="idle">👨‍🌾 空闲: <span id="idlePeasants">3</span></span>
            <button class="back-btn" id="collectBack">↩ 返回</button>
        </div>
        <div class="resource-grid" id="collectResources">
            <button class="resource-btn green" data-resource="wood">🌲 树林</button>
            <button class="resource-btn orange" data-resource="stone">⛰️ 山丘</button>
            <button class="resource-btn" data-resource="iron">⛏️ 矿井</button>
            <button class="resource-btn diamond" data-resource="diamond">💎 钻石矿井</button>
        </div>
        <div id="collectZones" style="display:none;">
            <div class="zone-grid" id="zoneButtons"></div>
            <div id="stealPanel" style="display:none;" class="steal-panel">
                <span style="width:100%; text-align:center; font-size:0.85rem;">偷物资 (消耗1农民)</span>
                <button class="steal-btn" data-steal="wood">🌲 偷木头</button>
                <button class="steal-btn" data-steal="stone">⛰️ 偷石头</button>
                <button class="steal-btn" data-steal="iron">⛏️ 偷铁</button>
                <button class="steal-btn" id="stealBack" style="background:#444;">↩ 取消</button>
            </div>
        </div>
    </div>

    <!-- 子面板:建造设施 -->
    <div class="sub-panel" id="panelBuild">
        <div class="panel-header">
            <span>🏗️ 建造设施</span>
            <button class="back-btn" id="buildBack">↩ 返回</button>
        </div>
        <div class="build-grid">
            <button class="build-btn wood" id="subBuildMachineWood">🪚 伐木机 (10木)</button>
            <button class="build-btn stone" id="subBuildMachineStone">⛏️ 钻头 (10石)</button>
            <button class="build-btn turret" id="subBuildTurret">🛡️ 炮台 (5石+3铁)</button>
            <button class="build-btn knight" id="subTrainKnight">⚔️ 骑士 (5木+3铁)</button>
            <button class="build-btn alloy" id="subAlloy">🔧 合金 (5钻+5碳)</button>
            <button class="build-btn castle" id="subUpgradeCastle">🏰 升级城堡 (5木+5石+5铁)</button>
        </div>
        <div id="buildZones" style="display:none;">
            <div style="display:flex; justify-content:space-between; margin-top:4px;">
                <span id="buildZoneTitle">选择区域</span>
                <button class="back-btn" id="buildZoneBack">↩ 取消</button>
            </div>
            <div class="zone-grid" id="buildZoneButtons"></div>
        </div>
    </div>

    <!-- 子面板:调遣骑士 -->
    <div class="sub-panel" id="panelOrder">
        <div class="panel-header">
            <span>⚔️ 调遣骑士</span>
            <button class="back-btn" id="orderBack">↩ 返回</button>
        </div>
        <div class="order-grid">
            <button class="order-btn attack" id="subOrderAttack">🗡️ 出征城堡</button>
            <button class="order-btn diamond" id="subOrderDiamond">💎 抢夺钻石</button>
            <button class="order-btn siege" id="subOrderSiege">🏰 攻击城堡</button>
        </div>
    </div>

    <!-- 结束回合 & 重置 -->
    <button class="end-btn" id="btnEndTurn">⏭️ 结束回合</button>
    <button class="reset-btn" id="btnReset">🔄 重新开局</button>
    <div class="footer">钻石矿井第4回合起 · 合金需5钻+5碳</div>
</div>

<script>
(function() {
    // ----- 游戏状态 -----
    const state = {
        turn: 0,
        wood: 0, stone: 0, iron: 0, carbon: 0, diamond: 0,
        peasants: 3,
        knights: 0,
        knightsSieging: 0,
        turrets: 0,
        enemyTurrets: 0,
        baseHp: 50,
        enemyBaseHp: 50,
        woodMachines: 0,
        stoneMachines: 0,
        attackBonus: 0,
        turretAttack: 1,
        gameOver: false,
        islandOpen: 4,
        playerWorkers: {
            wood1: 0, wood2: 0,
            stone1: 0, stone2: 0,
            iron1: 0, iron2: 0, iron3: 0
        },
        enemyWorkers: {
            wood1: 0, wood2: 0,
            stone1: 0, stone2: 0,
            iron1: 0, iron2: 0, iron3: 0
        },
        enemyWood: 0, enemyStone: 0, enemyIron: 0, enemyCarbon: 0, enemyDiamond: 0,
        enemyKnights: 0,
        enemyWoodMachines: 0,
        enemyStoneMachines: 0,
        enemyAttackBonus: 0,
        playerRaid: null,   // { knights: 0, peasants: 0 }
        enemyRaid: null,
        stealActions: [],
        actionLog: [],
        enemyMessages: [],
        collectResource: null,
        buildPending: null,
    };

    const ZONES = {
        wood: ['wood1', 'wood2'],
        stone: ['stone1', 'stone2'],
        iron: ['iron1', 'iron2', 'iron3']
    };
    const ZONE_LABELS = {
        wood1: '树林1区', wood2: '树林2区',
        stone1: '山丘1区', stone2: '山丘2区',
        iron1: '矿井1区', iron2: '矿井2区', iron3: '矿井3区'
    };
    const RESOURCE_NAMES = { wood: '木头', stone: '石头', iron: '铁' };

    const $ = id => document.getElementById(id);
    const woodEl = $('wood'), stoneEl = $('stone'), ironEl = $('iron');
    const carbonEl = $('carbon'), diamondEl = $('diamond');
    const peasantsEl = $('peasants'), knightsEl = $('knights'), knightsSiegingEl = $('knightsSieging');
    const turretsEl = $('turrets'), baseHpEl = $('baseHp'), enemyBaseHpEl = $('enemyBaseHp');
    const woodMachinesEl = $('woodMachines'), stoneMachinesEl = $('stoneMachines');
    const logEl = $('log'), turnDisplay = $('turnDisplay');
    const idlePeasantsEl = $('idlePeasants');

    const btnCollect = $('btnCollect'), btnBuild = $('btnBuild'), btnOrder = $('btnOrder');
    const panelCollect = $('panelCollect'), panelBuild = $('panelBuild'), panelOrder = $('panelOrder');
    const collectResources = $('collectResources'), collectZones = $('collectZones'), zoneButtons = $('zoneButtons');
    const stealPanel = $('stealPanel');
    const collectBack = $('collectBack');
    const buildBack = $('buildBack'), buildZones = $('buildZones'), buildZoneTitle = $('buildZoneTitle'), buildZoneButtons = $('buildZoneButtons'), buildZoneBack = $('buildZoneBack');
    const orderBack = $('orderBack');

    const subBuildMachineWood = $('subBuildMachineWood'), subBuildMachineStone = $('subBuildMachineStone');
    const subBuildTurret = $('subBuildTurret'), subTrainKnight = $('subTrainKnight');
    const subAlloy = $('subAlloy'), subUpgradeCastle = $('subUpgradeCastle');
    const subOrderAttack = $('subOrderAttack'), subOrderDiamond = $('subOrderDiamond'), subOrderSiege = $('subOrderSiege');
    const btnEndTurn = $('btnEndTurn'), btnReset = $('btnReset');

    function updateUI() {
        woodEl.textContent = state.wood;
        stoneEl.textContent = state.stone;
        ironEl.textContent = state.iron;
        carbonEl.textContent = state.carbon;
        diamondEl.textContent = state.diamond;
        peasantsEl.textContent = state.peasants;
        knightsEl.textContent = state.knights;
        knightsSiegingEl.textContent = state.knightsSieging;
        turretsEl.textContent = state.turrets;
        baseHpEl.textContent = state.baseHp;
        enemyBaseHpEl.textContent = state.enemyBaseHp;
        woodMachinesEl.textContent = state.woodMachines;
        stoneMachinesEl.textContent = state.stoneMachines;
        turnDisplay.textContent = `回合 ${state.turn}`;
        const idle = getIdlePeasants();
        idlePeasantsEl.textContent = idle;

        const disabled = state.gameOver;
        [btnCollect, btnBuild, btnOrder, btnEndTurn].forEach(b => b.disabled = disabled);
        updateOrderButtons();
        if (panelCollect.classList.contains('show') && state.collectResource) {
            refreshZoneButtons();
        }
    }

    function updateOrderButtons() {
        subOrderAttack.disabled = (state.knights === 0 || state.gameOver);
        subOrderDiamond.disabled = (state.knights === 0 || state.gameOver);
        subOrderSiege.disabled = (state.knightsSieging === 0 || state.gameOver);
    }

    function log(msg) {
        const lines = logEl.textContent.split('\n');
        lines.push(msg);
        if (lines.length > 20) lines.shift();
        logEl.textContent = lines.join('\n');
    }

    function clearLog() { logEl.textContent = ''; }
    function logAction(msg) { state.actionLog.push(msg); }

    function hideAllPanels() {
        panelCollect.classList.remove('show');
        panelBuild.classList.remove('show');
        panelOrder.classList.remove('show');
        [btnCollect, btnBuild, btnOrder].forEach(b => b.classList.remove('active'));
        collectResources.style.display = 'flex';
        collectZones.style.display = 'none';
        state.collectResource = null;
        stealPanel.style.display = 'none';
        buildZones.style.display = 'none';
        state.buildPending = null;
    }

    function showPanel(panel) {
        hideAllPanels();
        if (panel === 'collect') {
            panelCollect.classList.add('show');
            btnCollect.classList.add('active');
            collectResources.style.display = 'flex';
            collectZones.style.display = 'none';
            state.collectResource = null;
            stealPanel.style.display = 'none';
            updateUI();
        } else if (panel === 'build') {
            panelBuild.classList.add('show');
            btnBuild.classList.add('active');
            buildZones.style.display = 'none';
            state.buildPending = null;
            updateUI();
        } else if (panel === 'order') {
            panelOrder.classList.add('show');
            btnOrder.classList.add('active');
            updateOrderButtons();
            updateUI();
        }
    }

    function getIdlePeasants() {
        let working = 0;
        for (let key in state.playerWorkers) {
            working += state.playerWorkers[key];
        }
        return Math.max(0, state.peasants - working);
    }

    function getPlayerWorkers(zone) { return state.playerWorkers[zone] || 0; }
    function getEnemyWorkers(zone) { return state.enemyWorkers[zone] || 0; }

    function checkGameOver() {
        if (state.baseHp <= 0) {
            state.gameOver = true;
            log('💀 你的基地被摧毁,你输了...');
            updateUI();
            return true;
        } else if (state.enemyBaseHp <= 0) {
            state.gameOver = true;
            log('🎉 你摧毁了敌方基地,你赢了!');
            updateUI();
            return true;
        }
        return false;
    }

    function applyTurretDamage(knightsCount, turretCount, turretDamagePerShot) {
        const totalDamage = turretCount * turretDamagePerShot;
        let damageDealt = 0, killed = 0;
        const knightHP = 3;
        for (let i = 0; i < knightsCount; i++) {
            if (damageDealt >= totalDamage) break;
            let needed = knightHP;
            let dmg = Math.min(totalDamage - damageDealt, needed);
            damageDealt += dmg;
            if (dmg >= needed) killed++;
            else break;
        }
        return killed;
    }

    function assignPeasantToZone(zone) {
        if (state.gameOver) return false;
        const idle = getIdlePeasants();
        if (idle === 0) {
            log('没有空闲农民。');
            return false;
        }
        if (state.playerWorkers[zone] >= 1) {
            log('该区已有农民,不能重复派遣。');
            return false;
        }
        state.playerWorkers[zone] = 1;
        log(`派遣 1 个农民到 ${ZONE_LABELS[zone]}`);
        logAction(`采集 ${ZONE_LABELS[zone]}`);
        updateUI();
        refreshZoneButtons();
        return true;
    }

    function refreshZoneButtons() {
        const resource = state.collectResource;
        if (!resource || resource === 'diamond') return;
        const zones = ZONES[resource];
        const btns = zoneButtons.querySelectorAll('.zone-btn');
        btns.forEach(btn => {
            const zone = btn.dataset.zone;
            const count = getPlayerWorkers(zone);
            const idle = getIdlePeasants();
            btn.disabled = (count >= 1 || idle === 0 || state.gameOver);
            btn.innerHTML = `${ZONE_LABELS[zone]} <span class="sub">${count > 0 ? '✅已派' : '空闲'}</span>`;
        });
    }

    function onCollectResource(resource) {
        if (state.gameOver) return;
        if (resource === 'diamond') {
            if (state.turn < state.islandOpen) {
                log('钻石矿井尚未开放(需第4回合起)');
                return;
            }
            const idle = getIdlePeasants();
            if (idle === 0) {
                log('没有空闲农民。');
                return;
            }
            state.diamond += idle;
            log(`派遣 ${idle} 个农民开采钻石,获得 ${idle} 钻石`);
            logAction(`钻石矿井 +${idle}钻`);
            updateUI();
            hideAllPanels();
            return;
        }
        state.collectResource = resource;
        collectResources.style.display = 'none';
        collectZones.style.display = 'block';
        const zones = ZONES[resource];
        zoneButtons.innerHTML = '';
        zones.forEach(zone => {
            const btn = document.createElement('button');
            btn.className = 'zone-btn';
            btn.dataset.zone = zone;
            const count = getPlayerWorkers(zone);
            btn.innerHTML = `${ZONE_LABELS[zone]} <span class="sub">${count > 0 ? '✅已派' : '空闲'}</span>`;
            btn.onclick = function() {
                assignPeasantToZone(zone);
            };
            zoneButtons.appendChild(btn);
        });
        if (resource === 'iron') {
            stealPanel.style.display = 'flex';
        } else {
            stealPanel.style.display = 'none';
        }
        updateUI();
    }

    function startSteal(resource) {
        if (state.gameOver) return;
        const idle = getIdlePeasants();
        if (idle === 0) {
            log('没有空闲农民可以派去偷取。');
            return;
        }
        function showStealZones(resource) {
            collectResources.style.display = 'none';
            collectZones.style.display = 'block';
            stealPanel.style.display = 'none';
            const zones = ZONES[resource];
            zoneButtons.innerHTML = '';
            zones.forEach(zone => {
                const btn = document.createElement('button');
                btn.className = 'zone-btn';
                btn.dataset.zone = zone;
                btn.innerHTML = `🕵️ ${ZONE_LABELS[zone]}`;
                btn.onclick = function() {
                    if (state.gameOver) return;
                    if (state.peasants < 1) {
                        log('没有农民可派遣偷取。');
                        return;
                    }
                    state.peasants -= 1;
                    state.stealActions.push({ resource, zone });
                    log(`派遣1农民偷取 ${RESOURCE_NAMES[resource]} 的 ${ZONE_LABELS[zone]}`);
                    logAction(`偷取计划: ${RESOURCE_NAMES[resource]} ${ZONE_LABELS[zone]}`);
                    hideAllPanels();
                    updateUI();
                };
                zoneButtons.appendChild(btn);
            });
            const cancelBtn = document.createElement('button');
            cancelBtn.className = 'zone-btn';
            cancelBtn.textContent = '↩ 取消';
            cancelBtn.onclick = function() {
                collectResources.style.display = 'flex';
                collectZones.style.display = 'none';
                stealPanel.style.display = 'flex';
                state.collectResource = null;
                updateUI();
            };
            zoneButtons.appendChild(cancelBtn);
        }
        showStealZones(resource);
    }

    function autoCollectPlayer() {
        let woodGain = state.woodMachines * 3;
        let stoneGain = state.stoneMachines * 3;
        let ironGain = 0, carbonGain = 0;
        for (let zone in state.playerWorkers) {
            let count = state.playerWorkers[zone];
            if (count === 0) continue;
            if (zone.startsWith('wood')) woodGain += count * 3;
            else if (zone.startsWith('stone')) stoneGain += count * 3;
            else if (zone.startsWith('iron')) {
                ironGain += count * 3;
                if (Math.random() < 0.1 * count) carbonGain += 1;
            }
        }
        state.wood += woodGain;
        state.stone += stoneGain;
        state.iron += ironGain;
        state.carbon += carbonGain;
        for (let key in state.playerWorkers) state.playerWorkers[key] = 0;
        return { wood: woodGain, stone: stoneGain, iron: ironGain, carbon: carbonGain, diamond: 0 };
    }

    function assignEnemyPeasants() {
        for (let key in state.enemyWorkers) state.enemyWorkers[key] = 0;
        let zones = ['wood1','wood2','stone1','stone2','iron1','iron2','iron3'];
        let remaining = 3;
        while (remaining > 0) {
            let idx = Math.floor(Math.random() * zones.length);
            state.enemyWorkers[zones[idx]]++;
            remaining--;
        }
    }
    function autoCollectEnemy() {
        // 电脑资源获取翻倍(因为不会偷)
        let woodGain = state.enemyWoodMachines * 3 * 2;
        let stoneGain = state.enemyStoneMachines * 3 * 2;
        let ironGain = 0, carbonGain = 0;
        for (let zone in state.enemyWorkers) {
            let count = state.enemyWorkers[zone];
            if (count === 0) continue;
            if (zone.startsWith('wood')) woodGain += count * 3 * 2;
            else if (zone.startsWith('stone')) stoneGain += count * 3 * 2;
            else if (zone.startsWith('iron')) {
                ironGain += count * 3 * 2;
                if (Math.random() < 0.1 * count) carbonGain += 1 * 2;
            }
        }
        state.enemyWood += woodGain;
        state.enemyStone += stoneGain;
        state.enemyIron += ironGain;
        state.enemyCarbon += carbonGain;
    }
    function enemyAI() {
        assignEnemyPeasants();
        autoCollectEnemy();
        if (state.enemyStone >= 5 && state.enemyIron >= 3 && state.enemyTurrets < 3) {
            state.enemyStone -= 5; state.enemyIron -= 3; state.enemyTurrets += 1;
        } else if (state.enemyWood >= 10 && state.enemyWoodMachines < 2) {
            state.enemyWood -= 10; state.enemyWoodMachines += 1;
        } else if (state.enemyStone >= 10 && state.enemyStoneMachines < 2) {
            state.enemyStone -= 10; state.enemyStoneMachines += 1;
        } else if (state.enemyWood >= 5 && state.enemyIron >= 3 && state.enemyKnights < 4) {
            state.enemyWood -= 5; state.enemyIron -= 3; state.enemyKnights += 1;
        } else if (state.enemyCarbon >= 5 && state.enemyDiamond >= 5 && state.enemyAttackBonus < 3) {
            state.enemyCarbon -= 5; state.enemyDiamond -= 5; state.enemyAttackBonus += 1;
        }
        // 电脑进攻
        if (state.enemyKnights > 0 && Math.random() < 0.4) {
            let attackers = state.enemyKnights;
            state.enemyKnights = 0;
            let killed = applyTurretDamage(attackers, state.turrets, state.turretAttack);
            let survivors = attackers - killed;
            if (killed > 0) state.enemyMessages.push(`电脑 ${killed} 个骑士被你的炮台击杀。`);
            if (survivors > 0) {
                state.baseHp -= survivors * 1;
                state.enemyMessages.push(`电脑 ${survivors} 个骑士对你的基地造成 ${survivors} 点伤害。`);
            }
            if (checkGameOver()) return;
        }
        // 电脑抢夺钻石
        if (Math.random() < 0.3 && state.enemyKnights > 0) {
            state.enemyRaid = { knights: state.enemyKnights, peasants: 0 };
            state.enemyKnights = 0;
            state.enemyMessages.push(`电脑派出 ${state.enemyRaid.knights} 骑士抢夺钻石。`);
        } else {
            state.enemyRaid = null;
        }
    }

    // ----- 修改后的抢夺钻石结算(不再输出“未发生战斗”)-----
    function resolveDiamondRaid() {
        let pRaid = state.playerRaid || { knights: 0, peasants: 0 };
        let eRaid = state.enemyRaid || { knights: 0, peasants: 0 };
        let pKnights = pRaid.knights;
        let eKnights = eRaid.knights;

        // 如果没有任何骑士参与,直接返回(不输出任何日志)
        if (pKnights === 0 && eKnights === 0) {
            if (state.playerRaid) state.playerRaid = null;
            if (state.enemyRaid) state.enemyRaid = null;
            return;
        }

        // 只有一方有骑士时,直接归还,不输出
        if (pKnights > 0 && eKnights === 0) {
            state.knights += pKnights;
            state.playerRaid = null;
            state.enemyRaid = null;
            return;
        }
        if (eKnights > 0 && pKnights === 0) {
            state.enemyKnights += eKnights;
            state.playerRaid = null;
            state.enemyRaid = null;
            return;
        }

        // 双方都有骑士,交战
        if (pKnights > eKnights) {
            state.knights = pKnights - eKnights;
            state.enemyKnights = 0;
            log(`抢夺钻石:双方骑士交战后,你剩余 ${state.knights} 骑士,电脑剩余 0。`);
            logAction(`骑士战后 玩家${state.knights} 电脑0`);
        } else if (eKnights > pKnights) {
            state.enemyKnights = eKnights - pKnights;
            state.knights = 0;
            log(`抢夺钻石:双方骑士交战后,你剩余 0 骑士,电脑剩余 ${state.enemyKnights}。`);
            logAction(`骑士战后 玩家0 电脑${state.enemyKnights}`);
        } else {
            state.knights = 0;
            state.enemyKnights = 0;
            log('抢夺钻石:双方骑士势均力敌,全部阵亡。');
            logAction('骑士战后 双方0');
        }

        // 归还农民(如果有)
        if (state.playerRaid) {
            state.peasants += state.playerRaid.peasants;
            state.playerRaid = null;
        }
        if (state.enemyRaid) {
            state.enemyRaid = null;
        }
        updateUI();
    }

    function resolveSteal() {
        if (state.stealActions.length === 0) return;
        const actions = state.stealActions.slice();
        state.stealActions = [];
        for (let act of actions) {
            const { resource, zone } = act;
            let enemyCount = getEnemyWorkers(zone);
            if (enemyCount > 0) {
                log(`偷取失败!你的农民在 ${ZONE_LABELS[zone]} 被敌人杀死,未能返回。`);
                logAction(`偷取失败,农民死亡`);
            } else {
                state.peasants += 1;
                let gainedWood=0, gainedStone=0, gainedIron=0, gainedCarbon=0;
                if (resource === 'wood') {
                    gainedWood = 10;
                    state.wood += gainedWood;
                    state.woodMachines += state.enemyWoodMachines;
                    state.enemyWoodMachines = 0;
                    log(`偷取成功!获得 ${gainedWood} 木头,并夺取敌方所有伐木机 (${state.woodMachines}台),农民安全返回。`);
                    logAction(`偷树林成功,+${gainedWood}木,夺伐木机`);
                } else if (resource === 'stone') {
                    gainedStone = 10;
                    state.stone += gainedStone;
                    state.stoneMachines += state.enemyStoneMachines;
                    state.enemyStoneMachines = 0;
                    log(`偷取成功!获得 ${gainedStone} 石头,并夺取敌方所有钻头 (${state.stoneMachines}台),农民安全返回。`);
                    logAction(`偷山丘成功,+${gainedStone}石,夺钻头`);
                } else if (resource === 'iron') {
                    gainedIron = 10;
                    state.iron += gainedIron;
                    gainedCarbon = 1;
                    state.carbon += gainedCarbon;
                    log(`偷取成功!获得 ${gainedIron} 铁和 ${gainedCarbon} 碳,农民安全返回。`);
                    logAction(`偷矿井成功,+${gainedIron}铁,+${gainedCarbon}碳`);
                }
            }
        }
        updateUI();
    }

    // 建造设施(骑士不选区)
    function startBuild(action) {
        if (state.gameOver) return;
        let canBuild = false;
        switch(action) {
            case 'woodMachine':
                if (state.wood < 10) { log('木头不足 (需要10)'); return; }
                canBuild = true; break;
            case 'stoneMachine':
                if (state.stone < 10) { log('石头不足 (需要10)'); return; }
                canBuild = true; break;
            case 'turret':
                if (state.stone < 5 || state.iron < 3) { log('资源不足 (需要5石+3铁)'); return; }
                canBuild = true; break;
            case 'knight':
                if (state.wood < 5 || state.iron < 3) { log('资源不足 (需要5木+3铁)'); return; }
                executeBuild('knight');
                hideAllPanels();
                return;
            case 'alloy':
                if (state.diamond < 5 || state.carbon < 5) { log('资源不足 (需要5钻+5碳)'); return; }
                canBuild = true; break;
            case 'upgrade':
                if (state.wood < 5 || state.stone < 5 || state.iron < 5) { log('资源不足 (需要5木+5石+5铁)'); return; }
                canBuild = true; break;
            default: return;
        }
        if (!canBuild) return;
        state.buildPending = action;
        buildZones.style.display = 'block';
        buildZoneTitle.textContent = `选择建造 ${action} 的区域`;
        buildZoneButtons.innerHTML = '';
        ['1区', '2区'].forEach(label => {
            const btn = document.createElement('button');
            btn.className = 'zone-btn';
            btn.textContent = label;
            btn.onclick = function() {
                executeBuild(action);
                buildZones.style.display = 'none';
                state.buildPending = null;
                hideAllPanels();
            };
            buildZoneButtons.appendChild(btn);
        });
        buildZoneBack.onclick = function() {
            buildZones.style.display = 'none';
            state.buildPending = null;
        };
    }

    function executeBuild(action) {
        switch(action) {
            case 'woodMachine':
                state.wood -= 10;
                state.woodMachines += 1;
                log('建造了伐木机 (+3木/回合)');
                logAction('建造伐木机');
                break;
            case 'stoneMachine':
                state.stone -= 10;
                state.stoneMachines += 1;
                log('建造了钻头 (+3石/回合)');
                logAction('建造钻头');
                break;
            case 'turret':
                state.stone -= 5; state.iron -= 3;
                state.turrets += 1;
                log('建造了炮台 (自动防御)');
                logAction('建造炮台');
                break;
            case 'knight':
                state.wood -= 5; state.iron -= 3;
                state.knights += 1;
                log('训练了一名骑士');
                logAction('训练骑士');
                break;
            case 'alloy':
                state.diamond -= 5; state.carbon -= 5;
                state.attackBonus += 1;
                state.turretAttack += 1;
                log(`制造合金科技现在伤害+1 总+${state.attackBonus}`);
                logAction(`合金 +1 (总${state.attackBonus})`);
                break;
            case 'upgrade':
                state.wood -= 5; state.stone -= 5; state.iron -= 5;
                state.baseHp += 2;
                log(`城堡升级成功!生命+2 (当前 ${state.baseHp})`);
                logAction(`升级城堡 +2血`);
                break;
        }
        updateUI();
    }

    function orderAttack() {
        if (state.gameOver) return;
        if (state.knights === 0) { log('没有骑士可派遣。'); return; }
        let attackers = state.knights;
        state.knights = 0;
        log(`敌方有 ${state.enemyTurrets} 座炮台。`);
        logAction(`敌方炮台 ${state.enemyTurrets}`);
        let killed = applyTurretDamage(attackers, state.enemyTurrets, 1);
        let survivors = attackers - killed;
        if (killed > 0) {
            log(`你的 ${killed} 个骑士被敌方炮台击杀。`);
            logAction(`死亡 ${killed} 骑士`);
        }
        if (survivors > 0) {
            state.knightsSieging += survivors;
            log(`${survivors} 个骑士抵达城下,可点击“攻击城堡”造成伤害。`);
            logAction(`${survivors} 骑士抵达城下`);
        } else {
            log('所有骑士阵亡,无法攻城。');
            logAction('骑士全灭');
        }
        updateUI();
        hideAllPanels();
    }

    function orderSiege() {
        if (state.gameOver) return;
        if (state.knightsSieging === 0) { log('没有骑士在城下。'); return; }
        let damage = state.knightsSieging * (1 + state.attackBonus);
        state.enemyBaseHp -= damage;
        log(`城下骑士对敌方城堡造成 ${damage} 点伤害。`);
        logAction(`攻击城堡 -${damage}血`);
        state.knightsSieging = 0;
        updateUI();
        hideAllPanels();
        checkGameOver();
    }

    function orderDiamondRaid() {
        if (state.gameOver) return;
        if (state.knights === 0) {
            log('没有骑士可派遣抢夺钻石。');
            return;
        }
        let knightsSent = state.knights;
        state.knights = 0;
        state.playerRaid = { knights: knightsSent, peasants: 0 };
        log(`派出 ${knightsSent} 骑士抢夺钻石。`);
        logAction(`抢夺钻石:骑士${knightsSent}`);
        updateUI();
        hideAllPanels();
    }

    function endTurn() {
        if (state.gameOver) return;
        clearLog();
        state.enemyMessages = [];
        resolveSteal();
        const gains = autoCollectPlayer();
        log(`+${gains.wood}木,+${gains.stone}石,+${gains.iron}铁,+${gains.carbon}碳`);
        enemyAI();
        resolveDiamondRaid();
        if (state.actionLog.length > 0) {
            for (let msg of state.actionLog) log(msg);
            state.actionLog = [];
        } else {
            log('本回合未执行任何操作。');
        }
        if (state.enemyMessages.length > 0) {
            for (let msg of state.enemyMessages) log(msg);
        }
        state.turn += 1;
        if (state.turn === state.islandOpen) {
            log('钻石矿井已开放!可在获取物资中开采钻石。');
        }
        updateUI();
        if (!state.gameOver) {
            log('新回合开始,请操作。');
        }
        hideAllPanels();
    }

    // ----- 重置游戏(含玩法讲解)-----
    function resetGame() {
        state.turn = 0;
        state.wood = 0; state.stone = 0; state.iron = 0; state.carbon = 0; state.diamond = 0;
        state.peasants = 3;
        state.knights = 0;
        state.knightsSieging = 0;
        state.turrets = 0;
        state.enemyTurrets = 0;
        state.baseHp = 50;
        state.enemyBaseHp = 50;
        state.woodMachines = 0;
        state.stoneMachines = 0;
        state.attackBonus = 0;
        state.turretAttack = 1;
        state.gameOver = false;
        state.enemyWood = 0; state.enemyStone = 0; state.enemyIron = 0;
        state.enemyCarbon = 0; state.enemyDiamond = 0;
        state.enemyKnights = 0;
        state.enemyWoodMachines = 0;
        state.enemyStoneMachines = 0;
        state.enemyAttackBonus = 0;
        state.playerRaid = null;
        state.enemyRaid = null;
        state.stealActions = [];
        state.actionLog = [];
        state.enemyMessages = [];
        for (let key in state.playerWorkers) state.playerWorkers[key] = 0;
        for (let key in state.enemyWorkers) state.enemyWorkers[key] = 0;
        state.buildPending = null;
        state.collectResource = null;
        hideAllPanels();
        clearLog();
        // 开局讲解
        log('🎯 新游戏开始!');
        log('🗡️ 目标:摧毁敌方城堡(50血)');
        log('📦 获取物资:派农民去树林/山丘/矿井/钻石矿井(第4回合起)');
        log('🏗️ 建造设施:伐木机/钻头/炮台/骑士/合金/升级城堡');
        log('⚔️ 调遣骑士:出征城堡(炮台会反击)→ 攻击城堡造成伤害');
        log('💎 抢夺钻石:双方骑士交火,少的一方清零');
        log('🕵️ 偷物资:在矿井中消耗1农民偷取,若该区有敌人则农民死亡');
        log('💡 每回合先分配农民,再建造,最后调遣骑士,点击"结束回合"结算。');
        log('⏳ 钻石矿井第4回合起可用,合金需5钻+5碳。');
        updateUI();
    }

    document.querySelectorAll('[data-resource]').forEach(btn => {
        btn.addEventListener('click', function() {
            onCollectResource(this.dataset.resource);
        });
    });

    document.querySelectorAll('[data-steal]').forEach(btn => {
        btn.addEventListener('click', function() {
            const resource = this.dataset.steal;
            startSteal(resource);
        });
    });
    document.getElementById('stealBack').addEventListener('click', function() {
        collectResources.style.display = 'flex';
        collectZones.style.display = 'none';
        stealPanel.style.display = 'none';
        state.collectResource = null;
        updateUI();
    });

    collectBack.addEventListener('click', function() {
        hideAllPanels();
        showPanel('collect');
    });

    subBuildMachineWood.addEventListener('click', () => startBuild('woodMachine'));
    subBuildMachineStone.addEventListener('click', () => startBuild('stoneMachine'));
    subBuildTurret.addEventListener('click', () => startBuild('turret'));
    subTrainKnight.addEventListener('click', () => startBuild('knight'));
    subAlloy.addEventListener('click', () => startBuild('alloy'));
    subUpgradeCastle.addEventListener('click', () => startBuild('upgrade'));

    buildBack.addEventListener('click', function() {
        hideAllPanels();
        showPanel('build');
    });
    buildZoneBack.addEventListener('click', function() {
        buildZones.style.display = 'none';
        state.buildPending = null;
    });

    orderBack.addEventListener('click', function() {
        hideAllPanels();
        showPanel('order');
    });

    subOrderAttack.addEventListener('click', orderAttack);
    subOrderSiege.addEventListener('click', orderSiege);
    subOrderDiamond.addEventListener('click', orderDiamondRaid);

    btnCollect.addEventListener('click', () => showPanel('collect'));
    btnBuild.addEventListener('click', () => showPanel('build'));
    btnOrder.addEventListener('click', () => showPanel('order'));

    btnEndTurn.addEventListener('click', endTurn);
    btnReset.addEventListener('click', resetGame);

    resetGame();
})();
</script>
</body>
</html>

Game Source: 资源战争

Creator: LuckyFlame48

Libraries: none

Complexity: complex (1180 lines, 46.6 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: game-luckyflame48" to link back to the original. Then publish at arcadelab.ai/publish.