Skip to content
This repository has been archived by the owner on Nov 30, 2020. It is now read-only.

Commit

Permalink
Add CLI option to copy default config and link doc to wiki
Browse files Browse the repository at this point in the history
  • Loading branch information
McSinyx committed Feb 14, 2018
1 parent 8095bca commit e1db039
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 66 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
brutalmaze.egg-info
build
dist
wiki
__pycache__
*.pyc
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "wiki"]
path = wiki
url = https://github.com/McSinyx/brutalmaze.wiki.git
17 changes: 11 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,22 @@ from Brutal Maze wiki.
Configuration
-------------

Brutal Maze reads settings from both configuration file and command-line
arguments. These settings are read in the following order:
Brutal Maze supports both configuration file and command-line options.
Apparently one can change settings for graphics and control in the config file
and set graphics options using in CLI. These settings are read in the following
order:

0. Default configuration [0]_
1. System-wide configuration file [1]_
2. Local configuration file [1]_
3. Manually set configuration file [2]_
4. Command-line arguments [3]_
4. Command-line arguments

The later-read preferences will overide the previous ones.

.. [0] This can be copied to desired location by ``brutalmaze --write-config
PATH``. ``brutalmaze --write-config`` alone will print the file to stdout.
.. [1] These will be listed as fallback config in the help message
(``brutalmaze --help``).
.. [2] This can be set using ``brutalmaze --config PATH``.
.. [3] Listed in the help message.
(``brutalmaze --help``). See `wiki <https://github.com/McSinyx/brutalmaze/wiki/Configuration>`_
for more info.
.. [2] If specified by ``brutalmaze --config PATH``.
1 change: 1 addition & 0 deletions brutalmaze/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from pygame import image
from pygame.mixer import Sound

SETTINGS = resource_filename('brutalmaze', 'settings.ini')
ICON = image.load(resource_filename('brutalmaze', 'icon.png'))
MUSIC = resource_filename('brutalmaze', 'soundfx/music.ogg')
SFX_SPAWN = resource_filename('brutalmaze', 'soundfx/spawn.ogg')
Expand Down
85 changes: 28 additions & 57 deletions brutalmaze/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@
#
# Copyright (C) 2017 Nguyễn Gia Phong

__version__ = '0.5.1'
__version__ = '0.5.2'

import re
from argparse import ArgumentParser, RawTextHelpFormatter
from argparse import ArgumentParser, FileType, RawTextHelpFormatter
from collections import deque
try: # Python 3
from configparser import ConfigParser, NoOptionError, NoSectionError
except ImportError: # Python 2
from ConfigParser import ConfigParser, NoOptionError, NoSectionError
from os.path import join, pathsep
from sys import stdout


import pygame
Expand All @@ -41,75 +42,38 @@ class ConfigReader:
"""Object reading and processing INI configuration file for
Brutal Maze.
"""
DEFAULT_BINDINGS = (('New game', 'new', 'F2'),
('Pause', 'pause', 'p'),
('Move left', 'left', 'Left'),
('Move right', 'right', 'Right'),
('Move up', 'up', 'Up'),
('Move down', 'down', 'Down'),
('Long-range attack', 'shot', 'Mouse1'),
('Close-range attack', 'slash', 'Mouse3'))
DEFAULT_BINDINGS = (('New game', 'new'), ('Pause', 'pause'),
('Move left', 'left'), ('Move right', 'right'),
('Move up', 'up'), ('Move down', 'down'),
('Long-range attack', 'shot'),
('Close-range attack', 'slash'))
WEIRD_MOUSE_ERR = '{}: Mouse is not a suitable control'
INVALID_CONTROL_ERR = '{}: {} is not recognized as a valid control key'

def __init__(self, filenames):
self.config = ConfigParser()
self.config.read(SETTINGS) # default configuration
self.config.read(filenames)

def _getconf(self, section, option, val_t):
if val_t == str:
return self.config.get(section, option)
elif val_t == bool:
return self.config.getboolean(section, option)
elif val_t == float:
return self.config.getfloat(section, option)
elif val_t == int:
return self.config.getint(section, option)

def getconf(self, section, option, val_t=str, fallback=None):
"""Return the value of the option in the given section.
If the value is not found, return fallback.
"""
try:
return self._getconf(section, option, val_t)
except NoSectionError, NoOptionError:
return val_t() if fallback is None else fallback

def setconf(self, name, section, option, val_t=str, fallback=None):
"""Set the named attribute to the value of the option in
the given section.
If the value is not found and attribute does not exist,
use fallback.
"""
try:
setattr(self, name, self._getconf(section, option, val_t))
except NoSectionError, NoOptionError:
try:
getattr(self, name)
except AttributeError:
setattr(self, name, val_t() if fallback is None else fallback)

