22/10/08

Zambulléndose en Simutrans (IV): una pequeña modificación

Una vez que sabemos obtener el código, compilarlo y aplicar un parche, solo nos falta pensar en una modificación y aplicarla. Vamos a realizar una pequeña modificación que nos dará la posibilidad de tener convoys ferroviarios de más de 24 vagones, que es el límite actual.

Leer más...

Tengo que confesar que en este caso juego con ventaja, porque esto ya fue propuesto por otras personas y Prissi, el desarrollador que coordina Simutrans, dijo donde había que tocar para conseguir que los convoyes ferroviarios tuvieran más de 24 vagones.

De todas formas, como en cualquier proyecto que abordas, ya sea para modificarlo o para crear cosas nuevas desde cero, es necesaria algo de intuición. A primera vista, si pensamos donde habría que modificar para conseguir aumentar la longitud máxima del convoy, es probable que no supieramos por donde empezar....

Dando unas pocas vuelta más al asunto, podemos asociar los convoys con los depósitos o cocheras. Realmente no hay muchos más candidatos. Las estaciones no influyen en la disposición del convoy y el resto de estructuras ferroviarias como los puentes y los túneles tampoco tienen porque. ¿Los trenes en sí mismos? uhmm...podría ser, pero el juego está diseñado usando el paradigma de la orientación a objetos, por tanto los convoys no se consideran como un todo, sino como la asociación de varios objetos(instancias) de la clase tren. En ese caso, el único candidato que nos queda es el depósito de trenes.

Aunque el código de Simutrans está en alemán, gran parte de los comentarios están en inglés. En el idioma de shakespeare, cochera o depósito es depot, así que podemos empezar la busqueda por algun fichero que cuyo nombre contenga dicho término. ¡¡anda, mira por donde existe un fichero llamado simudepot.h!!

Abrimos el fichero con un editor de texto (Notepad, Vim, UltraEdit) y como podeís comprobar esta escrito en C++. El archivo contiene un conjunto de clases que representan a los distintos tipos de cocheras que existen en Simutrans (bus, camión, maglev, tren, tranvía, monorraíl, avión y ferry). Las distintas clases empiezan siempre por
class tipodepot_t : public depot_t

Como lo que nos interesa es la parte de trenes, nos situamos en la línea 219 que contiene lo siguiente:
class bahndepot_t : public depot_

No tengo ni idea de lo que significa, pero tres líneas más abajo aparecen las palabras Lokomotive y Waggon, por lo tanto supongo que esta será la parte relacionada con la cochera de trenes.

Proseguimos el rastreo. Lo que buscamos está relacionado con la longitud del convoy. Longitud en inglés es length. Si miramos unas líneas más abajo, concretamente en la 245, aparece la siguiente instrucción:
unsigned get_max_convoi_length() const { return convoi_t::max_rail_vehicle;

Parece que lo que hace esta función es obtener el valor de la longitud máxima de un convoy ferroviario. Para esto, consulta el atributo max_rail_vehicle del objeto convoi_t y devuelve su valor. Parece que hemos encontrado lo que buscábamos, ¿no?

En este punto tenemos dos opciones. Podemos poner un valor entero, como aparece en algunos de los otros depósitos, lineas 333 para bus,398 para avión y 370 para ferry. La otra opción es buscar donde se define el valor de dicho atributo max_rail_vehicle y modificarlo. Evidentemente la segunda opción supone más búsqueda en otros ficheros, principalmente los que se mencionan a partir de la línea 11, precedidos por la palabra include. Un buen candidato sería convoihandle_t.h

En este caso vamos a optar por la primera, por ser más fácil y rápida. Pues bien, sustituimos el contenido de la línea 245 por este otro:
unsigned get_max_convoi_length() const { return 30; }

que simplemente le dice que la long. máxima para un convoy ferroviario será de 30 vagones.

Ahora guardamos los cambios y solo nos queda compilar el código de nuevo. Si no sabes como, repasa este artículo sobre el tema. Una vez tenemos el ejecutable, comprobamos que los cambios han surtido efecto, creando un convoy de 30 vagones (1+29).

Como comprobareís no funciona porque aunque te deja comprar hasta 30 vagones, no los muestra cuando el vehículo sale del depósito. Eso significa, entre otras cosas, que la variable max_rail_vehicle tiene un valor fijo en algún lado, solo para cuando tiene que mostrar los elementos que componen el convoy en pantalla. Para solucionar esto, primero pulsamos deshacer para dejar esa línea como estaba y después hacemos una búsqueda del término max_rail_vehicle en todos los archivos con extensión *.cc o *.h. Entre los distintos resultados de la búsqueda, no fijamos en los relacionados con el archivo simconvoi.cc:
fahr.resize(max_rail_vehicle, NULL);
fahr.resize(max_rail_vehicle, NULL);

Esta lineas no usan un método get sino que obtiene el valor de la variable de forma directa. Además, en el fichero simconvoi.h vemos la siguiente línea:
enum { max_vehicle=4, max_rail_vehicle = 24 };

Si cambiamos ese valor 24 por 30, guardamos los cambios y compilamos de nuevo, comprobaremos que ahora si muestra los 30 vagones del convoy.

Podeís hacer otra prueba poniendo menos vagones, digamos 10, y comprobando que no te deja comprar más de dicha cantidad.

Como veís es algo sencillo y fácil de hacer. Pequeñas modificaciones como estas se pueden hacer a cientos, solo teneís que bucear un poco en el código. En futuros artículos propondremos otros pequeños cambios.

No quisiera terminar, sin agradecer la inestimable ayuda de isidoro en este tema, a la hora de resolver mis dudas. Muchas gracias.

Relacionados:
Zambulléndose en Simutrans (I): A por el código.
Zambulléndose en Simutrans (II): compilando el código fuente
Zambulléndose en Simutrans (III): aplicando un parche

No hay comentarios: