Massive static code cleanup

- Translating comments
- Flake8 & Pylint checking
- Adjust variable name consistency
- Rename tiles filename (and adds files)
This commit is contained in:
Fred Z 2018-03-30 10:22:01 +02:00
parent a2bfa46207
commit 19bf777484
11 changed files with 163 additions and 109 deletions

130
conf.py
View File

@ -5,60 +5,78 @@ Licence: `GNU GPL v3` GNU GPL v3: http://www.gnu.org/licenses/
This file is part of [_ocp3_ project](https://github.com/freezed/ocp3)
"""
from math import floor
import pygame
import math
# CONFIGURATION
ELEMENT_LIST = [
{'symbol': 'n', 'name': 'needle', 'cross': True, 'ressurect': False, 'collect': True, 'tile': 'img/3-blue-transp-30.png'},
{'symbol': 't', 'name': 'tube', 'cross': True, 'ressurect': False, 'collect': True, 'tile': 'img/1-blue-transp-30.png'},
{'symbol': 'e', 'name': 'ether', 'cross': True, 'ressurect': False, 'collect': True, 'tile': 'img/2-blue-transp-30.png'},
{'symbol': 'E', 'name': 'exit', 'cross': False, 'ressurect': False, 'collect': False, 'tile': 'img/g-orange-transp-30.png'},
{'symbol': ' ', 'name': 'void', 'cross': True, 'ressurect': True, 'collect': False, 'tile': 'img/blue-white-30.png'},
{'symbol': '.', 'name': 'wall', 'cross': False, 'ressurect': False, 'collect': False, 'tile': 'img/transp-30.png'},
{'symbol': 'X', 'name': 'player', 'cross': False, 'ressurect': False, 'collect': False, 'tile': 'img/player-30.png'},
{'symbol': '\n', 'name': 'nlin', 'cross': False, 'ressurect': False, 'collect': False, 'tile': False},
]
ELEMENTS = (
{
'symbol': 'n', 'name': 'needle', 'cross': True,
'ressurect': False, 'collect': True, 'tile': 'img/3-30.png'
},
{
'symbol': 't', 'name': 'tube', 'cross': True,
'ressurect': False, 'collect': True, 'tile': 'img/1-30.png'
},
{
'symbol': 'e', 'name': 'ether', 'cross': True,
'ressurect': False, 'collect': True, 'tile': 'img/2-30.png'
},
{
'symbol': 'E', 'name': 'exit', 'cross': False,
'ressurect': False, 'collect': False, 'tile': 'img/g-30.png'
},
{
'symbol': ' ', 'name': 'void', 'cross': True,
'ressurect': True, 'collect': False, 'tile': 'img/void-30.png'
},
{
'symbol': '.', 'name': 'wall', 'cross': False,
'ressurect': False, 'collect': False, 'tile': 'img/wall-30.png'
},
{
'symbol': 'X', 'name': 'player', 'cross': False,
'ressurect': False, 'collect': False, 'tile': 'img/player-30.png'
},
{
'symbol': '\n', 'name': 'nlin', 'cross': False,
'ressurect': False, 'collect': False, 'tile': False
},
)
# Possible returns of a move, keep the «ok» at the end
MOVE_STATUS = ['looser', 'wall', 'winner', 'collect', 'ok']
MOVE_STATUS_MSG = {
'looser': "Vous vous êtes fait assommé! Pour endormir le garde, il manqait: {}.\nPerdu!",
'wall': "Le déplacement est stoppé par un mur.",
'winner': "Gagné! Vous avez endormis le garde avec votre seringue.",
'collect': "Vous ramassez l'objet «{}»",
'ok': "Jusqu'ici, tout va bien…"
}
CELL_SIZE_PX = 30 # Size of the tiles, in pixels
MAZE_SIZE_TIL = 15 # Size of a map, in tiles
FONT_SIZE = math.floor(0.9 * CELL_SIZE_PX)
CELL_SIZE = 30 # Size of the tiles, in pixels
MAZE_SIZE = 15 # Size of a map, in tiles
BLACK = (0, 0, 0)
BLUE = (0, 0, 128)
GREEN = (0, 255, 0)
WHITE = (255, 255, 255)
# Messages
CAPTION = "OCP3, a pygame maze"
CAPTION = "OCP3, a maze based on pygame"
ERR_MAP = "ERR_MAP: «{}»"
HEADER_MESSAGES = {
HEAD_MESSAGES = {
'title': "Welcome in OCP3.",
'status': "Use arrow keys to play, any other key to quit.",
'items': "Items: {}/{}",
}
MSG_COLLECT = "You pick «{}»"
MSG_END = "End of game, press a key to quit."
MSG_LOSER = "You lose! You were missing: {}."
MSG_OK = ""
MSG_QUIT = "You decide to quit the game"
MSG_WALL = "That's a wall!"
MSG_WINNER = "Cogratulations! You asleep the guard."
# Files
BACKGROUND_IMG = 'img/zebra-800.png'
BACKGRND_FILE = 'img/back-800.png'
MAP_FILE = '01.map'
UNKNOWN_TILE = 'img/unknown-30.png'
UNKNOWN_FILE = 'img/unknown-30.png'
# Constant calculation
HEADER_HEIGHT = (2 * CELL_SIZE_PX)
WINDOW_SIZE_PX_W = CELL_SIZE_PX * MAZE_SIZE_TIL
WINDOW_SIZE_PX_H = WINDOW_SIZE_PX_W + HEADER_HEIGHT
WIN_DIM = (WINDOW_SIZE_PX_W, WINDOW_SIZE_PX_H)
FONT_SIZE = floor(0.9 * CELL_SIZE)
HEAD_SIZE_H = (2 * CELL_SIZE)
WIN_SIZE_W = CELL_SIZE * MAZE_SIZE
WIN_SIZE_H = WIN_SIZE_W + HEAD_SIZE_H
WIN_DIM = (WIN_SIZE_W, WIN_SIZE_H)
# FUNCTIONS
@ -66,7 +84,7 @@ WIN_DIM = (WINDOW_SIZE_PX_W, WINDOW_SIZE_PX_H)
def elmt_val(kval, ksel, vsel, nline=False):
"""
Return value(s) from ELEMENT_LIST
Return value(s) from ELEMENTS
:param str kval: key of the value returned
:param str ksel: key of the selection criteria
@ -74,53 +92,59 @@ def elmt_val(kval, ksel, vsel, nline=False):
:param bool/int nline: Default False, return value(s) in a list,
use a int() to return the `n` value from the list
:return str/bool/:
"""
try:
if nline is False:
return (element[kval] for element in ELEMENT_LIST if element[ksel] == vsel)
return (element[kval] for element in ELEMENTS
if element[ksel] == vsel)
else:
return [element[kval] for element in ELEMENT_LIST if element[ksel] == vsel][nline]
return [element[kval] for element in ELEMENTS
if element[ksel] == vsel][nline]
except IndexError:
return False
def maze_draw(WINDOW, map_string):
""" Take a map string and generate a graphic maze """
def maze_draw(surface, map_string):
"""
Take a map string and generate a graphic maze
:param obj surface: a pygame surface object
:param str map_string: map modelized in a string
"""
back_tiles = []
for cell, element in enumerate(map_string):
img = elmt_val('tile', 'symbol', element, 0)
if img is False:
back_tiles.append(pygame.image.load(UNKNOWN_TILE).convert())
back_tiles.append(pygame.image.load(UNKNOWN_FILE).convert())
else:
back_tiles.append(pygame.image.load(img).convert_alpha())
x = (cell % MAZE_SIZE_TIL) * CELL_SIZE_PX
y = (cell // MAZE_SIZE_TIL) * CELL_SIZE_PX + HEADER_HEIGHT
WINDOW.blit(back_tiles[cell], (x, y))
x = (cell % MAZE_SIZE) * CELL_SIZE
y = (cell // MAZE_SIZE) * CELL_SIZE + HEAD_SIZE_H
surface.blit(back_tiles[cell], (x, y))
# Refresh
pygame.display.flip()
def set_header(WINDOW, messages):
def set_header(surface, messages):
"""
Set the header message on the window
:param obj WINDOWS: display object
:param obj surface: surface surfaceect
:param list/str messages: list of messages per place
"""
pygame.draw.rect(WINDOW, BLACK, (0, 0, WINDOW_SIZE_PX_W, HEADER_HEIGHT))
pygame.draw.rect(surface, BLACK, (0, 0, WIN_SIZE_W, HEAD_SIZE_H))
FONT = pygame.font.Font(None, FONT_SIZE)
h_title = FONT.render(str(messages['title']), True, BLUE, WHITE)
h_status = FONT.render(str(messages['status']), True, WHITE, BLACK)
h_items = FONT.render(str(messages['items']), True, GREEN, BLACK)
h_title = FONT.render(messages['title'], True, BLUE, WHITE)
h_status = FONT.render(messages['status'], True, WHITE, BLACK)
h_items = FONT.render(messages['items'], True, GREEN, BLACK)
h_items_pos = h_items.get_rect(topright=(WINDOW_SIZE_PX_W, 0))
h_items_pos = h_items.get_rect(topright=(WIN_SIZE_W, 0))
WINDOW.blit(h_title, (0, 0))
WINDOW.blit(h_status, (0, CELL_SIZE_PX))
WINDOW.blit(h_items, h_items_pos)
surface.blit(h_title, (0, 0))
surface.blit(h_status, (0, CELL_SIZE))
surface.blit(h_items, h_items_pos)

BIN
img/1-30.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

BIN
img/2-30.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 874 B

BIN
img/3-30.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
img/back-800.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
img/g-30.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
img/m-30.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
img/void-30.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

BIN
img/wall-30.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

19
main.py
View File

@ -12,30 +12,28 @@ details
"""
import pygame
from pygame.locals import (
K_UP, K_DOWN, K_RIGHT, K_LEFT, KEYDOWN, QUIT, RESIZABLE
K_UP, K_DOWN, K_RIGHT, K_LEFT, KEYDOWN, QUIT
)
from map import Map
from conf import BACKGROUND_IMG, CAPTION, MAP_FILE, HEADER_HEIGHT, maze_draw, MSG_END, MSG_QUIT, set_header, WIN_DIM
from conf import (
BACKGRND_FILE, CAPTION, MAP_FILE, HEAD_SIZE_H, maze_draw,
MSG_END, MSG_QUIT, set_header, WIN_DIM
)
# Constant calculation
GAME_KEYS = [K_UP, K_DOWN, K_RIGHT, K_LEFT]
pygame.init()
WINDOW = pygame.display.set_mode(WIN_DIM, RESIZABLE)
WINDOW = pygame.display.set_mode(WIN_DIM)
pygame.display.set_caption(CAPTION)
WINDOW.blit(pygame.image.load(BACKGROUND_IMG).convert(), (0, HEADER_HEIGHT))
WINDOW.blit(pygame.image.load(BACKGRND_FILE).convert(), (0, HEAD_SIZE_H))
# Loading map
MAP_GAME = Map(MAP_FILE)
# Header messaging
set_header(WINDOW, MAP_GAME.status_message)
# Draw maze
maze_draw(WINDOW, MAP_GAME.map_print().replace('\n', ''))
pygame.time.Clock().tick(25)
# Game loop
# pygame.time.Clock().tick(25)
last_wait = True
while MAP_GAME.status:
for event in pygame.event.get():
@ -59,6 +57,7 @@ MAP_GAME.status_message['title'] = MSG_END
set_header(WINDOW, MAP_GAME.status_message)
pygame.display.flip()
# Loop for last messag before exit
while last_wait:
for event in pygame.event.get():
if event.type == KEYDOWN:

123
map.py
View File

@ -8,7 +8,10 @@ This file is part of [_ocp3_ project](https://github.com/freezed/ocp3)
import os
import random
from pygame.locals import K_UP, K_DOWN, K_RIGHT, K_LEFT
from conf import elmt_val, ERR_MAP, MOVE_STATUS_MSG, HEADER_MESSAGES, MAZE_SIZE_TIL
from conf import (
elmt_val, ERR_MAP, MSG_COLLECT, MSG_LOSER, MSG_OK,
MSG_WALL, MSG_WINNER, HEAD_MESSAGES, MAZE_SIZE
)
class Map:
@ -35,22 +38,24 @@ class Map:
:rtype map: str()
:return: None
"""
# Chargement du fichier carte choisi
# Loading map file
if os.path.isfile(map_file) is True:
with open(map_file, "r") as map_data:
# translate to a splited lines string list
# Translate to a splited lines string list
map_in_a_list = map_data.read().splitlines()
# map line number
if len(map_in_a_list) == MAZE_SIZE_TIL:
self._COLUM = MAZE_SIZE_TIL + 1
self._LINES = MAZE_SIZE_TIL
# Map line number
if len(map_in_a_list) == MAZE_SIZE:
self._COLUM = MAZE_SIZE + 1
self._LINES = MAZE_SIZE
self._MAXIM = (self._COLUM * self._LINES) - 1
# Add map checking here
# ++ Add other map checks here ++
# Constructing square map
map_in_a_list = [self.check_line(line) for line in map_in_a_list]
map_in_a_list = [self.check_line(line)
for line in map_in_a_list]
self._map_in_a_string = '\n'.join(map_in_a_list)
# Player's initial position
@ -59,44 +64,54 @@ class Map:
)
# Element under player at start
self._element_under_player = elmt_val('symbol', 'name', 'void', 0)
self._element_under_player = elmt_val(
'symbol', 'name', 'void', 0
)
# Place collectables on the map
for symbol_to_place in elmt_val('symbol', 'collect', True):
position = random.choice([idx for (idx, value) in enumerate(self._map_in_a_string) if value == elmt_val('symbol', 'name', 'void', 0)])
position = random.choice(
[idx for (idx, value) in enumerate(
self._map_in_a_string
) if value == elmt_val(
'symbol', 'name', 'void', 0
)])
self.place_element(symbol_to_place, pos=position)
self.status = True
self.collected_items = []
self.collected_items_num = 0
self.MAX_ITEMS = sum(1 for _ in elmt_val('name', 'collect', True))
self.MAX_ITEMS = sum(
1 for _ in elmt_val('name', 'collect', True)
)
self.status_message = {}
self.status_message['title'] = HEADER_MESSAGES['title']
self.status_message['status'] = HEADER_MESSAGES['status']
self.status_message['items'] = HEADER_MESSAGES['items'].format(self.collected_items_num, self.MAX_ITEMS)
self.status_message['title'] = HEAD_MESSAGES['title']
self.status_message['status'] = HEAD_MESSAGES['status']
self.status_message['items'] \
= HEAD_MESSAGES['items'].format(
self.collected_items_num, self.MAX_ITEMS
)
else:
self.status = False
print(ERR_MAP.format("maplines: " + str(len(map_in_a_list))))
# Erreur de chargement du fichier
# File error
else:
self.status = False
print(ERR_MAP.format(':'.join(["mapfile", map_file])))
def map_print(self):
""" Affiche la carte avec la position de jeu courante """
""" Return a string of the map state """
return self._map_in_a_string
def move_to(self, pressed_key):
"""
Deplace le plyr sur la carte
Move the player on the map
:param str pressed_key: mouvement souhaite
:return int: une cle de la constante MOVE_STATUS
:param str pressed_key: direction (pygame const)
"""
# supprime le plyr de son emplacement actuel et on replace
# l'elements «dessous»
# Replace player on the map by the under-element
self._map_in_a_string = self._map_in_a_string.replace(
elmt_val('symbol', 'name', 'player', 0),
self._element_under_player
@ -115,50 +130,66 @@ class Map:
elif pressed_key == K_LEFT:
next_position = self._player_position - 1
# TODO nove instruction to __init__
self._element_under_player = elmt_val('symbol', 'name', 'void', 0)
# Traitement en fonction de la case du prochain pas
# Next position treatment
if next_position >= 0 and next_position <= self._MAXIM:
next_char = self._map_in_a_string[next_position]
if next_char == elmt_val('symbol', 'name', 'void', 0):
self._player_position = next_position
self.status_message['status'] = MOVE_STATUS_MSG['ok']
self.status_message['status'] = MSG_OK
elif next_char in elmt_val('symbol', 'collect', True):
self._player_position = next_position
self._element_under_player = elmt_val('symbol', 'name', 'void', 0)
self.collected_items.append(elmt_val('name', 'symbol', next_char, 0))
self._element_under_player = elmt_val(
'symbol', 'name', 'void', 0
)
self.collected_items.append(
elmt_val('name', 'symbol', next_char, 0)
)
self.collected_items_num += 1
self.status_message['status'] = MOVE_STATUS_MSG['collect'].format(elmt_val('name', 'symbol', next_char, 0))
self.status_message['items'] = HEADER_MESSAGES['items'].format(self.collected_items_num, self.MAX_ITEMS)
self.status_message['status'] = MSG_COLLECT.format(
elmt_val('name', 'symbol', next_char, 0)
)
self.status_message['items'] \
= HEAD_MESSAGES['items'].format(
self.collected_items_num, self.MAX_ITEMS
)
elif next_char == elmt_val('symbol', 'name', 'exit', 0):
self.status = False
if sorted(self.collected_items) == sorted(elmt_val('name', 'collect', True)):
self.status_message['status'] = MOVE_STATUS_MSG['winner']
if sorted(self.collected_items) == sorted(
elmt_val('name', 'collect', True)
):
self.status_message['status'] = MSG_WINNER
else:
missed_item_flist = ', '.join((item for item in elmt_val('name', 'collect', True) if item not in self.collected_items))
self.status_message['status'] = MOVE_STATUS_MSG['looser'].format(missed_item_flist)
missed_item_flist = ', '.join(
(item for item in elmt_val(
'name', 'collect', True
) if item not in self.collected_items)
)
self.status_message['status'] = MSG_LOSER.format(
missed_item_flist
)
else: # wall, door or nline
self.status_message['status'] = MOVE_STATUS_MSG['wall']
else: # wall or nline
self.status_message['status'] = MSG_WALL
else:
self.status_message['status'] = MOVE_STATUS_MSG['wall']
self.status_message['status'] = MSG_WALL
# place le plyr sur sa nouvelle position
# Set the player on position
self.place_element(elmt_val('symbol', 'name', 'player', 0))
def place_element(self, element, **kwargs):
"""
Place l'element sur la carte.
Set an element on the map
La position est celle de l'attribut self._player_position au
moment de l'appel.
The position used is in ._player_position attribute
Used for player and void after collecting items
Utilise pour place le plyrt et remettre les portes.
:param str element: element a placer sur la carte
:param str element: the string of the element to place
"""
# FIXME cannot find a way to define default value to the
# method's arguments with class attributes
@ -177,12 +208,12 @@ class Map:
@staticmethod
def check_line(line):
"""
Checks if a line has a good length, fill it if it's too small,
truncate if it's too long
Checks if a line has a good length (configured in MAZE_SIZE const).
Fill it if it's too small, truncate if it's too long.
"""
differance = MAZE_SIZE_TIL - len(str(line))
differance = MAZE_SIZE - len(str(line))
if differance < 0:
return line[:MAZE_SIZE_TIL]
return line[:MAZE_SIZE]
elif differance > 0:
return line + (differance * elmt_val('symbol', 'name', 'void', 0))
else: