Manhla

Un programa de ordenador para jugar muchas variantes del Juego del 15.

Manual aún más avanzado

Los ficheros .puz

Como hemos avanzado en la segunda parte de este manual, lo esencial para definir un nuevo juego para Manhla es crear un fichero de texto con extensión .puz y ponerlo en uno de los subdirectorios del directorio puzzles (los conjuntos de juegos o puzzles). Podemos usar Otros o añadir un nuevo conjunto simplemente creando otro subdirectorio.

Hay que aclarar que la versión para MS-DOS usa su propia copia de los ficheros, respetando la longitud máxima de ocho caracteres para el nombre y usando letras mayúsculas. En este caso, el directorio correspondiente a puzzles es DOSPUZ y los nombres de los conjuntos de juegos (subdirectorios de DOSPUZ) también siguen la convención de los ocho caracteres y las mayúsculas.

Un fichero .puz consiste en una serie de asignaciones del tipo:

variable = valor

Aunque no siempre el valor está en la misma línea que el nombre de la variable. Hay dos tipos de asignaciones: simples y complejas. En las simples el valor está en la misma línea y en las complejas en las líneas siguientes (normalmente más de una). He aquí un ejemplo de asignación simple:

nombre = "Anillo"

Y aquí de una asignación compleja:

pos_fin =
   4 5 6
   3 0 7
   2 1 8

Se aplican las siguientes reglas de sintaxis generales:

Hay unas 20 variables distintas, pero la mayoría son opcionales. Salvo alguna excepción, el orden en que se declaran (se les asigna un valor) no importa, pero se recomienda seguir aproximandamente el orden en que se exponen aquí. Si una misma variable se declara varias veces solo se tiene en cuenta la última. Manhla detecta muchos de los posibles errores que puede haber en un fichero .puz, pero no todos, lo que en algunos casos puede provocar un error que aborte el programa abruptamente y sin explicaciones claras. La mayoría de mensajes relacionados con la lectura de ficheros .puz se muestran como el resto de mensajes del programa, salvo en el caso de la interfaz japi, en la que algunos mensajes de menos importancia se envían solo a la salida estándar (así que solo serán visibles si se ejecuta el programa desde un entorno de línea de órdenes).

Antes de explicar cada una de esas variables vamos a hacer un primer fichero .puz para abrir boca. Este será su contenido (podemos usar cualquier editor de texto para crearlo).

max_x = 3
max_y = 3

Si grabamos el texto con el nombre de prueba.puz en el directorio puzzles/Otros podemos jugarlo ejecutando:

manhla -p puzzles/Otros/prueba.puz

El aspecto inicial de nuestro «nuevo» juego será similar a este:

Fig. 1. Un juego poco original.

No es un juego muy original, ya que se trata de la versión 3×3 del clásico. De hecho está incluido en Clasicos con el nombre de Ocho (aunque usa otros gráficos para las piezas).

Veamos a continuación cada una de las variables que define un juego o puzzle.

nombre

Simplemente define el nombre del puzzle. El valor es una cadena de caracteres encerrada entre comillas dobles. Ejemplo:

nombre = "Juego del 15"

Esta variable no es obligatoria. Si no aparece se toma como nombre el del fichero .puz (sin la extensión).

El nombre que aparece en la ventana de selección de la interfaz japi no se toma de aquí, sino de un fichero diferente (como se explicará más adelante).

max_x y max_y

Son dos variables simples con valor numérico entero mayor que 1. Definen las dimensiones horizontal (max_x) y vertical (max_y) del puzzle (en casillas). Ejemplo:

max_x = 3
max_y = 3

Ambas son opcionales, ya que sus valores se pueden deducir de pos_fin.

valor_esp

Variable numérica que indica qué casilla de pos_fin corresponde al espacio o hueco. Si no se indica toma el mayor valor de los declarados en pos_fin. Veamos un ejemplo:

max_x = 3
max_y = 3
valor_esp = 5

Se trata de una definición completa de un 3×3 con hueco en el centro, en el lugar de la pieza 5. Esta sería su posición final:

Fig. 2. 3×3 con hueco central.

pos_fin

Variable compleja que consiste en una tabla de números enteros mayores o iguales que 0. He aquí un ejemplo:

pos_fin =
   9 8 7
   6 5 4
   3 2 1

