función rand() - Comportamiento raro en distintas plataformas

Started by FreeYourMind, October 18, 2009, 01:24:20 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

DCelso

No se si en div no era necesario, pero en fenix y en bennugd sí que es necesario iniciar la semilla si quieres aleatorios.
Por mi experiencia en juegos, me atrevo a decir que bennu no inicializa internamente la semilla con la fecha y hora, si debería hacer esto, lo hace mal ahora,(si hace algo siempre usa la misma semilla) sino prueba ese simple ejemplo varias veces, verás siempre el mismo resultado

Program rand_example;
Import "mod_say"
Import "mod_rand"
global
   int i;
Begin
   For (i=0;i<25;i++)
       say("Valor rand:" +rand(0,100));
End
End

Así que insisto en que pruebes lo que te dijo SplinterGU.
Te pongo el código resaltando la línea que debes introducir para probar.

PROCESS menu()
PRIVATE
   muslocal;
   randmus;

BEGIN

 muslocal = -1;
 timer[0] = 300;
  RAND_SEED( time() ); //<------------------ Te falta esto
 randmus = rand(1, 4);
 
 LOOP

   IF (timer[0] > 333)
     timer[0] = 0;
     muslocal++;
     IF (muslocal > 15)
       muslocal = 4;
     END

     SWITCH (randmus) // Aqui hago el switch basado en el random, en la Wiz sale siempre randmus = 4, porque puede ser ?
       CASE 1:
       IF (musica[muslocal].a)
         play_wav(baixo, 0);
       END
       IF (musica[muslocal].b)
         play_wav(batida, 0);
       END
       IF (musica[muslocal].c)
         play_wav(v1, 0);
       END
       IF (musica[muslocal].d)
         play_wav(v2, 0);
       END
       END

       CASE 2:
       IF (musica2[muslocal].a)
         play_wav(guitar1, 0);
       END
       IF (musica2[muslocal].b)
         play_wav(batida, 0);
       END
       IF (musica2[muslocal].c)
         play_wav(guitar2, 0);
       END
       IF (musica2[muslocal].d)
         play_wav(guitar3, 0);
       END
       END

       CASE 3:
       IF (musica3[muslocal].a)
         play_wav(effect3, 0);
       END
       IF (musica3[muslocal].b)
         play_wav(guitar4, 0);
       END
       IF (musica3[muslocal].c)
         play_wav(batida, 0);
       END
       IF (musica3[muslocal].d)
         play_wav(baixo, 0);
       END
       END

       CASE 4:
       IF (musica4[muslocal].a)
          play_wav(flip1, 0);
       END
       IF (musica4[muslocal].b)
play_wav(flip2, 0);
       END
       IF (musica4[muslocal].c)
play_wav(flip3, 0);
       END
       IF (musica4[muslocal].d)
play_wav(batida2, 0);
       END
       END
     END
   END

Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

FreeYourMind

#16
Si, de eso ya me habia enterado, si lo decia yo tambien, que la primera vez no hacia el random, salian siempre los mismos valores (fijos en cada plataforma y distintos, ejemplo del PC y Wiz).

Nunca me entere que en Fenix tampoco funcionara, ya que las funciones rand() que utilize eran para enemigos, y nunca te enteras a ojo que valores de rand esta processando, así que si no fuera por esto, nunca imaginarias que el primer rand en el tiro de un enemigo (ejemplo de Geca Blaster 2) fuera siempre con el mismo valor en los parametros del rand...

Pero aqui como es poner la musica de fondo, pues es facil enterarte que te salia siempre la misma al aceder al menu...


Lo voy a probar, pero para decir verdad, la version de DIV1 que aún he probado pocas veces parece (esto lo quiero comprobar con más pruebas para certificarme) de que le sale tambien siempre el mismo valor de rand, la primera vez de ejecución del rand().


Y para terminar, esto es por mania mia, lo que realmente quiero es la mayor fidelidad con el original DIV, si en el original la primera vez sale siempre el mismo valor rand, no me importaria dejarlo así en Bennu tambien (ya que parece devolver el mismo), lo que ocurre es que sólo pasa si ejecutado en el PC, la Wiz insiste en darme siempre el primer valor de rand distinto :) Así que me gustaria buscar una solución para que en la Wiz saliera tambien el mismo valor que sale en PC, la primera vez de ejecución ....

