import gradio as gr import os import subprocess import time from collections import deque # Criar pasta para armazenar as classes Java os.makedirs("combat_classes", exist_ok=True) # Templates de código para as aeronaves com altura dinâmica e novos atributos TEAM1_TEMPLATE = '''import java.util.ArrayList; import java.util.Random; /** * Time 1 - Configure sua aeronave! * * SISTEMA DE PONTOS: * - Você tem 100 pontos para distribuir entre os atributos * - Escolha com sabedoria para criar uma aeronave competitiva * * ATRIBUTOS: * - speed: Velocidade da aeronave (1-10) - Afeta quão rápido sua aeronave pode se mover * - fireRate: Taxa de disparo (1-10) - Controla com que frequência sua aeronave pode atirar * - maneuverability: Manobrabilidade (1-10) - Facilita mudanças de altitude e esquivas * - shotPower: Poder do tiro normal (5-20) - Dano causado por tiros normais * - supersonicPower: Poder do tiro supersônico (10-30) - Dano causado por tiros supersônicos * - missilePower: Poder do míssil (15-40) - Dano causado pelo míssil especial * - defense: Defesa (5-25) - Reduz o dano recebido * - stealthChance: Chance de furtividade (0-20) - Probabilidade de evitar ataques * - radar: Radar (0-10) - Capacidade de detectar projéteis inimigos * - doubleShot: Tiro duplo (0-10) - Permite disparar em duas altitudes diferentes * - nuclearPower: Poder nuclear (0-10) - Poder do míssil nuclear (dano massivo) */ public class Team1Aircraft extends Aircraft { private Random random = new Random(); private int maxAltitude; // Armazena a altura máxima do campo public Team1Aircraft() { super( // DISTRIBUA 100 PONTOS ENTRE ESSES ATRIBUTOS 5, // Velocidade (1-10) 5, // Taxa de fogo (1-10) 5, // Manobrabilidade (1-10) 15, // Dano do tiro normal (5-20) 20, // Dano do tiro supersônico (10-30) 25, // Dano do míssil (15-40) 15, // Defesa (5-25) 5, // Chance de furtividade (0-20) 2, // Radar (0-10) 2, // Tiro duplo (0-10) 1, // Poder nuclear (0-10) "▶" // Símbolo da aeronave (não altere) ); // IMPORTANTE: A soma de todos os atributos deve ser <= 100 // Exemplo: 5+5+5+15+20+25+15+5+2+2+1 = 100 // Verifica dinamicamente a altura do campo (será definida pelo BattleMain) try { String heightEnv = System.getProperty("battlefield.height", "3"); maxAltitude = Integer.parseInt(heightEnv) - 1; } catch (Exception e) { maxAltitude = 2; // Valor padrão se não conseguir ler } } /** * Controla o movimento da aeronave. * Valor padrão: Movimento aleatório baseado na velocidade * Dica: Você pode personalizar para criar padrões de movimento mais inteligentes */ @Override public int move() { // Retorna um número entre -speed/2 e +speed return random.nextInt(speed + 1) - speed / 2; } /** * Controla a mudança de altitude da aeronave. * Valor padrão: Mudança aleatória entre subir, descer ou manter altitude * Dica: Uma boa estratégia pode aumentar suas chances de esquiva */ @Override public int changeAltitude() { int direction = random.nextInt(3) - 1; // -1 (descer), 0 (manter), 1 (subir) this.posY = Math.max(0, Math.min(maxAltitude, posY + direction)); return direction; } /** * Tiro normal - mais frequente, menos dano */ @Override public Projectile shoot(int posX, int direction) { return new Projectile(posX, this.posY, direction, 1, "->"); } /** * Tiro supersônico - mais rápido, mais dano */ @Override public Projectile shootSupersonic(int posX, int direction) { return new Projectile(posX, this.posY, direction, 2, ">>"); } /** * Míssil especial - muito dano, com cooldown */ @Override public Projectile specialMissile(int posX, int direction) { if (missileCooldown == 0) { missileCooldown = 3; // Espera 3 turnos para usar novamente return new Projectile(posX, this.posY, direction, 1, "=>"); } missileCooldown--; return null; } /** * Tiro duplo - ataca em duas altitudes diferentes */ @Override public Projectile doubleShot(int posX, int direction) { // Define a segunda altitude para o tiro (diferente da atual) int currentAlt = this.posY; int secondAlt = (currentAlt + 1) % (maxAltitude + 1); // Guarda essa altitude para ser usada pelo BattleMain this.secondShotAltitude = secondAlt; // Retorna o projétil principal return new Projectile(posX, this.posY, direction, 1, "⇉"); } /** * Míssil nuclear - dano massivo */ @Override public Projectile nuclearMissile(int posX, int direction) { if (missileCooldown == 0) { missileCooldown = 5; // Longo cooldown para o poder nuclear return new Projectile(posX, this.posY, direction, 1, "-]=>"); } return null; } /** * Radar - detecta projéteis inimigos */ @Override public void radarScan(ArrayList projectiles, int enemyPosX, int enemyPosY) { // Implementação básica: apenas detecta projéteis próximos // Em uma implementação mais avançada, você poderia usar essas informações // para ajustar seu movimento e evitar projéteis } }''' TEAM2_TEMPLATE = '''import java.util.ArrayList; import java.util.Random; /** * Time 2 - Configure sua aeronave! * * SISTEMA DE PONTOS: * - Você tem 100 pontos para distribuir entre os atributos * - Escolha com sabedoria para criar uma aeronave competitiva * * ATRIBUTOS: * - speed: Velocidade da aeronave (1-10) - Afeta quão rápido sua aeronave pode se mover * - fireRate: Taxa de disparo (1-10) - Controla com que frequência sua aeronave pode atirar * - maneuverability: Manobrabilidade (1-10) - Facilita mudanças de altitude e esquivas * - shotPower: Poder do tiro normal (5-20) - Dano causado por tiros normais * - supersonicPower: Poder do tiro supersônico (10-30) - Dano causado por tiros supersônicos * - missilePower: Poder do míssil (15-40) - Dano causado pelo míssil especial * - defense: Defesa (5-25) - Reduz o dano recebido * - stealthChance: Chance de furtividade (0-20) - Probabilidade de evitar ataques * - radar: Radar (0-10) - Capacidade de detectar projéteis inimigos * - doubleShot: Tiro duplo (0-10) - Permite disparar em duas altitudes diferentes * - nuclearPower: Poder nuclear (0-10) - Poder do míssil nuclear (dano massivo) */ public class Team2Aircraft extends Aircraft { private Random random = new Random(); private int maxAltitude; // Armazena a altura máxima do campo public Team2Aircraft() { super( // DISTRIBUA 100 PONTOS ENTRE ESSES ATRIBUTOS 5, // Velocidade (1-10) 5, // Taxa de fogo (1-10) 5, // Manobrabilidade (1-10) 15, // Dano do tiro normal (5-20) 20, // Dano do tiro supersônico (10-30) 25, // Dano do míssil (15-40) 15, // Defesa (5-25) 5, // Chance de furtividade (0-20) 2, // Radar (0-10) 2, // Tiro duplo (0-10) 1, // Poder nuclear (0-10) "◀" // Símbolo da aeronave (não altere) ); // IMPORTANTE: A soma de todos os atributos deve ser <= 100 // Exemplo: 5+5+5+15+20+25+15+5+2+2+1 = 100 // Verifica dinamicamente a altura do campo (será definida pelo BattleMain) try { String heightEnv = System.getProperty("battlefield.height", "3"); maxAltitude = Integer.parseInt(heightEnv) - 1; } catch (Exception e) { maxAltitude = 2; // Valor padrão se não conseguir ler } } /** * Controla o movimento da aeronave. * Valor padrão: Movimento aleatório baseado na velocidade * Dica: Você pode personalizar para criar padrões de movimento mais inteligentes */ @Override public int move() { // Retorna um número entre -speed/2 e +speed return random.nextInt(speed + 1) - speed / 2; } /** * Controla a mudança de altitude da aeronave. * Valor padrão: Mudança aleatória entre subir, descer ou manter altitude * Dica: Uma boa estratégia pode aumentar suas chances de esquiva */ @Override public int changeAltitude() { int direction = random.nextInt(3) - 1; // -1 (descer), 0 (manter), 1 (subir) this.posY = Math.max(0, Math.min(maxAltitude, posY + direction)); return direction; } /** * Tiro normal - mais frequente, menos dano */ @Override public Projectile shoot(int posX, int direction) { return new Projectile(posX, this.posY, direction, 1, "<-"); } /** * Tiro supersônico - mais rápido, mais dano */ @Override public Projectile shootSupersonic(int posX, int direction) { return new Projectile(posX, this.posY, direction, 2, "<<"); } /** * Míssil especial - muito dano, com cooldown */ @Override public Projectile specialMissile(int posX, int direction) { if (missileCooldown == 0) { missileCooldown = 3; // Espera 3 turnos para usar novamente return new Projectile(posX, this.posY, direction, 1, "<="); } missileCooldown--; return null; } /** * Tiro duplo - ataca em duas altitudes diferentes */ @Override public Projectile doubleShot(int posX, int direction) { // Define a segunda altitude para o tiro (diferente da atual) int currentAlt = this.posY; int secondAlt = (currentAlt + 1) % (maxAltitude + 1); // Guarda essa altitude para ser usada pelo BattleMain this.secondShotAltitude = secondAlt; // Retorna o projétil principal return new Projectile(posX, this.posY, direction, 1, "⇇"); } /** * Míssil nuclear - dano massivo */ @Override public Projectile nuclearMissile(int posX, int direction) { if (missileCooldown == 0) { missileCooldown = 5; // Longo cooldown para o poder nuclear return new Projectile(posX, this.posY, direction, 1, "<[=-"); } return null; } /** * Radar - detecta projéteis inimigos */ @Override public void radarScan(ArrayList projectiles, int enemyPosX, int enemyPosY) { // Implementação básica: apenas detecta projéteis próximos // Em uma implementação mais avançada, você poderia usar essas informações // para ajustar seu movimento e evitar projéteis } }''' # Código base das classes Aircraft e Projectile aircraft_code = """ import java.util.ArrayList; public abstract class Aircraft { protected int health; // Agora definido externamente protected int speed; protected int fireRate; protected int maneuverability; protected int shotPower; protected int supersonicPower; protected int missilePower; protected int defense; protected int stealthChance; protected int radar; protected int doubleShot; protected int doubleShotPower; protected int nuclearPower; protected int secondShotAltitude = -1; protected int missileCooldown = 0; protected int posY = 1; protected String symbol; protected static final int TOTAL_POINTS = 100; public Aircraft(int speed, int fireRate, int maneuverability, int shotPower, int supersonicPower, int missilePower, int defense, int stealthChance, int radar, int doubleShot, int nuclearPower, String symbol) { this.health = 100; // Valor padrão que será substituído this.speed = speed; this.fireRate = fireRate; this.maneuverability = maneuverability; this.shotPower = shotPower; this.supersonicPower = supersonicPower; this.missilePower = missilePower; this.defense = defense; this.stealthChance = stealthChance; this.radar = radar; this.doubleShot = doubleShot; this.doubleShotPower = doubleShot; this.nuclearPower = nuclearPower; this.symbol = symbol; validateAttributes(); } public void setInitialHealth(int health) { this.health = health; } private void validateAttributes() { int total = speed + fireRate + maneuverability + shotPower + supersonicPower + missilePower + defense + stealthChance + radar + doubleShot + nuclearPower; if (total > TOTAL_POINTS) { throw new IllegalArgumentException("Erro: A soma dos atributos excede " + TOTAL_POINTS + " pontos! Total: " + total); } } public abstract int move(); public abstract int changeAltitude(); public abstract Projectile shoot(int posX, int direction); public abstract Projectile shootSupersonic(int posX, int direction); public abstract Projectile specialMissile(int posX, int direction); public abstract Projectile doubleShot(int posX, int direction); public abstract Projectile nuclearMissile(int posX, int direction); public abstract void radarScan(ArrayList projectiles, int enemyPosX, int enemyPosY); public int getHealth() { return health; } public void takeDamage(int damage) { this.health -= Math.max(0, damage - (defense / 10)); } public boolean isAlive() { return health > 0; } public int getPositionY() { return posY; } public int getSecondShotAltitude() { int alt = secondShotAltitude; secondShotAltitude = -1; // Reset após uso return alt; } } """ projectile_code = """ public class Projectile { int posX; int posY; int direction; int speed; String symbol; int power = 0; // Poder do projétil, usado para dano personalizado public Projectile(int posX, int posY, int direction, int speed, String symbol) { this.posX = posX; this.posY = posY; this.direction = direction; this.speed = speed; this.symbol = symbol; } public Projectile(int posX, int posY, int direction, int speed, String symbol, int power) { this(posX, posY, direction, speed, symbol); this.power = power; } public void move() { posX += direction * speed; } public boolean isOutOfBounds(int screenWidth) { return (posX < 0 || posX >= screenWidth); } public int getPower() { return power; } } """ def run_battle(code1, code2, screen_width, battlefield_height, p1_start_pos, p2_start_pos, team1_health, team2_health): # Caminhos dos arquivos Java aircraft_path = "combat_classes/Aircraft.java" projectile_path = "combat_classes/Projectile.java" class1_path = "combat_classes/Team1Aircraft.java" class2_path = "combat_classes/Team2Aircraft.java" main_path = "combat_classes/BattleMain.java" # Gerar o código do BattleMain com os parâmetros configuráveis battle_main_code = f""" import java.util.ArrayList; import java.util.Iterator; import java.util.Random; public class BattleMain {{ public static void main(String[] args) {{ // Definir a altura do campo como propriedade do sistema System.setProperty("battlefield.height", "{battlefield_height}"); Aircraft team1 = new Team1Aircraft(); Aircraft team2 = new Team2Aircraft(); // Definir a vida inicial de cada aeronave team1.setInitialHealth({team1_health}); team2.setInitialHealth({team2_health}); Random random = new Random(); int p1PosX = {p1_start_pos}; int p2PosX = {p2_start_pos}; int screenWidth = {screen_width}; int battlefieldHeight = {battlefield_height}; ArrayList projectiles = new ArrayList<>(); // Inicializar as altitudes das naves em uma posição média do campo team1.posY = battlefieldHeight / 2; team2.posY = battlefieldHeight / 2; while (team1.isAlive() && team2.isAlive()) {{ System.out.println("\\n=== NOVO TURNO ==="); System.out.flush(); String[][] battlefield = new String[battlefieldHeight][screenWidth]; for (int row = 0; row < battlefieldHeight; row++) {{ for (int i = 0; i < screenWidth; i++) {{ battlefield[row][i] = " "; }} }} // Radar scan para detectar projéteis team1.radarScan(projectiles, p2PosX, team2.getPositionY()); team2.radarScan(projectiles, p1PosX, team1.getPositionY()); // Movimento das aeronaves p1PosX += team1.move(); p2PosX += team2.move(); p1PosX = Math.max(0, Math.min(screenWidth - 1, p1PosX)); p2PosX = Math.max(0, Math.min(screenWidth - 1, p2PosX)); // Mudança de altitude team1.changeAltitude(); team2.changeAltitude(); // Garantir que a altitude não exceda o novo tamanho do campo de batalha team1.posY = Math.min(team1.posY, battlefieldHeight - 1); team2.posY = Math.min(team2.posY, battlefieldHeight - 1); // Atirar para Time 1 if (random.nextInt(10) < team1.fireRate) {{ Projectile shot = null; int shotType = random.nextInt(100); // Escolha aleatória do tipo de tiro baseado na probabilidade if (shotType < 5 && team1.nuclearPower > 0) {{ // Tiro nuclear (baixa probabilidade) shot = team1.nuclearMissile(p1PosX, 1); if (shot != null) {{ System.out.println("☢️ Time 1 lançou um MÍSSIL NUCLEAR!"); }} }} else if (shotType < 15 && team1.doubleShot > 0) {{ // Tiro duplo shot = team1.doubleShot(p1PosX, 1); if (shot != null) {{ System.out.println("➡️ Time 1 disparou um TIRO DUPLO!"); // Adicionar o segundo projétil em uma altitude diferente int secAlt = team1.getSecondShotAltitude(); if (secAlt >= 0 && secAlt < battlefieldHeight) {{ projectiles.add(new Projectile(p1PosX, secAlt, 1, 1, "->", team1.doubleShotPower)); }} }} }} else if (shotType < 30) {{ // Míssil especial shot = team1.specialMissile(p1PosX, 1); }} else if (shotType < 60) {{ // Tiro supersônico shot = team1.shootSupersonic(p1PosX, 1); }} else {{ // Tiro normal shot = team1.shoot(p1PosX, 1); }} if (shot != null) {{ // Garantir que a altitude do projétil não exceda o campo de batalha shot.posY = Math.min(shot.posY, battlefieldHeight - 1); projectiles.add(shot); }} }} // Atirar para Time 2 if (random.nextInt(10) < team2.fireRate) {{ Projectile shot = null; int shotType = random.nextInt(100); // Escolha aleatória do tipo de tiro baseado na probabilidade if (shotType < 5 && team2.nuclearPower > 0) {{ // Tiro nuclear (baixa probabilidade) shot = team2.nuclearMissile(p2PosX, -1); if (shot != null) {{ System.out.println("☢️ Time 2 lançou um MÍSSIL NUCLEAR!"); }} }} else if (shotType < 15 && team2.doubleShot > 0) {{ // Tiro duplo shot = team2.doubleShot(p2PosX, -1); if (shot != null) {{ System.out.println("⬅️ Time 2 disparou um TIRO DUPLO!"); // Adicionar o segundo projétil em uma altitude diferente int secAlt = team2.getSecondShotAltitude(); if (secAlt >= 0 && secAlt < battlefieldHeight) {{ projectiles.add(new Projectile(p2PosX, secAlt, -1, 1, "<-", team2.doubleShotPower)); }} }} }} else if (shotType < 30) {{ // Míssil especial shot = team2.specialMissile(p2PosX, -1); }} else if (shotType < 60) {{ // Tiro supersônico shot = team2.shootSupersonic(p2PosX, -1); }} else {{ // Tiro normal shot = team2.shoot(p2PosX, -1); }} if (shot != null) {{ // Garantir que a altitude do projétil não exceda o campo de batalha shot.posY = Math.min(shot.posY, battlefieldHeight - 1); projectiles.add(shot); }} }} // Posicionar aeronaves no campo de batalha com cores battlefield[team1.getPositionY()][p1PosX] = "\u001B[34m" + team1.symbol + "\u001B[0m"; // Azul para Time 1 battlefield[team2.getPositionY()][p2PosX] = "\u001B[31m" + team2.symbol + "\u001B[0m"; // Vermelho para Time 2 // Mover projéteis e verificar colisões Iterator iterator = projectiles.iterator(); while (iterator.hasNext()) {{ Projectile p = iterator.next(); p.move(); // Verificar colisões com Time 1 if (p.posX == p1PosX && p.posY == team1.getPositionY()) {{ int damage = 0; // Verificar se o projétil tem poder personalizado if (p.getPower() > 0) {{ damage = p.getPower(); }} else if (p.symbol.contains("<[=-")) {{ // Míssil nuclear do Time 2 damage = team2.nuclearPower * 2; System.out.println("💥💥💥 MÍSSIL NUCLEAR do Time 2 atingiu o Time 1!"); }} else if (p.symbol.contains("⇇")) {{ // Tiro duplo do Time 2 damage = team2.doubleShotPower; }} else if (p.symbol.equals("<=")) {{ damage = team2.missilePower; }} else if (p.symbol.equals("<<")) {{ damage = team2.supersonicPower; }} else {{ damage = team2.shotPower; }} if (random.nextInt(100) >= team1.stealthChance) {{ team1.takeDamage(damage); System.out.println("💥 Aeronave do Time 1 atingida! -" + damage + " pontos"); }} else {{ System.out.println("👻 Aeronave do Time 1 esquivou!"); if (team1.radar > 0) {{ System.out.println("📡 Radar do Time 1 detectou o projétil!"); }} }} iterator.remove(); continue; }} // Verificar colisões com Time 2 if (p.posX == p2PosX && p.posY == team2.getPositionY()) {{ int damage = 0; // Verificar se o projétil tem poder personalizado if (p.getPower() > 0) {{ damage = p.getPower(); }} else if (p.symbol.contains("-]=>")) {{ // Míssil nuclear do Time 1 damage = team1.nuclearPower * 2; System.out.println("💥💥💥 MÍSSIL NUCLEAR do Time 1 atingiu o Time 2!"); }} else if (p.symbol.contains("⇉")) {{ // Tiro duplo do Time 1 damage = team1.doubleShotPower; }} else if (p.symbol.equals("=>")) {{ damage = team1.missilePower; }} else if (p.symbol.equals(">>")) {{ damage = team1.supersonicPower; }} else {{ damage = team1.shotPower; }} if (random.nextInt(100) >= team2.stealthChance) {{ team2.takeDamage(damage); System.out.println("💥 Aeronave do Time 2 atingida! -" + damage + " pontos"); }} else {{ System.out.println("👻 Aeronave do Time 2 esquivou!"); if (team2.radar > 0) {{ System.out.println("📡 Radar do Time 2 detectou o projétil!"); }} }} iterator.remove(); continue; }} // Remover projéteis fora dos limites if (p.isOutOfBounds(screenWidth)) {{ iterator.remove(); continue; }} // Mostrar projéteis no campo de batalha com cores if (p.posX >= 0 && p.posX < screenWidth && p.posY >= 0 && p.posY < battlefieldHeight) {{ // Adicionar cores aos projéteis baseado na direção if (p.direction > 0) {{ battlefield[p.posY][p.posX]