dancresp escribió:A ver si el RPG se puede compilar sin problemas en el Turbo Pascal.
Así se podría disfrutar de una versión en CP/M y CP/M-86.
El compilador que uso es de Free Pascal, aunque supongo que se podría traducir sin problemas. De momento me mantendré en el mismo entorno de desarrollo, porque es el mismo que usé en mis tiempos de Pascal y estoy familiarizado con él.
El lunes estuve buscando mi código. Tuve que ir a buscarlo a mi viejo portátil. Después de seis años y dos incidentes de disco duro pude recuperar casi todo. Tras examinar los archivos recuperados me dí cuenta que las últimas versiones, las más avanzadas, faltan. Otras partes son tan pobres e ineficientes que he decidido reescribirlas. Así que el martes me dediqué a reescribir el sistema de movimiento por salas después de volver del trabajo. He decidido empezar por éste porque los pocos ejemplos que me he encontrado me han dado un poco de miedo... cuando empecé no me importaba cargar ciegamene contra los problemas aunque mi conocimiento fuera pobre, y el código que he encontrado lo refleja. La nueva versión és más simple, ocupa menos, es más legible y es más eficiente. Otra cosa, este post ha estado casi listo desde el martes por la noche, pero un malvado 403 ha evitado que lo publicara. Como ya he comentado, tengo que reescribir parte y eso significa que no habrá una publicación de una sola tirada, sino más bien por partes. De esta manera, a parte de tener más tiempo para estudiar código y hacer cambios también lo puedo plantear como un tutorial. Bueno, empecemos:
PARTE 1: Movimiento básicoEn esta parte (muy básica), se implementa de manera muy sencilla el movimiento por salas. Volveremos a esta parte más tarde, cuando se haya avanzado en otras partes, para hacerla más compleje e interesante.
Código: Seleccionar todo
location = record
region, room: byte;
name, description: string;
adjacent: directions;
end;
Esto es el tipo de datos estructurados que uso para el sistema de desplazamiento. No es mínimo, si se quisiera hacer espartano, sólo la última línea del registro sería necesaria para su funcionamiento, pero si el nodo no contiene información tampoco se puede probar nada. A medida que el proyecto avance se van a añadir algunas cosillas.
Código: Seleccionar todo
directions = record
options: byte;
choices: array[1..6] of direction;
end;
Esto es una pequeña lista basada en array, contiene las direcciones de las salas adyacientes. Si no contiene ninguna, el primer campo debe ser 0 (y lo es cuando se inicializa).
Código: Seleccionar todo
direction = ^location;
player = record
currentLocation: direction;
end;
Finalmente, los otros tipos definidos para montar el sistema básico es el tipo puntero para la sala y un registro que contiene variables del jugador. De momento sólo he definido la posición (el puntero a la sala) en que se encuentra, aunque otros campos se añadirán en el futuro.
Ahora toca definir funciones y métodos varios.
Código: Seleccionar todo
procedure printLocation(player: player);
procedure printChoices(player: player);
procedure move(var player: player; choice: byte);
function createDirection(region, room: byte; name, description: string): direction;
procedure connectRoom(var originRoom: direction; destinationRoom: direction);
procedure connectRoomBidirectional(var room_A, room_b: direction);
"printLocation" escribe los datos propios de la sala en la que el jugador se encuentra. "printChoices" escribe en pantalla los nombres de las salas adyacientes. "move" cambia la sala en la que se encuentra el jugador. "createDirection" crea una nueva sala y devuelve un puntero hacia ella. "connectRoom" añade el puntero de una sala en la lista de adyacientes de otra sala, funciona solo en una dirección, lo que es conveniente. "connectRoomBidirectional" añade el puntero de cada una de las dos salas que se pasan como parámetro en la lista de adyacientes de la otra, de manera que la conexión resulta bidireccional.
Definido esto, se procede a la implementación.

- code_1.png (39.77 KiB) Visto 452 veces

- code_2.png (33.89 KiB) Visto 452 veces
Esto no es un programa, sino una "unit", que es el nombre que reciben las librerías de Pascal. Un RPG, incluso el más sencillo, requiere de un numero bastante elevado de registros, listas y otros datos estructurados, además de bastantes métodos y funciones. Separando la definición de tipos y la lógica del programa en sí mejora la lectura en el programa y permite que distintos programas (como programas de pruebas o ejemplos básicos) puedan usarlos sin tener que reescribirlo todo otra vez.
Código: Seleccionar todo
program MovementTest;
uses RPGLogic, crt;
var
player: player;
well, stairs: direction;
choice: byte;
begin
player.currentLocation := createDirection(1,1,'Starting Room','Nothing worth to be seen...');
well := createDirection(1,2,'Well', 'Smell is awful!');
stairs := createDirection(1,3,'Stairs', 'Some old and fragile stairs... They seem dangerous buuuut...');
connectRoom(player.currentLocation, well);
connectRoomBidirectional(player.currentLocation, stairs);
connectRoomBidirectional(well, stairs);
repeat
clrscr;
printLocation(player);
printchoices(player);
choice := inputDirection(player);
if choice > 0 then
move(player, choice);
until choice = 0;
end.
Esto es el programa de prueba. La entrada de datos está ejecutando el futuro comando "go" permanentemente, pero sólo para ilustrar ya sirve. Voy a recuperar código para hacer una entrada de datos más decentilla la próxima vez. El programa es un ejemplo sencillo de navegación usando vínculos unidireccionales y bidireccionales. Tanto la librería como el programa compilan con Dev-Pascal. Si hay alguna cosa que no se entienda, no dudéis en preguntar. Si hay alguna sugerencia, idea o mejora que se quiera proponer soy todo oídos.
También tenéis disponibles los archivos, por si queréis compilar.
Saludos!