资源战争
by LuckyFlame481180 lines46.6 KB
<!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.