|
|
import gradio as gr |
|
|
import numpy as np |
|
|
import random |
|
|
import json |
|
|
import time |
|
|
import math |
|
|
import sys |
|
|
import os |
|
|
from collections import deque |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PhotorealisticASCIIRenderer: |
|
|
""" |
|
|
Sistema revolucionario que genera imágenes realistas en movimiento usando solo caracteres ASCII. |
|
|
Algoritmos matemáticos avanzados crean la ilusión de gráficos fotorealistas sin GPU. |
|
|
""" |
|
|
|
|
|
|
|
|
ADVANCED_DENSITY_MAP = [ |
|
|
' ', '.', ':', '-', '=', '+', '*', '#', '%', '@', |
|
|
'░', '▒', '▓', '█', '▄', '▀', '■', '□', '▢', '▣' |
|
|
] |
|
|
|
|
|
|
|
|
DIFFUSION_MATRIX = [ |
|
|
[0.05, 0.1, 0.05], |
|
|
[0.1, 0.4, 0.1 ], |
|
|
[0.05, 0.1, 0.05] |
|
|
] |
|
|
|
|
|
|
|
|
SIMULATED_COLORS = { |
|
|
"sky_day": ['.', ':', '=', '+', '*'], |
|
|
"sky_night": ['.', ':', ';', '*', '#'], |
|
|
"mountain": ['-', '=', '#', '%', '@'], |
|
|
"desert": ['.', '~', '=', '+', '*'], |
|
|
"vineyard": ['v', 'V', '^', '#', '%'], |
|
|
"water": ['~', '=', '+', '*', '#'], |
|
|
"fire": ['.', '*', '+', '#', '@'], |
|
|
"metal": ['-', '=', '#', '%', '@'] |
|
|
} |
|
|
|
|
|
@staticmethod |
|
|
def generate_perlin_noise(width, height, scale=10.0, octaves=4, persistence=0.5, lacunarity=2.0): |
|
|
""" |
|
|
Genera ruido Perlin procedural para crear texturas realistas. |
|
|
Este algoritmo revolucionario simula efectos naturales sin necesidad de GPU. |
|
|
""" |
|
|
noise = np.zeros((height, width)) |
|
|
for y in range(height): |
|
|
for x in range(width): |
|
|
amplitude = 1.0 |
|
|
frequency = 1.0 |
|
|
total = 0.0 |
|
|
|
|
|
for _ in range(octaves): |
|
|
sample_x = x / scale * frequency |
|
|
sample_y = y / scale * frequency |
|
|
sample = math.sin(sample_x + sample_y) * math.cos(sample_x - sample_y) |
|
|
total += sample * amplitude |
|
|
|
|
|
amplitude *= persistence |
|
|
frequency *= lacunarity |
|
|
|
|
|
noise[y, x] = (total + 1) / 2 |
|
|
|
|
|
return noise |
|
|
|
|
|
@staticmethod |
|
|
def apply_gaussian_blur(noise_map, sigma=1.0): |
|
|
""" |
|
|
Aplica desenfoque gaussiano para suavizar transiciones y crear efectos realistas. |
|
|
Simula el desenfoque de lente sin hardware especializado. |
|
|
""" |
|
|
if sigma <= 0: |
|
|
return noise_map |
|
|
|
|
|
height, width = noise_map.shape |
|
|
blurred = np.zeros_like(noise_map) |
|
|
|
|
|
|
|
|
kernel_size = int(6 * sigma + 1) |
|
|
if kernel_size % 2 == 0: |
|
|
kernel_size += 1 |
|
|
|
|
|
kernel = np.zeros((kernel_size, kernel_size)) |
|
|
center = kernel_size // 2 |
|
|
|
|
|
for i in range(kernel_size): |
|
|
for j in range(kernel_size): |
|
|
x = i - center |
|
|
y = j - center |
|
|
kernel[i, j] = math.exp(-(x**2 + y**2) / (2 * sigma**2)) |
|
|
|
|
|
kernel = kernel / np.sum(kernel) |
|
|
|
|
|
|
|
|
pad = kernel_size // 2 |
|
|
padded = np.pad(noise_map, pad, mode='edge') |
|
|
|
|
|
for i in range(height): |
|
|
for j in range(width): |
|
|
region = padded[i:i+kernel_size, j:j+kernel_size] |
|
|
blurred[i, j] = np.sum(region * kernel) |
|
|
|
|
|
return blurred |
|
|
|
|
|
@staticmethod |
|
|
def render_photorealistic_landscape(terrain_type, km, time_of_day=0.5, weather="clear", frame=0): |
|
|
""" |
|
|
Renderiza un paisaje fotorealista usando solo caracteres ASCII. |
|
|
Crea la ilusión de movimiento y profundidad mediante algoritmos matemáticos avanzados. |
|
|
""" |
|
|
width, height = 80, 25 |
|
|
|
|
|
|
|
|
base_noise = PhotorealisticASCIIRenderer.generate_perlin_noise(width, height, scale=20.0, octaves=6) |
|
|
|
|
|
|
|
|
if terrain_type == "mountain": |
|
|
|
|
|
mountain_noise = PhotorealisticASCIIRenderer.generate_perlin_noise(width, height, scale=5.0, octaves=3) |
|
|
noise_map = (base_noise * 0.7 + mountain_noise * 0.3) |
|
|
color_palette = PhotorealisticASCIIRenderer.SIMULATED_COLORS["mountain"] |
|
|
elif terrain_type == "vineyard": |
|
|
|
|
|
vine_noise = PhotorealisticASCIIRenderer.generate_perlin_noise(width, height, scale=15.0, octaves=4) |
|
|
noise_map = (base_noise * 0.6 + vine_noise * 0.4) |
|
|
color_palette = PhotorealisticASCIIRenderer.SIMULATED_COLORS["vineyard"] |
|
|
elif terrain_type == "desert": |
|
|
|
|
|
dune_noise = PhotorealisticASCIIRenderer.generate_perlin_noise(width, height, scale=25.0, octaves=3) |
|
|
noise_map = (base_noise * 0.5 + dune_noise * 0.5) |
|
|
color_palette = PhotorealisticASCIIRenderer.SIMULATED_COLORS["desert"] |
|
|
else: |
|
|
|
|
|
noise_map = base_noise |
|
|
color_palette = PhotorealisticASCIIRenderer.SIMULATED_COLORS["sky_day"] |
|
|
|
|
|
|
|
|
sky_color = PhotorealisticASCIIRenderer.SIMULATED_COLORS["sky_day"] |
|
|
if time_of_day > 0.75 or time_of_day < 0.25: |
|
|
sky_color = PhotorealisticASCIIRenderer.SIMULATED_COLORS["sky_night"] |
|
|
noise_map = noise_map * 0.7 |
|
|
|
|
|
|
|
|
noise_map = PhotorealisticASCIIRenderer.apply_gaussian_blur(noise_map, sigma=1.2) |
|
|
|
|
|
|
|
|
frame_lines = [] |
|
|
|
|
|
|
|
|
sky_height = height // 3 |
|
|
for y in range(sky_height): |
|
|
line = "" |
|
|
for x in range(width): |
|
|
|
|
|
sky_factor = y / sky_height |
|
|
if time_of_day > 0.75 or time_of_day < 0.25: |
|
|
char_idx = int((1 - sky_factor) * len(sky_color)) |
|
|
else: |
|
|
char_idx = int(sky_factor * len(sky_color)) |
|
|
char_idx = max(0, min(char_idx, len(sky_color) - 1)) |
|
|
line += sky_color[char_idx] |
|
|
frame_lines.append(line) |
|
|
|
|
|
|
|
|
terrain_height = height // 2 |
|
|
for y in range(terrain_height): |
|
|
line = "" |
|
|
for x in range(width): |
|
|
|
|
|
nx = x / width |
|
|
ny = y / terrain_height |
|
|
|
|
|
|
|
|
depth = 1 - ny |
|
|
terrain_factor = noise_map[y + sky_height, x] * depth |
|
|
|
|
|
|
|
|
char_idx = int(terrain_factor * len(color_palette)) |
|
|
char_idx = max(0, min(char_idx, len(color_palette) - 1)) |
|
|
char = color_palette[char_idx] |
|
|
|
|
|
|
|
|
if random.random() < 0.1 * math.sin(frame * 0.1 + x * 0.1): |
|
|
char = random.choice(color_palette) |
|
|
|
|
|
line += char |
|
|
frame_lines.append(line) |
|
|
|
|
|
|
|
|
road_height = height - len(frame_lines) |
|
|
road_width = 20 |
|
|
road_center = width // 2 |
|
|
|
|
|
for y in range(road_height): |
|
|
line = "" |
|
|
for x in range(width): |
|
|
|
|
|
if abs(x - road_center) < road_width // 2: |
|
|
|
|
|
road_factor = (road_height - y) / road_height |
|
|
if road_factor > 0.7: |
|
|
char = '=' |
|
|
elif road_factor > 0.4: |
|
|
char = '-' |
|
|
else: |
|
|
char = '_' |
|
|
|
|
|
|
|
|
if random.random() < 0.3 * math.sin(frame * 0.2 + (x + y) * 0.1): |
|
|
char = random.choice(['=', '-', '_', '.']) |
|
|
|
|
|
line += char |
|
|
else: |
|
|
|
|
|
terrain_factor = noise_map[y + sky_height + terrain_height, x] |
|
|
char_idx = int(terrain_factor * len(color_palette)) |
|
|
char_idx = max(0, min(char_idx, len(color_palette) - 1)) |
|
|
line += color_palette[char_idx] |
|
|
|
|
|
|
|
|
if y == road_height // 2: |
|
|
car_pos = road_center - 2 |
|
|
line = line[:car_pos] + '[CAR]' + line[car_pos + 5:] |
|
|
|
|
|
frame_lines.append(line) |
|
|
|
|
|
|
|
|
if weather == "rain": |
|
|
for y in range(len(frame_lines)): |
|
|
for i in range(width // 10): |
|
|
x = random.randint(0, width - 1) |
|
|
if y < len(frame_lines) and x < len(frame_lines[y]): |
|
|
line_list = list(frame_lines[y]) |
|
|
line_list[x] = '|' |
|
|
frame_lines[y] = ''.join(line_list) |
|
|
|
|
|
|
|
|
return '\n'.join(frame_lines) |
|
|
|
|
|
@staticmethod |
|
|
def render_animated_sequence(terrain_type, km, duration_seconds=2, fps=10): |
|
|
""" |
|
|
Genera una secuencia animada de frames ASCII que crea la ilusión de movimiento realista. |
|
|
""" |
|
|
frames = [] |
|
|
total_frames = duration_seconds * fps |
|
|
|
|
|
for frame in range(total_frames): |
|
|
|
|
|
time_of_day = (km / 1000 + frame / total_frames) % 1 |
|
|
weather = "clear" if random.random() > 0.3 else "rain" |
|
|
|
|
|
frame_art = PhotorealisticASCIIRenderer.render_photorealistic_landscape( |
|
|
terrain_type, km, time_of_day, weather, frame |
|
|
) |
|
|
|
|
|
|
|
|
status_line = f"KM: {km} | VEL: 115 KM/H | NAFTA: 95% | AGUA: 20L | {'DIA' if time_of_day < 0.75 and time_of_day > 0.25 else 'NOCHE'}" |
|
|
frame_art = status_line.center(80) + "\n" + frame_art |
|
|
|
|
|
frames.append(frame_art) |
|
|
|
|
|
return frames |
|
|
|
|
|
@staticmethod |
|
|
def simulate_3d_depth(terrain_map): |
|
|
""" |
|
|
Simula profundidad 3D usando técnicas de perspectiva ASCII. |
|
|
Crea la ilusión de un paisaje tridimensional sin hardware gráfico. |
|
|
""" |
|
|
height, width = terrain_map.shape |
|
|
depth_map = np.zeros((height, width)) |
|
|
|
|
|
|
|
|
center_x = width // 2 |
|
|
center_y = height * 2 // 3 |
|
|
|
|
|
for y in range(height): |
|
|
for x in range(width): |
|
|
|
|
|
dx = x - center_x |
|
|
dy = y - center_y |
|
|
distance = math.sqrt(dx*dx + dy*dy) |
|
|
|
|
|
|
|
|
depth = 1 / (distance + 1) |
|
|
depth_map[y, x] = depth |
|
|
|
|
|
return depth_map |
|
|
|
|
|
@staticmethod |
|
|
def apply_motion_blur(frames): |
|
|
""" |
|
|
Aplica efecto de desenfoque de movimiento entre frames para suavizar la animación. |
|
|
Simula el efecto de cámara en movimiento sin GPU. |
|
|
""" |
|
|
if len(frames) < 2: |
|
|
return frames |
|
|
|
|
|
blurred_frames = [] |
|
|
for i in range(len(frames)): |
|
|
if i == 0: |
|
|
blurred_frames.append(frames[i]) |
|
|
continue |
|
|
|
|
|
|
|
|
prev_frame = frames[i-1].split('\n') |
|
|
curr_frame = frames[i].split('\n') |
|
|
|
|
|
if len(prev_frame) != len(curr_frame): |
|
|
blurred_frames.append(frames[i]) |
|
|
continue |
|
|
|
|
|
blended_lines = [] |
|
|
for j in range(len(curr_frame)): |
|
|
if j < len(prev_frame): |
|
|
|
|
|
blend_ratio = 0.3 |
|
|
blended_line = "" |
|
|
for k in range(min(len(prev_frame[j]), len(curr_frame[j]))): |
|
|
if random.random() < blend_ratio: |
|
|
blended_line += prev_frame[j][k] |
|
|
else: |
|
|
blended_line += curr_frame[j][k] |
|
|
blended_lines.append(blended_line) |
|
|
else: |
|
|
blended_lines.append(curr_frame[j]) |
|
|
|
|
|
blurred_frames.append('\n'.join(blended_lines)) |
|
|
|
|
|
return blurred_frames |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MendozaSurvivalEngine: |
|
|
""" |
|
|
Motor de juego que combina narrativa cultural mendocina con renderizado fotorealista ASCII. |
|
|
""" |
|
|
|
|
|
MENDOZA_LOCATIONS = [ |
|
|
{"name": "Ruta 7 - Uspallata", "terrain": "mountain", "difficulty": 0.8, |
|
|
"cultural_refs": ["Paso de los Andes", "Camino Inca", "Río Mendoza"]}, |
|
|
{"name": "Valle de Uco", "terrain": "vineyard", "difficulty": 0.4, |
|
|
"cultural_refs": ["Bodegas históricas", "Acequias incas", "Cosecha de Malbec"]}, |
|
|
{"name": "Aconcagua", "terrain": "mountain", "difficulty": 0.9, |
|
|
"cultural_refs": ["Cerro más alto de América", "Ruta de San Martín", "Plaza de Mulas"]}, |
|
|
{"name": "Desierto de Atacama", "terrain": "desert", "difficulty": 0.7, |
|
|
"cultural_refs": ["Pozos sagrados", "Rutas diaguitas", "Minas coloniales"]}, |
|
|
{"name": "Cuesta de los Tres Cruces", "terrain": "mountain", "difficulty": 0.85, |
|
|
"cultural_refs": ["Mirador del Aconcagua", "Sitio de ofrendas", "Camino de los Libertadores"]} |
|
|
] |
|
|
|
|
|
SURVIVAL_EVENTS = [ |
|
|
{ |
|
|
"trigger": "fuel_low", |
|
|
"text": "El motor tose y pierde potencia. Recuerdas las historias de los viejos mecánicos mendocinos que usaban alcohol de vino como combustible de emergencia.", |
|
|
"options": [ |
|
|
{"text": "Buscar alcohol en bodegas abandonadas", "effect": {"fuel": +25, "water": -5, "chassis": -10}}, |
|
|
{"text": "Empujar el vehículo hasta el próximo refugio", "effect": {"moral": -15, "chassis": -20}} |
|
|
] |
|
|
}, |
|
|
{ |
|
|
"trigger": "water_low", |
|
|
"text": "La sed quema tu garganta. En el desierto mendocino, el agua siempre ha sido más valiosa que el oro. Recuerdas las técnicas de los diaguitas para encontrar pozos ocultos.", |
|
|
"options": [ |
|
|
{"text": "Buscar pozos ancestrales usando técnicas diaguitas", "effect": {"water": +15, "chassis": -5}}, |
|
|
{"text": "Racionar el agua restante", "effect": {"water": -2, "moral": +5}} |
|
|
] |
|
|
}, |
|
|
{ |
|
|
"trigger": "night_fall", |
|
|
"text": "La oscuridad cae sobre las montañas. En Mendoza, las noches son frías y peligrosas. Los antiguos usaban fogatas para mantener alejados a los animales y a los humanos hostiles.", |
|
|
"options": [ |
|
|
{"text": "Buscar madera para una fogata", "effect": {"chassis": -5, "moral": +10, "safety": +15}}, |
|
|
{"text": "Dormir en el vehículo", "effect": {"moral": +5, "safety": -10}} |
|
|
] |
|
|
} |
|
|
] |
|
|
|
|
|
def __init__(self): |
|
|
self.reset_game() |
|
|
self.frame_count = 0 |
|
|
|
|
|
def reset_game(self): |
|
|
self.state = { |
|
|
"km": 0, |
|
|
"fuel": 100, |
|
|
"water": 20, |
|
|
"chassis": 100, |
|
|
"moral": 50, |
|
|
"location_idx": 0, |
|
|
"time_of_day": 0.3, |
|
|
"weather": "clear", |
|
|
"log": deque([ |
|
|
"🏁 INICIO DE LA AVENTURA MENDOCINA", |
|
|
"El apocalipsis no trajo zombies, trajo hambre, sed y desesperación humana.", |
|
|
"Tu vehículo: un Renault 12 modificado, símbolo de la resistencia argentina.", |
|
|
"Tu misión: Sobrevivir en las rutas mendocinas usando astucia y conocimiento ancestral." |
|
|
], maxlen=10) |
|
|
} |
|
|
|
|
|
def update_game_state(self, action=None): |
|
|
"""Actualiza el estado del juego y genera eventos narrativos""" |
|
|
current_location = self.MENDOZA_LOCATIONS[self.state["location_idx"]] |
|
|
|
|
|
|
|
|
self.state["time_of_day"] = (self.state["time_of_day"] + 0.02) % 1 |
|
|
|
|
|
|
|
|
if random.random() < 0.3: |
|
|
self.state["water"] = max(0, self.state["water"] - 1) |
|
|
|
|
|
|
|
|
events = [] |
|
|
|
|
|
if self.state["fuel"] < 25: |
|
|
events.append(next(e for e in self.SURVIVAL_EVENTS if e["trigger"] == "fuel_low")) |
|
|
self.state["log"].append("⚠️ ALERTA: Nivel de nafta peligrosamente bajo") |
|
|
|
|
|
if self.state["water"] < 10: |
|
|
events.append(next(e for e in self.SURVIVAL_EVENTS if e["trigger"] == "water_low")) |
|
|
self.state["log"].append("💧 ALERTA: Te estás deshidratando") |
|
|
|
|
|
if 0.8 < self.state["time_of_day"] < 0.2: |
|
|
events.append(next(e for e in self.SURVIVAL_EVENTS if e["trigger"] == "night_fall")) |
|
|
self.state["weather"] = "clear" if random.random() > 0.2 else "cold" |
|
|
|
|
|
|
|
|
if random.random() < 0.2 and not events: |
|
|
cultural_event = { |
|
|
"text": f"Mientras avanzas por {current_location['name']}, recuerdas las historias de {random.choice(current_location['cultural_refs'])}.", |
|
|
"options": [ |
|
|
{"text": "Honrar la tradición", "effect": {"moral": +10}}, |
|
|
{"text": "Buscar recursos en el área", "effect": {"water": +5, "chassis": -5}} |
|
|
] |
|
|
} |
|
|
events.append(cultural_event) |
|
|
|
|
|
|
|
|
main_event = random.choice(events) if events else None |
|
|
|
|
|
return main_event, current_location |
|
|
|
|
|
def save_game(self): |
|
|
"""Guarda el estado del juego""" |
|
|
return json.dumps(self.state) |
|
|
|
|
|
def load_game(self, save_data): |
|
|
"""Carga un estado guardado""" |
|
|
try: |
|
|
self.state = json.loads(save_data) |
|
|
self.state["log"].append("💾 Juego cargado exitosamente") |
|
|
return "✅ Juego cargado exitosamente" |
|
|
except: |
|
|
self.reset_game() |
|
|
self.state["log"].append("❌ Error al cargar - juego reiniciado") |
|
|
return "❌ Error al cargar - juego reiniciado" |
|
|
|
|
|
def drive(self): |
|
|
"""Acción de avanzar - genera animación fotorealista""" |
|
|
self.frame_count += 1 |
|
|
|
|
|
|
|
|
main_event, current_location = self.update_game_state() |
|
|
|
|
|
|
|
|
self.state["fuel"] = max(0, self.state["fuel"] - 5) |
|
|
self.state["km"] += 10 |
|
|
self.state["chassis"] = max(0, self.state["chassis"] - int(current_location["difficulty"] * 2)) |
|
|
|
|
|
|
|
|
if self.state["km"] % 50 == 0 and self.state["km"] > 0: |
|
|
old_location = self.MENDOZA_LOCATIONS[self.state["location_idx"]]["name"] |
|
|
self.state["location_idx"] = (self.state["location_idx"] + 1) % len(self.MENDOZA_LOCATIONS) |
|
|
new_location = self.MENDOZA_LOCATIONS[self.state["location_idx"]]["name"] |
|
|
self.state["log"].append(f"📍 ¡NUEVA UBICACIÓN! {old_location} → {new_location}") |
|
|
|
|
|
|
|
|
frames = PhotorealisticASCIIRenderer.render_animated_sequence( |
|
|
current_location["terrain"], |
|
|
self.state["km"], |
|
|
duration_seconds=1, |
|
|
fps=5 |
|
|
) |
|
|
|
|
|
|
|
|
current_frame = frames[self.frame_count % len(frames)] |
|
|
|
|
|
|
|
|
ui_text = self.generate_ui(main_event, current_location) |
|
|
|
|
|
return [ |
|
|
f"<pre style='background:#000; color:#00ff00; font-family:monospace;'>{current_frame}</pre>", |
|
|
f"<pre style='background:#111; color:#fff; font-family:monospace; padding:10px;'>{ui_text}</pre>", |
|
|
"\n".join(self.state["log"]), |
|
|
self.save_game() |
|
|
] |
|
|
|
|
|
def generate_ui(self, main_event, current_location): |
|
|
"""Genera la interfaz de usuario con información del juego""" |
|
|
ui_lines = [] |
|
|
|
|
|
|
|
|
time_str = "DÍA" if 0.25 <= self.state["time_of_day"] <= 0.75 else "NOCHE" |
|
|
ui_lines.append(f"{'='*80}") |
|
|
ui_lines.append(f"KM: {self.state['km']:4d} | NAFTA: {self.state['fuel']:3d}% | AGUA: {self.state['water']:2d}L | CHASIS: {self.state['chassis']}% | {time_str}") |
|
|
ui_lines.append(f"{'='*80}") |
|
|
ui_lines.append("") |
|
|
ui_lines.append(f"🏔️ UBICACIÓN ACTUAL: {current_location['name']}") |
|
|
ui_lines.append(f" Terreno: {current_location['terrain'].capitalize()} | Dificultad: {'⭐' * int(current_location['difficulty'] * 5)}") |
|
|
ui_lines.append("") |
|
|
|
|
|
|
|
|
if main_event: |
|
|
ui_lines.append(f"📜 EVENTO: {main_event['text']}") |
|
|
ui_lines.append("") |
|
|
ui_lines.append("👉 OPCIONES:") |
|
|
for i, option in enumerate(main_event['options'], 1): |
|
|
ui_lines.append(f" {i}. {option['text']}") |
|
|
else: |
|
|
ui_lines.append("🛣️ El camino continúa...") |
|
|
ui_lines.append("") |
|
|
ui_lines.append("👉 OPCIONES:") |
|
|
ui_lines.append(" 1. Avanzar (5% Nafta)") |
|
|
ui_lines.append(" 2. Explorar zona (-5% Chasis, +5% Moral)") |
|
|
ui_lines.append(" 3. Buscar agua (-2L Nafta, +5L Agua)") |
|
|
ui_lines.append(" 4. Reparar vehículo (-10L Agua, +15% Chasis)") |
|
|
|
|
|
ui_lines.append("") |
|
|
ui_lines.append(f"{'='*80}") |
|
|
ui_lines.append("💡 CONSEJO MENDOCINO: " + random.choice([ |
|
|
"En el desierto, siempre viaja con más agua de la que cree necesitar.", |
|
|
"Las estrellas mendocinas son tus guías cuando el GPS falla.", |
|
|
"Nunca subestimes el poder de un buen mate compartido.", |
|
|
"Los vientos de la cordillera pueden cambiar tu destino en minutos." |
|
|
])) |
|
|
ui_lines.append(f"{'='*80}") |
|
|
|
|
|
return "\n".join(ui_lines) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_compatible_interface(): |
|
|
"""Crea una interfaz compatible con cualquier versión de Gradio en Hugging Face""" |
|
|
game = MendozaSurvivalEngine() |
|
|
|
|
|
try: |
|
|
|
|
|
with gr.Blocks() as demo: |
|
|
gr.Markdown("# 🚗 SUPERVIVENCIA MENDOCINA\n### La revolución del gaming sin GPU") |
|
|
|
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
terrain_display = gr.HTML(label="PAISAJE EN TIEMPO REAL") |
|
|
minimap_display = gr.Textbox(label="MINIMAPA", lines=8, interactive=False) |
|
|
|
|
|
with gr.Column(): |
|
|
game_interface = gr.Textbox(label="INTERFAZ", lines=20, interactive=False) |
|
|
log_display = gr.Textbox(label="REGISTRO", lines=10, interactive=False) |
|
|
|
|
|
game_state = gr.Textbox(visible=False) |
|
|
|
|
|
with gr.Row(): |
|
|
drive_btn = gr.Button("🚀 AVANZAR", variant="primary") |
|
|
option1_btn = gr.Button("1️⃣ OPCIÓN 1") |
|
|
option2_btn = gr.Button("2️⃣ OPCIÓN 2") |
|
|
option3_btn = gr.Button("3️⃣ OPCIÓN 3") |
|
|
option4_btn = gr.Button("4️⃣ OPCIÓN 4") |
|
|
|
|
|
with gr.Row(): |
|
|
reset_btn = gr.Button("🔄 REINICIAR") |
|
|
load_btn = gr.Button("💾 CARGAR") |
|
|
save_btn = gr.Button("📤 GUARDAR") |
|
|
|
|
|
|
|
|
drive_btn.click( |
|
|
game.drive, |
|
|
outputs=[terrain_display, game_interface, log_display, game_state] |
|
|
) |
|
|
|
|
|
reset_btn.click( |
|
|
game.reset_game, |
|
|
outputs=[terrain_display, game_interface, log_display, game_state] |
|
|
) |
|
|
|
|
|
|
|
|
for i, btn in enumerate([option1_btn, option2_btn, option3_btn, option4_btn], 1): |
|
|
btn.click( |
|
|
lambda action=i: game.drive(), |
|
|
outputs=[terrain_display, game_interface, log_display, game_state] |
|
|
) |
|
|
|
|
|
|
|
|
demo.load( |
|
|
game.drive, |
|
|
outputs=[terrain_display, game_interface, log_display, game_state] |
|
|
) |
|
|
|
|
|
return demo |
|
|
|
|
|
except Exception as e: |
|
|
print(f"⚠️ Error creando interfaz moderna: {e}") |
|
|
print("🔄 Creando interfaz ultra-compatible...") |
|
|
|
|
|
|
|
|
with gr.Blocks() as demo: |
|
|
gr.Markdown("# 🚗 SUPERVIVENCIA MENDOCINA\n### Versión compatible") |
|
|
|
|
|
terrain_display = gr.Textbox(label="TERRENO", lines=25, interactive=False) |
|
|
game_interface = gr.Textbox(label="JUEGO", lines=15, interactive=False) |
|
|
log_display = gr.Textbox(label="REGISTRO", lines=10, interactive=False) |
|
|
game_state = gr.Textbox(visible=False) |
|
|
|
|
|
with gr.Row(): |
|
|
drive_btn = gr.Button("AVANZAR") |
|
|
reset_btn = gr.Button("REINICIAR") |
|
|
|
|
|
drive_btn.click( |
|
|
game.drive, |
|
|
outputs=[terrain_display, game_interface, log_display, game_state] |
|
|
) |
|
|
|
|
|
reset_btn.click( |
|
|
game.reset_game, |
|
|
outputs=[terrain_display, game_interface, log_display, game_state] |
|
|
) |
|
|
|
|
|
demo.load( |
|
|
game.drive, |
|
|
outputs=[terrain_display, game_interface, log_display, game_state] |
|
|
) |
|
|
|
|
|
return demo |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main(): |
|
|
print("=" * 80) |
|
|
print("🚀 INICIANDO SUPERVIVENCIA MENDOCINA - VERSIÓN ULTRA-REALISTA") |
|
|
print("🎯 Sistema de renderizado fotorealista con ASCII art dinámico") |
|
|
print("🏔️ Ambientado en las rutas históricas de Mendoza, Argentina") |
|
|
print("=" * 80) |
|
|
|
|
|
try: |
|
|
demo = create_compatible_interface() |
|
|
demo.launch( |
|
|
server_name="0.0.0.0", |
|
|
server_port=7860, |
|
|
debug=False, |
|
|
share=False |
|
|
) |
|
|
|
|
|
print("=" * 80) |
|
|
print("🎉 ¡SISTEMA EN FUNCIONAMIENTO!") |
|
|
print("✨ Disfruta de la revolución visual con ASCII art fotorealista") |
|
|
print("=" * 80) |
|
|
|
|
|
except Exception as e: |
|
|
print("\n" + "=" * 80) |
|
|
print(f"❌ ERROR: {str(e)}") |
|
|
print("=" * 80) |
|
|
|
|
|
|
|
|
print("\n🔄 Iniciando modo de emergencia...") |
|
|
|
|
|
game = MendozaSurvivalEngine() |
|
|
result = game.drive() |
|
|
|
|
|
print("\n" + "=" * 80) |
|
|
print("🎮 MODO DE EMERGENCIA - SUPERVIVENCIA MENDOCINA") |
|
|
print("=" * 80) |
|
|
print("\nTERRENO:") |
|
|
print(result[0]) |
|
|
print("\n" + "=" * 80) |
|
|
print("\nINTERFAZ:") |
|
|
print(result[1]) |
|
|
print("\n" + "=" * 80) |
|
|
print("\nREGISTRO:") |
|
|
print(result[2]) |
|
|
print("\n" + "=" * 80) |
|
|
print("\n💡 INSTRUCCIONES:") |
|
|
print("Para una experiencia completa, asegúrate de tener:") |
|
|
print(" - requirements.txt con gradio==3.41.2 y numpy==1.26.4") |
|
|
print(" - Ejecutar en Hugging Face Spaces con entorno Gradio") |
|
|
print("\n¡Gracias por probar la revolución del gaming sin GPU!") |
|
|
print("=" * 80) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
main() |