DjSonyk

Puff!! eso va ser cosa muy muy dificil,que te den lo mismo las 2 plataformas,al no ser que uses una semilla igual,y aun asi es imposible,otra posibilidad es dar tu los primeros valores fijos y luego que sean aleatorios...

FreeYourMind

Bueno en primer lugar me alegro que ya lo tengo resuelto, pero tengo 2 noticias una buena y otra mala, y para la mala busco una explicación:



1 - Al final en DIV1 el rand() si funciona perfectamente en la primera ejecución, la musica del menu si cambia en distintas ejecuciones a la primera.
Así que poniendo la semilla time() en Bennu resuelvo el problema tanto en PC como en Wiz, ya que gracias a dios funciona en DIV1 y así aseguro fidelidad al original en la Wiz.


2 - He estando poniendo la semilla en todas las funciones rand() que el juego tiene que son mogollones por cierto (para efectos, explosiones, etc).
No se porque, pero al ejecutar el juego estos efectos han dejado de funcionar correctamente, como si el random no funcionara bien, por ejemplo las explosiones parecen mas estaticas que antes, el mismo para efectos de humo que no se mueven tanto, incluso enemigos que no aparecen (no he mirado en profundidad como utilizaban el rand() para que aparecezcan en pantalla).
Me da la impresion que los valores de los distintos randoms se han limitado en espacio de posibilidades...

Sólo puede ser provocado por repetir varias veces la semilla, no encuentro otra explicación, ya que el random a la primera si funciona bien en DIV1, y por observación el random parece seguir funcionando en todas sus llamadas pero con limite de margen de acción, dejando de existir tanta variedad en el movimiento de los efectos (me imagino que si funciona bien a la primera, incluso habria más azar en los efectos, aunque en este caso no se detecta a ojo, pero ahora con este comportamiento raro, a ojo se observa perfectamente que no esta funcionando correctamente...).

DCelso

La semilla con time solo la tienes que hacer una única vez en todo tu programa, suele ir en la funcion de inicialización del sistema, despues o antes de establecer la resolución de pantalla. Con esto creo que se solucionaría el segundo problema. Si cambias constantemente la semilla antes del rand (y mas usando time), los valores puede que sean muy parecidos ya que no estás siguiendo la línea de aletoriedad iniciada.
Vamos a ver aletoriedad en el ordenador es imposible de conseguir, el rand suele ser siempre una función gausiana en la que insertas de entrada la media y la varianza, así se consigue una semialetoriedad, esto quiere decir que es periódica (que se repiten los valores después de un cierto tiempo) para evitar que siempre siguas el mismo recorrido se usa la semilla que es como decir empieza a darme valores a partir de este punto. El usar el time es porque consiges una semilla distinta para cada ejecución. Si div no necesita semilla es porque hará eso mismo internamente, creará una semilla basándose en la hora y fecha del sistema.
Teóricamente si pones la misma semilla, digamos RAND_SEED( 5 ) en ambos equipos, deberán darte los mismos resultados la ejecución, pueden que sean diferentes por la resolución/precisión interna del sistema pero si son iguales en esto darán siempre los mismos resultados. Puede que sea esto lo que pasa en wiz frente al PC o quizas la semilla interna inicial que crea bennu use algun valor relaccionado con el sistema operativo.

Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

FreeYourMind

Muy buena tu explicación, estaba pensando en eso (y no lo digo de coña), como iniciaba (reseteaba) la semilla, pues no le daba tiempo para valores más extensos, así que el margen era menor.

Sobre lo de los distintos sistemas, pues algo habra distinto claro esta, sólo mirando la función interna de Bennu se sabrá la respuesta, y aunque pueda tener la misma semilla por defecto esta puede tener comportamiento distinto en distintas máquinas.

Bueno, tema encerrado, porque por lo menos ya tengo solución.

Gracias.

Espero ayudarte con tus dudas, cuando pruebe tu ejemplo, es que estamos siempre sin tiempo para todo  ;D

splinter_work

efectivamente, bennu no hace reinicializacion de la semilla rand en cada ejecucion, sino que la funcion rand esta iniciada con los valores que esta iniciada la misma en la funcion de C.
por eso trae los mismos valores en cada ejecucion, y eso es correcto.
iniciando la semilla en cada ejecucion con time(), hacemos que por lo menos en ejecuciones repititivas al menos cuando el segundo cambie entre ejecucion y ejecucion el retorno del rand sera diferente.

