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.
es correcto, tenes que cambiar la semilla al iniciar el programa, te suguiero que uses la fecha como semilla...
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).
:-[
RAND_SEED( semilla )
te suguiero
RAND_SEED( time() );
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...
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...
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...
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.
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.
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 ...
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...
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...
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....
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...
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í...
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
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 ....
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...
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...).
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.
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
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...
...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...
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.
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
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.
Venga te mereces un karma up :)
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
bueno, y ¿como exactamente va eso de la semilla o rand_seed ( time ( ) )????
en que parte del codigo o arriba del tido?¿?¿?
Pues lo tienes bien! Lo pones despues del begin principal y listo...
ok, karma +=1;
edito: aunque falla algo, ¿me hace falta una libreria o algo? es que me dá error...
re-edito: me faltaba poner un tal import "mod_time";, malditas librerias y agobio de importaciones... (yomentiendo) :)
Ja ja ja...
Yo al principio andaba igual que tú, ahora me sé prácticamente de memoria las dll que hay que importar y qué funciones tiene cada una xD
Cuando empieces a controlar puedes hacerte una plantilla que las importe todas, es lo que tengo yo preparado siembre para empezar nuevos proyectos, cuando ya están avanzados me preocupo de mirar las dll que no hacen falta y las quito, creo que sale un poco más productivo hacerlo así :P
Quote from: Windgate on May 06, 2010, 12:39:21 AM
Ja ja ja...
Yo al principio andaba igual que tú, ahora me sé prácticamente de memoria las dll que hay que importar y qué funciones tiene cada una xD
Cuando empieces a controlar puedes hacerte una plantilla que las importe todas, es lo que tengo yo preparado siembre para empezar nuevos proyectos, cuando ya están avanzados me preocupo de mirar las dll que no hacen falta y las quito, creo que sale un poco más productivo hacerlo así :P
Yo hago lo mismo... primero las incluyo todas y cuando el proyecto ya esta finalizado o quiero empezar a optimizar rendimiento/memoria empiezo a quitar las que sobran... pero ni me molesto en mirar cual si cual no... las comento // y compilo y si no se queja pues pa fuera... en plan vago jejejeje
Pues yo al reves, empiezo con 3 o 4 que se que siempre serán necesárias y despues voy poniendo según las funciones que desconozca al compilar :)
a ver si el año que viene estoy a la altura de ustedes...
je je je
Pues yo trabajo incluyéndolo todo, y al terminar, borro el bgdc.import y voy añadiendo.
Eso sí, es una pesadilla añadir las librerías de render, porque te falla y no sabes cual es la librería que te falta, no da ninguna pista :S