OK !!,
Marcos acaba de explicaros la manera mas sencilla y fiable de generar
numeros aleatorios, tal como se necesitan para juegos, y similares. Si
alguien quiere numeros aleatorios para utilizar en programas estadisticos,
simulaciones, etc, para eso estan las matematicas, y la funcion RND del
Basic.
La ventaja de este metodo (el de la tabla) , es que genera todos los
numeros, y con igual frecuencia.
La consulta a la tabla, es inmediata, sin necesitar ningun calculo.
Y el cambiar el indice de la tabla con frecuencia, hace que realmente su
comportamiento sea aleatorio e impredecible.
Y es que para programar, no hacen falta formulas matematicas, ni complejos
algoritmos, sino un poco de 'pereza' para hacer las cosas de la manera mas
sencilla, que acaba siendo la mejor.
Para completar, añado que para generar la tabla aleatoria, un metodo
sencillo es
un sencillo programa en Basic.
(Escrito a 'ojo' seria asi:)
10 ' Generador de tabla de 256 numeros aleatorios.
20 DIM N(255)
30 FORI=0TO255:N(I)=I:NEXT 'Rellena la tabla con 0,1,2,.....,254,255
40 FORK=1 TO 1000 'Hace 1000 descolocaciones(vale
cualquier otro valor)
50 P1=INT(RND(1)*256)
60 P2=INT(RND(1)*256)
70 SWAP N(P1),N(P2) 'Descoloca 2 entradas de la tabla
80 NEXT K
90 FORI=0TO255:PRINT N(I);:NEXT 'Muestra los resultados
Y anotas los valores de la tabla, o los mandas a un fichero para
ensamblador, o lo que quieras.
Y recalcar otra cosa en la que Marcos tenia razon:
Para comprobar la aleatoriedad de un metodo de generacion de numeros
aleatorios,
lo mejor es verlo graficamente.
( haced:)
10 SCREEN 8
20 GOSUB 100:X=R
30 GOSUB 100:Y=R:IF Y>211 THEN Y=Y-212
40 GOSUB 100:C=R
50 PSET(X,Y),C
60 GOTO 20
100 '=== Aqui se pone la rutina de generacion de numeros. Devuelve R entre 0
y 255
110 .... segun cada metodo ...
120 R=.... El numero aleatorio se escribe en R
130 RETURN
Si el metodo es bueno, la pantalla se ira llenando de puntos de colores,
sin formar lineas definidas.
Si lo que haceis es utilizar el registro R del Z80, vereis, como se forman
lineas, lo que indica que la aleatoriedad es muy baja.
Como conclusion, decir que el mejor metodo de generacion de numeros
aleatorios, depende del programa que los vaya a necesitar.
En muchos casos, leer el registro R del Z80 es suficiente. En otros, leer el
Timer del sistema, sirve. En otros, hacer un Peek de posiciones Rom puede
servir. En otros, se necesitara un complejo algoritmo matematico.
Chao.
Daniel Zorita.
----- Original Message -----
From: Marcos Vega Coso <mvcoso(_en_)terra(_punto_)es>
To: hispaMSX <hispamsx(_en_)egroups(_punto_)com>
Sent: Sunday, October 22, 2000 5:03 AM
Subject: Re: [hispamsx] Números aleatorios
Hola a todos.
Sobre los números aleatorios en ensamblador yo recuerdo que tambien le dí
en
su día vueltas al asunto.
Primeramente probé con LD A,R, pero lo que obtienes con eso francamente no
se si se le puede llamar aleatorio, en cualquier caso no sirve, "siempre
te
sale lo mismo", y no superó ni un par de pruebas. No obstante, puede
servir
si no necesitas más que obtener un par de numeros aleatorios y entre que
pides uno y que pides otro ha pasado suficiente tiempo (que menos de un
par
de segundos).
Lo siguiente que probé fué a leer directamente de la posición de memoria
64670 haciendo LD A,(64670). Pero nada, esto igualmente solo sirve si
necesitas un numero aleatorio unicamente de Pascuas a Ramos. Si
representas,
como yo hice, en screen 5 (por ej) los numeros que obtienes con este
metodo
lo descartas rápidamente porque si eso es aleatorio yo soy cura. Esto es
evidente, por otra parte, pero yo por entonces no lo sabía.
Lo siguiente fue pensar en el reloj del ordenador. Pero claro, no todos
los
modelos ni generaciones tienen el relojito para que puedas consultarle la
hora.... O sea, que nada por este lado, por no hablar de que tienes que
hacer llamadas a la ROM y eso consume mucho tiempo, cosa que no suele
sobrar
en lo que yo estaba haciendo en aquellos momentos (un juego).
Lo siguiente, y que fué la solución definitiva y la que sigo usando hoy en
día, fué currarme yo por mi mismo el número y pasar de las supuestas
ayudas
al respecto que te ofrece el ordenador.
Para ello me creé una tabla de 255 numeros ordenados por mí
aleatoriamente. Por ejemplo:
TABLA: DEFB 230, 3, 122, 66, 55, 0, 14, 21, 255 ...
Obviamente no debe haber ninguno repetido y para construir esta tabla pues
se puede hacer a ojo y usando un poco la inteligencia o bien con algo más
sofisticado y complicado (tira del número aleatorio de la calculadora, por
ej.).
Despues, cada vez que quería un número aleatorio hacía algo así:
LD HL, INDEX
LD C, (HL)
INC (HL)
LD HL, TABLA
LD B,0
ADD HL,BC
LD A, (HL) ; EN A OBTIENES EL N ALEATORIO
De esta manera vas cogiendo cada vez un número: la primera vez el 230,
la segunda el 3, la tercera el 122... (esto en el ejemplo de tabla que
puse
anteriormente, claro). En consecuencia se simula el efecto de obtener un
número aleatorio, cosa que por otra parte en realidad sí que estás
haciendo,
aunque sea indirectamente.
Aclarar que se necesita una posicion de memoria, del tipo:
INDEX: DEFB 0
Y que esta posicion de memoria hay que inicializarla al principio del
programa. Yo hacía para ello algo así, en las primeras lineas del juego, y
obviamente fuera el bucle del mismo:
LD A, (64670)
LD (INDEX),A
Con estas líneas de codigo se obtiene un numero "aleatorio" de la
posicion 64670 (que como dije, para usarla una vez puede dar el pego para
obtener algo aleatorio) y se guarda en INDEX.
De esta manera se consigue que cada vez que inicies el juego el valor
INDEX sea diferente y en consecuenia empezarás a leer de la tabla TABLA
cada
vez de una posición tambien diferente. Esto es importante ya que si se
empieza a leer la secuencia siempre desde el mismo sitio al final en el
juego siempre empezaría pasando lo mismo cada vez que jugaras, por que los
números "aleatorios" los obtendrías partida tras partida en el mismo
orden.
Esto es la idea basica. Luego tambien están otros trucos como que si
no
quieres molestarte en hacer una secuencia aleatoria de números puedes
hacer
que TABLA apunte a un fragmento de tu programa (un fragmento que no sea de
datos, claro, pues allí pudiera haber por ejemplo muchos 0 seguidos, lo
cual
estropearía el efecto de "aleatoriedad"), o si quieres hacer una tabla
pero
no de 255 numeros sino de 128 pues tendrías que poner el código tal que
así:
LD HL, INDEX
LD C, (HL)
INC (HL)
RES 7,(HL) ;ESTA SERÍA LA LINEA NUEVA A INTRODUCIR
LD HL, TABLA
LD B,0
ADD HL,BC
LD A, (HL) ; EN A OBTIENES EL N ALEATORIO
Y si quieras hacer la tabla de menos números todavía, como 64 o 32,
pues
deberías poner a 0 los bits correspondientes: el 7 y el 6 para 64 y el 7,
el
6 y el 5 para 32. Por ejemplo, para una tabla con 32 numeros, quedaría
algo
así:
LD HL, INDEX
LD C, (HL)
LD A, C
AND &B00011111
LD (HL),A
LD HL, TABLA
LD B,0
ADD HL,BC
LD A, (HL) ; EN A OBTIENES EL N ALEATORIO
Bueno, esto lo he hecho de cabeza, espero no haber metido la pata. Y
espero que se me haya entendido algo despues del pedazo de rollo que he
metido... Me he encontrado cómodo aquí en plan entendido en pájaras
preñadas
y casi hago la tesis sobre la generación de un maldito número
aleatorio....
Y son las 5 de la mañana, joder... debo estar loco.
En fin, un saludo a todos.
Marcos Vega.