Add multi-player support (2-4 players) and AI bots
This commit is contained in:
121
public/ai-bot.js
Normal file
121
public/ai-bot.js
Normal file
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* AI Bot for Hexo game
|
||||
* Controls computer-controlled players
|
||||
*/
|
||||
|
||||
import { CELL_TYPES } from './map.js';
|
||||
|
||||
export class AIBot {
|
||||
constructor(playerId, map, gameUI) {
|
||||
this.playerId = playerId;
|
||||
this.map = map;
|
||||
this.gameUI = gameUI;
|
||||
this.thinkingTime = 1000; // ms delay between moves
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute AI turn
|
||||
*/
|
||||
async playTurn() {
|
||||
// Get all player cells
|
||||
const playerCells = this.map.getPlayerCells(this.playerId);
|
||||
|
||||
if (playerCells.length === 0) return;
|
||||
|
||||
// Find all possible moves
|
||||
const moves = this.findPossibleMoves(playerCells);
|
||||
|
||||
if (moves.length === 0) {
|
||||
// No moves available, end turn
|
||||
this.gameUI.endTurn();
|
||||
return;
|
||||
}
|
||||
|
||||
// Sort moves by priority (attack > expand > reinforce)
|
||||
moves.sort((a, b) => this.movePriority(b) - this.movePriority(a));
|
||||
|
||||
// Execute best move
|
||||
const bestMove = moves[0];
|
||||
|
||||
// Wait for thinking time
|
||||
await this.wait(this.thinkingTime);
|
||||
|
||||
// Execute the move
|
||||
this.executeMove(bestMove);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all possible moves for AI
|
||||
*/
|
||||
findPossibleMoves(playerCells) {
|
||||
const moves = [];
|
||||
|
||||
for (const cell of playerCells) {
|
||||
if (cell.getStrength() <= 1) continue;
|
||||
|
||||
const neighbors = this.map.getNeighbors(cell.q, cell.r);
|
||||
|
||||
for (const neighbor of neighbors) {
|
||||
// Skip own cells
|
||||
if (neighbor.getOwner() === this.playerId) continue;
|
||||
|
||||
const attackStrength = cell.getStrength() - 1;
|
||||
const defenseStrength = neighbor.getStrength();
|
||||
|
||||
moves.push({
|
||||
from: cell,
|
||||
to: neighbor,
|
||||
attackStrength,
|
||||
defenseStrength,
|
||||
type: neighbor.type === CELL_TYPES.EMPTY ? 'expand' : 'attack'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return moves;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate move priority (higher = better)
|
||||
*/
|
||||
movePriority(move) {
|
||||
let priority = 0;
|
||||
|
||||
// Prefer attacks on weak enemies
|
||||
if (move.type === 'attack') {
|
||||
if (move.attackStrength > move.defenseStrength) {
|
||||
priority += 100; // Likely to win
|
||||
priority += move.attackStrength - move.defenseStrength;
|
||||
} else {
|
||||
priority -= 50; // Risky attack
|
||||
}
|
||||
}
|
||||
|
||||
// Prefer expanding to empty cells
|
||||
if (move.type === 'expand') {
|
||||
priority += 50;
|
||||
priority += move.attackStrength; // Stronger placement = better
|
||||
}
|
||||
|
||||
// Prefer moves that create strong positions
|
||||
priority += move.attackStrength * 0.5;
|
||||
|
||||
return priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a move
|
||||
*/
|
||||
executeMove(move) {
|
||||
this.gameUI.selectedCell = move.from;
|
||||
this.gameUI.currentTarget = move.to;
|
||||
this.gameUI.executeAttack();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for specified time
|
||||
*/
|
||||
wait(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user