[javascript] Probabilidades de Captura en Juego

Iniciado por Brian1511, 23 Julio 2015, 04:17 AM

0 Miembros y 1 Visitante están viendo este tema.

Brian1511

Estoy en la creacion de un juego Pokemon con javascript,

Quiero hacer el sistema de captura de Pokemon, quisiera hacer probabilidades al capturar algun pokemon.

Tengo algo como esto:

Código (javascript) [Seleccionar]
var PokeBall = 15;
var MasterBall = 25;
var UltraBall = 50;
var PokemonLvl1 = 5;
var PokemonLvl2 = 10;
var PokemonLvl3 = 20;


Como hago para hacer que dependiendo el nivel y el valor de la pokebolas se genere una probabilidad de captura exitosa?



Creador de BrainMind

v4char

puedes hacer que se genere un numero al azar entre 1 y 20 por ejemplo y luego segun lo pokeball y el nivel puedes ir reducciendo a 1 entre 5.

Usuario Invitado

Según fuentes oficiales la fórmula es así:

a =  ((([ (3 x HPmax - 2 x HPcurrent)] x (RATE x BONUSball)) + BONUSstatus - 1) / HPmax) / 2.56

Donde:

  • HPmax es la vida máxima del pokemón.
  • HPcurrent es la vida actual del pokemón.
  • RATE es el ratio del pokemón.
  • BONUSball ratio de la pokeball (puedes ver los ratios aquí http://www.pokexperto.net/index2.php?sección=color/balldexGBC)
  • BONUSstatus es el bonus por el estado del pokemon. Congelación o sueño vale 10 y quemaduras o veneno 5.

    Por ejemplo. Un pokemon tiene 160 de HPmax y 120 de HPcurrent y tiene un ratio de 2. La pokeball tiene un ratio de 1.5 y el estado del pokemon es de sueño, lo que equivale 10.

    Aplicando la fórmula:

    ((([3 x 160 - 2 x 120] x (2 x 1.5)) + 10 - 1) / 160) / 2.56

    Nos da como resultado:

    a = 1.4868 = 1.49

    Ahora hallamos b, por medio de la sifuiente fórmula:

    (2 ^16 - 1) SQRT4 (a / 2^8 - 1)

    Lo que nos da:

    b = 65535 x 0.32 = 20971.2

    Generamos 4 números aleatorios:

    (b / 2^16)^4 = 0.1

    Por lo tanto, la probabilidad es:

    p = 0.1 x 100 = 10%.

    Tuvimos 10% de probabilidades de capturar al pokemón.
"La vida es muy peligrosa. No por las personas que hacen el mal, si no por las que se sientan a ver lo que pasa." Albert Einstein

#!drvy

#3
Pfff, te has metido en un asunto complicado xD. Digamos que en los juegos de pokemon la captura depende de muchos mas factores que el nivel y el tipo de bola. Por ejemplo, en la primera generación los factores son:


  • Nivel de pokeball
  • Hechizos (dormir, congelar, quemar etc..)
  • Factor de captura del propio pokemon (cada uno es diferente)
  • Factor aleatorio

Como ves, ni se nombra el nivel del pokemon. Y ya después de la primera generación cambia drásticamente. Puedes ver 'los algoritmos' en esta pagina:

Catch rate
http://bulbapedia.bulbagarden.net/wiki/Catch_rate

Basándome en el algoritmo de la primera generación y los valores que da la bulbapedia, he hecho un PoC.

HTML
Código (html4strict) [Seleccionar]
<!DOCTYPE html>
<html lang='es'>
<head>
   <meta charset='utf-8'>
   <title>PoC - Captura pokemon</title>
   <link rel='stylesheet' href='http://yui.yahooapis.com/pure/0.6.0/pure-min.css'>
   <style type='text/css'>
       body { font-size: 14px;}
       input[type='text'] { max-width: 50px; }
       label { color: #555; padding: 5px 10px; }
       #wrap { max-width: 600px; margin: 0 auto;}
       #log > div { padding: 2px; color: #444; text-align: justify;}
       #clear {cursor:pointer; text-decoration: underline; color: #888;}
   </style>
</head>
<body>
<div id='wrap'>
<form class='pure-form'>
   <fieldset>
       <legend>Seleciona el Pokemon!</legend>

       <label for='pokemon'>Pokemon</label>
       <select id='pokemon'>
           <option value='255'>Caterpie</option>
           <option value='225'>Gulpin</option>
           <option value='190'>Pikachu</option>
           <option value='127'>Bibarel</option>
           <option value='90'>Arbok</option>
       </select>

       <label for='vida'>Vida (actual/max)</label>
       <input type='text' id='vida_act' value='20'>
       <input type='text' id='vida_max' value='35'>
   </fieldset>

   <fieldset>
       <legend>Seleciona la pokeball y efectos!</legend>

       <label for='pokeball'>Pokeball a usar</label>
       <select id='pokeball'>
           <option value='255'>PokeBall</option>
           <option value='200'>SuperBall</option>
           <option value='150'>SafariBall</option>
           <option value='150'>UltraBall</option>
           <option value='0'>MasterBall</option>
       </select>

       <label for='efecto'>Efecto</label>
       <select id='efecto'>
           <option value='0'>Ninguno</option>
           <option value='25'>Dormido</option>
           <option value='25'>Congelado</option>
           <option value='12'>Paralizado</option>
           <option value='12'>Quemado</option>
           <option value='12'>Envenenado</option>
       </select>

       <input type='button' class='pure-button pure-button-primary' id='capturar' value='Capturar!'>
   </fieldset>
   <fieldset>
       <legend>Log (<span id='clear'>borrar</span>)</legend>
       <div id='log'></div>
   </fieldset>
</form>
</div>
<script type='text/javascript' src='pokemon.js'></script>
</body>
</html>


pokemon.js
Código (javascript) [Seleccionar]
var capturar = function(){

   /* Pokemon y su factor de captura */
   var pokemon = document.getElementById('pokemon');
   var pokemon_nombre = pokemon.options[pokemon.selectedIndex].text;
   var pokemon_factor = pokemon.options[pokemon.selectedIndex].value;

   var vida = document.getElementById('vida_act').value;
   var vida_max = document.getElementById('vida_max').value;

   /* Tipo de pokeball */
   var pball = document.getElementById('pokeball');
   var pball_nombre = pball.options[pball.selectedIndex].text;
   var pball_factor = pball.options[pball.selectedIndex].value;

   /* Tipo de efecto adverso */
   var efecto = document.getElementById('efecto');
   var efecto_nombre = efecto.options[efecto.selectedIndex].text;
   var efecto_factor = efecto.options[efecto.selectedIndex].value;

   /* Por mostrar algo */
   addLog('Pokemon: '+pokemon_nombre+' | Vida: '+vida+'/'+vida_max);
   addLog('Pokeball: '+pball_nombre+' ('+pball_factor+') | Efecto: '+efecto_nombre+' ('+efecto_factor+')');

   /* --------------------------------------------------------------------
       Aquí empieza la magia.
       ------------------------------------------------------------------- */

   /* La MasterBall siempre funciona xD */
   if(pball_factor === '0'){
       addLog('Capturas el pokemon con una '+pball_nombre+'!<hr>');
       return true;
   }

   /* Generamos un numero aleatorio dependiendo del factor de la pokeball */
   var n = Math.floor((Math.random() * pball_factor) + 1);

   /* Comprobamos si el efecto es capaz de capturarlo */
   if(n!=='0' && n < efecto_factor){
       addLog('Capturas el pokemon con una '+pball_nombre+' debido a '+efecto_nombre+'!<hr>');
       return true;
   }

   /* Comprobamos si el pokemon se escapa negando el efecto */
   if(n-efecto_factor > pokemon_factor){
       addLog('El pokemon se escapa!<hr>');
       return false;
   }

   /* Generamos un numero aleatorio entre 0 y 255 */
   var m = Math.floor((Math.random() * 255) + 1);


   /* Si es una SuperBall el factor pasa a 8 sino a 12 */
   if(pball_factor==='200'){ var ball = 8; } else { var ball = 12; }

   /* Calculamos f (no debe ser inferior a 1 ni superior a 255 */
   var f = Math.floor((vida_max * 255 * 4) / (vida * ball));
   if(f<1){ f = 1; } else if(f>255){ f=255; }

   /* Si f es igual o superior a m, capturamos. */
   if(f >= m){
       addLog('Capturas el pokemon con una '+pball_nombre+'!<hr>');
       return true;
   }

   addLog('El pokemon escapa!<hr>');
   return false;
};

/* Evento capturar */
document.getElementById('capturar').addEventListener('click', capturar);

/* Evento borrar log */
document.getElementById('clear').addEventListener('click', function(){
   document.getElementById('log').innerHTML = '';
});

var addLog = function(message){
   var element = document.getElementById('log');
   element.insertAdjacentHTML('beforeend','<div>'+message+'</div>');
   return true;
};


DEMO: http://jsfiddle.net/drvy/n9ur9L5s/




Si solo quieres el factor de captura, la funcion capturar() se reduce drásticamente.
Código (javascript) [Seleccionar]
var capturar = function(){

    /* Pokemon y su factor de captura */
    var pokemon = document.getElementById('pokemon');
    var pokemon_factor = pokemon.options[pokemon.selectedIndex].value;

    var vida = document.getElementById('vida_act').value;
    var vida_max = document.getElementById('vida_max').value;

    /* Tipo de pokeball */
    var pball = document.getElementById('pokeball');
    var pball_factor = pball.options[pball.selectedIndex].value;

    /* Tipo de efecto adverso */
    var efecto = document.getElementById('efecto');
    var efecto_factor = efecto.options[efecto.selectedIndex].value;

    /* --------------------------------------------------------------------
        Aquí empieza la magia.
        ------------------------------------------------------------------- */

    /* La MasterBall siempre funciona xD */
    if(pball_factor === '0'){ return 100; }

    /* Calcular f */
    if(pball_factor==='200'){ var ball = 8; } else { var ball = 12; }
    var f = Math.floor((vida_max * 255 * 4) / (vida * ball));
    if(f<1){ f = 1; } else if(f>255){ f=255; }

    var p0 = (efecto_factor+1) / (pball_factor+1);
    var p1 = ((pokemon_factor+1)/(pball_factor+1)) * ((f+1)/256);

    return p0+p1;
};


PD: Los factores de captura de los pokemon los puedes ver aquí:
http://bulbapedia.bulbagarden.net/wiki/List_of_Pok%C3%A9mon_by_catch_rate

PD2: De todos modos, la respuesta de @Gus te servirá mejor yo creo.

Saludos

Brian1511

#4
Wow chicos muchas gracias en serio, no sabia que tendria tanto apoyo en esta comunidad!,
Bueno el caso es que antes de publicar este post ya tenia una formula parecida a la que indica v4char

Código (javascript) [Seleccionar]
function CapturePokemon(name,hp,lvl,pb){
/*
name = Nombre del pokemon.
hp = Vida actual del pokemon.
lvl = Nivel del pokemon.
pb = Ratio de la pokebola.
*/
var TLT = lvl - pb;
al = Math.floor(Math.random()*TLT);
if(al==0||al<0){
//Capturado
}elese{
//Escapado
}
}

Y me funciona pero queria respuestas de personas conocedoras :).

Intentara implementar la formula de Gus Garsaky  porque es la mas corta, pero sino funciona como quiero usare la de #!drvy.

Una ves mas muchas gracias amigos en serio, y gracias a #!drvy  por tomarte el tiempo de hacer todo eso.


Mod: No olvidar las GeSHi



Creador de BrainMind

Usuario Invitado

Estaba trabajando, no pude contestar. Te pongo un pequeñito ejemplo que acabo de leer de la wiki de pokemón:

El ratio de captura se saca con ésta fórmula según esa wiki:


Donde:

  • PSmax = Puntos de salud totales del Pokemón.
  • PSactual = Puntos de salud actuales.
  • Rc = Ratio de captura del Pokemón.
  • Rb = Ratio de Poké Ball.
  • Be = Bono extra que se agrega cuando un Pokemón tiene un problema de estado: dommido: 2, congelado: 2, paralizado: 1.5, quemado: 1.5, envenenado 1.5, sin problemas: 1.

    Si a es mayor a 255, el pokemón es capturado. Caso contrario, encontramos b:


    Explicación:

    El juego generará 4 números entre 0 y 65535 (2^16 - 1) y se comparan con los valores de b. Nótese que b depende de a. Con un número menor o igual que b, la Poke Ball rebotará una vez, con dos rebotará dos veces, con tres rebotará tres veces y con el cuarto número lo capturará. Es decir, se necesita que los 4 números sean menores o iguales a 65535.

    Por ejemplo, si b = 350 y las combinaciones son:

  • 1er número = 200
  • 2do número = 300
  • 3er número = 500
  • 4to número = 120

    No se capturará al pokemón, solo rebotará tres veves ya que el tercer número aleatorio es mayor a 350.

    Recursos:

    Para saber el ratio de captura de un pokemón consulta: Lista de pokemones por ratio de captura
    Para saber el ratio de las Poke Balls: Poke Balls ratios

    Ejemplo:

    Demo JSFiddle

"La vida es muy peligrosa. No por las personas que hacen el mal, si no por las que se sientan a ver lo que pasa." Albert Einstein

MinusFour

Tu formula es un poco extraña, pero sin duda está mal. No es lo mismo capturar un Pokemon Legendario, en su segunda/tercera evolución (o preevolución), un Pokemon raro, etc. Por ejemplo, un Mewtwo LVL 1 es mucho mucho más difícil de capturar que un Pidgey LVL 1, pese a cualquier condición que pudiera tener (%hp bajo, status infligido, ratio de captura de pokebola, etc).

Lo que puedes hacer es muy simple, calculas la probabilidad de que el Pokemon pueda ser capturado (entre 0 y 100). Y luego generas un número aleatorio entre 0 y 100. Sí la probabilidad de captura es mayor al número generado entonces se captura el Pokemon, si no el Pokemon escapa. Lo más díficil es hacer la formula para la probabilidad de captura del Pokemon.

Una formula muy simple es: Por cada % de HP menos que tenga (%dmg) hay una probabilidad de captura para un Pokemon de %dmg * ratio de Pokebola. Por ejemplo, un Pokemon con 1% de daño (suponiendo que tiene 100 hp, sufrio 1 de daño) al lanzarle una pokebola normal (digamos que su factor es de 1) tenemos que  1% * 1.0 = Probabilidad de Captura (1.0). Ahora digamos que sufrió 99% de daño: 99% * 1.0 = 99% Probabilidad de Captura.

Hasta ahora la formula para probabilidad de captura es de: %daño * factor de captura de pokebola. Muy sencillo. Ahora, digamos que quieres tomar en cuenta la rareza del pokemon (legendario, evolucionado, etc). Simplemente añades otro factor de rareza. Algunos valores que se me vienen a la mente:

Caterpie: 2.0
Mewtwo: 0.01

La formula ahora es: %daño * factor de captura * rareza. Por ejemplo un Metwo que ha sufrido %99 de daño, le lanzas una pokebola con factor de 1.0 tendrás: %99 * 1.0 * 0.01 = %.99 probabilidad de captura (100 pokebolas en promedio para capturarlo). Un Caterpie que ha sufrido 10% de daño, le lanzas una pokebola con factor de 1.0: %10 * 1.0 * 2.0 = 20% probabilidad de captura (5 pokebolas en promedio para capturarlo).

Para status infligido, simplemente agregas otro factor:

% daño * factor de captura * rareza * status.

Por ejemplo, digamos que el estar congelado aumenta la probabilidad de captura 10 veces. Retomando el ejemplo de Metwo: 10 * (.99) = 9.9% (ahora 10 pokebolas en promedio para capturar).

Claro que está formula tiene sus problemas, por ejemplo, es posible pasarse de 100% (en mi opinión, siempre debe haber una probabilidad de falla a menos que sea una master ball). Sin mencionar que no estás recreando Pokemon, sino que estás cambiando la forma interna en la que trabaja el juego.

Brian1511

Oppaaa!, en serio les agradezco mucho las explicaciones ya se como lo hare.
Gracias por el apoyo! ñ.ñ y a MinusFour por tomarse su tiempo en explicarme todo eso que me sirvio de mucho!.



Creador de BrainMind