Pular para o conteúdo principal

O arquivo de configuração

O programa não pergunta nada ao usuário antes de gerar: tudo o que ele precisa saber (o tamanho do labirinto, onde ficam a entrada e a saída, onde gravar o resultado) vem de um arquivo de texto, o arquivo de configuração, passado na linha de comando:

python3 a_maze_ing.py config.txt

O nome config.txt é só um exemplo: o programa aceita qualquer nome de arquivo.

Formato​

Uma opção por linha, no formato CHAVE=valor. Linhas que começam com # são comentários, ignorados pelo programa. Este é o config.txt que acompanha o projeto:

# Width of the maze, in cells (1 to 100)
WIDTH=20
# Height of the maze, in cells (1 to 100)
HEIGHT=15
# Entry cell as x,y (x = column, y = row, both from 0)
ENTRY=0,0
# Exit cell as x,y
EXIT=19,14
# File that receives the maze in hexadecimal
OUTPUT_FILE=maze.txt
# True: perfect maze (single path); False: Pac-Man board (default)
PERFECT=False
# Uncomment to get the same maze on every run
# SEED=42

Os comentários estão em inglês porque todos os textos do projeto (código, mensagens, arquivos) estão em inglês.

As opções​

ChaveObrigatóriaExemploO que define
WIDTHsim20quantas colunas a grade tem
HEIGHTsim15quantas linhas a grade tem
ENTRYsim0,0a célula de entrada, no formato x,y
EXITsim19,14a célula de saída, no formato x,y; diferente da entrada
OUTPUT_FILEsimmaze.txto nome do arquivo onde o labirinto é gravado
PERFECTsimFalseo tipo de labirinto: True para perfeito, False para tabuleiro de Pac-Man
SEEDnão42a semente do sorteio (explicada abaixo)

As seis primeiras são exigidas pelo enunciado. SEED é uma opção que este projeto acrescenta, o que o enunciado permite.

Lembrando o endereço de uma célula: em x,y, o x é a coluna (posição na horizontal) e o y é a linha (posição na vertical), contando de 0 a partir do canto de cima à esquerda. Em 20x15, a entrada 0,0 é o canto de cima à esquerda e a saída 19,14 é o canto de baixo à direita.

A semente (SEED)​

O labirinto é sorteado: cada execução gera um labirinto diferente. Mas o enunciado exige que dê para repetir um labirinto, por exemplo para mostrar o mesmo resultado na avaliação.

O sorteio de um computador não é aleatório de verdade: ele sai de uma conta que parte de um número inicial, a semente. Mesma semente, mesma sequência de sorteios, mesmo labirinto.

  • Sem SEED, o programa usa uma semente diferente a cada execução.
  • Com SEED=42, toda execução gera exatamente o mesmo labirinto.

Limites de tamanho​

O enunciado não fixa limites para WIDTH e HEIGHT, só manda recusar valores impossíveis, como tamanho negativo. Este projeto aceita de 1 a 100:

  • o mínimo 1 vem da lógica: não existe labirinto com 0 colunas;
  • o máximo 100 é uma escolha do projeto: uma grade 200x100 já leva mais de 10 segundos para ser gerada, e valores enormes estouram a memória. Com o limite, um WIDTH=1000000 dá uma mensagem de erro em vez de travar o computador.

Regras de leitura​

O arquivo é escrito por pessoas, então a leitura perdoa o que é inofensivo e recusa o que é ambíguo:

SituaçãoO que acontece
espaços em volta (WIDTH = 20)ignorados
chave em minúsculas (width=20)aceita: WIDTH e width são a mesma chave
linha vazia ou comentáriopulada
chave repetidavale a última
chave desconhecida (COLOR=red)ignorada
linha sem = (HEIGHT 15)erro, citando o número da linha
chave obrigatória faltandoerro, listando todas as que faltam
valor inválido (WIDTH=abc)erro, citando a chave e o valor

As regras de perdoar ou recusar são escolhas do projeto: o enunciado só exige que todo erro vire uma mensagem clara.

Erros​

Quando algo está errado, o programa termina com uma única linha de mensagem, começando com Error: :

Error: config.txt: missing mandatory key(s): WIDTH, HEIGHT
Error: config.txt: WIDTH must be an integer, got 'abc'
Error: config.txt: ENTRY and EXIT must differ

Três detalhes dessa mensagem:

  • ela sai em stderr, a saída de erros do programa, separada da saída normal (stdout). Num terminal as duas aparecem juntas, mas um script consegue separá-las;
  • o programa termina com código de saída 1. Todo programa devolve um número ao terminar: 0 quer dizer sucesso e qualquer outro valor quer dizer erro. Esse número aparece no terminal com echo $?;
  • nunca aparece traceback, a listagem de linhas de código que o Python imprime quando uma exceção (um erro em andamento no programa) não é tratada. O enunciado exige que o programa nunca quebre assim.

O enunciado só exige que todo erro vire uma mensagem clara. O prefixo Error: , a saída em stderr e o código 1 são escolhas do projeto: um formato fixo deixa o erro fácil de reconhecer, e o código diferente de 0 avisa um script que algo deu errado.

Duas mensagens fogem dessa regra. O aviso de que o "42" não coube no labirinto também começa com Error: , mas o programa continua e termina com código 0. A página do "42" explica por quê. E a linha de uso, impressa quando o programa recebe zero ou mais de um argumento, começa com Usage: em vez de Error: (e termina com código 1), no formato tradicional dos programas de terminal para dizer como chamá-los (parte 14).

A parte 11 implementa a leitura e as mensagens.