no hay que hacer rand_seed constantemente, ya que esto no provoca aleatoriedad asegurada... se debe hacer 1 sola vez...

Windgate

...y si haciendo rand_seed ( time ( ) ) una ÚNICA vez sigues teniendo el problema de que el primer rand ( ) te da siempre el mismo valor pues haz rand_seed ( time ( ) ) seguido de un rand ( ) una ÚNICA vez ignorando ese valor y luego ya lo usas sin problemas...
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

DCelso

Win, no le veo mucho sentido a ello. Si te pasó eso algo anduvo mal en tu programa o en esa versión de bennu/fenix/div que usaste.
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

Windgate

No me pasó a mí, es lo que me había quedado en mente de lo que le pasaba a FreeYourMind, que siempre le devolvía 1 en la primera ejecución de rand ( ), una solución fácil es invocarlo una vez ignorando lo que devuelve y luego todo bien. Aunque tienes razón, si pasa eso tendría que ser problema del programa o de la versión de bennu/fenix/div.

Ahora leo que FreeYourMind dijo que ya tenía la solución así que no problem :P
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

DCelso

Sipo, yo era por aclararte las ideas. Veamos
Program rand_example;

Import "mod_say"
Import "mod_rand"
global
    int i;
Begin
    rand_seed(12035);
    For (i=0;i<5;i++)
        say("Valor rand:" +rand(0,100));
End
End

Este código siempre devuelve el mismo resultado, si pusieramos un rand despues de rand_seed para eliminar el primer valor seguiria dando mismos resultados entre ejecuciones es más serán iguales al código anterior desfasado en un elemento

Import "mod_say"
Import "mod_rand"
global
    int i;
Begin
    rand_seed(12035);
   rand(0,0); // <-- aqui puedes poner lo que quieras, es indiferente, rand(2,100) hará exactamente lo mismo
    For (i=0;i<5;i++)
        say("Valor rand:" +rand(0,100));
End
End

El resultado de este código es el mismo que el del anterior pero sin el valor primero (en mi caso es un 6, para vosotros debería serlo también)

Valor rand:2
Valor rand:39
Valor rand:25
Valor rand:81
Valor rand:52


Así que lo que propones de hacer un rand después de el rand_seed el único efecto sería adelantar un elemento, claro está que el siguente código es imposible que devuelva el mismo valor siempre en el primer elemento ya que la semilla es diferente para cada ejecución, a no ser que lo ejecutemos dos veces muy rápidamente para que el tiempo no cambie y la semilla sea la misma.

Program rand_example;
Import "mod_say"
Import "mod_rand"
Import "mod_time"
Global
    int i;
Begin
    rand_seed(time());
    For (i=0;i<5;i++)
        say("Valor rand:" +rand(0,100));
End
End

yo he hecho esto

bgdi prueba_rand
ping -n 2 127.0.0.1 >NUL
bgdi prueba_rand

si varias el valor "2" a 1 o quitas la linea ping, devuelve el mismo resultado, si dejas el 2 ya no.
La precisión es en segundos. Este 2 significa espera 2 segundos.
En resumen, la semilla rand_seed(time()) cambia cada segundo, dicho de otra forma, si en el mismo segundo ejecutas el código varias veces devuelve el mismo resultado.
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/


Drumpi

Jejeje, todo esto me ha recordado a un problema que tuve en DIV hace lustros (hoy estoy en modo abuelo Cebolleta): Un juego en modo 7 de esquivar meteoritos, usaba rand de forma masiva (para la posición de los meteoritos, para los meteoritos de decorado, para elegir direccion de rotación...), y de pronto le puse items. Pues lo curioso es que el tipo de items no era aleatorio, salían en orden, y encima se repetían tantas veces como la probabilidad de salir (si tenía un 30% salía tres veces, si un 50% salía 5...).
No recuerdo si se solucionó ;D
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

Futu-block

bueno, y ¿como exactamente va eso de la semilla o rand_seed ( time ( ) )????

en que parte del codigo o arriba del tido?¿?¿?

FreeYourMind

Pues lo tienes bien! Lo pones despues del begin principal y listo...