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.

FreeYourMind

Buenas, he estado mirando porque en la Wiz la musica del menu era siempre la misma y distinta a la que sale si ejecutado en el PC.

La musica del menu es un conjunto de 4 sonidos que tocan de forma random haciendo de la musica un remix dinamico en tiempo de ejecución (o sea, los 4 sonidos forman la musica del menu), aparte de esto los 4 sonidos estan agrupados en 4 grupos, y cuando acedemos al menu se selecciona uno de ellos a traves de la funcion rand(1, 4);


Me gustaria saber en que se basa la función rand() de Bennu para elegir este valor, ya que por lo que veo en la Wiz me esta elegiendo siempre el mismo grupo de musicas y ya he ejecutado el juego mogollon de veces, no puede ser tanta casualidad, ya que la que el valor que elije en la Wiz nunca me lo ha elejido en el PC.

Os pongo parte del código:

PROCESS menu()
PRIVATE
   muslocal;
   randmus;

BEGIN

 muslocal = -1;
 timer[0] = 300;
 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

Resumiendo, en el PC me ha salido siempre randmus = 1 y en la Wiz randmus = 4, esto no puede tanta ser casualidad, ya lo ejecute en ambas plataformas mogollon de veces.

SplinterGU

es correcto, tenes que cambiar la semilla al iniciar el programa, te suguiero que uses la fecha como semilla...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

FreeYourMind

No te entendi lo de la semilla al principio del programa....

Me estas asustando, en mis anteriores ports tengo rands para dar y vender y nunca me parecio ver problemas en ellos (todo a ojo claro).
:-[


SplinterGU

Download Lastest BennuGD Release: http://www.bennugd.org/node/2

SplinterGU

igual olvidate a la idea de que vayas a tener los mismos valores rand en wiz que en pc... no tiene que ser necesariamente asi...

en teoria hay una semilla nueva por ejecucion, lo hace internamente el bgdi... pero no esta mal forzarlo nuevamente a cambiar...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

SplinterGU

viendo la logica de tu ejemplo, puede que tengas otra cosa ahi... y que sea logica... no es bueno probarlo asi... quita todo el tema de los play y haz un ejemplo mas simple...

captura el timer[0] en una variable, imprimela a archivo y lo mismo los valores de rand en cada caso...

creo que es otra cosa...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

DjSonyk

Hombre la verdad que las maquinas realmente no hacen eleciones al azar,como bien ha dicho Splinter se vasan en una semilla pre-fijada,de ahi que te recomiende Splinter poner una semilla,y el truco que normalmente se usa es ese cojer la hora actual para que sea siempre distinta,pasa desde siempre en los Amstrad CPC de 8 bit en Basic por ejemplo se utilizaba Randomize "TIME" ^^ y lo veras en cualquier lenguaje que se utiliza cojer la FECHA/HORA para hacer eleciones al azar...
Espero que te despeje las dudas...

Windgate

Yo siempre uso rand_seed ( time ( ) );

Como una norma general entre las primeras instrucciones de cualquier proyecto en Bennu, es "obligatorio" xD

En cualquier caso, ¿Wiz responde correctamente a time()?, con PC lo tengo claro pero con una consola no estoy seguro... Llevo años sin usar consolas.
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

FreeYourMind

Que se suele utilizar el time para los random ya lo sabia, me imagino que rand() lo hace por defecto en DIV/FENIX/BENNU  ;)

El caso es que tampoco hay que profundizar el tema, sencillamente solo se resume a esto:

porque rand(1, 4); me devuelve siempre 1 en el PC y 4 en la Wiz.

Como dije ya utilizé rand() a saco en otros ports y siempre vi su aleatoriedad, lo mejor y como bien dice Splinter, el problema puede que este en otro sitio y el CASE no funcione correctamente, lo voy a debugear a ver si simplifico el tema para ver el origen de tal estraña circunstancia.

Gracias.

FreeYourMind

Ya lo he estado mirando y debugeando. Parece que funciona bien tal como esta, pero sólo cuando vuelvo al menu(), o sea, vuelve hacer el mismo rand() por segunda vez en tiempo de ejecución del juego, y ya voy obteniendo valores distintos (1, 2, 3 o 4 tanto en PC como en la Wiz).

La primera vez que se ejecuta el menu(), tengo SIEMPRE valor 1 de rand si ejecutado en el PC y valor 4 si ejecutado en la Wiz.

Por eso no vi problemas de rand en anteriores juegos, ya que el rand se suele usar muchas veces en los enemigos, etc, y no para cosas tan visibles, así que seria muy dificil enterarme por ejemplo que la velocidad de un enemigo o tiro la primera vez que sale iba tener siempre el mismo valor de random, o por otras palabras, para un rand(minvalue, maxvalue), tener el minvalue en el PC o el maxvalue en la Wiz la primera vez que se llame el rand...

Splinter, tu sabras que funcionamiento interno tiene tu funcion rand() por defecto, y porque ocurre siempre esto en su primer ejecución y sobre todo porque difiere en las 2 plataformas ...

SplinterGU

me refiero a cosas como...

1) quizas > 333 es un fragmento un poco corto segun las operaciones que tengas que hacer... (lo dudo)

2) quizas algunos sonidos no se reproducen o demoran demasiado (mas de 333) en cargarlos, entonces los estas matando unos a otros... o tambien el no chequear que otro sonido este corriendo antes de lanzar otro... canales reservados...

no se, estoy tirando cosas sin mucho analisis... y no mire bien la logica de tu algoritmo... pero puede ir por ahi...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

SplinterGU

pero te podria decir con seguridad que el rand no va a devolver los mismos valores entre ejecucion y ejecucion... si te reproduce siempre el mismo, a menos que sea demasiada casualidad... hay algun otro comportamiento en tu logica que fuerza a que eso pase...

modifica el ejemplo imprimiendo los valores en cada frame...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

FreeYourMind

Las musicas suenan perfectamente en los 2.

He puesto un write del 'randmus' justo despues de hacer el rand, así que el resto del código no interesa para nada, y me imprime siempre el 1 o 4 respectivamente la primera vez que ejecuto el menu(), así que no puede ser de otra cosa....

DjSonyk

Humm ,yo recuerdo que cuando empece allá por el 97 ,hacer cosas en C ,hice un programa tipico que elije la maquina un numero al azar y tu le vas metiendo un valor y te dice si es mas alto o mas bajo,el caso esque siempre me dava el mismo valor al menos en la primera jugada,creo que es lo que te pasa a ti...lo que pasa que lo solucione con un time,igual es que deve de ser asi o al ser unos numeros tan bajos....no se me suena ya raro lo que te pasa...

Windgate

Para curarte en salud y evitar ese mismo valor en el primer rand() prueba a sustituir el "aleatorizador":

rand_seed ( time ( ) );

Por:

rand ( 1 , 100 );
rand_seed ( time ( ) );
rand ( 1 , 100 );


No es eficiente, sino eficaz. Así absorbes los primeros valores, tanto antes como después de poner la semilla, recuerdo que en un ejemplo que le estuve enseñando a un alumno hace tiempo me pasó algo parecido, que nada más empezar invocaba un personaje en una posición x aleatoria y me salió en el mismo sitio...

Cuando había más cosas generando números aleatorios en paralelo no se apreciaba, pero en ese ejemplo tan megasencillo que generaba un único número me sucedió, y me quedé con la duda de si ese PC tenía la pila mal o algo así...
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