Esta sola declaración es suficiente para definir un puzzle 3×3 con movimiento clásico y la siguiente posición final:

Fig. 3. 3×3 con posición final inversa.

Cada fila de la tabla debe tener el mismo número de elementos. Debe haber dos o más filas y dos o más columnas. Si no se han declarado antes, el número de filas y de columnas definen max_x y max_y.

Los números de cada fila se puede separar con comas (una sola), espacios (uno o más) o una combinación de ambos.

Los números deben ser correlativos, desde el 1 y sin repetirse. Estos números pueden considerarse marcas que identifican cada casilla y cada pieza, teniendo en cuenta que a una casilla no le corresponde ninguna pieza (la de número valor_esp).

Más adelante hablaremos sobre los ficheros gráficos para las interfaces japi, dosgraf y vga, que imponen un límite a los números que podemos usar. Si se usa un número demasiado alto se producirá un error run-time, aunque antes se enviará a la salida estándar un mensaje del tipo «No está la pieza número tal».

pos_fin puede contener ceros. Un cero indica una posición que no pertenece al tablero de juego, no es una casilla. Estos espacios se llaman bloques y se diferencian gráficamente de alguna forma, como por un aspecto de madera de color más oscuro que el fondo por el que se mueven las piezas (en el caso de las interfaces texto y simple estos bloques quedan vacíos, mientras que el hueco se marca con un punto). Veamos un ejemplo y su resultado:

pos_fin =
   0 1 2
   3 4 5
   6 7 0
Fig. 4. 3×3 con dos bloques.

Fig. 5. El mismo puzzle en la interfaz texto.

Nótese en la figura cinco que las piezas 3 y 4 (de azul) se pueden mover, pero las 2, 5 y 6 no, porque están junto a un bloque, no junto al hueco.

No es obligatorio declarar pos_fin si se han declarado max_x y max_y o pos_ini. Si se han declarado max_x y max_y y no pos_ini (que tomará el valor "aleat") se rellenará la tabla con números 1, 2,... hasta el producto de max_x y max_y. Si se ha declarado pos_ini se construye pos_fin ordenando los números que contenga distintos de cero y dejando los ceros en el mismo sitio.

equiv

Variable compleja para definir piezas equivalentes. Hemos visto al hablar de pos_fin que cada pieza se indentifica con un número único. Pero eso no quiere decir que no pueda haber piezas idénticas y por tanto, intercambiables en cuanto a la posición final. Imaginemos, por ejemplo, un puzzle en el que las piezas tienen pintadas letras en vez de números (esto solo se aplica a la interfaz japi, en las otras siempre se ven números). El objetivo de este puzzle hipotético es formar la palabra «MANDARIN» en un tablero 3×3 dejando el hueco al final. Este puzzle tendrá 8 piezas, identificadas por los números del 1 al 8; pero las piezas 2 y 5 (la primera y la segunda A) tendrán el mismo aspecto (usarán el mismo fichero gráfico) y lo mismo las piezas 3 y 8 (las dos N). Debemos contar con ficheros gráficos 1 (M), 2 (A), 3 (N), 4 (D), 6 (R) y 7 (I). Y definiremos el siguiente fichero .puz:

pos_fin =
   1 2 3
   4 5 6
   7 8 9

equiv =
   2 = 5
   3 = 8

En ese caso concreto podríamos haber sustituido pos_fin por:

max_x = 3
max_y = 3

Esta podría ser la imagen de este puzzle (no resuelto):

Fig. 6. Juego con letras repetidas.

En casos como este de piezas repetidas podemos encontrarnos con situaciones como las de la imagen, aparentemente irresolubles. Es conocido que en el Juego del 15 y cualquiera similar no se puede hacer un intercambio de dos piezas y en este caso parece que hace falta intercambiar las dos piezas N e I del final. Si pulsamos J para que aparezcan los números únicos que identifican las piezas veremos lo que pasa:

Fig. 7. Juego con letras repetidas.

La N de la tercera posición no es la que va allí. También se podría resolver intercambiando las piezas A. Esto quiere decir que la posición:

   1 5 8
   4 2 6
   7 3 9
también es una solución válida aunque no aparezca en pos_fin.

equiv debe tener tantas líneas como conjuntos de piezas equivalentes. A la izquierda del signo = aparece el número de la pieza que tiene el fichero gráfico; a la derecha, las demás piezas que usan ese mismo fichero (separadas por comas o espacios). El orden de los números de la derecha del = y de las líneas es irrelevante. Esta es la declaración equiv del juego 4x3 con paredes - 2 (gráfico 2).

equiv = 
   1 = 5, 9
   2 = 7
   4 = 6, 10

barreras

La variable barreras permite limitar los movimientos entre ciertas casillas. He aquí una definición de puzzle y su posición final:

max_x = 3
max_y = 3
barreras =
   2 | 5
   4 | 5
   8 < 9
Fig. 8. Juego con barreras.

Cada fila consiste en dos números de casilla, como aparecen identificados en pos_fin (en el ejemplo con el valor por defecto) separados por uno de los caracteres: |, < o >. El carácter < indica que se prohíbe el movimiento desde la primera casilla hacia la segunda; el carácter > indica que se prohíbe el movimiento desde la segunda casilla hacia la primera; El carácter | indica que se prohíben ambos movimientos.

Las dos casillas entre las que hay una barrera no tienen por qué ser contiguas (pensemos, por ejemplo, en juegos con movimiento tipo caballo de ajedrez). Si son contiguas se muestran de alguna forma, como una línea continua o una flecha (véanse las imágenes 8 y 9).

Fig. 9. El mismo juego en la interfaz simple.

A las barreras en ambas direcciones entre casillas contiguas las llamo paredes.

clave_mov

clave_mov es una variable que define de forma general el tipo de movimiento de un puzzle. A diferencia de conectores o barreras no se refiere a casillas concretas, sino a la relación de una casilla con respecto al hueco. Ejemplo:

clave_mov =
   0, 1
   0,-1
  -1, 0
   1, 0

Cada línea consiste en una pareja de números, que pueden ser positivos, negativos o cero (ambos cero no). Este par de números define la posición de una casilla con respecto al hueco. El primer número del par es la coordenada horizontal y el segundo la vertical. Por ejemplo, el par (2,-1) indica que en cualquier momento podemos mover hacia el hueco la pieza que esá en la casilla dos pasos a la derecha y un paso hacia arriba de este. (Por cierto, los paréntesis son opcionales, al igual que la coma). La siguiente imagen muestra las coordenadas de las casillas a dos o menos pasos del hueco.

Fig. 10. Coordenadas para clave_mov.

clave_mov contendrá normalmente (o más bien siempre) cuatro pares de números o más. Los cuatro pares del ejemplo anterior corresponden a las cuatro casillas contiguas al hueco (ese es el valor por defecto de clave_mov). Si un par se encuentra en la lista, la correspondiente casilla se podrá mover (por supuesto, salvo que lo impida barreras) y si solo vamos a usar el ratón para mover las piezas el puesto que ocupe en la lista nos dará igual. El orden tiene que ver con el uso del teclado. El par primero se moverá con la tecla de dirección Arriba (o w), el segundo con Abajo (o s), el tercero con Derecha (o d) y el cuarto con Izquierda (o a).

Los cuatro pares siguientes están reservados para las combinaciones de las mismas teclas de dirección con Ctrl o las correspondientes mayúsculas: WSDA. Puede haber más pares en clave_mov, pero no están asociados a ninguna tecla: esas piezas habría que moverlas con otro método, como teclear su número.

conectores

Esta es una tercera variable para definir el movimiento de las piezas entre las casillas. Se puede decir que es la opuesta de barreras, pues dice qué casillas están conectadas, es decir se puede mover una pieza entre ellas. La siguiente es una forma alternativa de definir el clásico 3×3:

pos_fin =
   1 2 3
   4 5 6
   7 8 9

conectores =
   1 - 2, 4
   2 - 3, 5
   3 - 6
   4 - 5, 7
   5 - 6, 8
   6 - 9
   7 - 8
   8 - 9

La línea «1 - 2, 4» indica que la casilla 1 está conectada con las 2 y 4. La línea «2 - 3, 5» indica que la casilla 2 está conectada con las 3 y 5. También está conectada con la 1, pero eso ya lo sabíamos por la primera línea (el signo - indica una conexión bidireccional). Vemos que el resultado es el conocido 3×3, pero mostrando pequeñas líneas de conexión entre las casillas (esto es una característica exclusiva de las interfaces japi, grafdos y vga):

Fig. 11. 3×3 con líneas de conexión.

Otra diferencia no apreciable en la imagen es que no se pueden utilizar las teclas de dirección (o wasd) para mover las piezas. Las dos diferencias se pueden eliminar con esta otra versión de conectores:

conectores =
   1 = 2, 4 (d, b)
   2 = 3, 5 (d, b)
   3 = 6    (b)
   4 = 5, 7 (d, b)
   5 = 6, 8 (d, b)
   6 = 9    (b)
   7 = 8    (d)
   8 = 9    (d)

Cada línea de conectores está formada por:

Cada elemento de la lista a la derecha de - (o el símbolo que sea) representa una conexión. Por ejemplo, «1 - 2, 4» implica que hay una conexión 1-2 y otra 1-4. El carácter - representa una conexión bidireccional y el par -> una conexión unidireccional (se puede mover una pieza desde la primera casilla hasta la segunda, pero no al contrario). En ambos casos podemos sustituir - por = para indicar que no queremos que las conexiones sean visibles.

Opcionalmente, al final de cada línea de conectores se puede poner una lista de teclas correspondientes a cada conexión. Se usan las letras a, b, i, d, en minúsculas y mayúsculas, con el siguiente significado:

Letra Tecla de dirección Tecla alternativa
a Arriba w
b Abajo s
i Izquierda a
d Derecha d
A Ctrl-Arriba W
B Ctrl-Abajo S
I Ctrl-Izquierda A
D Ctrl-Derecha D

Por ejemplo, en «1 = 2, 4 (d, b)», la d corresponde a la conexión 1=2 y la b a la conexión 1=4. Esto quiere decir que para mover una pieza de la casilla 1 a la casilla 2 se puede usar la tecla Derecha y para mover una pieza de la casilla 1 a la casilla 4 se puede usar la tecla Abajo. Como las conexiones son bidireccionales (aparece = y no =>) también se puede mover de 2 a 1 y de 4 a 1. Automáticamente se usan las teclas inversas, es decir (en este caso) Izquierda y Arriba.

Usando la variable conectores es posible asignar a una conexión más de una tecla. Lo ilustraré con el siguiente puzzle:

Fig. 12. Otro puzzle.

Es obvio que a las conexiones horizontales les vienen bien las teclas Izquierda y Derecha y a las verticales las teclas Arriba y Abajo. Podemos usar las combinaciones con Control para las diagonales, pero no hay ninguna razón para preferir Ctrl-Derecha o Ctrl-Abajo para llevar, en la posición de la imagen, la pieza 5 al hueco. Como no hay conflicto con ninguna otra conexión, podemos poner las dos con en una línea de conectores como esta:

   5 - 7, 9 (IB, DB)

Podemos ir de la casilla 5 a la 7 con Ctrl-Izquierda o con Ctrl-Abajo y podemos ir de la casilla 5 a la casilla 9 con Ctrl-Derecha o con Ctrl-Abajo. Aunque se use Ctrl-Abajo en los dos casos no hay conflicto, porque el hueco no puede estar a la vez en 7 y en 9.

El conflicto se produce cuando el hueco está en el centro. Para 7->5 se han definido D (inverso de I) y A (inverso de B); para 9->5 se han definido I y A. Si pulsamos A (es decir, Ctrl-Arriba) se elige la primera de las conexiones en que aparece, esto es, 7->5. Puede resultar extraño llevar la pieza del centro a la casilla 9 con Ctrl-Abajo y después pulsar la inversa, Ctrl-Arriba y que en vez de regresar la misma pieza se mueva la que estaba en la casilla 7.

La lista de teclas, si está presente, debe ir entre paréntesis y sus elementos (una o más teclas) deben separarse por comas. La lista de números no necesita comas.

pos_ini

Variable que define la posición inicial de las piezas. Es la única que puede ser simple o compleja. Si es simple debe valer "aleat", indicando que la posición inicial es aleatoria. Si es compleja tiene la misma forma que pos_fin, pero con los números en otro orden (los ceros no pueden cambiar). Ejemplo:

pos_fin =
   1 2 3
   4 5 6
   7 8 9

pos_ini =
   9 8 7
   6 5 4
   3 2 1

Su valor por defecto es "aleat".

macros

En la segunda parte del manual vimos cómo se pueden definir macros de forma interactiva usando el programa. También es posible definirlas dentro del fichero .puz. Para ello basta añadir una variable macros, con tantas líneas como macros. En cada línea se define una macro, que es simplemente una lista de números positivos, correspondientes a casillas del puzzle. El primer número indica la posición inicial del hueco y los demás los movimientos a realizar. Puede haber hasta 12 macros, que se podrán ejecutar con F1, F2, etc. No se puede definir la macro 2 sin definir antes la 1, etc. Si hay más de 12 líneas se ignoran de la 13 en adelante.

Las macros creadas ejecutando Manhla se graban en un fichero de extensión .mac. En caso de que tanto el fichero .puz como el .mac definan un mismo número de macro prevalecerá la definición del segundo.

Recordemos que dentro de la asignación se pueden insertar comentarios, que en este caso son especialmente importantes. Ejemplo:

macros =
   --
   -- F1
   -- (Z) = 11 c' 12 D
   -- efecto: (4 8 11 10 7)
      12 11 10 6 2 3 7 11 12 8 4 3 2 6 10 11 12

subpuzzles

En la segunda parte del manual se explicó el concepto de subpuzzle. El lugar para definirlos es también el fichero .puz. La declaración de la variable subpuzzles debe contener un número de líneas múltiplo de 3. Cada tres líneas representa una definición de subpuzzle:

He aquí un ejemplo (con dos subpuzzles):

subpuzzles =
   "Cuadriagonal"
   "cuadriagonal1"
   1,7,0,2,4,0,0,0,0,3,8,0,5,0,0,10,0,0,9,0,6,11,0,0,12
   "Reloj"
   "reloj2"
   4,9,0,3,5,0,0,0,0,2,10,0,8,0,0,6,0,0,11,0,1,7,0,0,12

Este ejemplo está tomado del fichero manda.puz. El primer subpuzzle es Cuadriagonal 1. La lista «1,7,0,2...» contiene 25 elementos, tantos como casillas tiene Manda. Las posiciones dentro de la lista representan casillas de Manda y los números identifican casillas de Cuadriagonal 1. Las posiciones con ceros representan casillas en las que debe estar la pieza bien colocada para poder cargar el subpuzzle. En ese caso son las casillas números 3, 6, 7, 8, 9, 12, 14, 15, 17, 18, 20, 23 y 24. (Véase la figura 14 de la segunda parte del manual.) Los números distintos de cero indican las correspondencias entre el resto de casillas y las del subpuzzle. Por ejemplo, en la lista del ejemplo (la primera) hay 12 números positivos, cada una indicando la equivalencia entre una casilla de Manda (la posición en la lista) y una casilla de Cuadriagonal 1 (el número que sea). Así, a la casilla 1 de Manda le corresponde la 1 de Cuadriagonal 1; a la 2, la 7; a la 4, la 2; etc.

Copiemos de la segunda parte del manual el grafo de Cuadriagonal 1 equivalente a una parte de Manda (véase allí la animación que dejaba clara la equivalencia):

Fig. 13. Grafo de Cuadriagonal 1, con los números de Manda.

Fig. 14. Tablero de Cuadriagonal 1.

La lista «1,7,0,2...» se puede construir así:

Buscamos en la figura 13 el 1 y qué número le corresponde en la figura 2. Le corresponde el 1. Eso quiere decir que en la posición 1 de la lista debe ir un 1.

Buscamos en la figura 13 el 2 y qué número le corresponde en la figura 2. Le corresponde el 7. Eso quiere decir que en la posición 2 de la lista debe ir un 7.

En la figura 13 no aparece el número 3. Eso implica que en esa posición de la lista va un 0.

Lo demás se deja como ejercicio.

esquema_simple y esquema_texto

Los juegos basados en una cuadrícula son fácilmente representables en modo de texto. Pero los que se basan en otras disposiciones de casillas y conexiones son más complicados de adaptar. Se trata de representar las líneas de conexión entre las casillas usando caracteres como /, |, \, -... El resultado no siempre es perfecto.

Tanto esquema_simple (para la interfaz simple) como esquema_texto (para la interfaz texto) son variables complejas que contienen varias líneas de texto, encerradas entre comillas. Estas son las correspondientes variables de Redondo 11:

esquema_simple =
      "",
      "",
      "",
      "         \     /",
      "           \ /",
      "            X",
      "           / \",
      "          |   |",
      "        --+---+-",
      "          |   |"

esquema_texto =
      "",
      "",
      "",
      "       \      /",
      "         \  /",
      "       ---X---"

Si es necesario insertar líneas en blanco al principio o por en medio se ponen cadenas vacías (""). Las comas del final son opcionales.

En este caso el resultado es, creo yo, bastante aceptable:

Fig. 15. Redondo 11 en la interfaz simple.

Fig. 16. Redondo 11 en la interfaz texto.

La idea es indicar las conexiones entre las casillas según sus posiciones en pos_fin o pos_ini. Hay que tener cuidado de que no tapen los números.

Por supuesto, pos_fin y pos_ini solo cumplen una función visual, las conexiones reales hay que establecerlas con otras variables (sobre todo conexiones, pero puede que también clave_mov o barreras).

posiciones

Esta es una variable que solo se utiliza en la interfaz japi y que permite salirse de la estructura de cuadrícula para colocar las casillas en cualquier posición del tablero. Se usa, por ejemplo, en el juego Redondo 11:

posiciones=
   1 (161,344)
   2 (238,344)
   3 (306,306)
   4 (344,238)
   5 (344,161)
   6 (306,93)
   7 (238,55)
   8 (161,55)
   9 (93,93)
   10 (55,161)
   11 (55,238)
   12 (93,306)

Cada línea consiste en un número de casilla y un par de coordenadas. Los paréntesis y la coma son opcionales.

Las coordenadas correspoden a los píxeles que hay desde el centro de la casilla hasta los bordes izquierdo (primera coordenada) y superior (segunda coordenada) del tablero. El marco tambien cuenta.

Fig. 17. Coordenadas de la casilla 1 en Redondo 11.

info, info_simple, info_texto e info_japi

Este conjunto de variables consisten en listas de cadenas de texto (una cadena en cada línea) para dar información al usuario sobre el juego definido en ese fichero.

En cada caso solo se mostrará el contenido de una de estas variables. Si solo está definida info se usará esta en todas las interfaces. Podemos definir una de las otras tres para adaptar la información a la correspondiente interfaz.

El texto correspondiente aparece al pulsar H o, en japi, con la opción Información del menú Ayuda. Si no se declara info ni la variable que corresponda a la interfaz usada, no se mostrará ningún texto (en japi la opción estará desactivada).

No existe una variable especial para las interfaces gráficas de MS-DOS, pero como en este sistema se usan ficheros específicos se puede adaptar info si se considera coveniente.

Esta es la declaración que incluye el fichero quince.puz:

info =
   "En este juego clásico cada movimiento consiste en deslizar",
   "hacia el hueco una pieza que esté a su lado. El objetivo",
   "es ordenar todas las piezas según su número, desde el 1",
   "hasta el 15, dejando el hueco al final."

Aunque el programa no lo controla, las dimensiones del texto están limitadas por las características de la interfaz y el tamaño del tablero. Se recomienda no superar las seis líneas de texto y que estas no alcancen los 80 caracteres. En algunos casos (al menos en las interfaces texto y las dos gráficas de MS-DOS) se pueden producir errores que aborten el programa al intentar escribir fuera de la pantalla.

japi_imag

Esta última variable (solo para la interfaz japi, como es obvio), es útil para hacer que varios juegos compartan los mismos ficheros gráficos. Lo único que hace es definir un nombre de subdirectorio de imag/japi donde el programa encontrará los ficheros gráficos que debe utilizar. En la siguiente sección se explican cómo deben ser esos ficheros gráficos. Esta es la definición que incluyen los juegos del conjunto Cuadriagonal:

   japi_imag = "parchis"

Los ficheros gráficos

En el directorio principal de Manhla hay un subdirectorio llamado imag que a su vez contiene dos subdirectorios: grafdos y japi. No está prevista a opción de personalizar los gráficos para MS-DOS, así que no hablaremos del contenido de grafdos. En cuanto a japi, incluye dos subdirectorios fundamentales y otros dependientes de los juegos instalados. Los dos fundamentales son estandar y puzzles.

El directorio estandar

El directorio estandar contiene los gráficos que se usan por defecto. Gracias a él podemos crear nuevos puzzles sin tener que añadir ficheros gráficos, aunque el resultado puede no ser siempre muy atractivo.

