{"id":25042,"date":"2025-07-21T13:31:06","date_gmt":"2025-07-21T11:31:06","guid":{"rendered":"https:\/\/www.erekibeon.com\/blog\/?p=25042"},"modified":"2025-07-21T13:46:22","modified_gmt":"2025-07-21T11:46:22","slug":"minijuegos-de-habilidad-en-lugar-de-tiradas-de-dado","status":"publish","type":"post","link":"https:\/\/www.erekibeon.com\/blog\/minijuegos-de-habilidad-en-lugar-de-tiradas-de-dado\/","title":{"rendered":"Minijuegos de habilidad en lugar de tiradas de dado"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">\u00bfNunca os han dado rabia las <strong>rachas de mala suerte<\/strong> durante las partidas? Ya sab\u00e9is, ese encadenamiento de malas tiradas que hacen que tu personaje pase de ser alguien competente (m\u00e1s o menos) a convertirse de repente en un metepatas al que no le sale nada bien.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A ver, que soy el primero en carcajearse cuando veo a mi B\u00e1rbaro furioso cuando falla dos o tres veces seguidas. Pero cuando est\u00e1s en plena escena culminante de la aventura y el dado comienza a sacar solo doses y treses&#8230; pues oye, igual vosotros sois seres de luz y os lo tom\u00e1is con una sonrisa beat\u00edfica. A m\u00ed no siempre me sale.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Y para esas ocasiones me encantar\u00eda que hubiera <strong>alguna otra forma de resolver<\/strong> c\u00f3mo lo hace mi personaje. Que el resultado no dependiera \u00fanicamente del capricho de mis querid\u00edsimos cachos de pl\u00e1stico-resina-metal-elmaterialrarunodemoda, sino que hubiera <strong>alg\u00fan modo de que fuera mi propia habilidad<\/strong> la que determinara el resultado. Lo cual podr\u00eda salir tambi\u00e9n mal, claro \ud83d\ude1b Pero al menos ser\u00eda por culpa m\u00eda, no de un azar caprichoso sobre el que no tengo absolutamente ninguna capacidad de influir.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img data-dominant-color=\"7d7b72\" data-has-transparency=\"false\" style=\"--dominant-color: #7d7b72;\" loading=\"lazy\" decoding=\"async\" width=\"1280\" height=\"720\" sizes=\"auto, (max-width: 645px) 100vw, 645px\" src=\"https:\/\/www.erekibeon.com\/blog\/wp-content\/uploads\/castigandodados.webp\" alt=\"\" class=\"wp-image-25318 not-transparent\" srcset=\"https:\/\/www.erekibeon.com\/blog\/wp-content\/uploads\/castigandodados.webp 1280w, https:\/\/www.erekibeon.com\/blog\/wp-content\/uploads\/castigandodados-300x169.webp 300w, https:\/\/www.erekibeon.com\/blog\/wp-content\/uploads\/castigandodados-150x84.webp 150w, https:\/\/www.erekibeon.com\/blog\/wp-content\/uploads\/castigandodados-768x432.webp 768w\" \/><figcaption class=\"wp-element-caption\">Ehm&#8230; y no, esto no cuenta como \u00abinfluir en el azar\u00bb. Por cierto, cu\u00e1ntos art\u00edculos hay para castigar a los que sacan malas tiradas&#8230; y no hay ninguno para premiar a los que las sacan buenas. \u00bfPosible nicho de mercado?<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Si a esto le unimos el hecho de que pr\u00e1cticamente todo el mundo llevamos un m\u00f3vil a cuestas, una soluci\u00f3n que se me ocurri\u00f3 ser\u00eda <strong>desarrollar alguna aplicaci\u00f3n<\/strong> con la que realices una sencilla prueba de habilidad. En funci\u00f3n de c\u00f3mo te salga, se traducir\u00eda al resultado de una tirada de dado. \u00bfQue clavas la prueba? Pues es como si hubieras sacado un 20 en 1d20. \u00bfQue la sacas reguleras? Pues un 12 o un 13. \u00bfQue la fallas estrepitosamente? Pues has sacado un 1.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Y esto lleva en mi carpeta de \u00abpaluegos\u00bb desde hace&#8230; pufff&#8230; ya ni me acuerdo. Porque claro, para ello tendr\u00eda que <strong>aprender a programar<\/strong>. Y voto a br\u00edos que estuve trasteando con <a href=\"https:\/\/en.wikipedia.org\/wiki\/Grasshopper_(mobile_app)\" data-type=\"link\" data-id=\"https:\/\/en.wikipedia.org\/wiki\/Grasshopper_(mobile_app)\">Grasshopper<\/a>, que le ech\u00e9 mis horas a <a href=\"https:\/\/es.wikipedia.org\/wiki\/Android_Studio\" data-type=\"link\" data-id=\"https:\/\/es.wikipedia.org\/wiki\/Android_Studio\" target=\"_blank\" rel=\"noreferrer noopener\">Android Studio<\/a> y a <a href=\"https:\/\/kotlinlang.org\/\" data-type=\"link\" data-id=\"https:\/\/kotlinlang.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">Kotlin<\/a> y que incluso estuve trasteando con <a href=\"https:\/\/godotengine.org\/es\/\" data-type=\"link\" data-id=\"https:\/\/godotengine.org\/es\/\">Godot<\/a>&#8230; pero no consegu\u00ed ni acercarme al concepto que ten\u00eda en mente. As\u00ed que lo dej\u00e9 en esa lista de pendientes donde tambi\u00e9n est\u00e1n <strong>aprender a dibujar<\/strong>, a <strong>tocar un instrumento<\/strong> (siempre <a href=\"https:\/\/www.erekibeon.com\/blog\/curso-intensivo-para-escuchar-el-bajo\/\" data-type=\"link\" data-id=\"https:\/\/www.erekibeon.com\/blog\/curso-intensivo-para-escuchar-el-bajo\/\" target=\"_blank\" rel=\"noreferrer noopener\">he sido un fan del bajo<\/a>), a <strong>maquetar<\/strong> textos, a <strong>manejar un programa de creaci\u00f3n y edici\u00f3n musical<\/strong> para crear mis propios temas de Punk Elegante, a hablar en <strong>esperanto<\/strong>&#8230; y bastantes cosas m\u00e1s, que tampoco os quiero aburrir. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pero tampoco quiero que os llev\u00e9is la impresi\u00f3n de que mi \u00ablista de pendientes\u00bb es una especie de cementerio donde voy poniendo cosas que luego nunca salen. Resulta que consegu\u00ed tachar de esa lista cosas como <strong>aprender a editar im\u00e1genes<\/strong> con Photoshop y Gimp, <strong>a editar v\u00eddeo<\/strong> con VEGAS Movie Studio y Adobe Premiere, <strong>a editar audio<\/strong> con Audacity&#8230; y en breve con FL Studio, e incluso a <strong>crear un tema propio de WordPress<\/strong>. Por poner unos cuantos ejemplos.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Sin embargo, la vida da para lo que da<\/strong>, entre ser Padre, Marido, Friki y currito. Eso sin tener en cuenta que no todos tenemos las mismas capacidades intelectuales y de concentraci\u00f3n. Por eso una de mis secretas esperanzas (bueno, ahora ya no es tan secreta) es que alguien invente la pastilla rejuvenecedora antes de que sea demasiado tarde (para m\u00ed). As\u00ed podr\u00e9 dedicarme a aprender tod\u00edsimo lo que me encantar\u00eda aprender para tachar m\u00e1s y m\u00e1s cosas de esa lista. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pero hete aqu\u00ed que estamos en 2025 y la IA est\u00e1 ahora mismo en ese punto en que <strong>puede programar por ti un concepto que le cuentes en lenguaje natural<\/strong>. Lo cual tiene un nombre muy <em>cool and fresh<\/em> que no aprend\u00ed hasta hace dos d\u00edas, aunque estuve haci\u00e9ndolo durante varias semanas. S\u00ed se\u00f1ores, estuve haciendo <em><a href=\"https:\/\/es.wikipedia.org\/wiki\/Vibe_coding\" data-type=\"link\" data-id=\"https:\/\/es.wikipedia.org\/wiki\/Vibe_coding\" target=\"_blank\" rel=\"noreferrer noopener\">vibe coding<\/a><\/em> \ud83d\ude0e<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Primer prototipo: barra deslizante<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Cuando me enter\u00e9 de que los <a href=\"https:\/\/es.wikipedia.org\/wiki\/Modelo_extenso_de_lenguaje\" data-type=\"link\" data-id=\"https:\/\/es.wikipedia.org\/wiki\/Modelo_extenso_de_lenguaje\">LLMs<\/a> ya estaban facilitando bloques de c\u00f3digo completo, lo primero que pens\u00e9 fue en ese viejo proyecto sobre las Tiradas de habilidad, claro. Lo desempolv\u00e9 y decid\u00ed comprobar si <strong><a href=\"https:\/\/es.wikipedia.org\/wiki\/Gemini_(bot_conversacional)\" data-type=\"link\" data-id=\"https:\/\/es.wikipedia.org\/wiki\/Gemini_(bot_conversacional)\">Gemini<\/a><\/strong> pod\u00eda hacer algo m\u00ednimamente decente con \u00e9l. Que, ahora que lo pienso, no tengo ni idea de por qu\u00e9 empec\u00e9 a probarlo con \u00e9l y no con <strong>Claude<\/strong> o con <strong>ChatGPT<\/strong>&#8230; pero bueno, una vez que comenc\u00e9 con <strong>Gemini<\/strong>, ya me dio pereza cambiarme y segu\u00ed con \u00e9l. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Y este fue mi primer prompt:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-background\" style=\"background-color:#9dd8ed73;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--40);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--40)\">Necesito programar una aplicaci\u00f3n que permita traducir el resultado de una prueba de habilidad del usuario a un n\u00famero entre 1 y 20. <br \/><br \/>La prueba es la cl\u00e1sica de parar un cursor que va y viene sobre una barra en el lugar marcado. En funci\u00f3n de c\u00f3mo de cerca de ese lugar quede el cursor, la puntuaci\u00f3n estar\u00e1 m\u00e1s o menos cerca del 20, con un bot\u00f3n de extra para resetarlo.<br \/><br \/>Quisiera programarlo en HTML5. \u00bfMe escribes el c\u00f3digo que necesito? <\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Lo de insistir en el HTML5 para programarlo puede sonar a una limitaci\u00f3n, pero al mismo tiempo es una forma de liberarlo: no depende de una app, ni de iOS, Android, Windows, Linux o Mac. Se podr\u00eda utilizar en cualquier cacharro, mientras tenga alg\u00fan tipo de navegador web.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Y el c\u00f3digo que me devolvi\u00f3 <strong>Gemini<\/strong> es lo que hace funcionar esto:<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<!DOCTYPE html>\n<html lang=\"es\">\n<head>\n    <meta charset=\"UTF-8\"\/>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\/>\n    <title>Prueba de Habilidad con Cursor<\/title>\n    <style>\n        \/*\n         * NOTA IMPORTANTE para WordPress:\n         * Evita poner estilos directos sobre <body> o <html> aqu\u00ed,\n         * ya que WordPress los gestiona con su tema.\n         * Si necesitas modificar el <body> globalmente, usa \"CSS Adicional\" del tema.\n         *\n         * Los estilos a continuaci\u00f3n son espec\u00edficos para el contenedor del juego (#juegoHabilidad1)\n         * y sus elementos internos, para evitar conflictos con otros juegos o el tema.\n         *\/\n\n        \/* --- Estilos espec\u00edficos para el juego de Habilidad #juegoHabilidad1 --- *\/\n        #juegoHabilidad1 {\n            \/* Ocupa el 100% del ancho del contenedor padre de WordPress *\/\n            width: 100%;\n            max-width: 600px; \/* L\u00edmite de ancho para este juego *\/\n            \n            \/* Centra el contenedor horizontalmente si no ocupa el 100% del ancho disponible *\/\n            margin: 0 auto;\n            \n            background-color: transparent; \/* Fondo del contenedor del juego transparente *\/\n            padding: 20px;\n            border-radius: 8px;\n            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); \/* Sombra opcional para el contenedor *\/\n            text-align: center;\n            margin-bottom: 30px; \/* Espacio entre juegos si hubiera varios *\/\n            border: 1px solid rgba(0,0,0,0.1); \/* Borde sutil para delimitar el juego *\/\n            box-sizing: border-box; \/* Asegura que padding y border no sumen al ancho total *\/\n        }\n\n        #juegoHabilidad1 h2 {\n            color: #333;\n            margin-top: 0;\n            font-size: 1.8em;\n            margin-bottom: 20px;\n        }\n\n        #juegoHabilidad1 #bar {\n            width: 100%;\n            height: 30px;\n            background-color: #ddd;\n            position: relative;\n            margin-bottom: 20px;\n            border-radius: 5px;\n            overflow: hidden;\n            border: 1px solid #ccc;\n        }\n\n        #juegoHabilidad1 #cursor {\n            width: 15px;\n            height: 100%;\n            background-color: #ff0000;\n            position: absolute;\n            top: 0;\n            left: 0;\n            border-radius: 3px;\n        }\n\n        #juegoHabilidad1 #target {\n            width: 40px;\n            height: 100%;\n            background-color: rgba(0, 255, 0, 0.5);\n            position: absolute;\n            top: 0;\n            left: calc(50% - 20px);\n            border-left: 2px dashed #006400;\n            border-right: 2px dashed #006400;\n            box-sizing: border-box;\n        }\n\n        #juegoHabilidad1 .button-group {\n            display: flex;\n            flex-wrap: wrap; \/* Permite que los botones se envuelvan en pantallas peque\u00f1as *\/\n            justify-content: center;\n            gap: 15px;\n            margin-top: 20px;\n        }\n\n        #juegoHabilidad1 .game-button {\n            padding: 10px 20px;\n            font-size: 18px;\n            cursor: pointer;\n            color: white;\n            border: none;\n            border-radius: 5px;\n            transition: background-color 0.3s ease, transform 0.1s ease;\n            box-shadow: 0 2px 5px rgba(0,0,0,0.2);\n        }\n\n        #juegoHabilidad1 .game-button:active {\n            transform: translateY(1px);\n            box-shadow: 0 1px 3px rgba(0,0,0,0.2);\n        }\n\n        #juegoHabilidad1 #startButton {\n            background-color: #007bff; \/* Azul *\/\n        }\n        #juegoHabilidad1 #startButton:hover {\n            background-color: #0056b3;\n        }\n\n        #juegoHabilidad1 #stopButton {\n            background-color: #dc3545; \/* Rojo *\/\n        }\n\n        #juegoHabilidad1 #stopButton:hover {\n            background-color: #c82333;\n        }\n\n        #juegoHabilidad1 #stopButton:disabled,\n        #juegoHabilidad1 #startButton:disabled {\n            background-color: #cccccc;\n            cursor: not-allowed;\n            box-shadow: none;\n        }\n\n        #juegoHabilidad1 #retryButton {\n            background-color: #28a745; \/* Verde *\/\n            display: none;\n        }\n\n        #juegoHabilidad1 #retryButton:hover {\n            background-color: #218838;\n        }\n\n        #juegoHabilidad1 #result {\n            margin-top: 20px;\n            font-size: 1.2em;\n            font-weight: bold;\n            min-height: 40px;\n            color: #333;\n        }\n    <\/body><\/html><\/body><\/style>\n<\/head>\n<body>\n\n    <div id=\"juegoHabilidad1\">\n        <h2>Det\u00e9n el Cursor<\/h2>\n        <div id=\"bar\">\n            <div id=\"target\"><\/div>\n            <div id=\"cursor\"><\/div>\n        <\/div>\n        <div class=\"button-group\">\n            <button id=\"startButton\" class=\"game-button\">Empezar<\/button>\n            <button id=\"stopButton\" class=\"game-button\" disabled>\u00a1Parar!<\/button>\n            <button id=\"retryButton\" class=\"game-button\">Otra tirada<\/button>\n        <\/div>\n        <div id=\"result\"><\/div>\n    <\/div>\n\n    <script>\n        \/\/ --- JavaScript para el juego #juegoHabilidad1 ---\n\n        \/\/ Funci\u00f3n que toma el ID del contenedor del juego como argumento\n        function inicializarJuegoHabilidad(containerId) {\n            const gameContainer = document.getElementById(containerId);\n            if (!gameContainer) {\n                console.error(`Contenedor de juego no encontrado: ${containerId}`);\n                return;\n            }\n\n            \/\/ Usamos gameContainer.querySelector para encontrar elementos DENTRO de este juego\n            const bar = gameContainer.querySelector('#bar');\n            const cursor = gameContainer.querySelector('#cursor');\n            const target = gameContainer.querySelector('#target');\n            const startButton = gameContainer.querySelector('#startButton');\n            const stopButton = gameContainer.querySelector('#stopButton');\n            const retryButton = gameContainer.querySelector('#retryButton');\n            const resultDiv = gameContainer.querySelector('#result');\n\n            \/\/ Verificar si los elementos se encontraron correctamente\n            if (!bar || !cursor || !target || !startButton || !stopButton || !retryButton || !resultDiv) {\n                console.error(\"Uno o m\u00e1s elementos del juego no se encontraron dentro del contenedor:\", {\n                    bar, cursor, target, startButton, stopButton, retryButton, resultDiv\n                });\n                resultDiv.innerHTML = \"Error: Algunos elementos del juego no se cargaron correctamente. Consulta la consola.\";\n                return; \/\/ Detener la ejecuci\u00f3n si faltan elementos cruciales\n            }\n\n            let animationId;\n            let cursorPosition = 0;\n            let speed = 5;\n            let direction = 1;\n            let gameStarted = false; \/\/ Nuevo estado para controlar si el juego ha empezado\n\n            let barWidth;\n            let cursorWidth;\n            let targetWidth;\n            let targetLeft;\n            let targetCenter;\n            let maxCursorCenter;\n            let minCursorCenter;\n\n            function getDimensions() {\n                barWidth = bar.offsetWidth;\n                cursorWidth = cursor.offsetWidth;\n                targetWidth = target.offsetWidth;\n                targetLeft = target.offsetLeft;\n                \n                \/\/ Estos logs son para depuraci\u00f3n y puedes eliminarlos si todo funciona bien\n                console.log(`[getDimensions] barWidth: ${barWidth}, cursorWidth: ${cursorWidth}, targetWidth: ${targetWidth}, targetLeft: ${targetLeft}`);\n\n                \/\/ Si alguna dimensi\u00f3n es 0, podr\u00eda ser un problema de CSS o renderizado\n                if (barWidth === 0 || cursorWidth === 0 || targetWidth === 0) {\n                    console.warn(\"Advertencia: Una o m\u00e1s dimensiones son 0. Esto podr\u00eda causar problemas de juego. Revisa el CSS.\");\n                    \/\/ resultDiv.innerHTML = \"Error de dimensiones. Aseg\u00farate de que los elementos sean visibles.\";\n                }\n\n                targetCenter = targetLeft + targetWidth \/ 2;\n                minCursorCenter = cursorWidth \/ 2;\n                maxCursorCenter = barWidth - cursorWidth \/ 2;\n\n                console.log(`[getDimensions Calculated] targetCenter: ${targetCenter}, minCursorCenter: ${minCursorCenter}, maxCursorCenter: ${maxCursorCenter}`);\n            }\n\n            function animateCursor() {\n                if (!gameStarted) return; \/\/ Solo anima si el juego ha comenzado\n\n                cursorPosition += speed * direction;\n\n                \/\/ Logs para depuraci\u00f3n\n                console.log(`[Frame] pos: ${cursorPosition.toFixed(2)}, dir: ${direction}, barW: ${barWidth}, cursorW: ${cursorWidth}`);\n\n                if (cursorPosition + cursorWidth >= barWidth) { \/\/ CONDICI\u00d3N MEJORADA: de '>' a '>='\n                    console.log(`[Right Edge Hit] Before: ${cursorPosition.toFixed(2)}, Dir: ${direction}`);\n                    cursorPosition = barWidth - cursorWidth; \/\/ Ajusta para que el cursor no se salga\n                    direction = -1;\n                    console.log(`[Right Edge Hit] After: ${cursorPosition.toFixed(2)}, New Dir: ${direction}`);\n                } else if (cursorPosition < 0) {\n                    console.log(`[Left Edge Hit] Before: ${cursorPosition.toFixed(2)}, Dir: ${direction}`);\n                    cursorPosition = 0; \/\/ Ajusta para que el cursor no se salga\n                    direction = 1;\n                    console.log(`[Left Edge Hit] After: ${cursorPosition.toFixed(2)}, New Dir: ${direction}`);\n                }\n\n                cursor.style.left = cursorPosition + 'px';\n                animationId = requestAnimationFrame(animateCursor);\n            }\n\n            function startGame() {\n                \/\/ *** ESTE ES EL CAMBIO CLAVE: Llama a getDimensions() justo antes de empezar la animaci\u00f3n ***\n                \/\/ Esto asegura que las dimensiones de la barra y el cursor se lean correctamente\n                \/\/ en el momento en que se va a iniciar el movimiento, evitando valores de 0 o incorrectos.\n                getDimensions(); \n\n                gameStarted = true;\n                startButton.style.display = 'none'; \/\/ Oculta el bot\u00f3n de empezar\n                stopButton.disabled = false; \/\/ Habilita el bot\u00f3n de parar\n                animateCursor(); \/\/ Inicia la animaci\u00f3n\n            }\n\n            function stopGame() {\n                cancelAnimationFrame(animationId);\n                gameStarted = false; \/\/ El juego se detiene\n                stopButton.disabled = true;\n                retryButton.style.display = 'inline-block';\n\n                const finalCursorLeft = cursorPosition;\n                const finalCursorCenter = finalCursorLeft + cursorWidth \/ 2;\n                const error = Math.abs(finalCursorCenter - targetCenter);\n\n                console.log(`[stopGame] finalCursorLeft: ${finalCursorLeft}, finalCursorCenter: ${finalCursorCenter}`);\n                console.log(`[stopGame] targetCenter: ${targetCenter}, error: ${error}`);\n\n                const maxError = Math.max(\n                    Math.abs(targetCenter - minCursorCenter),\n                    Math.abs(targetCenter - maxCursorCenter)\n                );\n                \n                console.log(`[stopGame] minCursorCenter: ${minCursorCenter}, maxCursorCenter: ${maxCursorCenter}, maxError: ${maxError}`);\n\n                let score;\n                \/\/ Prevenir NaN si maxError es 0 (esto ocurrir\u00eda si barWidth es igual a cursorWidth, o si target es muy peque\u00f1o)\n                if (maxError === 0) {\n                    score = (error === 0) ? 20 : 1; \/\/ Si no hay error y maxError es 0, es 20. Si hay error, es 1.\n                    console.warn(\"Advertencia: maxError es 0, ajustando el c\u00e1lculo de la puntuaci\u00f3n.\");\n                } else {\n                    score = 20 - (error \/ maxError) * 19;\n                }\n                \n                score = Math.max(1, Math.min(20, Math.round(score)));\n\n                resultDiv.innerHTML = `\n                    Distancia al centro: ${error.toFixed(2)}px<br \/>\n                    Puntuaci\u00f3n: <span style=\"color: ${score>= 15 ? 'green' : (score >= 10 ? 'orange' : 'red')}\">${score} \/ 20<\/span>\n                `;\n            }\n\n            function resetGame() {\n                cancelAnimationFrame(animationId);\n                cursorPosition = 0;\n                direction = 1;\n                cursor.style.left = cursorPosition + 'px';\n                gameStarted = false; \/\/ Restablece el estado del juego a no iniciado\n\n                startButton.style.display = 'inline-block'; \/\/ Muestra el bot\u00f3n de empezar\n                stopButton.disabled = true; \/\/ Deshabilita el bot\u00f3n de parar\n                retryButton.style.display = 'none'; \/\/ Oculta el bot\u00f3n de reintentar\n                resultDiv.innerHTML = ''; \/\/ Limpia el resultado\n\n                \/\/ No llamamos a animateCursor aqu\u00ed, se espera al bot\u00f3n \"Empezar\"\n            }\n\n            \/\/ Inicializaci\u00f3n del juego al cargar el DOM\n            \/\/ Aqu\u00ed, solo aseguramos que las dimensiones se lean una primera vez\n            \/\/ y que el juego est\u00e9 en estado de \"espera\" para empezar.\n            document.addEventListener('DOMContentLoaded', () => {\n                getDimensions(); \/\/ Lee las dimensiones iniciales\n                resetGame(); \/\/ Prepara el juego para empezar\n            });\n\n            \/\/ Re-calcular dimensiones al redimensionar la ventana\n            window.addEventListener('resize', getDimensions);\n\n            \/\/ Asignar eventos a los botones\n            startButton.addEventListener('click', startGame); \/\/ Evento para el nuevo bot\u00f3n \"Empezar\"\n            stopButton.addEventListener('click', stopGame);\n            retryButton.addEventListener('click', resetGame);\n        }\n\n        \/\/ --- Llamada para inicializar el juego ---\n        \/\/ Se ejecuta despu\u00e9s de que el DOM est\u00e9 completamente cargado para asegurar que los elementos existan.\n        document.addEventListener('DOMContentLoaded', () => {\n            inicializarJuegoHabilidad('juegoHabilidad1');\n        });\n    <\/script>\n\n<\/body>\n<\/html>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Es verdad que tuve que pedirle que \u00abencapsulara\u00bb el resultado para que no despirulara los estilos del resto de la p\u00e1gina, pero oye, se trata de un <a href=\"https:\/\/es.wikipedia.org\/wiki\/Producto_viable_m%C3%ADnimo\" data-type=\"link\" data-id=\"https:\/\/es.wikipedia.org\/wiki\/Producto_viable_m%C3%ADnimo\" target=\"_blank\" rel=\"noreferrer noopener\">producto m\u00ednimo viable<\/a> que me parece de lo m\u00e1s interesante. Se mueve y hace exactamente lo que ped\u00ed. Muy mejorable en todos los sentidos, por supuesto, pero es que eso es el \u00abm\u00ednimo\u00bb de \u00abproducto m\u00ednimo viable\u00bb.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Por supuesto, en cuanto lo vi lo fui ense\u00f1ando por casa para que todo el mundo lo probara. Y en una de esas fue <strong>Fusa<\/strong> quien me indic\u00f3 lo que ahora os parecer\u00e1 lo m\u00e1s evidente. Y es que \u00bf<strong>qui\u00e9n va a sacar un 1<\/strong> en ese minijuego? Es m\u00e1s, con el suficiente tiempo de por medio, lo m\u00e1s probable es que todo el mundo saque tiradas de 17 para arriba.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Y&#8230; claro, eso no est\u00e1 bien. Si existe la oportunidad de sacar una buena tirada, tambi\u00e9n deber\u00eda estar la posibilidad de sacar una tirada mala.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As\u00ed que le di un par de vueltas a c\u00f3mo podr\u00eda nivelar los resultados, y se me ocurrieron estos tres caminos:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Limitar el deslizador<\/strong> para hacerlo m\u00e1s dif\u00edcil. Es decir, poner un l\u00edmite a las veces que el cursor puede ir y volver por la barra, o acelerar el cursor, o estrechar a\u00fan m\u00e1s el espacio verde donde sacas el 20.<\/li>\n\n\n\n<li><strong>Hacer un examen previo de la habilidad<\/strong> del jugador. Realizar unos tests previos para medir la habilidad del jugador, y luego hacer la tirada \u00abbuena\u00bb ajustando la dificultad a su habilidad. Un concepto que me mola, pero que ralentizar\u00eda demasiado el proceso&#8230; as\u00ed que de momento lo dej\u00e9 a un lado.<\/li>\n\n\n\n<li>Desechar completamente lo de la barra deslizante y explorar el concepto de las <strong>\u00abcasillas brillantes\u00bb<\/strong>: que se muestren todos los resultados posibles en pantalla y se vayan iluminando aleatoriamente. El jugador tiene un bot\u00f3n para detener el juego cuando se ilumine el resultado que quiera (aunque&#8230; \u00bfqui\u00e9n va a querer sacar un 14 pudiendo sacar un 20?).<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Lo flipante de esto del <em>vibe coding<\/em> es que puedo pedirle las dos pruebas de concepto que me quedan, obtener el resultado r\u00e1pidamente y ponerme a testearlas en un pliki. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As\u00ed que comenc\u00e9 con el primer camino: <strong>hacer m\u00e1s dif\u00edcil<\/strong> la barra deslizante. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Segundo prototipo: barra deslizante de la muerte<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A ver qu\u00e9 tal se os da:<\/p>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<!DOCTYPE html>\n<html lang=\"es\">\n<head>\n    <meta charset=\"UTF-8\"\/>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\/>\n    <title>Prueba de Habilidad<\/title>\n    <style>\n        \/* ... (tus estilos CSS anteriores) ... *\/\n        #juegoHabilidad2 {\n            width: 100%;\n            max-width: 700px;\n            margin: 0 auto;\n            background-color: transparent;\n            padding: 25px;\n            border-radius: 8px;\n            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);\n            text-align: center;\n            margin-bottom: 40px;\n            border: 1px solid rgba(0,0,0,0.1);\n            box-sizing: border-box;\n            overflow: hidden;\n            position: relative;\n            \/* Flexbox para organizar el contenido y mantener los botones fijos *\/\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n        }\n\n        #juegoHabilidad2 h2 {\n            color: #2c3e50;\n            margin-top: 0;\n            font-size: 2em;\n            margin-bottom: 15px; \/* Espacio ajustado *\/\n            text-shadow: 1px 1px 2px rgba(0,0,0,0.1);\n        }\n\n        #juegoHabilidad2 p {\n            margin-bottom: 25px; \/* Espacio para el aviso *\/\n        }\n\n        \/* La barra como una hoja de espada (aproximaci\u00f3n CSS) *\/\n        #juegoHabilidad2 #bar {\n            width: 100%;\n            height: 40px;\n            background: linear-gradient(to right, #bdbdbd, #e0e0e0, #bdbdbd);\n            position: relative;\n            margin-bottom: 20px;\n            border-radius: 5px;\n            overflow: hidden;\n            border: 1px solid #9e9e9e;\n            box-shadow: inset 0 0 5px rgba(0,0,0,0.2);\n            \/* Forma de espada: apunta a la derecha *\/\n            clip-path: polygon(0 0, 100% 0, 95% 50%, 100% 100%, 0 100%);\n        }\n\n        #juegoHabilidad2 #cursor {\n            width: 18px;\n            height: 100%;\n            background-color: #e74c3c;\n            position: absolute;\n            top: 0;\n            left: 0;\n            border-radius: 3px;\n            box-shadow: 0 0 8px rgba(231, 76, 60, 0.7);\n        }\n\n        #juegoHabilidad2 #target {\n            width: 50px;\n            height: 100%;\n            background-color: rgba(46, 204, 113, 0.6);\n            position: absolute;\n            top: 0;\n            left: calc(50% - 25px);\n            border-left: 2px dashed #27ae60;\n            border-right: 2px dashed #27ae60;\n            box-sizing: border-box;\n        }\n\n        #juegoHabilidad2 .button-group {\n            display: flex;\n            justify-content: center;\n            gap: 15px;\n            margin-top: 0; \/* No margin-top aqu\u00ed para que no se mueva *\/\n            min-height: 50px; \/* Asegura un espacio m\u00ednimo para los botones *\/\n            width: 100%; \/* Ocupa todo el ancho disponible *\/\n        }\n\n        #juegoHabilidad2 .game-button {\n            padding: 12px 25px;\n            font-size: 1.1em;\n            cursor: pointer;\n            color: white;\n            border: none;\n            border-radius: 6px;\n            transition: background-color 0.3s ease, transform 0.1s ease;\n            box-shadow: 0 2px 5px rgba(0,0,0,0.2);\n        }\n\n        #juegoHabilidad2 .game-button:active {\n            transform: translateY(1px);\n            box-shadow: 0 1px 3px rgba(0,0,0,0.2);\n        }\n\n        #juegoHabilidad2 #startButton {\n            background-color: #1a73e8;\n        }\n        #juegoHabilidad2 #startButton:hover {\n            background-color: #155bbd;\n        }\n\n\n        #juegoHabilidad2 #stopButton {\n            background-color: #3498db;\n        }\n\n        #juegoHabilidad2 #stopButton:hover {\n            background-color: #2980b9;\n        }\n\n        #juegoHabilidad2 #stopButton:disabled {\n            background-color: #cccccc;\n            cursor: not-allowed;\n            box-shadow: none;\n        }\n\n        #juegoHabilidad2 #retryButton {\n            background-color: #2ecc71;\n            display: none;\n        }\n\n        #juegoHabilidad2 #retryButton:hover {\n            background-color: #27ae60;\n        }\n        \n        #juegoHabilidad2 #countdown {\n            font-size: 2em;\n            font-weight: bold;\n            color: #34495e;\n            margin-bottom: 20px;\n            height: 60px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            text-shadow: 2px 2px 4px rgba(0,0,0,0.1);\n        }\n        #juegoHabilidad2 #countdown.hidden {\n            display: none;\n        }\n\n        #juegoHabilidad2 #result {\n            margin-top: 25px;\n            font-size: 2.5em; \/* Tama\u00f1o m\u00e1s grande para el n\u00famero *\/\n            font-weight: bold;\n            min-height: 80px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n        }\n        \n        \/* Colores din\u00e1micos para el resultado *\/\n        #juegoHabilidad2 #result.score-high {\n            color: #27ae60; \/* Verde, para puntuaciones altas (cercanas a 20) *\/\n            text-shadow: 0 0 5px rgba(39, 174, 96, 0.5);\n        }\n        #juegoHabilidad2 #result.score-medium {\n            color: #e67e22; \/* Naranja, para puntuaciones medias *\/\n            text-shadow: 0 0 5px rgba(230, 126, 34, 0.5);\n        }\n        #juegoHabilidad2 #result.score-low {\n            color: #e74c3c; \/* Rojo, para puntuaciones bajas (cercanas a 1) *\/\n            text-shadow: 0 0 5px rgba(231, 76, 60, 0.5);\n        }\n\n        #juegoHabilidad2 #last-scores-container {\n            margin-top: 30px;\n            border-top: 1px solid #eee;\n            padding-top: 20px;\n            font-size: 0.95em;\n            color: #555;\n            width: 100%; \/* Asegura que ocupa el ancho completo para centrado *\/\n        }\n        #juegoHabilidad2 #last-scores-list {\n            list-style: none;\n            padding: 0;\n            margin: 10px 0 0 0;\n            display: flex;\n            flex-wrap: wrap;\n            justify-content: center;\n            gap: 10px;\n        }\n        #juegoHabilidad2 #last-scores-list li {\n            background-color: #f0f0f0;\n            padding: 5px 10px;\n            border-radius: 4px;\n            border: 1px solid #e0e0e0;\n            color: #444;\n            font-weight: bold;\n        }\n\n        \/* Estilo para el contador de usos *\/\n        #usage-counter {\n            margin-top: 20px;\n            font-size: 1em;\n            color: #777;\n        }\n    <\/style>\n<\/head>\n<body>\n\n    <div id=\"juegoHabilidad2\">\n        <h2>Det\u00e9n el cursor<\/h2>\n        <p>\u00a1Cuidado! S\u00f3lo tendr\u00e1s <b>un \u00fanico intento<\/b> para detener el cursor en la zona verde.<\/p>\n\n        <div id=\"countdown\"><\/div>\n        <div id=\"bar\">\n            <div id=\"target\"><\/div>\n            <div id=\"cursor\"><\/div>\n        <\/div>\n\n        <div class=\"button-group\">\n            <button id=\"startButton\" class=\"game-button\">\u00a1Empezar!<\/button>\n            <button id=\"stopButton\" class=\"game-button\">\u00a1Parar!<\/button>\n            <button id=\"retryButton\" class=\"game-button\">Jugar de nuevo<\/button>\n        <\/div>\n        \n        <div id=\"result\"><\/div>\n        <div id=\"last-scores-container\">\n            <h3>\u00daltimas 5 tiradas:<\/h3>\n            <ul id=\"last-scores-list\">\n            <\/ul>\n        <\/div>\n        <div id=\"usage-counter\">Veces utilizado: <span id=\"counter-value\">0<\/span><\/div>\n    <\/div>\n\n    <script>\n        \/\/ Funci\u00f3n que toma el ID del contenedor del juego como argumento\n        function inicializarJuegoHabilidadCaballero(containerId) {\n            const gameContainer = document.getElementById(containerId);\n            if (!gameContainer) {\n                console.error(`Contenedor de juego no encontrado: ${containerId}`);\n                return;\n            }\n\n            \/\/ Referencias a los elementos dentro de ESTE contenedor\n            const bar = gameContainer.querySelector('#bar');\n            const cursor = gameContainer.querySelector('#cursor');\n            const target = gameContainer.querySelector('#target');\n            const startButton = gameContainer.querySelector('#startButton');\n            const stopButton = gameContainer.querySelector('#stopButton');\n            const retryButton = gameContainer.querySelector('#retryButton');\n            const resultDiv = gameContainer.querySelector('#result');\n            const countdownDiv = gameContainer.querySelector('#countdown');\n            const lastScoresList = gameContainer.querySelector('#last-scores-list');\n            const gameDescriptionP = gameContainer.querySelector('p'); \/\/ El p\u00e1rrafo con la descripci\u00f3n\n            const counterValueSpan = gameContainer.querySelector('#counter-value'); \/\/ Span para el valor del contador global\n\n            let animationId;\n            let cursorPosition = 0;\n            let speed = 7;\n            let direction = 1; \/\/ Siempre a la derecha\n            let gameActive = false;\n            let gameEndedByButton = false;\n            \n            \/\/ La URL de tu script PHP. \u00a1AJUSTA ESTO A LA RUTA REAL EN TU SERVIDOR!\n            const GLOBAL_API_URL = 'https:\/\/www.erekibeon.com\/blog\/contadores\/counter2.php'; \n            \/\/ O si est\u00e1 en el tema principal: 'http:\/\/tudominio.com\/wp-content\/themes\/tu-tema\/counter.php';\n\n            const MAX_LAST_SCORES = 5;\n            let lastScores = [];\n            \n            let barWidth;\n            let cursorWidth;\n            let targetWidth;\n            let targetLeft;\n            let targetCenter;\n            let maxCursorCenter;\n            let minCursorCenter;\n\n            function getDimensions() {\n                barWidth = bar.offsetWidth;\n                cursorWidth = cursor.offsetWidth;\n                targetWidth = target.offsetWidth;\n                targetLeft = target.offsetLeft;\n                targetCenter = targetLeft + targetWidth \/ 2;\n                minCursorCenter = cursorWidth \/ 2;\n                maxCursorCenter = barWidth - cursorWidth \/ 2;\n            }\n\n            function animateCursor() {\n                if (!gameActive) return;\n\n                cursorPosition += speed * direction;\n\n                \/\/ Detener el juego cuando el cursor llega al final\n                if (cursorPosition + cursorWidth >= barWidth) {\n                    cursorPosition = barWidth - cursorWidth;\n                    stopGame(false); \/\/ Indica que no fue detenido por el bot\u00f3n\n                    return;\n                } else if (cursorPosition < 0) { \/\/ En caso de que se fuera negativo por alguna raz\u00f3n\n                    cursorPosition = 0;\n                }\n\n                cursor.style.left = cursorPosition + 'px';\n                animationId = requestAnimationFrame(animateCursor);\n            }\n\n            function stopGame(byButton = true) {\n                cancelAnimationFrame(animationId);\n                gameActive = false;\n                gameEndedByButton = byButton;\n\n                stopButton.style.display = 'none'; \/\/ Ocultar parar\n                startButton.style.display = 'none'; \/\/ Asegurar que empezar est\u00e9 oculto\n                retryButton.style.display = 'inline-block'; \/\/ Mostrar reintentar\n\n                const finalCursorLeft = cursorPosition;\n                const finalCursorCenter = finalCursorLeft + cursorWidth \/ 2;\n\n                const error = Math.abs(finalCursorCenter - targetCenter);\n                const maxError = Math.max(\n                    Math.abs(targetCenter - minCursorCenter),\n                    Math.abs(targetCenter - maxCursorCenter)\n                );\n\n                let score;\n                if (!byButton) {\n                    \/\/ Si el juego termin\u00f3 autom\u00e1ticamente (lleg\u00f3 al final), la puntuaci\u00f3n es 1\n                    score = 1;\n                } else {\n                    score = 20 - (error \/ maxError) * 19;\n                    score = Math.max(1, Math.min(20, Math.round(score)));\n                }\n\n                \/\/ Incrementa el contador global y env\u00eda la puntuaci\u00f3n\n                incrementGlobalStats(score);\n\n                \/\/ Almacenar la puntuaci\u00f3n en el historial local para mostrarla\n                lastScores.unshift(score);\n                if (lastScores.length > MAX_LAST_SCORES) {\n                    lastScores.pop();\n                }\n                updateLastScoresDisplay();\n\n                \/\/ Mostrar el resultado como un n\u00famero con color din\u00e1mico\n                resultDiv.textContent = `Resultado: ${score}\/20`;\n                resultDiv.className = ''; \/\/ Limpiar clases anteriores\n                if (score >= 15) {\n                    resultDiv.classList.add('score-high');\n                } else if (score >= 10) {\n                    resultDiv.classList.add('score-medium');\n                } else {\n                    resultDiv.classList.add('score-low');\n                }\n            }\n\n            \/\/ Funci\u00f3n para obtener las estad\u00edsticas globales del servidor\n            async function getGlobalStats() {\n                try {\n                    const response = await fetch(GLOBAL_API_URL);\n                    if (!response.ok) {\n                        throw new Error(`HTTP error! status: ${response.status}`);\n                    }\n                    const data = await response.json();\n                    if (data.success) {\n                        counterValueSpan.textContent = data.global_count;\n                        \/\/ Aqu\u00ed 'data.scores_history' contiene el historial, pero no lo mostramos en el frontend del juego\n                        console.log('Historial de puntuaciones:', data.scores_history); \/\/ Puedes verlo en la consola\n                    } else {\n                        console.error('Error al obtener las estad\u00edsticas:', data.message);\n                    }\n                } catch (error) {\n                    console.error('No se pudo obtener las estad\u00edsticas globales:', error);\n                    counterValueSpan.textContent = 'Error'; \/\/ Mostrar error si falla\n                }\n            }\n\n            \/\/ Funci\u00f3n para incrementar el contador global y enviar la puntuaci\u00f3n\n            async function incrementGlobalStats(score) {\n                try {\n                    const response = await fetch(GLOBAL_API_URL, {\n                        method: 'POST',\n                        headers: {\n                            'Content-Type': 'application\/json'\n                        },\n                        body: JSON.stringify({ score: score }) \/\/ Enviar la puntuaci\u00f3n en el cuerpo de la solicitud\n                    });\n                    if (!response.ok) {\n                        throw new Error(`HTTP error! status: ${response.status}`);\n                    }\n                    const data = await response.json();\n                    if (data.success) {\n                        counterValueSpan.textContent = data.global_count; \/\/ Actualizar con el nuevo valor del servidor\n                        console.log('Puntuaci\u00f3n guardada. Total de puntuaciones en el servidor:', data.scores_saved);\n                    } else {\n                        console.error('Error al guardar las estad\u00edsticas:', data.message);\n                    }\n                } catch (error) {\n                    console.error('No se pudieron actualizar las estad\u00edsticas globales:', error);\n                }\n            }\n\n            function updateLastScoresDisplay() {\n                lastScoresList.innerHTML = '';\n                if (lastScores.length === 0) {\n                    lastScoresList.innerHTML = '<li>A\u00fan no hay tiradas.<\/li>';\n                    return;\n                }\n                lastScores.forEach((s, index) => {\n                    const li = document.createElement('li');\n                    li.textContent = `Tirada ${lastScores.length - index}: ${s}\/20`;\n                    \/\/ Ajuste de colores para contraste en la lista\n                    if (s >= 15) {\n                        li.style.backgroundColor = '#d4edda'; li.style.borderColor = '#28a745'; li.style.color = '#155724';\n                    } else if (s >= 10) {\n                        li.style.backgroundColor = '#fff3cd'; li.style.borderColor = '#ffc107'; li.style.color = '#856404';\n                    } else {\n                        li.style.backgroundColor = '#f8d7da'; li.style.borderColor = '#dc3545'; li.style.color = '#721c24';\n                    }\n                    lastScoresList.appendChild(li);\n                });\n            }\n\n            function startCountdownAndGame() {\n                gameActive = false;\n                startButton.style.display = 'none'; \/\/ Oculta el bot\u00f3n de empezar\n                stopButton.style.display = 'none'; \/\/ Oculta el bot\u00f3n de parar durante el countdown\n                retryButton.style.display = 'none'; \/\/ Oculta el bot\u00f3n de reintentar\n                resultDiv.innerHTML = ''; \/\/ Limpiar resultado\n                resultDiv.className = ''; \/\/ Limpiar clases de color\n                cursor.style.display = 'none'; \/\/ Ocultar cursor durante el countdown\n                bar.style.visibility = 'hidden'; \/\/ Ocultar barra durante el countdown\n                gameDescriptionP.style.visibility = 'hidden'; \/\/ Oculta el p\u00e1rrafo de descripci\u00f3n durante el countdown\n\n                countdownDiv.classList.remove('hidden');\n                countdownDiv.textContent = `Preparados...`;\n\n                setTimeout(() => {\n                    countdownDiv.textContent = `Listos...`;\n                }, 1000);\n\n                setTimeout(() => {\n                    countdownDiv.textContent = `\u00a1YA!`;\n                }, 2000);\n\n                setTimeout(() => {\n                    countdownDiv.classList.add('hidden');\n                    cursor.style.display = 'block'; \/\/ Mostrar cursor\n                    bar.style.visibility = 'visible'; \/\/ Mostrar barra\n                    gameDescriptionP.style.visibility = 'visible'; \/\/ Muestra el p\u00e1rrafo de descripci\u00f3n\n                    gameActive = true; \/\/ Activar el juego\n                    animateCursor(); \/\/ Iniciar la animaci\u00f3n\n                    stopButton.style.display = 'inline-block'; \/\/ Habilitar y mostrar el bot\u00f3n de parar\n                }, 3000);\n            }\n\n            function resetGame() {\n                cancelAnimationFrame(animationId);\n                cursorPosition = 0;\n                direction = 1;\n                cursor.style.left = cursorPosition + 'px';\n\n                resultDiv.innerHTML = ''; \/\/ Limpiar resultado\n                resultDiv.className = ''; \/\/ Limpiar clases de color\n\n                startButton.style.display = 'inline-block'; \/\/ Mostrar bot\u00f3n de empezar\n                stopButton.style.display = 'none'; \/\/ Ocultar bot\u00f3n de parar\n                retryButton.style.display = 'none'; \/\/ Ocultar bot\u00f3n de reintentar\n                cursor.style.display = 'none'; \/\/ Ocultar cursor\n                bar.style.visibility = 'hidden'; \/\/ Ocultar barra\n                gameDescriptionP.style.visibility = 'visible'; \/\/ Asegurar que el p\u00e1rrafo est\u00e9 visible\n                countdownDiv.classList.add('hidden'); \/\/ Asegurarse de que el contador est\u00e1 oculto\n\n                gameActive = false; \/\/ El juego no est\u00e1 activo hasta que se pulse \"Empezar\"\n            }\n\n            \/\/ Inicializaci\u00f3n al cargar el DOM\n            document.addEventListener('DOMContentLoaded', () => {\n                getDimensions();\n                updateLastScoresDisplay();\n                resetGame(); \/\/ Configura el estado inicial con el bot\u00f3n \"Empezar\" visible\n                getGlobalStats(); \/\/ Obtener las estad\u00edsticas globales (contador y puntuaciones) al cargar la p\u00e1gina\n            });\n\n            \/\/ Re-calcular dimensiones al redimensionar la ventana\n            window.addEventListener('resize', getDimensions);\n\n            \/\/ Asignar eventos a los botones\n            startButton.addEventListener('click', startCountdownAndGame);\n            stopButton.addEventListener('click', () => stopGame(true));\n            retryButton.addEventListener('click', resetGame);\n        }\n\n        \/\/ --- Llamada para inicializar el juego (juegoHabilidad2) ---\n        inicializarJuegoHabilidadCaballero('juegoHabilidad2');\n    <\/script>\n\n<\/body>\n<\/html>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Aqu\u00ed hay un par de elementos que incrementan la dificultad. Por un lado est\u00e1 el que <strong>s\u00f3lo tienes un intento<\/strong> para detener el cursor, sabiendo que, si no lo detienes antes de que llegue al final, tu resultado habr\u00e1 sido un 1. Pero tambi\u00e9n est\u00e1 la faena de que <strong>el bot\u00f3n de \u00abParar\u00bb no aparezca hasta que no acaba la cuenta atr\u00e1s<\/strong> de \u00abPreparados, listos, ya\u00bb. Si no ten\u00edas el rat\u00f3n justo encima del bot\u00f3n, vas a perder un tiempo precioso movi\u00e9ndolo antes de clickarlo&#8230; demasiado tarde, la mayor\u00eda de las veces.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Con todo esto lo normal es que la primera vez (o la segunda tambi\u00e9n) saques una tirada muy mala. Que le des demasiado r\u00e1pido al bot\u00f3n, o que el cursor se vaya al final antes de que puedas reaccionar y acabes sacando el fat\u00eddico 1. Pero tambi\u00e9n es normal que para la siguiente tirada ya le hayas pillado el truco y lo hagas bastante bien&#8230; y entonces vuelva a pasar como en el primer minijuego: que no bajes de 18 otra vez. Es decir, que <strong>las tiradas son o muy malas<\/strong> (al principio) <strong>o muy buenas.<\/strong> Sin t\u00e9rmino medio. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pensando en esto y en ese m\u00e1ster que tiene que comprobar si la tirada se ha hecho sin trampas, le ped\u00ed a <strong>Gemini<\/strong> que a\u00f1adiera ese <strong>registro de las \u00faltimas 5 tiradas<\/strong> que se ve debajo del resultado. As\u00ed el m\u00e1ster puede verificar si se ha logrado a la primera o a la quinta vez.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Y ya puestos, le ped\u00ed que a\u00f1adiera un par de cosas m\u00e1s. Lo primero, que me guardara <strong>un registro de las \u00faltimas 500 tiradas<\/strong> que se han hecho, para poder ir chequeando peri\u00f3dicamente si el juego es f\u00e1cil o no. Y lo segundo, ese <strong>contador de \u00abveces utilizado\u00bb<\/strong>, un poco por no tener que meterme en el registro para ver si esto lo va a utilizar alguien m\u00e1s aparte de m\u00ed mismo.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Peeeero&#8230; fue entonces cuando se me ocurri\u00f3 que todas las pruebas las estaba haciendo en el ordenador, <strong>pero a\u00fan no lo hab\u00eda probado en el m\u00f3vil<\/strong>. Lo cual no deja de tener su gracia, porque desde el principio me estaba planteando todo esto para llevarlo en el m\u00f3vil, sacarlo en mitad de una partida, hacer la tirada y guardarlo.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pues nada, hora de remediar ese error:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img data-dominant-color=\"2c3635\" data-has-transparency=\"false\" loading=\"lazy\" decoding=\"async\" width=\"862\" height=\"1844\" sizes=\"auto, (max-width: 598px) 100vw, 598px\" src=\"https:\/\/www.erekibeon.com\/blog\/wp-content\/uploads\/TiradasenMovil.webp\" alt=\"\" class=\"wp-image-25266 not-transparent\" style=\"--dominant-color: #2c3635; width:598px;height:auto\" srcset=\"https:\/\/www.erekibeon.com\/blog\/wp-content\/uploads\/TiradasenMovil.webp 862w, https:\/\/www.erekibeon.com\/blog\/wp-content\/uploads\/TiradasenMovil-140x300.webp 140w, https:\/\/www.erekibeon.com\/blog\/wp-content\/uploads\/TiradasenMovil-748x1600.webp 748w, https:\/\/www.erekibeon.com\/blog\/wp-content\/uploads\/TiradasenMovil-70x150.webp 70w, https:\/\/www.erekibeon.com\/blog\/wp-content\/uploads\/TiradasenMovil-768x1643.webp 768w, https:\/\/www.erekibeon.com\/blog\/wp-content\/uploads\/TiradasenMovil-718x1536.webp 718w\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Como veis, los tres primeros intentos fueron un aut\u00e9ntico fracaso. La barra es <strong>considerablemente m\u00e1s corta en el m\u00f3vil que en el ordenador<\/strong>, con lo que tienes a\u00fan menos tiempo para pulsar. Sin embargo, curiosamente, las siguiente dos tiradas fueron muy altas. Lo cual me llama la atenci\u00f3n&#8230; parece ser, <strong>una vez m\u00e1s, <\/strong>que<strong> no hay tiradas intermedias<\/strong>. <strong>O fracasas <\/strong>vilmente<strong> o tienes un \u00e9xito absoluto<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A ver, es una mejora respecto al primer prototipo, donde s\u00f3lo pod\u00edas sacar tiradas buenas&#8230; pero sigue sin ser suficiente. Para que esta prueba sea una alternativa seria a una tirada de dado <strong>tiene que haber tambi\u00e9n resultados intermedios<\/strong>. Tal vez no exactamente igual a la dispersi\u00f3n estad\u00edstica de los dados de 20, pero hombre, un poco m\u00e1s de variedad.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As\u00ed que nada, a seguir prototipando. All\u00e1 vamos con la tercera opci\u00f3n, la de las \u00abcasillas brillantes\u00bb.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Tercer prototipo: Detener la luz<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Lo primero es lo primero. Antes de nada, dadle un tiento:<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<!DOCTYPE html>\n<html lang=\"es\">\n<head>\n    <meta charset=\"UTF-8\"\/>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\/>\n    <title>Juego Habilidad para tirada d20<\/title>\n    <style>\n        \/* Contenedor principal del juego *\/\n        #juegoDadoHabilidad {\n            width: 100%;\n            max-width: 800px;\n            margin: 0 auto;\n            background-color: transparent;\n            padding: 25px;\n            border-radius: 8px;\n            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);\n            text-align: center;\n            margin-bottom: 40px;\n            border: 1px solid rgba(0,0,0,0.1);\n            box-sizing: border-box;\n            overflow: hidden;\n            position: relative;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n        }\n\n        #juegoDadoHabilidad h2 {\n            color: #2c3e50;\n            margin-top: 0;\n            font-size: 2em;\n            margin-bottom: 15px;\n            text-shadow: 1px 1px 2px rgba(0,0,0,0.1);\n        }\n\n        #juegoDadoHabilidad p {\n            margin-bottom: 20px; \/* Consistencia en m\u00e1rgenes *\/\n            font-size: 0.9em;\n            color: #555;\n            line-height: 1.4; \/* Mejora legibilidad *\/\n        }\n\n        \/* Estilo del temporizador de tirada *\/\n        #turn-timer {\n            font-size: 1.4em;\n            font-weight: bold;\n            color: #e74c3c; \/* Rojo *\/\n            margin-bottom: 20px; \/* Espacio debajo del temporizador *\/\n            min-height: 20px; \/* Para mantener espacio incluso si est\u00e1 vac\u00edo *\/\n        }\n\n        \/* Contenedor de hex\u00e1gonos *\/\n        #hexagon-container {\n            display: flex;\n            flex-wrap: wrap;\n            justify-content: center;\n            gap: 10px;\n            width: 100%;\n            padding: 10px;\n            box-sizing: border-box;\n            margin-bottom: 20px; \/* Consistencia en m\u00e1rgenes *\/\n        }\n\n        \/* Estilo de los hex\u00e1gonos *\/\n        .hexagon {\n            position: relative;\n            width: 50px; \/* Ancho del hex\u00e1gono *\/\n            height: 28px; \/* Altura de la parte central *\/\n            background-color: #34495e;\n            margin: 15px 5px; \/* Margen vertical y horizontal para separaci\u00f3n *\/\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            font-size: 1.2em; \/* Tama\u00f1o de fuente de los n\u00fameros *\/\n            font-weight: bold;\n            color: white;\n            transition: background-color 0.2s ease, transform 0.1s ease;\n            cursor: default;\n            box-shadow: 0 2px 5px rgba(0,0,0,0.2);\n        }\n\n        .hexagon::before,\n        .hexagon::after {\n            content: \"\";\n            position: absolute;\n            width: 0;\n            height: 0;\n            border-left: 25px solid transparent; \/* Mitad del ancho *\/\n            border-right: 25px solid transparent; \/* Mitad del ancho *\/\n        }\n\n        .hexagon::before {\n            bottom: 100%;\n            border-bottom: 14px solid #34495e; \/* Altura de las puntas *\/\n        }\n\n        .hexagon::after {\n            top: 100%;\n            border-top: 14px solid #34495e; \/* Altura de las puntas *\/\n        }\n\n        \/* Hex\u00e1gono iluminado (activo) *\/\n        .hexagon.active {\n            background-color: #2ecc71; \/* Verde brillante *\/\n            transform: scale(1.05);\n            box-shadow: 0 0 15px rgba(46, 204, 113, 0.8);\n        }\n\n        .hexagon.active::before {\n            border-bottom-color: #2ecc71;\n        }\n\n        .hexagon.active::after {\n            border-top-color: #2ecc71;\n        }\n\n        \/* Estilos de botones *\/\n        .button-group {\n            display: flex;\n            justify-content: center;\n            gap: 15px;\n            margin-top: 0;\n            min-height: 50px;\n            width: 100%;\n        }\n\n        .game-button {\n            padding: 12px 25px;\n            font-size: 1.1em;\n            cursor: pointer;\n            color: white;\n            border: none;\n            border-radius: 6px;\n            transition: background-color 0.3s ease, transform 0.05s ease; \/* M\u00e1s r\u00e1pido para feedback t\u00e1ctil *\/\n            box-shadow: 0 2px 5px rgba(0,0,0,0.2);\n        }\n\n        .game-button:active {\n            transform: translateY(1px) scale(0.98); \/* Ligero hundimiento y escala *\/\n            box-shadow: 0 1px 3px rgba(0,0,0,0.2);\n        }\n\n        #startButton {\n            background-color: #1a73e8;\n        }\n        #startButton:hover {\n            background-color: #155bbd;\n        }\n\n        #stopButton {\n            background-color: #e74c3c; \/* Rojo para parar *\/\n        }\n        #stopButton:hover {\n            background-color: #c0392b;\n        }\n\n        #stopButton:disabled {\n            background-color: #cccccc;\n            cursor: not-allowed;\n            box-shadow: none;\n        }\n\n        #retryButton {\n            background-color: #3498db; \/* Azul para reintentar *\/\n            display: none;\n        }\n        #retryButton:hover {\n            background-color: #2980b9;\n        }\n\n        \/* Resultado de la tirada *\/\n        #result {\n            margin-top: 20px; \/* Consistencia en m\u00e1rgenes *\/\n            font-size: 1.5em; \/* Tama\u00f1o de fuente del resultado *\/\n            font-weight: bold;\n            min-height: 70px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            text-shadow: 0 0 8px rgba(0,0,0,0.3);\n            transition: color 0.3s ease, text-shadow 0.3s ease;\n        }\n\n        \/* Colores din\u00e1micos para el resultado *\/\n        #result.score-high {\n            color: #27ae60; \/* Verde *\/\n            text-shadow: 0 0 10px rgba(39, 174, 96, 0.8);\n        }\n        #result.score-medium {\n            color: #f39c12; \/* Naranja\/Amarillo *\/\n            text-shadow: 0 0 10px rgba(243, 156, 18, 0.8);\n        }\n        #result.score-low {\n            color: #e74c3c; \/* Rojo *\/\n            text-shadow: 0 0 10px rgba(231, 76, 60, 0.8);\n        }\n\n        \/* \u00daltimas tiradas *\/\n        #last-scores-container {\n            margin-top: 30px;\n            border-top: 1px solid #eee;\n            padding-top: 20px;\n            font-size: 0.95em;\n            color: #555;\n            width: 100%;\n        }\n        #last-scores-list {\n            list-style: none;\n            padding: 0;\n            margin: 10px 0 0 0;\n            display: flex;\n            flex-wrap: wrap;\n            justify-content: center;\n            gap: 10px;\n        }\n        #last-scores-list li {\n            padding: 5px 10px;\n            border-radius: 4px;\n            font-weight: bold;\n            transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;\n        }\n\n        \/* Colores para las tiradas en la lista *\/\n        #last-scores-list li.score-high {\n            background-color: #d4edda; border: 1px solid #28a745; color: #155724; \/* Verde suave *\/\n        }\n        #last-scores-list li.score-medium {\n            background-color: #fff3cd; border: 1px solid #ffc107; color: #856404; \/* Amarillo suave *\/\n        }\n        #last-scores-list li.score-low {\n            background-color: #f8d7da; border: 1px solid #dc3545; color: #721c24; \/* Rojo suave *\/\n        }\n\n        \/* Contador de usos global *\/\n        #usage-counter {\n            margin-top: 20px;\n            font-size: 1em;\n            color: #777;\n        }\n    <\/style>\n<\/head>\n<body>\n\n    <div id=\"juegoDadoHabilidad\">\n        <p>Intenta detener la secuencia en el n\u00famero que elijas (que normalmente ser\u00e1 el 20, pero nunca se sabe). La secuencia cambia en cada partida. <b>Cuidado<\/b>, <b>s\u00f3lo tienes 5 segundos<\/b> para apretar el bot\u00f3n. <b>Si se acaba el tiempo, sacar\u00e1s un 1<\/b>. \u00a1Buena suerte! O m\u00e1s bien \u00a1buena habilidad!<\/p>\n        <h2>Tira 1d20<\/h2>\n        <div id=\"hexagon-container\">\n            <\/div>\n        <div id=\"turn-timer\" aria-live=\"polite\">Tiempo: <span>Cargando&#8230;<\/span><\/div>\n        <div class=\"button-group\">\n            <button id=\"startButton\" class=\"game-button\">\u00a1Comenzar!<\/button>\n            <button id=\"stopButton\" class=\"game-button\">\u00a1Parar!<\/button>\n            <button id=\"retryButton\" class=\"game-button\">Jugar de nuevo<\/button>\n        <\/div>\n\n        <div id=\"result\" aria-live=\"polite\"><\/div>\n        <div id=\"last-scores-container\">\n            <h3>\u00daltimas 5 tiradas:<\/h3>\n            <ul id=\"last-scores-list\">\n            <\/ul>\n        <\/div>\n        <div id=\"usage-counter\">Utilizaciones globales: <span id=\"counter-value\">Cargando&#8230;<\/span><\/div>\n    <\/div>\n\n    <script>\n        function inicializarJuegoDadoHabilidad(containerId) {\n            const gameContainer = document.getElementById(containerId);\n            if (!gameContainer) {\n                console.error(`Contenedor de juego no encontrado: ${containerId}`);\n                return;\n            }\n\n            \/\/ Referencias a los elementos del DOM\n            const hexagonContainer = gameContainer.querySelector('#hexagon-container');\n            const startButton = gameContainer.querySelector('#startButton');\n            const stopButton = gameContainer.querySelector('#stopButton');\n            const retryButton = gameContainer.querySelector('#retryButton');\n            const resultDiv = gameContainer.querySelector('#result');\n            const lastScoresList = gameContainer.querySelector('#last-scores-list');\n            const counterValueSpan = gameContainer.querySelector('#counter-value');\n            const turnTimerDiv = gameContainer.querySelector('#turn-timer');\n            const turnTimerSpan = turnTimerDiv.querySelector('span');\n\n\n            let gameInterval; \/\/ Para el intervalo de la animaci\u00f3n de hex\u00e1gonos\n            let turnTimerInterval; \/\/ Para el temporizador de la tirada\n            let currentHexIndex = 0;\n            let gameActive = false;\n            let timeLeft = 5; \/\/ Tiempo inicial del temporizador de tirada\n            const GAME_DURATION_SECONDS = 5; \/\/ Duraci\u00f3n fija de la cuenta atr\u00e1s\n            const numbers = Array.from({ length: 20 }, (_, i) => i + 1); \/\/ [1, 2, ..., 20]\n            let shuffledSequence = []; \/\/ La secuencia aleatoria para la partida actual\n\n            const MAX_LAST_SCORES = 5;\n            let lastScores = [];\n\n            \/\/ La URL del script PHP.\n            const GLOBAL_API_URL = 'https:\/\/www.erekibeon.com\/blog\/contadores\/counternumero.php';\n\n            \/\/ Detectar si es un dispositivo m\u00f3vil (para la vibraci\u00f3n)\n            const isMobileDevice = \/Mobi|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini\/i.test(navigator.userAgent);\n\n            \/\/ Funci\u00f3n para generar la secuencia aleatoria (Fisher-Yates shuffle)\n            function generateShuffledSequence() {\n                const arr = [...numbers]; \/\/ Copia el array original\n                for (let i = arr.length - 1; i > 0; i--) {\n                    const j = Math.floor(Math.random() * (i + 1));\n                    [arr[i], arr[j]] = [arr[j], arr[i]]; \/\/ Intercambio\n                }\n                shuffledSequence = arr;\n                console.log(\"Nueva secuencia para la partida:\", shuffledSequence);\n            }\n\n            \/\/ Funci\u00f3n para crear los hex\u00e1gonos en el DOM\n            function createHexagons() {\n                hexagonContainer.innerHTML = ''; \/\/ Limpiar anteriores\n                numbers.forEach(num => {\n                    const hexagon = document.createElement('div');\n                    hexagon.classList.add('hexagon');\n                    hexagon.textContent = num;\n                    hexagon.dataset.number = num; \/\/ Para f\u00e1cil acceso al n\u00famero\n                    hexagonContainer.appendChild(hexagon);\n                });\n            }\n\n            \/\/ Funci\u00f3n para iluminar el siguiente hex\u00e1gono\n            function highlightNextHexagon(numberToHighlight = null) {\n                const hexagons = Array.from(hexagonContainer.children);\n\n                \/\/ Quitar 'active' de todos los hex\u00e1gonos\n                if (hexagons.length > 0) {\n                    hexagons.forEach(hex => hex.classList.remove('active'));\n                }\n\n                let numToActivate;\n                if (numberToHighlight !== null) {\n                    numToActivate = numberToHighlight; \/\/ Si se proporciona un n\u00famero, \u00fasalo\n                } else {\n                    numToActivate = shuffledSequence[currentHexIndex]; \/\/ Si no, sigue la secuencia\n                    currentHexIndex = (currentHexIndex + 1) % shuffledSequence.length; \/\/ Ciclar la secuencia solo si no es un n\u00famero forzado\n                }\n\n                \/\/ Encontrar y activar el hex\u00e1gono con ese n\u00famero\n                const targetHexagon = hexagons.find(hex => parseInt(hex.dataset.number) === numToActivate);\n                if (targetHexagon) {\n                    targetHexagon.classList.add('active');\n                }\n\n                \/\/ Reinicia el intervalo con un nuevo tiempo aleatorio si el juego sigue activo\n                \/\/ y no estamos forzando un n\u00famero (lo que indicar\u00eda que el juego est\u00e1 a punto de parar)\n                if (gameActive && numberToHighlight === null) {\n                    clearInterval(gameInterval); \/\/ Detiene el intervalo actual\n                    const randomDelay = generateRandomDelay(); \/\/ Genera un nuevo retardo\n                    gameInterval = setInterval(highlightNextHexagon, randomDelay); \/\/ Inicia un nuevo intervalo\n                }\n            }\n\n            \/\/ Genera un retardo aleatorio entre 50ms y 150ms en tramos de 10ms\n            function generateRandomDelay() {\n                const minDelayValue = 50; \/\/ 0.05 segundos\n                const maxDelayValue = 150; \/\/ 0.15 segundos\n                const step = 10; \/\/ Tramos de 10 milisegundos\n\n                const numSteps = (maxDelayValue - minDelayValue) \/ step;\n                const randomSteps = Math.floor(Math.random() * (numSteps + 1));\n                return minDelayValue + (randomSteps * step);\n            }\n\n            function startGameAnimation() {\n                if (gameActive) {\n                    const initialDelay = generateRandomDelay();\n                    gameInterval = setInterval(highlightNextHexagon, initialDelay);\n                }\n            }\n\n         \/\/ Funci\u00f3n para iniciar el temporizador de la tirada\n            function startTurnTimer() {\n                timeLeft = GAME_DURATION_SECONDS;\n                turnTimerSpan.textContent = timeLeft;\n                turnTimerInterval = setInterval(() => {\n                    timeLeft--;\n                    turnTimerSpan.textContent = timeLeft;\n                    if (timeLeft <= 0) {\n                        clearInterval(turnTimerInterval);\n                        if (gameActive) { \/\/ Si el juego a\u00fan est\u00e1 activo (no se ha pulsado parar)\n                            \/\/ Detener la animaci\u00f3n de hex\u00e1gonos inmediatamente\n                            clearInterval(gameInterval); \n\n                            \/\/ Asegurarse de que el '1' se ilumine\n                            highlightNextHexagon(1); \n                            \n                            \/\/ Un peque\u00f1o retardo para que la iluminaci\u00f3n del '1' sea visible antes de detener todo\n                            setTimeout(() => stopGame(1), 50); \n                        }\n                    }\n                }, 1000); \/\/ Cada segundo\n            }\n\n            \/\/ Funci\u00f3n auxiliar para obtener la clase de color seg\u00fan la puntuaci\u00f3n\n            function getScoreColorClass(score) {\n                if (score >= 15) {\n                    return 'score-high'; \/\/ Verde (bueno)\n                } else if (score >= 8) {\n                    return 'score-medium'; \/\/ Amarillo (medio)\n                } else {\n                    return 'score-low'; \/\/ Rojo (malo)\n                }\n            }\n\n            \/\/ stopGame ahora acepta un par\u00e1metro 'forcedScore'\n            function stopGame(forcedScore = null) {\n                clearInterval(gameInterval);\n                clearInterval(turnTimerInterval); \/\/ Detener el temporizador de la tirada\n                gameActive = false;\n\n                stopButton.style.display = 'none';\n                startButton.style.display = 'none';\n                retryButton.style.display = 'inline-block';\n\n                let finalResult;\n                if (forcedScore !== null) {\n                    finalResult = forcedScore; \/\/ Usar la puntuaci\u00f3n forzada (1 en este caso)\n                } else {\n                    const activeHexagon = gameContainer.querySelector('.hexagon.active');\n                    finalResult = activeHexagon ? parseInt(activeHexagon.dataset.number) : null;\n                }\n\n                resultDiv.textContent = `Has sacado un ${finalResult || '?'}`;\n\n                \/\/ Aplicar clase de color al resultado principal\n                resultDiv.className = ''; \/\/ Limpiar clases anteriores\n                if (finalResult !== null) {\n                    resultDiv.classList.add(getScoreColorClass(finalResult));\n                }\n\n                \/\/ Vibrar si es m\u00f3vil y la API est\u00e1 disponible\n                if (isMobileDevice && \"vibrate\" in navigator) {\n                    navigator.vibrate(50); \/\/ Peque\u00f1a vibraci\u00f3n al detener el juego\n                }\n\n                \/\/ Incrementar contador global y guardar puntuaci\u00f3n\n                if (finalResult !== null) {\n                    incrementGlobalStats(finalResult);\n                }\n\n                \/\/ Almacenar la puntuaci\u00f3n en el historial local\n                if (finalResult !== null) {\n                    lastScores.unshift(finalResult);\n                    if (lastScores.length > MAX_LAST_SCORES) {\n                        lastScores.pop();\n                    }\n                    updateLastScoresDisplay();\n                }\n            }\n\n            \/\/ Funci\u00f3n para obtener las estad\u00edsticas globales del servidor\n            async function getGlobalStats() {\n                counterValueSpan.textContent = 'Cargando...'; \/\/ Feedback de carga\n                try {\n                    const response = await fetch(GLOBAL_API_URL);\n                    if (!response.ok) {\n                        throw new Error(`HTTP error! status: ${response.status}`);\n                    }\n                    const data = await response.json();\n                    if (data.success) {\n                        counterValueSpan.textContent = data.global_count;\n                    } else {\n                        console.error('Error al obtener las estad\u00edsticas:', data.message);\n                        counterValueSpan.textContent = 'Error';\n                    }\n                } catch (error) {\n                    console.error('No se pudo obtener las estad\u00edsticas globales:', error);\n                    counterValueSpan.textContent = 'Error';\n                }\n            }\n\n            \/\/ Funci\u00f3n para incrementar el contador global y enviar la puntuaci\u00f3n\n            async function incrementGlobalStats(score) {\n                try {\n                    const response = await fetch(GLOBAL_API_URL, {\n                        method: 'POST',\n                        headers: {\n                            'Content-Type': 'application\/json'\n                        },\n                        body: JSON.stringify({ score: score }) \/\/ Enviar la puntuaci\u00f3n en el cuerpo de la solicitud\n                    });\n                    if (!response.ok) {\n                        throw new Error(`HTTP error! status: ${response.status}`);\n                    }\n                    const data = await response.json();\n                    if (data.success) {\n                        counterValueSpan.textContent = data.global_count; \/\/ Actualizar con el nuevo valor del servidor\n                    } else {\n                        console.error('Error al guardar las estad\u00edsticas:', data.message);\n                    }\n                } catch (error) {\n                    console.error('No se pudieron actualizar las estad\u00edsticas globales:', error);\n                }\n            }\n\n            function updateLastScoresDisplay() {\n                lastScoresList.innerHTML = '';\n                if (lastScores.length === 0) {\n                    lastScoresList.innerHTML = '<li>A\u00fan no hay tiradas.<\/li>';\n                    return;\n                }\n                lastScores.forEach((s, index) => {\n                    const li = document.createElement('li');\n                    li.textContent = `Tirada ${lastScores.length - index}: ${s}`;\n                    li.classList.add(getScoreColorClass(s)); \/\/ Aplicar clase de color aqu\u00ed\n                    lastScoresList.appendChild(li);\n                });\n            }\n\n            \/\/ Funci\u00f3n para iniciar el juego\n            function startGame() {\n                gameActive = true;\n                startButton.style.display = 'none';\n                stopButton.style.display = 'inline-block'; \/\/ Mostrar bot\u00f3n de parar\n                retryButton.style.display = 'none';\n                resultDiv.innerHTML = '';\n                resultDiv.className = ''; \/\/ Limpiar clases de color\n\n                \/\/ Quitar 'active' de todos los hex\u00e1gonos\n                Array.from(hexagonContainer.children).forEach(hex => hex.classList.remove('active'));\n\n                currentHexIndex = 0; \/\/ Reiniciar el \u00edndice para empezar la secuencia\n                startGameAnimation(); \/\/ Iniciar la animaci\u00f3n de hex\u00e1gonos\n                startTurnTimer(); \/\/ Iniciar el temporizador de la tirada\n            }\n\n            function resetGame() {\n                clearInterval(gameInterval); \/\/ Detener cualquier animaci\u00f3n de hex\u00e1gonos en curso\n                clearInterval(turnTimerInterval); \/\/ Detener el temporizador de la tirada\n                gameActive = false;\n\n                \/\/ Generar una nueva secuencia aleatoria para la pr\u00f3xima partida\n                generateShuffledSequence();\n\n                \/\/ Restablecer el estado visual\n                Array.from(hexagonContainer.children).forEach(hex => hex.classList.remove('active'));\n                resultDiv.innerHTML = '';\n                resultDiv.className = ''; \/\/ Limpiar clases de color\n                turnTimerSpan.textContent = GAME_DURATION_SECONDS; \/\/ Resetear el texto del temporizador\n\n                startButton.style.display = 'inline-block';\n                stopButton.style.display = 'none';\n                retryButton.style.display = 'none';\n            }\n\n            \/\/ Inicializaci\u00f3n al cargar el DOM\n            document.addEventListener('DOMContentLoaded', () => {\n                createHexagons(); \/\/ Crear los elementos de los hex\u00e1gonos\n                getGlobalStats(); \/\/ Obtener y mostrar el contador global\n                updateLastScoresDisplay(); \/\/ Inicializar la lista de \u00faltimas tiradas\n                resetGame(); \/\/ Configura el estado inicial y genera la primera secuencia\n            });\n\n            \/\/ Asignar eventos a los botones\n            startButton.addEventListener('click', startGame);\n            stopButton.addEventListener('click', () => stopGame(null)); \/\/ stopGame se llama sin score forzado\n            retryButton.addEventListener('click', resetGame);\n        }\n\n        \/\/ --- Llamada para inicializar el juego ---\n        inicializarJuegoDadoHabilidad('juegoDadoHabilidad');\n    <\/script>\n\n<\/body>\n<\/html>\n\n\n\n<p class=\"wp-block-paragraph\">No s\u00e9 a vosotros, pero esta versi\u00f3n <strong>me convence mucho m\u00e1s<\/strong> que las anteriores.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Tambi\u00e9n es verdad que le he dedicado m\u00e1s tiempo que a los otros. Desde la primera versi\u00f3n a \u00e9sta que acab\u00e1is de probar he pedido un mont\u00f3n de cambios, entre los cuales est\u00e1n:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Estilos generales<\/strong>: cambiar las formas geom\u00e9tricas del fondo de los n\u00fameros, tama\u00f1os de letra, separaci\u00f3n entre figuras, ubicaci\u00f3n de las frases, del t\u00edtulo, del contador de tiempo&#8230; todo pensando en la experiencia en el m\u00f3vil.<\/li>\n\n\n\n<li><strong>Eliminaci\u00f3n del \u00abpreparados, listos, ya\u00bb<\/strong> del juego anterior.<\/li>\n\n\n\n<li><strong>Cambio en la velocidad de paso <\/strong>de la secuencia (en milisegundos): era muy sencillo contar mentalmente dos segundos desde que se iluminaba el 20, y lo clavabas. Ahora ya no.<\/li>\n\n\n\n<li>Adici\u00f3n de un <strong>contador de tiempo<\/strong>: con un l\u00edmite de 5 segundos y la amenaza de sacar un 1 si se acaba, tienes que pulsar s\u00ed o s\u00ed. Una presi\u00f3n extra que en los \u00faltimos segundos puede llevar a pulsar desesperadamente para evitar el 1.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Las pruebas que le hecho han devuelto unos <strong>resultados much\u00edsimo m\u00e1s variados<\/strong>, d\u00f3nde va a parar. Curiosamente me resulta m\u00e1s sencillo sacar tiradas por encima de 10 si lo juego en el ordenador que desde el m\u00f3vil&#8230; y eso que en ambos casos intento \u00abapuntar\u00bb a casillas que est\u00e9n en la mitad inferior, donde est\u00e1n los n\u00fameros altos. Pero en el m\u00f3vil, con esa misma t\u00e1ctica, siempre hay tiradas que acaban entre los n\u00fameros m\u00e1s bajos.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A ver, no es una versi\u00f3n definitiva porque <strong>siempre va a haber peque\u00f1as mejoras que hacerle<\/strong>, tal vez en la distribuci\u00f3n de los n\u00fameros o ajustando la velocidad, etc etc. Sin embargo, <strong>me parece un prototipo tan s\u00f3lido<\/strong> que lo voy a introducir en mis partidillas de andar por casa. Entre ese rodaje y el an\u00e1lisis de las 500 \u00faltimas tiradas (s\u00ed, tambi\u00e9n he implementado ese registro para este juego) seguir\u00e9 puli\u00e9ndolo poco a poco.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pero claro, no voy a estar viniendo a esta entrada y haciendo scroll hasta abajo para encontrarlo, as\u00ed que <a href=\"https:\/\/www.erekibeon.com\/blog\/tira-1d20-con-tu-habilidad\" data-type=\"link\" data-id=\"https:\/\/www.erekibeon.com\/blog\/tira-1d20-con-tu-habilidad\">le he creado una p\u00e1gina propia<\/a> para tenerla siempre abierta entre mis 77 pesta\u00f1as del Firefox del m\u00f3vil \ud83d\ude1b . Tambi\u00e9n lo he puesto en la portada del blog, con este bot\u00f3n:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/www.erekibeon.com\/blog\/tira-1d20-con-tu-habilidad\"><img data-dominant-color=\"3f5b86\" data-has-transparency=\"true\" style=\"--dominant-color: #3f5b86;\" loading=\"lazy\" decoding=\"async\" width=\"463\" height=\"430\" sizes=\"auto, (max-width: 463px) 100vw, 463px\" src=\"https:\/\/www.erekibeon.com\/blog\/wp-content\/uploads\/botontiradados.webp\" alt=\"\" class=\"wp-image-25363 has-transparency\" srcset=\"https:\/\/www.erekibeon.com\/blog\/wp-content\/uploads\/botontiradados.webp 463w, https:\/\/www.erekibeon.com\/blog\/wp-content\/uploads\/botontiradados-300x279.webp 300w, https:\/\/www.erekibeon.com\/blog\/wp-content\/uploads\/botontiradados-150x139.webp 150w\" \/><\/a><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">As\u00ed me resultar\u00e1 m\u00e1s sencillo localizarlo para cuando quiera utilizarlo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Concluyendo<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Dudo mucho que acabe dejando de utilizar dados <\/strong>en mis partidas de rol. Faltar\u00eda m\u00e1s, con la cantidad que tengo, de todos los tama\u00f1os, formas, colores y materiales&#8230; y con lo que me encanta tirarlos en la mesa, en las torres de dados o en las bandejas de felpa. O hacerlos bailar. <a href=\"https:\/\/www.erekibeon.com\/blog\/diversion-con-dados\/\" data-type=\"link\" data-id=\"https:\/\/www.erekibeon.com\/blog\/diversion-con-dados\/\">O apilarlos en torres inveros\u00edmiles<\/a>. Qu\u00e9 le voy a hacer, sigo siendo un fetichista, y sigo pensando que <strong>no hay nada m\u00e1s ic\u00f3nico de los juegos de rol<\/strong> (incluso para los <em>muggles<\/em>) que nuestros querid\u00edsimos dados de formas \u00abraras\u00bb.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dicho lo cual, me sigue pareciendo interesante esto de tener una cierta <strong>ilusi\u00f3n de control<\/strong> sobre lo bien o lo mal que lo hace mi personaje en los momentos de tensi\u00f3n, de incertidumbre. Me gusta tener la opci\u00f3n de que su destino no s\u00f3lo dependa de mis decisiones, sino tambi\u00e9n de mi habilidad. Y si sale la cosa sale mal, al menos no sentir esa impotencia de haberlo dejado en manos de una fortuna sobre la que no he tenido ninguna manera de influir. M\u00e1s all\u00e1 de haber aplicado modificadores, me refiero. No, la culpa habr\u00e1 sido enteramente m\u00eda&#8230; o de mis reflejos. Que ir\u00e1n decayendo con la edad, ahora que lo pienso. \ud83e\udd14<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pero bueno, ya cruzaremos ese r\u00edo cuando lleguemos a \u00e9l. Mientras tanto, se me siguen ocurriendo ideas para ampliar este juguetito. M\u00e1s variedad de dados, que hay vida m\u00e1s all\u00e1 del d20. Poder enviar la tirada a un servidor, a un email o incluso a una plataforma de rol online. O incluso convertir esta mec\u00e1nica de \u00abminijuegos de habilidad\u00bb en el sistema central de alg\u00fan juego de rol&#8230;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En fin, multitud de cosas que no podr\u00eda haberme ni planteado sin haber tenido una IA&#8230; o todo el tiempo del mundo para aprender c\u00f3mo hacerlas. As\u00ed que ya sab\u00e9is, \u00a1daos prisa en comercializar esa pastilla de rejuvenecimiento!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u00bfNunca os han dado rabia las rachas de mala suerte durante las partidas? Ya sab\u00e9is, ese encadenamiento de malas tiradas que hacen que tu personaje pase de ser alguien competente (m\u00e1s o menos) a convertirse de repente en un metepatas al que no le sale nada bien. A ver, que soy el primero en carcajearse [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":25338,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[15],"tags":[1017,45,1015,1016,916,530],"class_list":["post-25042","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-rol","tag-d20","tag-dados","tag-gemini","tag-habilidad","tag-ia","tag-rol"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/www.erekibeon.com\/blog\/wp-content\/uploads\/juegohabilidadtirada2.webp","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":5325,"url":"https:\/\/www.erekibeon.com\/blog\/hercules-and-xena-roleplaying-game-el-contenido\/","url_meta":{"origin":25042,"position":0},"title":"Hercules and Xena Roleplaying Game: \u00a1el contenido!","author":"Erek\u00edbeon","date":"12\/06\/2013","format":false,"excerpt":"Vale, el otro d\u00eda vimos la caja, pero \u00bfqu\u00e9 hay del contenido? \u00bfMereci\u00f3 la pena el desembolso? Pues venga, vamos a echarle un vistazo a fondo a lo que se oculta entre las tapas de todos esos librillos. Hero's Guide O el \"Manual del Jugador\" de toda la vida. La\u2026","rel":"","context":"En \u00abrol\u00bb","block_context":{"text":"rol","link":"https:\/\/www.erekibeon.com\/blog\/category\/rol\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/dadoshampx_zps3e1c6223.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/dadoshampx_zps3e1c6223.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/dadoshampx_zps3e1c6223.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/dadoshampx_zps3e1c6223.jpg?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":6118,"url":"https:\/\/www.erekibeon.com\/blog\/5-anos-sin-dave-arneson\/","url_meta":{"origin":25042,"position":1},"title":"5 a\u00f1os sin Dave Arneson","author":"Erek\u00edbeon","date":"08\/04\/2014","format":false,"excerpt":"Ayer fue el d\u00eda en que nos dej\u00f3 el otro co-creador de D&D, el \u00ednclito\u00a0Dave Arneson.\u00a0Como bien me record\u00f3 Jon Nieve en Google Plus, todos los a\u00f1os hago algo en honor de Gary Gygax, pero nunca he hecho nada para recordar al otro pap\u00e1 de nuestra afici\u00f3n. Y sabiendo lo\u2026","rel":"","context":"En \u00abEventos\u00bb","block_context":{"text":"Eventos","link":"https:\/\/www.erekibeon.com\/blog\/category\/eventos\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/Jarduntildeo_zps220f1f54.gif?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/Jarduntildeo_zps220f1f54.gif?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/Jarduntildeo_zps220f1f54.gif?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/Jarduntildeo_zps220f1f54.gif?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":187,"url":"https:\/\/www.erekibeon.com\/blog\/todo-al-azar\/","url_meta":{"origin":25042,"position":2},"title":"Todo al azar","author":"Erek\u00edbeon","date":"28\/10\/2008","format":false,"excerpt":"Desde hace alg\u00fan tiempo, muchos roleros en los EEUU est\u00e1n volviendo la vista atr\u00e1s y recuperando los juegos de la Vieja Escuela, o incluso creando \"clones\" de los mismos, como Labyrinth Lord, OSRIC, Castles & Crusades, etc. Este movimiento se ha acentuado \u00faltimamente con la publicaci\u00f3n de la 4\u00aa edici\u00f3n\u2026","rel":"","context":"En \u00abrol\u00bb","block_context":{"text":"rol","link":"https:\/\/www.erekibeon.com\/blog\/category\/rol\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/farm3.static.flickr.com\/2378\/2311696682_f51f751edf.jpg?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":25047,"url":"https:\/\/www.erekibeon.com\/blog\/un-resumen-de-zagales-en-audio\/","url_meta":{"origin":25042,"position":3},"title":"Un resumen de \u00a1Zagales!&#8230; \u00a1en audio!","author":"Erek\u00edbeon","date":"08\/06\/2025","format":false,"excerpt":"De vez en cuando me mola ir dejando constancia en el blog del estado de la tecnolog\u00eda en cada momento. Tiene su punto echar un vistazo atr\u00e1s y comprobar c\u00f3mo han envejecido seg\u00fan qu\u00e9 temas que fueron punteros en su momento, como aquella carcasa con bater\u00eda para el \u00a1Galaxy S2!\u2026","rel":"","context":"En \u00abInternet\u00bb","block_context":{"text":"Internet","link":"https:\/\/www.erekibeon.com\/blog\/category\/cosas-de-internet\/"},"img":{"alt_text":"Dos robots de juguete, uno rosa y otro azul, hablando a un micr\u00f3fono de estilo antiguo. De fondo tienen un marco donde se ve la portada de la aventura \"Zagales\" y una de sus p\u00e1ginas","src":"https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/AudioZagales.webp?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/AudioZagales.webp?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/AudioZagales.webp?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/AudioZagales.webp?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/AudioZagales.webp?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/AudioZagales.webp?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":2628,"url":"https:\/\/www.erekibeon.com\/blog\/explicando-el-rol-con-una-demo-2\/","url_meta":{"origin":25042,"position":4},"title":"Explicando el rol con una demo","author":"Erek\u00edbeon","date":"20\/06\/2011","format":false,"excerpt":"Hace ya casi dos a\u00f1os que, a ra\u00edz de esta entrada de Carlos de la Cruz sobre su intervenci\u00f3n en un programa de Radio Enlace, empec\u00e9 a darle vueltas a c\u00f3mo explicar lo que es el rol de una forma m\u00e1s r\u00e1pida y vistosa. De hecho, gran parte de la\u2026","rel":"","context":"En \u00abrol\u00bb","block_context":{"text":"rol","link":"https:\/\/www.erekibeon.com\/blog\/category\/rol\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/2011\/06\/scarlettmary.gif?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":2265,"url":"https:\/\/www.erekibeon.com\/blog\/la-presentacion-de-cliffhanger-en-madrid\/","url_meta":{"origin":25042,"position":5},"title":"La presentaci\u00f3n de Cliffhanger en Madrid","author":"Erek\u00edbeon","date":"01\/02\/2011","format":false,"excerpt":"Qu\u00e9 peligro tiene eso de acostumbrarse a lo bueno. Despu\u00e9s de dos meses seguidos con una gran presentaci\u00f3n rolera a a la que acudir, se me hace muy cuesta arriba no saber cu\u00e1ndo va a ser la siguiente fecha, si es que va a haberla. Y es que uno sale\u2026","rel":"","context":"En \u00abNoticias\u00bb","block_context":{"text":"Noticias","link":"https:\/\/www.erekibeon.com\/blog\/category\/noticias\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/DSCF6869.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/DSCF6869.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/DSCF6869.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.erekibeon.com\/blog\/wp-content\/uploads\/DSCF6869.jpg?resize=700%2C400&ssl=1 2x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.erekibeon.com\/blog\/wp-json\/wp\/v2\/posts\/25042","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.erekibeon.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.erekibeon.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.erekibeon.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.erekibeon.com\/blog\/wp-json\/wp\/v2\/comments?post=25042"}],"version-history":[{"count":4,"href":"https:\/\/www.erekibeon.com\/blog\/wp-json\/wp\/v2\/posts\/25042\/revisions"}],"predecessor-version":[{"id":25403,"href":"https:\/\/www.erekibeon.com\/blog\/wp-json\/wp\/v2\/posts\/25042\/revisions\/25403"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.erekibeon.com\/blog\/wp-json\/wp\/v2\/media\/25338"}],"wp:attachment":[{"href":"https:\/\/www.erekibeon.com\/blog\/wp-json\/wp\/v2\/media?parent=25042"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.erekibeon.com\/blog\/wp-json\/wp\/v2\/categories?post=25042"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.erekibeon.com\/blog\/wp-json\/wp\/v2\/tags?post=25042"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}