TP1 - Sokoban

El Sokoban es un videojuego estilo puzzle o rompecabezas en el que el jugador empuja un conjunto de cajas en un depósito, con el objetivo de ubicar las cajas en lugares específicos.

Reglas

La grilla:

  • El juego se desarrolla en una grilla rectangular de F filas y C columnas, formando así un total de F x C celdas.
  • Una celda puede contener una pared, que impide que cualquier otro elemento se ubique en ese lugar.
  • Una celda (que no sea una pared) puede estar marcada con un objetivo.
  • Una celda (que no sea una pared) puede contener una caja.
  • La grilla contiene al menos tantas cajas como objetivos.
  • Una celda se considera vacía si no es una pared y no contiene una caja.
  • La grilla contiene un jugador que comienza ubicado en una celda vacía.
  • El jugador, las cajas y los objetivos están rodeados de paredes (es decir, no debería ser posible que el jugador o las cajas lleguen mediante un movimiento a los límites de la grilla).

Movimiento:

  • El juego se desarrolla por pasos, y en cada paso el jugador tiene la opción de moverse en cualquiera de las cuatro direcciones: norte, este, sur, oeste. El jugador intentará moverse a la celda vecina en esa dirección.
  • Si la celda vecina está vacía, el movimiento está permitido y el jugador se mueve a esa celda.
  • Si la celda vecina es una pared, el movimiento no está permitido y el jugador se queda en su lugar.
  • Si la celda vecina es una caja, puede ocurrir dos cosas, dependiendo de la celda vecina a la caja en la dirección de movimiento. Sea C1 a la celda vecina al jugador (la celda que contiene una caja) y C2 la celda vecina a la caja (la celda siguente en la dirección de movimiento).
    • Si la celda C2 está vacía, el movimiento está permitido. En ese caso, la caja que estaba en la celda C1 se mueve a la celda C2, y el jugador se mueve a la celda C1.
    • En caso contrario, el movimiento no está permitido.

Resolución:

  • El juego se considera ganado cuando todas las celdas objetivo tienen una caja encima.

Consigna

El objetivo de este ejercicio es implementar las funciones para controlar la lógica del juego Sokoban.

Se deberá crear un archivo soko.py con (al menos) las siguientes funciones:

def crear_grilla(desc):
    '''Crea una grilla a partir de la descripción del estado inicial.

    La descripción es una lista de cadenas, cada cadena representa una
    fila y cada caracter una celda. Los caracteres pueden ser los siguientes:

    Caracter  Contenido de la celda
    --------  ---------------------
           #  Pared
           $  Caja
           @  Jugador
           .  Objetivo
           *  Objetivo + Caja
           +  Objetivo + Jugador

    Ejemplo:

    >>> crear_grilla([
        '#####',
        '#.$ #',
        '#@  #',
        '#####',
    ])
    '''

def dimensiones(grilla):
    '''Devuelve una tupla con la cantidad de columnas y filas de la grilla.'''

def hay_pared(grilla, c, f):
    '''Devuelve True si hay una pared en la columna y fila (c, f).'''

def hay_objetivo(grilla, c, f):
    '''Devuelve True si hay un objetivo en la columna y fila (c, f).'''

def hay_caja(grilla, c, f):
    '''Devuelve True si hay una caja en la columna y fila (c, f).'''

def hay_jugador(grilla, c, f):
    '''Devuelve True si el jugador está en la columna y fila (c, f).'''

def juego_ganado(grilla):
    '''Devuelve True si el juego está ganado.'''

def mover(grilla, direccion):
    '''Mueve el jugador en la dirección indicada.

    La dirección es una tupla con el movimiento horizontal y vertical. Dado que
    no se permite el movimiento diagonal, la dirección puede ser una de cuatro
    posibilidades:

    direccion  significado
    ---------  -----------
    (-1, 0)    Oeste
    (1, 0)     Este
    (0, -1)    Norte
    (0, 1)     Sur

    La función debe devolver una grilla representando el estado siguiente al
    movimiento efectuado. La grilla recibida NO se modifica; es decir, en caso
    de que el movimiento sea válido, la función devuelve una nueva grilla.
    '''

Nota: La primera función a implementar será crear_grilla, y habrás notado que en su documentación no se especifica qué tipo de dato devuelve la función. Parte del objetivo del TP es que vos decidas cuál es la estructura de datos más apropiada para representar la grilla. Todas las demás funciones recibirán como primer parámetro la grilla creada mediante crear_grilla. Si la estructura fue bien elegida la implementación de todas las funciones será fácil.

Pruebas

Se dispone de un archivo de pruebas, que valida la implementación de soko.py con algunos casos comunes.

Para utilizarlo, ubicar el archivo soko_test.py en la misma carpeta que soko.py, y ejecutar:

python3 soko_test.py

Si la implementación es correcta, se imprimirá un mensaje indicándolo. En caso contrario, se imprime un mensaje de error describiendo la prueba que falló. La documentación de cada prueba indica cuál es el caso que se está contemplando.

Nota: Las pruebas provistas no son exhaustivas. Es posible que exista algún caso donde el código no funcione correctamente. No obstante, una de las condiciones mínimas para que el trabajo práctico esté aprobado es que pase el archivo de pruebas soko_test.py.

Entrega

La corrección de los trabajos a partir del TP1 serán por la plataforma GitHub. Para esto será necesario crearse una cuenta de GitHub e indicarnos el usuario mediante este formulario.

Una vez completado el formulario, se deberá entregar el archivo soko.py utilizando el sistema de entregas de nuestra página.