Los ficheros gráficos pueden ser de cualquiera de estos formatos: GIF, PNG, JPG o BMP. En Linux, la extensión puede estar enteramente en minúsculas o en mayúsculas, pero no mezclando letras minúsculas y mayúsculas (GIF o gif, pero no Gif). Normalmente esto no se aplica a Windows, ya que no diferencia las letras de uno y otro tipo en los nombres de ficheros (creo en las últimas versiones puede cambiarse). Si hay un fichero con extensión gif y otro con extensión GIF se prefiere el primero. La extensión para JPG puede ser también JPEG (o jpeg).

En estandar hay cinco ficheros gráficos y tres subdirectorios. Los ficheros son los siguientes:

fijo_trozo.png Se usa para las posiciones que no forman parte del tablero, es decir, los ceros de pos_fin.
fondo_trozo.png Se usa para la única casilla sin una pieza encima (el hueco). Pero si las piezas no ocupan el cuadrado entero también se muestra debajo de ellas.
mov.png Es una imagen con transparecia que, superponiéndose a ellas, destaca (opcionalmente) las piezas que se pueden mover. Si está activada la opción correspondiente solo se usa para las piezas que se mueven sin la tecla Control.
mov2.png Imagen similar a la anterior pero de otro color. Solo se usa (si está activada la opción) para las piezas que se mueven con el teclado usando la tecla Control.
tick.gif Imagen con transparencia que resalta (opcionalmente) las piezas bien colocadas.

Los subdirectorios son los siguientes:

marco Contiene 8 imágenes (desde 1.gif hasta 8.gif) con las que se representa el marco del tablero.
nums Contiene 25 imágenes (desde 1.png hasta 25.png) con pequeños números que se usan cuando se identifican las piezas pulsando J.
piezas Contiene 25 imágenes (desde 1.png hasta 25.png) que representan las piezas correspondientes a esos números.

El directorio puzzles

El directorio puzzles permite personalizar los gráficos de puzzles o juegos concretos. Hay que tener en cuenta que si se usan ficheros gráficos no apropiados (especialmente en cuanto a su tamaño) se pueden producir errores que en el mejor de los casos hagan que el juego no se vea bien y en el peor que el programa se interrumpa.

El directorio puzzles contiene subdirectorios para conjuntos de juegos y dentro de cada uno un subdirectorio para cada puzzle con gráficos personalizados. El nombre de este subdirectorio debe coincidir con el del fichero .puz sin la extensión. Este directorio puede contener los subdirectorios marco, nums y piezas y los siguientes ficheros (todos ellos opcionales, pues si no están se usan los gráficos estándar; no se incluyen las extensiones, que pueden ser cualesquiera de las antes mencionadas):

fijo_trozo Sustituye a imag/japi/estandar/fijo_trozo.png.
fondo_trozo Sustituye a imag/japi/estandar/fondo_trozo.png.
mov Sustituye a imag/japi/estandar/mov.png. Normalmente será una imagen con transparencia y del mismo tamaño que las piezas. Su esquina superior izquierda se alinea con la esquina superior izquierda de la pieza.
mov2 Sustituye a imag/japi/estandar/mov2.png. Es del mismo tipo que mov, normalmente solo variará el color.
fondo También sustituye a imag/japi/estandar/fondo_trozo.png, pero en este caso se usa para representar todo el interior del tablero, incluyendo, si las hay, las zonas que correspondían a fijo_trozo.png. Esta imagen se puede aprovechar para insertar los números de las casillas o las líneas de conexión (que como explicamos pueden ser invisibles).

No se puede personalizar tick.gif, pero se pueden usar en su lugar piezas alternativas (como veremos en seguida).

El directorio marco contiene imágenes alternativas para el marco. Los nombres de los ficheros deben consistir en los números del 1 al 8 (con la extensión pertinente). Los números 1, 3, 5 y 7 corresponden a las esquinas y deben ser imágenes cuadradas del mismo tamaño. Los números 2, 4, 6 y 8 forman los listones horizontales y verticales y normalmente se repiten. Este esquema representa el caso de quince.puz (realmente el único juego con marco personalizado hasta el momento):

   1 2 2 2 2 3
   8         4
   8         4
   8         4
   8         4
   7 6 6 6 6 5

