#!/bin/bash

# Author: Christophe Casalegno / Brain 0verride
# Contact: brain@christophe-casalegno.com
# Version 0.1
#
# Copyright (c) 2023 Christophe Casalegno
#
# This program is free software: you can redistribute it and/or modify
#
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <https://www.gnu.org/licenses/>
#
# The license is available on this server here:
# https://www.christophe-casalegno.com/licences/gpl-3.0.txt

# On setup la largeur et la hauteur + un fixe une valeur par défaut à 11
width=${1:-11}
height=${2:-11}

# On déclare 2 tableaux : 1 pour le labyrinthe et un autre pour les directions
declare -A maze
directions=(0 1 2 3)

# On initialise la "matière brute" du labyrinthe et on définit le point de départ ainsi que le point d'arrivée 

function initialize() {
    for ((i=0; i<$height; i++)); do
        for ((j=0; j<$width; j++)); do
            maze[$i,$j]=1
        done
    done
    maze[1,0]=0
    maze[$((height-2)),$((width-1))]=0
}

# On va creuser dans le labyrinthe selon l'algorithme DFS (Depth-First Search) 

function carve() {
    local x=$1 y=$2

    # On utilise shuf pour choisir un mouvement aléatoire dans le tableau de directions
    directions=( $(shuf -e "${directions[@]}") ) 

    # On vérifie si la cellule dans la direction choisie est un mur (est = à 1)
    # Si la valeur est à 1, la cellule actuelle ainsi que la cellule dans cette direction est alors marquée
    # comme un chemin "ouvert" avec une valeur à 0. Le labyrinthe se "creuse" ainsi petit à petit
    
    for direction in "${directions[@]}"; do
        dx=0; dy=0
        case $direction in
            0) ((dx=-1));;
            1) ((dy=1));;
            2) ((dx=1));;
            3) ((dy=-1));;
        esac
        nx=$((x+2*dx)); ny=$((y+2*dy))
        if ((nx > 0 && nx < width-1 && ny > 0 && ny < height-1)) && [[ "${maze[$ny,$nx]}" == 1 ]]; then
            maze[$((y+dy)),$((x+dx))]=0
            maze[$ny,$nx]=0
	    # on appelle la fonction carve de manière récursive sur la nouvelle cellule
            carve $nx $ny
        fi
    done
}

# On affiche le labyrinthe en convertissant les statuts 1 ou 0 en cases vides ou pleines. 

function print_maze() {
    for ((i=0; i<$height; i++)); do
        for ((j=0; j<$width; j++)); do
            if [[ ${maze[$i,$j]} -eq 1 ]]; then
                printf "▒"
            else
                printf " "
            fi
        done
        printf "\n"
    done
}

initialize
carve 1 1
print_maze

