Texto en la imagen que dice XAU/USD con un ícono de una barra azul en medio y fondo negro.
Logotipo de RoboForex con letra 'R' azul y texto 'RoboForex' en tonos azules.

Código para ANDROID Pydroid 3

# -*- coding: utf-8 -*-

# ================================================================
# KEVIN VILLA BTC PUZZLE 7.1 BTC - V15 (ULTIMATE EDITION)
# Récord Guardado | Anti-Crash de Salida | Minería Real | 1 Portal
# ================================================================

import ui, hashlib, os, time, random, math, sound, console, threading
from ecdsa import SigningKey, SECP256k1

console.set_idle_timer_disabled(True)

# ================= RANGO PUZZLE Y CRIPTO =================

MIN_K = 0x400000000000000000
MAX_K = 0x7fffffffffffffffff
RANGE_SIZE = MAX_K - MIN_K + 1
TARGET_ADDR = "1PWo3JeB9jrGwfHDNpdGK54CRas7fsVzXU"
B58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

def b58enc(v):
    n = int.from_bytes(v, 'big')
    r = ''
    while n > 0:
        n, mod = divmod(n, 58)
        r = B58[mod] + r
    for b in v:
        if b == 0: r = '1' + r
        else: break
    return r

def get_h160(addr):
    n = 0
    for c in addr: n = n * 58 + B58.index(c)
    return n.to_bytes(25, 'big')[1:21]

TARGET_H160 = get_h160(TARGET_ADDR)

def priv_to_address(priv_int):
    try:
        pb = priv_int.to_bytes(32, 'big')
        sk = SigningKey.from_string(pb, curve=SECP256k1)
        vk = sk.verifying_key
        x = vk.to_string()[:32]
        y = vk.to_string()[32:]
        prefix = b'\x02' if int.from_bytes(y, 'big') % 2 == 0 else b'\x03'
        pub = prefix + x
        sha = hashlib.sha256(pub).digest()
        ripe = hashlib.new('ripemd160', sha).digest()
        payload = b'\x00' + ripe
        cs = hashlib.sha256(hashlib.sha256(payload).digest()).digest()[:4]
        return b58enc(payload + cs), pub.hex()
    except Exception:
        return "ERROR", "ERROR"

# ================= COLORES =================
BLACK       = '#050505'
GRAY_BG     = '#0d0d12'
GRID_C      = '#181822'
GREEN_F     = '#00ff41'
GOLD        = '#ffd700'
BLUE_BTC    = '#0088ff'
RED         = '#ff3333'
CYAN        = '#00ffff'
PURPLE      = '#aa00ff'
WHITE       = '#ffffff'

def get_rgba(hex_color, alpha):
    h = hex_color.lstrip('#')
    r, g, b = tuple(int(h[i:i+2], 16) for i in (0, 2, 4))
    return (r/255.0, g/255.0, b/255.0, alpha)

# ================= CLASES DEL JUEGO =================

class GameCanvas(ui.View):
    def draw(self):
        if hasattr(self, 'game_engine') and self.game_engine:
            self.game_engine.render_frame()

class SnakeGameV15(ui.View):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.background_color = BLACK
        self.touch_enabled = True
        self._swipe_start = None
        self.is_running = True # Interruptor maestro para evitar zombis en memoria
        
        # Cargar Récord Guardado
        self.high_score = 0.0
        self._load_high_score()
        
        sw, sh = ui.get_screen_size()
        self.is_portrait = sw < sh
        
        safe_top = 40
        hud_height = 100
        canvas_y = safe_top + hud_height + 5 
        avail_h = sh - canvas_y
        
        self.CELL = 20 if self.is_portrait else 18
        self.COLS = int(sw / self.CELL)
        self.ROWS = int(avail_h / self.CELL)
        
        self.W = self.COLS * self.CELL
        self.H = self.ROWS * self.CELL
        
        self._build_ui(sw, sh, safe_top, hud_height, canvas_y)
        self.mining_active = False
        self.new_game()

    def _load_high_score(self):
        try:
            with open('btc_record.txt', 'r') as f:
                self.high_score = float(f.read().strip())
        except:
            self.high_score = 0.0

    def _save_high_score(self):
        if self.score > self.high_score:
            self.high_score = self.score
            try:
                with open('btc_record.txt', 'w') as f:
                    f.write(str(self.high_score))
            except: pass

    def _build_ui(self, sw, sh, safe_top, hud_h, canvas_y):
        self.hud_panel = ui.View(frame=(5, safe_top, sw-10, hud_h))
        self.hud_panel.background_color = '#0a0a10'
        self.hud_panel.border_color = GREEN_F
        self.hud_panel.border_width = 1
        self.hud_panel.corner_radius = 8
        self.hud_panel.touch_enabled = False 
        self.add_subview(self.hud_panel)
        
        self.lbl_stats = ui.Label(frame=(10, 5, self.hud_panel.width-20, 25))
        self.lbl_stats.font = ('Courier-Bold', 12)
        self.lbl_stats.text_color = GREEN_F
        self.hud_panel.add_subview(self.lbl_stats)

        self.lbl_crypto = ui.Label(frame=(10, 35, self.hud_panel.width-20, hud_h-40))
        self.lbl_crypto.font = ('Courier', 11)
        self.lbl_crypto.text_color = GOLD
        self.lbl_crypto.number_of_lines = 0
        self.hud_panel.add_subview(self.lbl_crypto)

        cx = (sw - self.W) / 2
        self.canvas = GameCanvas(frame=(cx, canvas_y, self.W, self.H))
        self.canvas.background_color = GRAY_BG
        self.canvas.border_color = '#222'
        self.canvas.border_width = 2
        self.canvas.game_engine = self
        self.canvas.touch_enabled = False 
        self.add_subview(self.canvas)

    def new_game(self):
        cx, cy = self.COLS // 2, self.ROWS // 2
        self.snake = [{'x': cx, 'y': cy}, {'x': cx-1, 'y': cy}, {'x': cx-2, 'y': cy}]
        self.direction = {'x': 1, 'y': 0}
        self.next_dir = {'x': 1, 'y': 0}
        
        self.is_behind = False 
        self.score = 0.0
        self.current_fps = 5.0 
        
        self.portal = {'x': -1, 'y': -1}
        self.portal = self._spawn_portal()
        self.coin = self._spawn_coin()
        
        self.blue_coin = None
        self.last_blue_time = time.time()
        
        self.game_over = False
        self.game_won = False
        self.keys_checked = 0
        self.start_time = time.time()
        
        self.live_miner_priv = "INICIANDO MOTOR SECP256k1..."
        self.live_miner_addr = ""
        self.anim_time = 0.0
        
        if not self.mining_active and self.is_running:
            ui.delay(self._start_mining_thread, 1.0)
        
        self._tick()

    def _start_mining_thread(self):
        if not getattr(self, 'is_running', False): return
        self.mining_active = True
        threading.Thread(target=self._background_miner, daemon=True).start()

    def _background_miner(self):
        while self.mining_active and getattr(self, 'is_running', False):
            if self.game_over or self.game_won:
                time.sleep(0.5)
                continue
                
            for _ in range(2):
                k = random.randint(MIN_K, MAX_K)
                addr, _ = priv_to_address(k)
                self.live_miner_priv = hex(k)
                self.live_miner_addr = addr
                self.keys_checked += 1
                
                try:
                    if get_h160(addr) == TARGET_H160:
                        self.coin = {'priv': k, 'addr': addr} 
                        self._trigger_win()
                        return
                except: pass
            
            time.sleep(0.01)

    def _spawn_coin(self, is_special=False):
        while True:
            rx, ry = random.randint(0, self.COLS-1), random.randint(0, self.ROWS-1)
            in_snake = any(s['x'] == rx and s['y'] == ry for s in self.snake)
            in_portal = (rx == self.portal['x'] and ry == self.portal['y'])
            
            if not in_snake and not in_portal:
                layer = random.choice([True, False]) 
                if is_special:
                    return {'x': rx, 'y': ry, 'is_behind': layer, 'spawn_time': time.time(), 'anim': random.random()*10}
                else:
                    k = random.randint(MIN_K, MAX_K)
                    addr, _ = priv_to_address(k)
                    return {'x': rx, 'y': ry, 'priv': k, 'addr': addr, 'is_behind': layer, 'anim': random.random()*10}

    def _spawn_portal(self):
        while True:
            rx, ry = random.randint(1, self.COLS-2), random.randint(1, self.ROWS-2)
            in_snake = any(s['x'] == rx and s['y'] == ry for s in self.snake)
            if not in_snake:
                return {'x': rx, 'y': ry, 'color': PURPLE}

    def _move_coin(self, c_dict):
        moves = [{'x': 0, 'y': 1}, {'x': 0, 'y': -1}, {'x': 1, 'y': 0}, {'x': -1, 'y': 0}]
        random.shuffle(moves)
        for m in moves:
            cx = (c_dict['x'] + m['x']) % self.COLS
            cy = (c_dict['y'] + m['y']) % self.ROWS
            in_snake = any(s['x'] == cx and s['y'] == cy for s in self.snake)
            in_portal = (self.portal['x'] == cx and self.portal['y'] == cy)
            if not in_snake and not in_portal:
                c_dict['x'] = cx
                c_dict['y'] = cy
                break

    def _trigger_win(self):
        self.game_won = True
        self.mining_active = False 
        self._save_high_score()
        try:
            with open('WINNER.txt', 'a') as f:
                f.write(f"=== ¡PUZZLE RESUELTO! ===\nPRIV: {hex(self.coin['priv'])}\nADDR: {self.coin['addr']}\n")
        except: pass
        try:
            sound.play_effect('arcade:Coin_4')
            ui.delay(lambda: sound.play_effect('arcade:Coin_5'), 0.2)
            ui.delay(lambda: sound.play_effect('arcade:Powerup_1'), 0.4)
            ui.delay(lambda: sound.play_effect('arcade:Jump_1'), 0.6)
        except: pass
        self.canvas.set_needs_display()
        self._update_hud()

    def _tick(self):
        if not getattr(self, 'is_running', False): return # Anti-Zombie Loop
        if self.game_over or self.game_won: return 
        
        self._update_logic()
        self.canvas.set_needs_display()
        self._update_hud()
        
        if getattr(self, 'is_running', False):
            ui.delay(self._tick, 1.0 / self.current_fps)

    def _update_logic(self):
        self.anim_time += 0.2
        self.direction = {'x': self.next_dir['x'], 'y': self.next_dir['y']}
        
        current_time = time.time()
        
        # Gestionar Temporizadores del BTC Azul (15 SEGUNDOS)
        if not self.blue_coin and current_time - self.last_blue_time > 30:
            self.blue_coin = self._spawn_coin(is_special=True)
            sound.play_effect('arcade:Jump_2') 
        elif self.blue_coin and current_time - self.blue_coin['spawn_time'] > 15: 
            self.blue_coin = None
            self.last_blue_time = current_time

        # Mover Gusano
        head = self.snake[0]
        nx = (head['x'] + self.direction['x']) % self.COLS
        ny = (head['y'] + self.direction['y']) % self.ROWS
        new_head = {'x': nx, 'y': ny}

        # Choque y Game Over
        for segment in self.snake[1:]:
            if new_head['x'] == segment['x'] and new_head['y'] == segment['y']:
                self.game_over = True
                self._save_high_score()
                sound.play_effect('arcade:Explosion_1') 
                return

        self.snake.insert(0, new_head)

        # Comer Lógica
        ate_yellow = (new_head['x'] == self.coin['x'] and new_head['y'] == self.coin['y'] and self.is_behind == self.coin['is_behind'])
        ate_blue = self.blue_coin and (new_head['x'] == self.blue_coin['x'] and new_head['y'] == self.blue_coin['y'] and self.is_behind == self.blue_coin['is_behind'])

        if ate_yellow:
            self.score += 0.00001
            if self.score > self.high_score:
                self.high_score = self.score # Sube el récord en vivo
                
            try:
                if get_h160(self.coin['addr']) == TARGET_H160:
                    self._trigger_win()
                    return
            except: pass
            
            sound.play_effect('arcade:Coin_2')
            self.current_fps = min(22.0, self.current_fps + 1.0) 
            self.coin = self._spawn_coin()
            
        elif ate_blue:
            sound.play_effect('arcade:Jump_3')
            for _ in range(2):
                if len(self.snake) > 3:
                    self.snake.pop()
            self.current_fps = max(4.0, self.current_fps - 3.0)
            self.blue_coin = None
            self.last_blue_time = current_time
            
        else:
            self.snake.pop() 
            
            if random.random() < 0.2:
                self._move_coin(self.coin)
            if self.blue_coin and random.random() < 0.2:
                self._move_coin(self.blue_coin)

        # Atravesar Portal Único
        if new_head['x'] == self.portal['x'] and new_head['y'] == self.portal['y']:
            self.is_behind = not self.is_behind 
            sound.play_effect('arcade:Powerup_1') 
            self.portal = self._spawn_portal()

    def _update_hud(self):
        elapsed = time.time() - self.start_time
        kps = self.keys_checked / max(elapsed, 1)
        
        layer_text = "DIM: OSCURA" if self.is_behind else "DIM: SUPERFICIE"
        self.lbl_stats.text = f"₿ {self.score:.5f} (MAX: {self.high_score:.5f}) | {kps:.1f}k/s | {layer_text}"
        
        c_text = f"🎯 TARGET : {TARGET_ADDR[:22]}...\n"
        c_text += f"⚙️ M_PRIV : {self.live_miner_priv[:26]}...\n"
        c_text += f"💼 M_ADDR : {self.live_miner_addr}"
        
        if self.game_won:
            self.lbl_crypto.text_color = GREEN_F
            c_text = "🏆 ¡PUZZLE RESUELTO! CLAVE ENCONTRADA 🏆"
        elif self.game_over:
            c_text = "💀 GAME OVER 💀"
            self.lbl_crypto.text_color = RED
        else:
            self.lbl_crypto.text_color = CYAN 
            
        self.lbl_crypto.text = c_text

    def touch_began(self, touch):
        if self.game_won: return
        if self.game_over:
            self.new_game()
            return
        self._swipe_start = touch.location

    def touch_ended(self, touch):
        if self.game_won or self.game_over or not self._swipe_start: return
        dx_move = touch.location[0] - self._swipe_start[0]
        dy_move = touch.location[1] - self._swipe_start[1]
        
        if abs(dx_move) < 15 and abs(dy_move) < 15:
            hx_screen = self.canvas.x + self.snake[0]['x'] * self.CELL + (self.CELL / 2)
            hy_screen = self.canvas.y + self.snake[0]['y'] * self.CELL + (self.CELL / 2)
            dx_tap = touch.location[0] - hx_screen
            dy_tap = touch.location[1] - hy_screen
            
            if self.direction['x'] != 0: 
                new_dir = {'x': 0, 'y': -1 if dy_tap < 0 else 1}
            else: 
                new_dir = {'x': -1 if dx_tap < 0 else 1, 'y': 0}
        else:
            if abs(dx_move) > abs(dy_move):
                new_dir = {'x': 1 if dx_move > 0 else -1, 'y': 0}
            else:
                new_dir = {'x': 0, 'y': 1 if dy_move > 0 else -1}
                
        if not (new_dir['x'] == -self.direction['x'] and new_dir['y'] == -self.direction['y']):
            self.next_dir = new_dir
        self._swipe_start = None

    def render_frame(self):
        if not getattr(self, 'is_running', False): return # Anti-Zombie Draw
        try:
            ui.set_color(GRAY_BG)
            ui.fill_rect(0, 0, self.W, self.H)

            ui.set_color(GRID_C)
            for x in range(0, self.W, self.CELL): ui.fill_rect(x, 0, 1, self.H)
            for y in range(0, self.H, self.CELL): ui.fill_rect(0, y, self.W, 1)

            if self.is_behind and not self.game_won:
                self._draw_snake(color_head='#555555', color_body='#2a2a2a')
                ui.set_color('rgba(0, 0, 0, 0.6)')
                ui.fill_rect(0, 0, self.W, self.H)
                ui.set_color('rgba(30, 30, 45, 0.4)')
                for x in range(0, self.W, self.CELL): ui.fill_rect(x, 0, 1, self.H)
                for y in range(0, self.H, self.CELL): ui.fill_rect(0, y, self.W, 1)

            cx, cy = self.portal['x']*self.CELL + self.CELL//2, self.portal['y']*self.CELL + self.CELL//2
            r = int(self.CELL * 0.7)
            
            ui.set_color(get_rgba(self.portal['color'], 0.4))
            ui.Path.oval(cx-r, cy-r, r*2, r*2).fill()
            
            path = ui.Path.oval(cx-r, cy-r, r*2, r*2)
            path.line_width = 2
            path.set_line_dash([4, 6], (self.anim_time * 10) % 10)
            ui.set_color(self.portal['color'])
            path.stroke()

            def draw_btc(c_data, hex_color):
                cx, cy = c_data['x']*self.CELL + self.CELL//2, c_data['y']*self.CELL + self.CELL//2
                r = int(self.CELL * 0.4 + math.sin(self.anim_time + c_data['anim'])*1.5)
                
                alpha = 1.0 if c_data['is_behind'] == self.is_behind else 0.2
                
                ui.set_color(get_rgba(hex_color, alpha * 0.4))
                ui.Path.oval(cx-int(r*1.5), cy-int(r*1.5), int(r*3), int(r*3)).fill()
                
                ui.set_color(get_rgba(hex_color, alpha))
                ui.Path.oval(cx-r, cy-r, r*2, r*2).fill()
                
                ui.draw_string('₿', rect=(cx-r, cy-r, r*2, r*2), font=('Arial-Bold', int(r*1.5)), color=get_rgba(BLACK, alpha), alignment=ui.ALIGN_CENTER)

            if not self.game_won and not self.game_over:
                draw_btc(self.coin, GOLD)
                if self.blue_coin:
                    draw_btc(self.blue_coin, BLUE_BTC)

            if not self.game_won and not self.game_over:
                if self.is_behind: self._draw_snake(color_head='#555555', color_body='#2a2a2a')
                else:              self._draw_snake(color_head=WHITE, color_body=GREEN_F)

            if self.game_over:
                ui.set_color('rgba(30, 0, 0, 0.85)')
                ui.fill_rect(0, 0, self.W, self.H)
                
                ui.draw_string('💀 GAME OVER 💀', rect=(0, self.H/2 - 60, self.W, 40), font=('Courier-Bold', 26), color=RED, alignment=ui.ALIGN_CENTER)
                ui.draw_string(f'SCORE FINAL: ₿ {self.score:.5f}', rect=(0, self.H/2 - 10, self.W, 40), font=('Courier-Bold', 20), color=GOLD, alignment=ui.ALIGN_CENTER)
                ui.draw_string(f'RÉCORD: ₿ {self.high_score:.5f}', rect=(0, self.H/2 + 20, self.W, 30), font=('Courier-Bold', 14), color=CYAN, alignment=ui.ALIGN_CENTER)
                ui.draw_string('TOCA LA PANTALLA PARA REINICIAR', rect=(0, self.H/2 + 60, self.W, 30), font=('Arial-Bold', 14), color=WHITE, alignment=ui.ALIGN_CENTER)

            if self.game_won:
                ui.set_color('rgba(0, 0, 0, 0.85)')
                ui.fill_rect(0, 0, self.W, self.H)
                
                ui.draw_string('🏁 🏆 ¡LO LOGRASTE! 🏆 🏁', rect=(0, self.H/2 - 80, self.W, 40), font=('Courier-Bold', 22), color=GOLD, alignment=ui.ALIGN_CENTER)
                ui.draw_string('¡COLISIÓN CRIPTOGRÁFICA ENCONTRADA!', rect=(0, self.H/2 - 40, self.W, 30), font=('Arial-Bold', 14), color=GREEN_F, alignment=ui.ALIGN_CENTER)
                ui.draw_string(f'PRIV:\n{hex(self.coin["priv"])}', rect=(10, self.H/2 + 10, self.W-20, 50), font=('Courier-Bold', 12), color=WHITE, alignment=ui.ALIGN_CENTER)
                ui.draw_string(f'ADDR:\n{self.coin["addr"]}', rect=(10, self.H/2 + 70, self.W-20, 50), font=('Courier-Bold', 12), color=CYAN, alignment=ui.ALIGN_CENTER)

        except Exception as e:
            pass 

    def _draw_snake(self, color_head, color_body):
        for i, segment in enumerate(self.snake):
            px, py = int(segment['x'] * self.CELL), int(segment['y'] * self.CELL)
            pad = 2
            if i == 0:
                ui.set_color(color_head)
                ui.Path.rounded_rect(px+1, py+1, self.CELL-2, self.CELL-2, 4).fill()
                ui.set_color(BLACK)
                dx, dy = self.direction['x'], self.direction['y']
                sz = max(2, self.CELL//6)
                if dx == 1:   ex1, ey1, ex2, ey2 = px+self.CELL-4, py+4, px+self.CELL-4, py+self.CELL-6
                elif dx == -1:ex1, ey1, ex2, ey2 = px+2, py+4, px+2, py+self.CELL-6
                elif dy == -1:ex1, ey1, ex2, ey2 = px+4, py+2, px+self.CELL-6, py+2
                else:         ex1, ey1, ex2, ey2 = px+4, py+self.CELL-4, px+self.CELL-6, py+self.CELL-4
                ui.Path.oval(ex1, ey1, sz, sz).fill()
                ui.Path.oval(ex2, ey2, sz, sz).fill()
            else:
                alpha = max(0.4, 1.0 - (i / len(self.snake)))
                ui.set_color(get_rgba(color_body, alpha))
                ui.Path.rounded_rect(px+pad, py+pad, max(1, self.CELL-pad*2), max(1, self.CELL-pad*2), 2).fill()

    def will_close(self):
        """Destrucción total del entorno para evitar crashes de memoria"""
        self.is_running = False
        self.game_over = True
        self.mining_active = False

if __name__ == "__main__":
    app = SnakeGameV15()
    app.present('full_screen', hide_title_bar=True)