def parse_graphics(self):
"""Parse graphics configurations."""
self.setconf('width', 'Graphics', 'Screen width', int, 640)
self.setconf('height', 'Graphics', 'Screen height', int, 480)
self.setconf('opengl', 'Graphics', 'OpenGL', bool)
self.setconf('max_fps', 'Graphics', 'Maximum FPS', float, 60.0)
self.size = (self.config.getint('Graphics', 'Screen width'),
self.config.getint('Graphics', 'Screen height'))
self.opengl = self.config.getboolean('Graphics', 'OpenGL')
self.max_fps = self.config.getfloat('Graphics', 'Maximum FPS')

def parse_control(self):
"""Parse control configurations."""
self.key, self.mouse = {}, {}
for cmd, alias, bind in self.DEFAULT_BINDINGS:
i = self.getconf('Control', cmd, fallback=bind).lower()
if re.match('mouse[1-3]$', i):
for cmd, alias in self.CONTROL_ALIASES:
i = self.config.get('Control', cmd)
if re.match('mouse[1-3]$', i.lower()):
if alias not in ('shot', 'slash'):
raise ValueError(self.WEIRD_MOUSE_ERR.format(cmd))
self.mouse[alias] = int(i[-1]) - 1
continue
if len(i) == 1:
self.key[alias] = ord(i)
self.key[alias] = ord(i.lower())
continue
try:
self.key[alias] = getattr(pygame, 'K_{}'.format(i.upper()))
Expand All @@ -118,7 +82,7 @@ def parse_control(self):

def read_args(self, arguments):
"""Read and parse a ArgumentParser.Namespace."""
if arguments.size is not None: self.width, self.height = arguments.size
if arguments.size is not None: self.size = arguments.size
if arguments.opengl is not None: self.opengl = arguments.opengl
if arguments.max_fps is not None: self.max_fps = arguments.max_fps

Expand All @@ -137,14 +101,17 @@ def main():
parser = ArgumentParser(formatter_class=RawTextHelpFormatter)
parser.add_argument('-v', '--version', action='version',
version='Brutal Maze {}'.format(__version__))
parser.add_argument(
'--write-config', nargs='?', const=stdout, type=FileType('w'),
metavar='PATH', dest='defaultcfg',
help='write default config and exit, if PATH not specified use stdout')
parser.add_argument(
'-c', '--config', metavar='PATH',
help='location of the configuration file (fallback: {})'.format(
pathsep.join(filenames)))
parser.add_argument(
'-s', '--size', type=int, nargs=2, metavar=('X', 'Y'),
help='the desired screen size (fallback: {}x{})'.format(config.width,
config.height))
help='the desired screen size (fallback: {}x{})'.format(*config.size))
parser.add_argument(
'--opengl', action='store_true', default=None,
help='enable OpenGL (fallback: {})'.format(config.opengl))
Expand All @@ -154,6 +121,10 @@ def main():
'-f', '--max-fps', type=float, metavar='FPS',
help='the desired maximum FPS (fallback: {})'.format(config.max_fps))
args = parser.parse_args()
if args.defaultcfg is not None:
with open(SETTINGS) as settings: args.defaultcfg.write(settings.read())
args.defaultcfg.close()
exit()

# Manipulate config
if args.config: config.config.read(args.config)
Expand All @@ -170,7 +141,7 @@ def main():
pygame.fastevent.init()
clock, flash_time, fps = pygame.time.Clock(), deque(), config.max_fps
scrtype = (config.opengl and DOUBLEBUF|OPENGL) | RESIZABLE
maze = Maze((config.width, config.height), scrtype, fps)
maze = Maze(config.size, scrtype, fps)

# Main loop
going = True
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

setup(
name='brutalmaze',
version='0.5.1',
version='0.5.2',
description='A minimalist hack and slash game with fast-paced action',
long_description=long_description,
url='https://github.com/McSinyx/brutalmaze',
Expand All @@ -28,5 +28,5 @@
keywords='pygame action-game arcade-game maze',
packages=['brutalmaze'],
install_requires=['appdirs', 'pygame>=1.9'],
package_data={'brutalmaze': ['icon.png', 'soundfx/*.ogg']},
package_data={'brutalmaze': ['icon.png', 'soundfx/*.ogg', 'settings.ini']},
entry_points={'gui_scripts': ['brutalmaze = brutalmaze:main']})
1 change: 1 addition & 0 deletions wiki
Submodule wiki added at 3b0145

0 comments on commit e1db039

Please sign in to comment.