Obviamente, la altura de 2 y de 6 deben ser iguales al lado de los cuadrados de las esquinas y lo mismo la anchura de 4 y de 8. La anchura de 2 y 6 y la altura de 4 y 8 deben ser iguales y divisores tanto de max_x × ancho_pieza como de max_y × alto_pieza, siendo ancho_pieza la anchura de los ficheros de piezas y alto_pieza la altura (ahora veremos los ficheros de piezas).

Los gráficos que forman el marco pueden incluir transparencias, sobre todo en la parte exterior (en el marco incluido en Juego del 15 sucede esto en las esquinas).

El directorio nums contiene ficheros gráficos con pequeños números para identificar las piezas no numéricas (cuando se pulsa J). Los nombres deben ser 1, 2, etc. Este directorio solo hará falta cuando los números estándar no se vean bien en un juego concreto.

El directorio piezas contiene un fichero gráfico para cada pieza con nombre numérico (1, 2, 3...). Si hay piezas equivalentes puede haber saltos en la serie. Por ejemplo, si la pieza 3 se ha declarado equivalente a la 2:

equiv =
   2 = 3

el fichero 2 se usaría para las piezas 2 y 3.

Las piezas deben tener todas las mismas dimensiones. Aunque todos los puzzles incluidos actualmente tienen piezas cuadradas, es posible hacerlas rectangulares. Sí se debe cumplir la relación antes especificada entre el marco y las piezas.

Las piezas pueden incluir transparencias para tener apariencia no cuadrada o no cubrir todo el espacio que le corresponde por la anchura y altura del fichero gráfico correspondiente. Así puede haber piezas cuadradas pero con bordes redondeados o completamente redondas.

El tamaño del tablero en japi depende de max_x, max_y, ancho_pieza y alto_pieza. Estas dos últimas variables no se declaran en el fichero .puz, sino que se establecen directamente al leer los ficheros de las piezas.

El directorio piezas puede tener un subdirectorio llamado ok que sirve para poner imágenes alternativas para las piezas bien colocadas. Deben tener el mismo tamaño que las versiones normales. Si falta alguna se usa en su lugar tick.gif superpuesta a la pieza normal.

Otros directorios de imágenes

Además de estandar y puzzles, en imag/japi puede haber otros subdirectorios. Cada uno de ellos puede tener los mismos ficheros y subdirectorios que los sudirectorios de juegos concretos que acabamos de describir. Esto es una forma de permitir que varios juegos compartan los mismos gráficos no estándar. Por ejemplo, todos los juegos con movimiento tipo salto de caballo usan los mismos gráficos. En lugar de copiarlos en sendos subdirectorios de imag/japi/puzzles/Manda, creamos uno solo en imag/japi (manda) y añadimos a cada correspondiente fichero .puz la línea:

   japi_imag = "manda"

A la hora de buscar los gráficos, el orden es el siguiente:

Los ficheros para la ventana de selección

Junto a cada fichero .puz (no en DOSPUZ) hay otro par de ficheros que solo son útiles en la interfaz japi. Concretamente se usan en la ventana de selección (pulsando S). Los dos deben tener el mismo nombre que el fichero .puz. Uno es un fichero gráfico de tipo PNG y extensión .png (solo PNG y solo minúsculas en este caso) cuya misión es contener una miniatura del juego de 140 × 140 píxeles. En caso de que el tablero correspondiente no sea cuadrado se puede usar un fondo transparente. La imagen puede mostrar (a elección del que añade el juego) la posición objetivo, la inicial (si tiene posición inicial fija) o una aleatoria.

Fig. 18. Miniatura de Juego del 15.

El otro es un fichero de texto simple, con extensión .txt. Este fichero contiene en la primera línea el nombre del juego (debe ser el mismo que el de la variable nombre del fichero .puz) y en las siguientes un texto descriptivo que puede o no coincidir con el de info. Se recomienda que estas líneas no superen los 40 caracteres. El nombre del juego aparece en la parte superior de la ventana de selección y el texto en un área destinada a ese fin. Si no cabe se puede desplazar el texto. Este es el contenido de quince.txt:

Juego del 15
En este juego clásico cada movimiento
consiste en deslizar hacia el hueco una
pieza que esté a su lado. El objetivo
es ordenar todas las piezas según su
número, desde el 1 hasta el 15, dejando
el hueco al final.

Ninguno de los dos ficheros es obligatorio. Si no está la miniatura aparece una imagen (que dice que no hay imagen), un texto genérico y el nombre del fichero .puz como título.