summary refs log tree commit diff homepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.gitmodules3
-rw-r--r--README.rst17
-rw-r--r--brutalmaze/constants.py1
-rw-r--r--brutalmaze/main.py85
-rw-r--r--brutalmaze/settings.ini (renamed from settings.ini)0
-rwxr-xr-xsetup.py4
m---------wiki0
8 files changed, 45 insertions, 66 deletions
diff --git a/.gitignore b/.gitignore
index 3186336..b537ddb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,5 @@
 brutalmaze.egg-info
 build
 dist
-wiki
 __pycache__
 *.pyc
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..59fa830
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "wiki"]
+	path = wiki
+	url = https://github.com/McSinyx/brutalmaze.wiki.git
diff --git a/README.rst b/README.rst
index fac504a..c5c54f3 100644
--- a/README.rst
+++ b/README.rst
@@ -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``.
diff --git a/brutalmaze/constants.py b/brutalmaze/constants.py
index d7f3630..0792808 100644
--- a/brutalmaze/constants.py
+++ b/brutalmaze/constants.py
@@ -23,6 +23,7 @@ from pkg_resources import resource_filename
 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')
diff --git a/brutalmaze/main.py b/brutalmaze/main.py
index 8d391f1..79e84c3 100644
--- a/brutalmaze/main.py
+++ b/brutalmaze/main.py
@@ -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
@@ -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()))
@@ -118,7 +82,7 @@ class ConfigReader:
 
     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
 
@@ -138,13 +102,16 @@ def main():
     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))
@@ -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)
@@ -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
diff --git a/settings.ini b/brutalmaze/settings.ini
index 00a071f..00a071f 100644
--- a/settings.ini
+++ b/brutalmaze/settings.ini
diff --git a/setup.py b/setup.py
index db966d1..8f408f1 100755
--- a/setup.py
+++ b/setup.py
@@ -7,7 +7,7 @@ with open('README.rst') as f:
 
 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',
@@ -28,5 +28,5 @@ setup(
     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']})
diff --git a/wiki b/wiki
new file mode 160000
+Subproject 3b014564eb185bb525a59378fd2d9ede65bf0d3