2018-02-06 16:59:29 +00:00
|
|
|
"""
|
|
|
|
Author: freezed <freezed@users.noreply.github.com> 2018-02-06
|
|
|
|
Version: 0.1
|
|
|
|
Licence: `GNU GPL v3` GNU GPL v3: http://www.gnu.org/licenses/
|
|
|
|
|
|
|
|
Ce fichier fait partie du projet `roboc`
|
|
|
|
|
|
|
|
"""
|
2018-02-15 10:00:12 +00:00
|
|
|
# TODO sortir les doctests
|
2018-02-06 16:59:29 +00:00
|
|
|
import os
|
2018-02-15 10:00:12 +00:00
|
|
|
from configuration import DIRECTIONS, ERR_MAP_FILE, ERR_MAP_ROBO, \
|
2018-02-15 10:00:12 +00:00
|
|
|
MIN_MAP_SIDE, ERR_MAP_SIZE, ERR_UNKNOW, MAZE_ELEMENTS, MSG_START_GAME
|
2018-02-15 10:00:12 +00:00
|
|
|
|
2018-02-06 16:59:29 +00:00
|
|
|
|
|
|
|
class Map:
|
|
|
|
"""
|
|
|
|
Classe gerant les cartes disponibles et la carte utilisee en cours
|
|
|
|
de partie.
|
|
|
|
|
|
|
|
:Example:
|
2018-02-12 16:08:03 +00:00
|
|
|
>>> EasyMap = Map("cartes/facile.txt")
|
2018-02-09 23:29:04 +00:00
|
|
|
>>> TestMap = Map("cartes/test.txt")
|
2018-02-13 16:19:16 +00:00
|
|
|
>>> MiniMap = Map("cartes/mini.txt")
|
2018-02-09 23:29:04 +00:00
|
|
|
>>> PrisonMap = Map("cartes/prison.txt")
|
2018-02-12 16:08:03 +00:00
|
|
|
>>> EmptyMap = Map("cartes/vide.txt")
|
|
|
|
>>> TooSmallMap = Map("cartes/trop_petite.txt")
|
|
|
|
>>> NoRoboMap = Map("cartes/sans_robo.txt")
|
|
|
|
|
|
|
|
>>> print(EmptyMap.status_message)
|
|
|
|
#!@?# Oups… carte «cartes/vide.txt», dimensions incorrecte: «0 x 0»
|
|
|
|
>>> print(TooSmallMap.status_message)
|
2018-02-13 14:59:02 +00:00
|
|
|
#!@?# Oups… carte «cartes/trop_petite.txt», dimensions incorrecte: «3 x 2»
|
2018-02-12 16:08:03 +00:00
|
|
|
>>> print(NoRoboMap.status_message)
|
|
|
|
#!@?# Oups… robo est introuvable sur la carte «cartes/sans_robo.txt»!
|
2018-02-09 23:29:04 +00:00
|
|
|
|
|
|
|
>>> print("_column_nb: {}".format(TestMap._column_nb))
|
2018-02-13 14:59:02 +00:00
|
|
|
_column_nb: 6
|
2018-02-09 23:29:04 +00:00
|
|
|
>>> print("_line_nb: {}".format(TestMap._line_nb))
|
|
|
|
_line_nb: 4
|
2018-02-10 21:38:43 +00:00
|
|
|
|
2018-02-15 10:00:12 +00:00
|
|
|
>>> TestMap.move_to("N3")
|
2018-02-13 14:59:02 +00:00
|
|
|
4
|
|
|
|
>>> TestMap.map_print()
|
|
|
|
01X34
|
|
|
|
abcde
|
|
|
|
ABCDE
|
|
|
|
zy wv
|
2018-02-15 10:00:12 +00:00
|
|
|
>>> TestMap.move_to("O2")
|
2018-02-13 14:59:02 +00:00
|
|
|
4
|
2018-02-15 10:00:12 +00:00
|
|
|
>>> TestMap.move_to("S3")
|
2018-02-13 14:59:02 +00:00
|
|
|
4
|
2018-02-15 10:00:12 +00:00
|
|
|
>>> TestMap.move_to("E4")
|
2018-02-13 14:59:02 +00:00
|
|
|
4
|
|
|
|
|
2018-02-15 10:00:12 +00:00
|
|
|
>>> MiniMap.move_to("O")
|
2018-02-13 16:19:16 +00:00
|
|
|
1
|
|
|
|
>>> MiniMap.move_to("Z1")
|
|
|
|
0
|
|
|
|
>>> MiniMap.move_to("4")
|
|
|
|
0
|
2018-02-15 10:00:12 +00:00
|
|
|
>>> MiniMap.move_to("E1")
|
2018-02-14 14:54:20 +00:00
|
|
|
2
|
2018-02-13 16:19:16 +00:00
|
|
|
>>> MiniMap.map_print()
|
2018-02-14 14:32:08 +00:00
|
|
|
OOO
|
|
|
|
O X
|
|
|
|
OOO
|
2018-02-06 16:59:29 +00:00
|
|
|
"""
|
|
|
|
|
2018-02-09 15:11:31 +00:00
|
|
|
def __init__(self, map_file):
|
2018-02-06 16:59:29 +00:00
|
|
|
"""
|
2018-02-09 15:11:31 +00:00
|
|
|
Initialisation de la carte utilise
|
|
|
|
:param map_file:
|
2018-02-06 16:59:29 +00:00
|
|
|
"""
|
2018-02-09 15:11:31 +00:00
|
|
|
# Chargement du fichier carte choisi
|
|
|
|
if os.path.isfile(map_file) is True:
|
|
|
|
with open(map_file, "r") as map_data:
|
2018-02-12 15:01:31 +00:00
|
|
|
|
2018-02-10 06:54:54 +00:00
|
|
|
# contenu de la carte en texte
|
|
|
|
self._data_text = map_data.read()
|
2018-02-12 15:01:31 +00:00
|
|
|
|
2018-02-10 06:54:54 +00:00
|
|
|
# contenu de la carte ligne a ligne
|
2018-02-12 14:39:42 +00:00
|
|
|
map_data_list = self._data_text.splitlines()
|
2018-02-12 15:01:31 +00:00
|
|
|
|
2018-02-14 17:21:37 +00:00
|
|
|
# nbre de colonne de la 1ere ligne de la carte
|
2018-02-12 16:08:03 +00:00
|
|
|
try:
|
2018-02-14 17:21:37 +00:00
|
|
|
self._column_nb = len(map_data_list[0]) + 1
|
2018-02-12 16:08:03 +00:00
|
|
|
except IndexError:
|
2018-02-14 17:21:37 +00:00
|
|
|
self._column_nb = 0
|
2018-02-12 16:08:03 +00:00
|
|
|
|
|
|
|
# nbre de ligne de la carte
|
|
|
|
try:
|
|
|
|
self._line_nb = len(map_data_list)
|
|
|
|
except IndexError:
|
|
|
|
self._line_nb = 0
|
|
|
|
|
2018-02-14 17:21:37 +00:00
|
|
|
# position du robot
|
|
|
|
self._robo_position = self._data_text.find(
|
|
|
|
MAZE_ELEMENTS['robo']
|
|
|
|
)
|
2018-02-12 16:08:03 +00:00
|
|
|
|
2018-02-15 10:00:12 +00:00
|
|
|
# element «sous» le robo, au depart
|
2018-02-15 10:00:12 +00:00
|
|
|
self._element_under_robo = MAZE_ELEMENTS['void']
|
|
|
|
|
2018-02-15 10:00:12 +00:00
|
|
|
# Quelques controle sur la carte chargee:
|
2018-02-14 17:21:37 +00:00
|
|
|
# dimensions assez grande pour deplacer un robo?
|
|
|
|
if self._column_nb < MIN_MAP_SIDE or \
|
|
|
|
self._line_nb < MIN_MAP_SIDE:
|
2018-02-12 16:08:03 +00:00
|
|
|
self.status = False
|
|
|
|
self.status_message = ERR_MAP_SIZE.format(
|
|
|
|
map_file, self._column_nb, self._line_nb
|
|
|
|
)
|
|
|
|
|
2018-02-14 17:21:37 +00:00
|
|
|
# y a t il un robo?
|
2018-02-12 16:08:03 +00:00
|
|
|
elif self._robo_position == -1:
|
|
|
|
self.status = False
|
|
|
|
self.status_message = ERR_MAP_ROBO.format(map_file)
|
|
|
|
|
2018-02-15 10:00:12 +00:00
|
|
|
# on peu ajouter plein d'autres controles ici
|
2018-02-14 17:21:37 +00:00
|
|
|
|
2018-02-15 10:00:12 +00:00
|
|
|
# carte consideree utilisable
|
2018-02-12 16:08:03 +00:00
|
|
|
else:
|
|
|
|
self.status = True
|
2018-02-15 10:00:12 +00:00
|
|
|
self.status_message = MSG_START_GAME
|
2018-02-06 16:59:29 +00:00
|
|
|
|
2018-02-12 14:39:42 +00:00
|
|
|
# Erreur de chargement du fichier
|
2018-02-09 15:11:31 +00:00
|
|
|
else:
|
2018-02-12 14:39:42 +00:00
|
|
|
self.status = False
|
|
|
|
self.status_message = ERR_MAP_FILE.format(map_file)
|
|
|
|
|
2018-02-09 15:36:48 +00:00
|
|
|
def map_print(self):
|
|
|
|
""" Affiche la carte avec la position de jeu courante """
|
2018-02-09 16:23:10 +00:00
|
|
|
print(self._data_text)
|
2018-02-09 15:36:48 +00:00
|
|
|
|
2018-02-12 21:34:39 +00:00
|
|
|
def move_to(self, move):
|
2018-02-09 15:36:48 +00:00
|
|
|
"""
|
2018-02-14 17:21:37 +00:00
|
|
|
Deplace le robo sur la carte
|
2018-02-09 15:36:48 +00:00
|
|
|
|
|
|
|
:param move: mouvement souhaite
|
2018-02-14 17:21:37 +00:00
|
|
|
:return: une cle de la constante MOVE_STATUS
|
2018-02-09 15:36:48 +00:00
|
|
|
"""
|
2018-02-13 14:18:57 +00:00
|
|
|
# decompose le mouvement
|
2018-02-15 10:00:12 +00:00
|
|
|
try: # on recupere le 1er caractere (la direction)
|
2018-02-14 16:21:33 +00:00
|
|
|
direction = move[0]
|
2018-02-17 00:53:22 +00:00
|
|
|
except IndexError:
|
|
|
|
return 0
|
|
|
|
except TypeError:
|
|
|
|
return 0
|
2018-02-14 16:21:33 +00:00
|
|
|
|
2018-02-15 10:00:12 +00:00
|
|
|
if len(move[1:]) > 0: # on recupere les caractere suivants (dist)
|
|
|
|
try:
|
|
|
|
goal = int(move[1:])
|
|
|
|
except ValueError as except_detail:
|
|
|
|
# print("ValueError: «{}»".format(except_detail))
|
|
|
|
return 0
|
|
|
|
else: # si pas de chiffre, on avance d'une seule unite
|
|
|
|
goal = 1
|
2018-02-14 14:45:27 +00:00
|
|
|
|
2018-02-13 14:59:02 +00:00
|
|
|
steps = 0
|
2018-02-12 21:34:39 +00:00
|
|
|
# direction non conforme
|
|
|
|
if direction not in DIRECTIONS:
|
2018-02-13 14:18:57 +00:00
|
|
|
move_status = 0
|
2018-02-12 21:34:39 +00:00
|
|
|
|
|
|
|
else:
|
2018-02-15 10:00:12 +00:00
|
|
|
|
|
|
|
# supprime le robo de son emplacement actuel
|
|
|
|
self._data_text = self._data_text.replace(
|
|
|
|
MAZE_ELEMENTS['robo'],
|
|
|
|
self._element_under_robo
|
|
|
|
)
|
|
|
|
|
2018-02-13 14:59:02 +00:00
|
|
|
# pour chaque pas on recupere la position suivante
|
2018-02-14 14:39:32 +00:00
|
|
|
while steps < goal:
|
2018-02-13 14:59:02 +00:00
|
|
|
steps += 1
|
|
|
|
if direction == DIRECTIONS[0]: # nord
|
|
|
|
next_position = self._robo_position - self._column_nb
|
|
|
|
|
|
|
|
elif direction == DIRECTIONS[1]: # sud
|
|
|
|
next_position = self._robo_position + self._column_nb
|
|
|
|
|
|
|
|
elif direction == DIRECTIONS[2]: # est
|
|
|
|
next_position = self._robo_position + 1
|
|
|
|
|
|
|
|
elif direction == DIRECTIONS[3]: # ouest
|
|
|
|
next_position = self._robo_position - 1
|
|
|
|
|
|
|
|
else: # juste au cas ou
|
2018-02-14 17:21:37 +00:00
|
|
|
raise NotImplementedError(ERR_UNKNOW)
|
2018-02-13 14:59:02 +00:00
|
|
|
|
2018-02-15 10:00:12 +00:00
|
|
|
self._element_under_robo = MAZE_ELEMENTS['void']
|
|
|
|
|
2018-02-14 17:21:37 +00:00
|
|
|
# Traitement en fonction de la case du prochain pas
|
2018-02-15 10:00:12 +00:00
|
|
|
# FIXME: next_char = self._data_text[next_position] : \
|
2018-02-15 10:00:12 +00:00
|
|
|
# IndexError: string index out of range
|
2018-02-13 14:59:02 +00:00
|
|
|
next_char = self._data_text[next_position]
|
|
|
|
if next_char == MAZE_ELEMENTS['wall']:
|
|
|
|
move_status = 1
|
2018-02-14 14:39:32 +00:00
|
|
|
steps = goal
|
2018-02-12 21:34:39 +00:00
|
|
|
|
|
|
|
elif next_char == MAZE_ELEMENTS['exit']:
|
2018-02-13 14:59:02 +00:00
|
|
|
self._robo_position = next_position
|
|
|
|
move_status = 2
|
2018-02-14 14:39:32 +00:00
|
|
|
steps = goal
|
|
|
|
|
2018-02-13 14:59:02 +00:00
|
|
|
elif next_char == MAZE_ELEMENTS['door']:
|
|
|
|
self._robo_position = next_position
|
2018-02-15 10:00:12 +00:00
|
|
|
self._element_under_robo = MAZE_ELEMENTS['door']
|
2018-02-13 14:59:02 +00:00
|
|
|
move_status = 3
|
2018-02-14 14:39:32 +00:00
|
|
|
steps = goal
|
2018-02-12 21:34:39 +00:00
|
|
|
|
|
|
|
else:
|
2018-02-13 14:59:02 +00:00
|
|
|
self._robo_position = next_position
|
2018-02-14 14:39:32 +00:00
|
|
|
move_status = 4
|
2018-02-13 14:59:02 +00:00
|
|
|
|
|
|
|
# place le robo sur sa nouvelle position
|
2018-02-15 10:00:12 +00:00
|
|
|
self.place_element(MAZE_ELEMENTS['robo'])
|
2018-02-09 15:36:48 +00:00
|
|
|
|
2018-02-13 14:18:57 +00:00
|
|
|
return move_status
|
2018-02-09 15:36:48 +00:00
|
|
|
|
2018-02-15 10:00:12 +00:00
|
|
|
def place_element(self, element):
|
|
|
|
"""
|
|
|
|
Place l'element sur la carte.
|
|
|
|
|
|
|
|
La position est celle de l'attribut self._robo_position au
|
|
|
|
moment de l'appel.
|
2018-02-09 15:36:48 +00:00
|
|
|
|
2018-02-15 10:00:12 +00:00
|
|
|
Utilise pour place le robot et remettre les portes.
|
|
|
|
|
|
|
|
:param element: element a placer sur la carte
|
|
|
|
"""
|
|
|
|
pos = self._robo_position
|
|
|
|
txt = self._data_text
|
|
|
|
self._data_text = txt[:pos] + element + txt[pos + 1:]
|
2018-02-09 15:36:48 +00:00
|
|
|
|
2018-02-15 10:00:12 +00:00
|
|
|
|
2018-02-06 16:59:29 +00:00
|
|
|
if __name__ == "__main__":
|
|
|
|
""" Starting doctests """
|
|
|
|
|
|
|
|
import doctest
|
2018-02-15 10:00:12 +00:00
|
|
|
doctest.testmod()
|