Batalla Por Terra < 100% VALIDATED >

// Tipos de unidad const UNITS = INFANTRY: name: "⚔️", baseAtk: 8, baseDef: 5, range: 1, hp: 20, icon: "⚔️" , ARCHER: name: "🏹", baseAtk: 6, baseDef: 3, range: 3, hp: 15, icon: "🏹" , CAVALRY: name: "🐎", baseAtk: 10, baseDef: 4, range: 1, hp: 18, icon: "🐎" ;

// Verificar si está en rango (distancia Manhattan) function isInRange(ax, ay, dx, dy, range) return (Math.abs(ax - dx) + Math.abs(ay - dy)) <= range;

def attack(self, ax, ay, dx, dy): attacker = self.grid[ax][ay] defender = self.grid[dx][dy] if not attacker or not defender: return False, "No hay unidad" if attacker.side == defender.side: return False, "No puedes atacar aliados" if attacker.side != self.current_turn: return False, "No es tu turno" if not self.in_range(ax, ay, dx, dy, attacker.range): return False, "Fuera de rango" damage = self.calculate_damage(attacker, defender, self.terrain[ax][ay], self.terrain[dx][dy]) defender.hp -= damage msg = f"attacker.icon ataca a defender.icon y causa damage de daño!" if defender.hp <= 0: msg += f" defender.icon ha muerto!" self.grid[dx][dy] = None return True, msg batalla por terra

// Terrenos const TERRAIN = PLAIN: name: "🌾", dmgModAttacker: 1.0, dmgModDefender: 1.0, defBonus: 0 , FOREST: name: "🌲", dmgModAttacker: 0.9, dmgModDefender: 1.1, defBonus: 2 , HILL: name: "⛰️", dmgModAttacker: 1.15, dmgModDefender: 0.95, defBonus: 1 ;

def display(self): os.system('cls' if os.name == 'nt' else 'clear') print("\n" + "="*60) print("⚔️ BATALLA POR TIERRA ⚔️".center(60)) print(f"Turno: self.current_turn.upper()".center(60)) print("="*60) print(" " + " ".join(f"j:2" for j in range(self.size))) for i in range(self.size): row_display = f"i:2 " for j in range(self.size): unit = self.grid[i][j] terrain_char = "Plain":"🌾","Forest":"🌲","Hill":"⛰️"[self.terrain[i][j]["name"]] if unit: row_display += f"unit.iconunit.hp:2 " else: row_display += f" terrain_char " print(row_display) print("-"*60) // Tipos de unidad const UNITS = INFANTRY:

def change_turn(self): self.current_turn = "defender" if self.current_turn == "attacker" else "attacker" print(f"\n🔄 Turno cambiado a self.current_turn.upper()")

// Inicializar grid function initGrid() grid = Array(GRID_SIZE).fill().map(() => Array(GRID_SIZE).fill().map(() => ( terrain: randomTerrain(), unit: null, side: null // "attacker", "defender" ))); ARCHER: name: "🏹"

// Lógica de selección y ataque function handleCellClick(x, y) if (checkVictory()) return; const cell = grid[x][y]; // Si tenemos unidad seleccionada if (selectedUnit) const sel = selectedUnit; if (cell.side && cell.side !== currentTurn) // Atacar attack(sel.x, sel.y, x, y); selectedUnit = null; updateUI(); const winner = checkVictory(); if (!winner) // Después de atacar no se cambia turno automáticamente (opcional, puedes cambiarlo) // Por diseño: ataque consume turno? En muchos juegos sí. Aquí decidimos que después de atacar termina turno // Descomentar si quieres que atacar termine turno: endTurn(); updateUI(); else // Selección inválida addLog("❌ No puedes atacar ahí"); selectedUnit = null; updateUI(); // Si no hay selección, seleccionar unidad propia si es el turno correcto else if (cell.side === currentTurn && cell.unit !== null) selectedUnit = x, y ; addLog(`✅ Unidad $cell.unit.icon seleccionada en ($x,$y)`); updateUI(); else addLog("⚠️ Selecciona una unidad de tu ejército.");

// Colocar ejércitos (ejemplo equilibrado) function placeArmies() // Atacante (zona izquierda) const attackerPositions = [[0,0],[1,1],[2,0],[0,2],[3,1],[1,3],[4,2],[5,0],[0,4],[2,3]]; const defenderPositions = [[9,9],[8,8],[9,7],[7,9],[6,8],[9,6],[8,5],[7,7],[9,4],[6,9]]; // Tipos variados const unitTypes = [UNITS.INFANTRY, UNITS.ARCHER, UNITS.CAVALRY, UNITS.INFANTRY, UNITS.ARCHER, UNITS.CAVALRY, UNITS.INFANTRY, UNITS.ARCHER, UNITS.CAVALRY, UNITS.INFANTRY]; attackerPositions.forEach((pos, idx) => if (pos[0] < GRID_SIZE && pos[1] < GRID_SIZE) const type = unitTypes[idx % unitTypes.length]; grid[pos[0]][pos[1]].unit = ...type, hp: type.hp, maxHp: type.hp ; grid[pos[0]][pos[1]].side = "attacker"; ); defenderPositions.forEach((pos, idx) => if (pos[0] < GRID_SIZE && pos[1] < GRID_SIZE) const type = unitTypes[(idx+3) % unitTypes.length]; grid[pos[0]][pos[1]].unit = ...type, hp: type.hp, maxHp: type.hp ; grid[pos[0]][pos[1]].side = "defender"; );

// Inicializar resetGame(); </script> </body> </html> import random import os class Terrain: PLAIN = "name": "Plain", "dmg_atk": 1.0, "dmg_def": 1.0, "def_bonus": 0 FOREST = "name": "Forest", "dmg_atk": 0.9, "dmg_def": 1.1, "def_bonus": 2 HILL = "name": "Hill", "dmg_atk": 1.15, "dmg_def": 0.95, "def_bonus": 1

Join the Discussion