Move all the logging to log.py and prefix all the log names with "erynrl"
This commit is contained in:
parent
5d4e0cff3d
commit
ce63c825b0
8 changed files with 126 additions and 102 deletions
|
@ -1,21 +1,16 @@
|
||||||
# Eryn Wells <eryn@erynwells.me>
|
# Eryn Wells <eryn@erynwells.me>
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
|
||||||
import logging
|
|
||||||
import logging.config
|
|
||||||
import os.path
|
import os.path
|
||||||
import sys
|
import sys
|
||||||
import tcod
|
import tcod
|
||||||
|
from . import log
|
||||||
from .engine import Configuration, Engine
|
from .engine import Configuration, Engine
|
||||||
from .events import EventHandler
|
from .events import EventHandler
|
||||||
from .geometry import Size
|
from .geometry import Size
|
||||||
|
|
||||||
LOG = logging.getLogger('main')
|
|
||||||
|
|
||||||
CONSOLE_WIDTH, CONSOLE_HEIGHT = 80, 50
|
CONSOLE_WIDTH, CONSOLE_HEIGHT = 80, 50
|
||||||
MAP_WIDTH, MAP_HEIGHT = 80, 45
|
MAP_WIDTH, MAP_HEIGHT = 80, 45
|
||||||
|
|
||||||
FONT = 'terminal16x16_gs_ro.png'
|
FONT = 'terminal16x16_gs_ro.png'
|
||||||
|
|
||||||
def parse_args(argv, *a, **kw):
|
def parse_args(argv, *a, **kw):
|
||||||
|
@ -24,23 +19,6 @@ def parse_args(argv, *a, **kw):
|
||||||
args = parser.parse_args(argv)
|
args = parser.parse_args(argv)
|
||||||
return args
|
return args
|
||||||
|
|
||||||
def init_logging(args):
|
|
||||||
'''Set up the logging system by (preferrably) reading a logging configuration file.'''
|
|
||||||
logging_config_path = find_logging_config()
|
|
||||||
if logging_config_path:
|
|
||||||
with open(logging_config_path, encoding='utf-8') as logging_config_file:
|
|
||||||
logging_config = json.load(logging_config_file)
|
|
||||||
logging.config.dictConfig(logging_config)
|
|
||||||
LOG.info('Found logging configuration at %s', logging_config_path)
|
|
||||||
else:
|
|
||||||
root_logger = logging.getLogger('')
|
|
||||||
root_logger.setLevel(logging.DEBUG if args.debug else logging.INFO)
|
|
||||||
|
|
||||||
stderr_handler = logging.StreamHandler()
|
|
||||||
stderr_handler.setFormatter(logging.Formatter("%(asctime)s %(name)s: %(message)s"))
|
|
||||||
|
|
||||||
root_logger.addHandler(stderr_handler)
|
|
||||||
|
|
||||||
def walk_up_directories_of_path(path):
|
def walk_up_directories_of_path(path):
|
||||||
while path and path != '/':
|
while path and path != '/':
|
||||||
path = os.path.dirname(path)
|
path = os.path.dirname(path)
|
||||||
|
@ -51,38 +29,26 @@ def find_fonts_directory():
|
||||||
for parent_dir in walk_up_directories_of_path(__file__):
|
for parent_dir in walk_up_directories_of_path(__file__):
|
||||||
possible_fonts_dir = os.path.join(parent_dir, 'fonts')
|
possible_fonts_dir = os.path.join(parent_dir, 'fonts')
|
||||||
if os.path.isdir(possible_fonts_dir):
|
if os.path.isdir(possible_fonts_dir):
|
||||||
LOG.info('Found fonts dir %s', possible_fonts_dir)
|
log.ROOT.info('Found fonts dir %s', possible_fonts_dir)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return possible_fonts_dir
|
return possible_fonts_dir
|
||||||
|
|
||||||
def find_logging_config():
|
|
||||||
'''Walk up the filesystem from this script to find a logging_config.json'''
|
|
||||||
for parent_dir in walk_up_directories_of_path(__file__):
|
|
||||||
possible_logging_config_file = os.path.join(parent_dir, 'logging_config.json')
|
|
||||||
if os.path.isfile(possible_logging_config_file):
|
|
||||||
LOG.info('Found logging config file %s', possible_logging_config_file)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return possible_logging_config_file
|
|
||||||
|
|
||||||
def main(argv):
|
def main(argv):
|
||||||
args = parse_args(argv[1:], prog=argv[0])
|
args = parse_args(argv[1:], prog=argv[0])
|
||||||
|
|
||||||
init_logging(args)
|
log.init()
|
||||||
|
|
||||||
fonts_directory = find_fonts_directory()
|
fonts_directory = find_fonts_directory()
|
||||||
if not fonts_directory:
|
if not fonts_directory:
|
||||||
LOG.error("Couldn't find a fonts/ directory")
|
log.ROOT.error("Couldn't find a fonts/ directory")
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
font = os.path.join(fonts_directory, FONT)
|
font = os.path.join(fonts_directory, FONT)
|
||||||
if not os.path.isfile(font):
|
if not os.path.isfile(font):
|
||||||
LOG.error("Font file %s doesn't exist", font)
|
log.ROOT.error("Font file %s doesn't exist", font)
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
tileset = tcod.tileset.load_tilesheet(font, 16, 16, tcod.tileset.CHARMAP_CP437)
|
tileset = tcod.tileset.load_tilesheet(font, 16, 16, tcod.tileset.CHARMAP_CP437)
|
||||||
|
|
|
@ -18,18 +18,16 @@ Action : Base class of all actions
|
||||||
WaitAction
|
WaitAction
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import logging
|
|
||||||
from typing import Optional, TYPE_CHECKING
|
from typing import Optional, TYPE_CHECKING
|
||||||
|
|
||||||
from . import items
|
from . import items
|
||||||
|
from . import log
|
||||||
from .geometry import Direction
|
from .geometry import Direction
|
||||||
from .object import Actor, Item
|
from .object import Actor, Item
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .engine import Engine
|
from .engine import Engine
|
||||||
|
|
||||||
LOG = logging.getLogger('actions')
|
|
||||||
|
|
||||||
class ActionResult:
|
class ActionResult:
|
||||||
'''The result of an Action.
|
'''The result of an Action.
|
||||||
|
|
||||||
|
@ -158,12 +156,12 @@ class BumpAction(MoveAction):
|
||||||
else:
|
else:
|
||||||
entity_occupying_position = None
|
entity_occupying_position = None
|
||||||
|
|
||||||
LOG.debug('Bumping %s into %s (in_bounds:%s walkable:%s overlaps:%s)',
|
log.ACTIONS.debug('Bumping %s into %s (in_bounds:%s walkable:%s overlaps:%s)',
|
||||||
self.actor,
|
self.actor,
|
||||||
new_position,
|
new_position,
|
||||||
position_is_in_bounds,
|
position_is_in_bounds,
|
||||||
position_is_walkable,
|
position_is_walkable,
|
||||||
entity_occupying_position)
|
entity_occupying_position)
|
||||||
|
|
||||||
if not position_is_in_bounds or not position_is_walkable:
|
if not position_is_in_bounds or not position_is_walkable:
|
||||||
return self.failure()
|
return self.failure()
|
||||||
|
@ -180,7 +178,7 @@ class WalkAction(MoveAction):
|
||||||
def perform(self, engine: 'Engine') -> ActionResult:
|
def perform(self, engine: 'Engine') -> ActionResult:
|
||||||
new_position = self.actor.position + self.direction
|
new_position = self.actor.position + self.direction
|
||||||
|
|
||||||
LOG.debug('Moving %s to %s', self.actor, new_position)
|
log.ACTIONS.debug('Moving %s to %s', self.actor, new_position)
|
||||||
self.actor.position = new_position
|
self.actor.position = new_position
|
||||||
|
|
||||||
return self.success()
|
return self.success()
|
||||||
|
@ -201,13 +199,13 @@ class MeleeAction(MoveAction):
|
||||||
|
|
||||||
damage = self.actor.fighter.attack_power - self.target.fighter.defense
|
damage = self.actor.fighter.attack_power - self.target.fighter.defense
|
||||||
if damage > 0 and self.target:
|
if damage > 0 and self.target:
|
||||||
LOG.debug('%s attacks %s for %d damage!', self.actor, self.target, damage)
|
log.ACTIONS.debug('%s attacks %s for %d damage!', self.actor, self.target, damage)
|
||||||
self.target.fighter.hit_points -= damage
|
self.target.fighter.hit_points -= damage
|
||||||
else:
|
else:
|
||||||
LOG.debug('%s attacks %s but does no damage!', self.actor, self.target)
|
log.ACTIONS.debug('%s attacks %s but does no damage!', self.actor, self.target)
|
||||||
|
|
||||||
if self.target.fighter.is_dead:
|
if self.target.fighter.is_dead:
|
||||||
LOG.info('%s is dead!', self.target)
|
log.ACTIONS.info('%s is dead!', self.target)
|
||||||
return ActionResult(self, alternate=DieAction(self.target))
|
return ActionResult(self, alternate=DieAction(self.target))
|
||||||
|
|
||||||
return self.success()
|
return self.success()
|
||||||
|
@ -216,18 +214,18 @@ class WaitAction(Action):
|
||||||
'''Wait a turn'''
|
'''Wait a turn'''
|
||||||
|
|
||||||
def perform(self, engine: 'Engine') -> ActionResult:
|
def perform(self, engine: 'Engine') -> ActionResult:
|
||||||
LOG.debug('%s is waiting a turn', self.actor)
|
log.ACTIONS.debug('%s is waiting a turn', self.actor)
|
||||||
return self.success()
|
return self.success()
|
||||||
|
|
||||||
class DieAction(Action):
|
class DieAction(Action):
|
||||||
'''Kill an Actor'''
|
'''Kill an Actor'''
|
||||||
|
|
||||||
def perform(self, engine: 'Engine') -> ActionResult:
|
def perform(self, engine: 'Engine') -> ActionResult:
|
||||||
LOG.debug('%s dies', self.actor)
|
log.ACTIONS.debug('%s dies', self.actor)
|
||||||
engine.entities.remove(self.actor)
|
engine.entities.remove(self.actor)
|
||||||
|
|
||||||
if self.actor.yields_corpse_on_death:
|
if self.actor.yields_corpse_on_death:
|
||||||
LOG.debug('%s leaves a corpse behind', self.actor)
|
log.ACTIONS.debug('%s leaves a corpse behind', self.actor)
|
||||||
corpse = Item(kind=items.Corpse, name=f'{self.actor.name} Corpse', position=self.actor.position)
|
corpse = Item(kind=items.Corpse, name=f'{self.actor.name} Corpse', position=self.actor.position)
|
||||||
return ActionResult(self, alternate=DropItemAction(self.actor, corpse))
|
return ActionResult(self, alternate=DropItemAction(self.actor, corpse))
|
||||||
|
|
||||||
|
|
14
erynrl/ai.py
14
erynrl/ai.py
|
@ -1,12 +1,12 @@
|
||||||
# Eryn Wells <eryn@erynwells.me>
|
# Eryn Wells <eryn@erynwells.me>
|
||||||
|
|
||||||
import logging
|
|
||||||
import random
|
import random
|
||||||
from typing import TYPE_CHECKING, List, Optional
|
from typing import TYPE_CHECKING, List, Optional
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import tcod
|
import tcod
|
||||||
|
|
||||||
|
from . import log
|
||||||
from .actions import Action, BumpAction, WaitAction
|
from .actions import Action, BumpAction, WaitAction
|
||||||
from .components import Component
|
from .components import Component
|
||||||
from .geometry import Direction, Point
|
from .geometry import Direction, Point
|
||||||
|
@ -15,8 +15,6 @@ from .object import Entity
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .engine import Engine
|
from .engine import Engine
|
||||||
|
|
||||||
LOG = logging.getLogger('ai')
|
|
||||||
|
|
||||||
class AI(Component):
|
class AI(Component):
|
||||||
def __init__(self, entity: Entity) -> None:
|
def __init__(self, entity: Entity) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
@ -34,7 +32,7 @@ class HostileEnemy(AI):
|
||||||
radius=self.entity.sight_radius)
|
radius=self.entity.sight_radius)
|
||||||
|
|
||||||
if engine.map.visible[tuple(self.entity.position)]:
|
if engine.map.visible[tuple(self.entity.position)]:
|
||||||
LOG.debug("AI for %s", self.entity)
|
log.AI.debug("AI for %s", self.entity)
|
||||||
|
|
||||||
hero_position = engine.hero.position
|
hero_position = engine.hero.position
|
||||||
hero_is_visible = visible_tiles[hero_position.x, hero_position.y]
|
hero_is_visible = visible_tiles[hero_position.x, hero_position.y]
|
||||||
|
@ -46,13 +44,13 @@ class HostileEnemy(AI):
|
||||||
entity_position = self.entity.position
|
entity_position = self.entity.position
|
||||||
|
|
||||||
if engine.map.visible[tuple(self.entity.position)]:
|
if engine.map.visible[tuple(self.entity.position)]:
|
||||||
LOG.debug('|-> Path to hero %s', path_to_hero)
|
log.AI.debug('|-> Path to hero %s', path_to_hero)
|
||||||
|
|
||||||
next_position = path_to_hero.pop(0) if len(path_to_hero) > 1 else hero_position
|
next_position = path_to_hero.pop(0) if len(path_to_hero) > 1 else hero_position
|
||||||
direction_to_next_position = entity_position.direction_to_adjacent_point(next_position)
|
direction_to_next_position = entity_position.direction_to_adjacent_point(next_position)
|
||||||
|
|
||||||
if engine.map.visible[tuple(self.entity.position)]:
|
if engine.map.visible[tuple(self.entity.position)]:
|
||||||
LOG.info('`-> Hero is visible to %s, bumping %s (%s)', self.entity, direction_to_next_position, next_position)
|
log.AI.info('`-> Hero is visible to %s, bumping %s (%s)', self.entity, direction_to_next_position, next_position)
|
||||||
|
|
||||||
return BumpAction(self.entity, direction_to_next_position)
|
return BumpAction(self.entity, direction_to_next_position)
|
||||||
else:
|
else:
|
||||||
|
@ -68,13 +66,13 @@ class HostileEnemy(AI):
|
||||||
tile_is_walkable = engine.map.tile_is_walkable(new_position)
|
tile_is_walkable = engine.map.tile_is_walkable(new_position)
|
||||||
if not overlaps_existing_entity and tile_is_walkable:
|
if not overlaps_existing_entity and tile_is_walkable:
|
||||||
if engine.map.visible[tuple(self.entity.position)]:
|
if engine.map.visible[tuple(self.entity.position)]:
|
||||||
LOG.info('Hero is NOT visible to %s, bumping %s randomly', self.entity, direction)
|
log.AI.info('Hero is NOT visible to %s, bumping %s randomly', self.entity, direction)
|
||||||
action = BumpAction(self.entity, direction)
|
action = BumpAction(self.entity, direction)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# If this entity somehow can't move anywhere, just wait
|
# If this entity somehow can't move anywhere, just wait
|
||||||
if engine.map.visible[tuple(self.entity.position)]:
|
if engine.map.visible[tuple(self.entity.position)]:
|
||||||
LOG.info("Hero is NOT visible to %s and it can't move anywhere, waiting", self.entity)
|
log.AI.info("Hero is NOT visible to %s and it can't move anywhere, waiting", self.entity)
|
||||||
action = WaitAction(self.entity)
|
action = WaitAction(self.entity)
|
||||||
|
|
||||||
return action
|
return action
|
||||||
|
|
|
@ -2,21 +2,19 @@
|
||||||
|
|
||||||
'''Defines the core game engine.'''
|
'''Defines the core game engine.'''
|
||||||
|
|
||||||
import logging
|
|
||||||
import random
|
import random
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import MutableSet
|
from typing import MutableSet
|
||||||
|
|
||||||
import tcod
|
import tcod
|
||||||
|
|
||||||
|
from . import log
|
||||||
from . import monsters
|
from . import monsters
|
||||||
from .ai import HostileEnemy
|
from .ai import HostileEnemy
|
||||||
from .geometry import Size
|
from .geometry import Size
|
||||||
from .map import Map
|
from .map import Map
|
||||||
from .object import Entity, Hero, Monster
|
from .object import Entity, Hero, Monster
|
||||||
|
|
||||||
LOG = logging.getLogger('engine')
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Configuration:
|
class Configuration:
|
||||||
map_size: Size
|
map_size: Size
|
||||||
|
@ -66,7 +64,7 @@ class Engine:
|
||||||
else:
|
else:
|
||||||
monster = Monster(monsters.Orc, ai_class=HostileEnemy, position=random_start_position)
|
monster = Monster(monsters.Orc, ai_class=HostileEnemy, position=random_start_position)
|
||||||
|
|
||||||
LOG.info('Spawning %s', monster)
|
log.ENGINE.info('Spawning %s', monster)
|
||||||
self.entities.add(monster)
|
self.entities.add(monster)
|
||||||
|
|
||||||
self.update_field_of_view()
|
self.update_field_of_view()
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
'''Defines event handling mechanisms.'''
|
'''Defines event handling mechanisms.'''
|
||||||
|
|
||||||
import logging
|
|
||||||
from typing import Optional, TYPE_CHECKING
|
from typing import Optional, TYPE_CHECKING
|
||||||
|
|
||||||
import tcod
|
import tcod
|
||||||
|
|
||||||
|
from . import log
|
||||||
from .actions import Action, ActionResult, ExitAction, RegenerateRoomsAction, BumpAction, WaitAction
|
from .actions import Action, ActionResult, ExitAction, RegenerateRoomsAction, BumpAction, WaitAction
|
||||||
from .geometry import Direction
|
from .geometry import Direction
|
||||||
from .object import Actor
|
from .object import Actor
|
||||||
|
@ -14,9 +14,6 @@ from .object import Actor
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .engine import Engine
|
from .engine import Engine
|
||||||
|
|
||||||
LOG = logging.getLogger('events')
|
|
||||||
ACTIONS_TREE_LOG = logging.getLogger('actions.tree')
|
|
||||||
|
|
||||||
class EventHandler(tcod.event.EventDispatch[Action]):
|
class EventHandler(tcod.event.EventDispatch[Action]):
|
||||||
'''Handler of `tcod` events'''
|
'''Handler of `tcod` events'''
|
||||||
|
|
||||||
|
@ -35,11 +32,11 @@ class EventHandler(tcod.event.EventDispatch[Action]):
|
||||||
|
|
||||||
# Unhandled event. Ignore it.
|
# Unhandled event. Ignore it.
|
||||||
if not action:
|
if not action:
|
||||||
LOG.debug('Unhandled event: %s', event)
|
log.EVENTS.debug('Unhandled event: %s', event)
|
||||||
return
|
return
|
||||||
|
|
||||||
ACTIONS_TREE_LOG.info('Processing Hero Actions')
|
log.ACTIONS_TREE.info('Processing Hero Actions')
|
||||||
ACTIONS_TREE_LOG.info('|-> %s', action.actor)
|
log.ACTIONS_TREE.info('|-> %s', action.actor)
|
||||||
|
|
||||||
result = self.perform_action_until_done(action)
|
result = self.perform_action_until_done(action)
|
||||||
|
|
||||||
|
@ -54,7 +51,7 @@ class EventHandler(tcod.event.EventDispatch[Action]):
|
||||||
self.engine.entities,
|
self.engine.entities,
|
||||||
key=lambda e: e.position.euclidean_distance_to(hero_position))
|
key=lambda e: e.position.euclidean_distance_to(hero_position))
|
||||||
|
|
||||||
ACTIONS_TREE_LOG.info('Processing Entity Actions')
|
log.ACTIONS_TREE.info('Processing Entity Actions')
|
||||||
|
|
||||||
for i, ent in enumerate(entities):
|
for i, ent in enumerate(entities):
|
||||||
if not isinstance(ent, Actor):
|
if not isinstance(ent, Actor):
|
||||||
|
@ -65,7 +62,7 @@ class EventHandler(tcod.event.EventDispatch[Action]):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if self.engine.map.visible[tuple(ent.position)]:
|
if self.engine.map.visible[tuple(ent.position)]:
|
||||||
ACTIONS_TREE_LOG.info('%s-> %s', '|' if i < len(entities) - 1 else '`', ent)
|
log.ACTIONS_TREE.info('%s-> %s', '|' if i < len(entities) - 1 else '`', ent)
|
||||||
|
|
||||||
action = ent_ai.act(self.engine)
|
action = ent_ai.act(self.engine)
|
||||||
self.perform_action_until_done(action)
|
self.perform_action_until_done(action)
|
||||||
|
@ -76,17 +73,17 @@ class EventHandler(tcod.event.EventDispatch[Action]):
|
||||||
'''Perform the given action and any alternate follow-up actions until the action chain is done.'''
|
'''Perform the given action and any alternate follow-up actions until the action chain is done.'''
|
||||||
result = action.perform(self.engine)
|
result = action.perform(self.engine)
|
||||||
|
|
||||||
if ACTIONS_TREE_LOG.isEnabledFor(logging.INFO) and self.engine.map.visible[tuple(action.actor.position)]:
|
if log.ACTIONS_TREE.isEnabledFor(log.INFO) and self.engine.map.visible[tuple(action.actor.position)]:
|
||||||
if result.alternate:
|
if result.alternate:
|
||||||
alternate_string = f'{result.alternate.__class__.__name__}[{result.alternate.actor.symbol}]'
|
alternate_string = f'{result.alternate.__class__.__name__}[{result.alternate.actor.symbol}]'
|
||||||
else:
|
else:
|
||||||
alternate_string = str(result.alternate)
|
alternate_string = str(result.alternate)
|
||||||
ACTIONS_TREE_LOG.info('| %s-> %s => success=%s done=%s alternate=%s',
|
log.ACTIONS_TREE.info('| %s-> %s => success=%s done=%s alternate=%s',
|
||||||
'|' if not result.success or not result.done else '`',
|
'|' if not result.success or not result.done else '`',
|
||||||
action,
|
action,
|
||||||
result.success,
|
result.success,
|
||||||
result.done,
|
result.done,
|
||||||
alternate_string)
|
alternate_string)
|
||||||
|
|
||||||
while not result.done:
|
while not result.done:
|
||||||
action = result.alternate
|
action = result.alternate
|
||||||
|
@ -94,12 +91,12 @@ class EventHandler(tcod.event.EventDispatch[Action]):
|
||||||
|
|
||||||
result = action.perform(self.engine)
|
result = action.perform(self.engine)
|
||||||
|
|
||||||
if ACTIONS_TREE_LOG.isEnabledFor(logging.INFO) and self.engine.map.visible[tuple(action.actor.position)]:
|
if log.ACTIONS_TREE.isEnabledFor(log.INFO) and self.engine.map.visible[tuple(action.actor.position)]:
|
||||||
if result.alternate:
|
if result.alternate:
|
||||||
alternate_string = f'{result.alternate.__class__.__name__}[{result.alternate.actor.symbol}]'
|
alternate_string = f'{result.alternate.__class__.__name__}[{result.alternate.actor.symbol}]'
|
||||||
else:
|
else:
|
||||||
alternate_string = str(result.alternate)
|
alternate_string = str(result.alternate)
|
||||||
ACTIONS_TREE_LOG.info('| %s-> %s => success=%s done=%s alternate=%s',
|
log.ACTIONS_TREE.info('| %s-> %s => success=%s done=%s alternate=%s',
|
||||||
'|' if not result.success or not result.done else '`',
|
'|' if not result.success or not result.done else '`',
|
||||||
action,
|
action,
|
||||||
result.success,
|
result.success,
|
||||||
|
|
69
erynrl/log.py
Normal file
69
erynrl/log.py
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
# Eryn Wells <eryn@erynwells.me>
|
||||||
|
|
||||||
|
'''
|
||||||
|
Initializes and sets up
|
||||||
|
'''
|
||||||
|
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import logging.config
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
# These are re-imports so clients of this module don't have to also import logging
|
||||||
|
# pylint: disable=unused-import
|
||||||
|
from logging import CRITICAL, DEBUG, ERROR, FATAL, INFO, NOTSET, WARN, WARNING
|
||||||
|
|
||||||
|
def _log_name(*components):
|
||||||
|
return '.'.join(['erynrl'] + list(components))
|
||||||
|
|
||||||
|
ROOT = logging.getLogger(_log_name())
|
||||||
|
AI = logging.getLogger(_log_name('ai'))
|
||||||
|
ACTIONS = logging.getLogger(_log_name('actions'))
|
||||||
|
ACTIONS_TREE = logging.getLogger(_log_name('actions', 'tree'))
|
||||||
|
ENGINE = logging.getLogger(_log_name('engine'))
|
||||||
|
EVENTS = logging.getLogger(_log_name('events'))
|
||||||
|
MAP = logging.getLogger(_log_name('map'))
|
||||||
|
|
||||||
|
def walk_up_directories_of_path(path):
|
||||||
|
'''Walk up a path, yielding each directory, until the root of the filesystem is found'''
|
||||||
|
while path and path != '/':
|
||||||
|
if os.path.isdir(path):
|
||||||
|
yield path
|
||||||
|
path = os.path.dirname(path)
|
||||||
|
|
||||||
|
def find_logging_config():
|
||||||
|
'''Walk up the filesystem from this script to find a logging_config.json'''
|
||||||
|
for parent_dir in walk_up_directories_of_path(__file__):
|
||||||
|
possible_logging_config_file = os.path.join(parent_dir, 'logging_config.json')
|
||||||
|
if os.path.isfile(possible_logging_config_file):
|
||||||
|
ROOT.info('Found logging config file %s', possible_logging_config_file)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return possible_logging_config_file
|
||||||
|
|
||||||
|
def init(config_file=None):
|
||||||
|
'''
|
||||||
|
Set up the logging system by (preferrably) reading a logging configuration file.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
config_file : str
|
||||||
|
Path to a file containing a Python logging configuration in JSON
|
||||||
|
'''
|
||||||
|
logging_config_path = config_file if config_file else find_logging_config()
|
||||||
|
|
||||||
|
if os.path.isfile(logging_config_path):
|
||||||
|
with open(logging_config_path, encoding='utf-8') as logging_config_file:
|
||||||
|
logging_config = json.load(logging_config_file)
|
||||||
|
logging.config.dictConfig(logging_config)
|
||||||
|
ROOT.info('Found logging configuration at %s', logging_config_path)
|
||||||
|
else:
|
||||||
|
root_logger = logging.getLogger('')
|
||||||
|
root_logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
stderr_handler = logging.StreamHandler()
|
||||||
|
stderr_handler.setFormatter(logging.Formatter("%(asctime)s %(name)s: %(message)s"))
|
||||||
|
|
||||||
|
root_logger.addHandler(stderr_handler)
|
|
@ -1,6 +1,5 @@
|
||||||
# Eryn Wells <eryn@erynwells.me>
|
# Eryn Wells <eryn@erynwells.me>
|
||||||
|
|
||||||
import logging
|
|
||||||
import random
|
import random
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Iterator, List, Optional
|
from typing import Iterator, List, Optional
|
||||||
|
@ -8,11 +7,10 @@ from typing import Iterator, List, Optional
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import tcod
|
import tcod
|
||||||
|
|
||||||
|
from . import log
|
||||||
from .geometry import Direction, Point, Rect, Size
|
from .geometry import Direction, Point, Rect, Size
|
||||||
from .tile import Empty, Floor, Shroud, Wall
|
from .tile import Empty, Floor, Shroud, Wall
|
||||||
|
|
||||||
LOG = logging.getLogger('map')
|
|
||||||
|
|
||||||
class Map:
|
class Map:
|
||||||
def __init__(self, size: Size):
|
def __init__(self, size: Size):
|
||||||
self.size = size
|
self.size = size
|
||||||
|
@ -120,7 +118,7 @@ class RoomsAndCorridorsGenerator(MapGenerator):
|
||||||
node_bounds = self.__rect_from_bsp_node(node)
|
node_bounds = self.__rect_from_bsp_node(node)
|
||||||
|
|
||||||
if node.children:
|
if node.children:
|
||||||
LOG.debug(node_bounds)
|
log.MAP.debug(node_bounds)
|
||||||
|
|
||||||
left_room: RectangularRoom = getattr(node.children[0], room_attrname)
|
left_room: RectangularRoom = getattr(node.children[0], room_attrname)
|
||||||
right_room: RectangularRoom = getattr(node.children[1], room_attrname)
|
right_room: RectangularRoom = getattr(node.children[1], room_attrname)
|
||||||
|
@ -128,8 +126,8 @@ class RoomsAndCorridorsGenerator(MapGenerator):
|
||||||
left_room_bounds = left_room.bounds
|
left_room_bounds = left_room.bounds
|
||||||
right_room_bounds = right_room.bounds
|
right_room_bounds = right_room.bounds
|
||||||
|
|
||||||
LOG.debug(' left: %s, %s', node.children[0], left_room_bounds)
|
log.MAP.debug(' left: %s, %s', node.children[0], left_room_bounds)
|
||||||
LOG.debug('right: %s, %s', node.children[1], right_room_bounds)
|
log.MAP.debug('right: %s, %s', node.children[1], right_room_bounds)
|
||||||
|
|
||||||
start_point = left_room_bounds.midpoint
|
start_point = left_room_bounds.midpoint
|
||||||
end_point = right_room_bounds.midpoint
|
end_point = right_room_bounds.midpoint
|
||||||
|
@ -140,16 +138,16 @@ class RoomsAndCorridorsGenerator(MapGenerator):
|
||||||
else:
|
else:
|
||||||
corner = Point(start_point.x, end_point.y)
|
corner = Point(start_point.x, end_point.y)
|
||||||
|
|
||||||
LOG.debug('Digging a tunnel between %s and %s with corner %s', start_point, end_point, corner)
|
log.MAP.debug('Digging a tunnel between %s and %s with corner %s', start_point, end_point, corner)
|
||||||
LOG.debug('|-> start: %s', left_room_bounds)
|
log.MAP.debug('|-> start: %s', left_room_bounds)
|
||||||
LOG.debug('`-> end: %s', right_room_bounds)
|
log.MAP.debug('`-> end: %s', right_room_bounds)
|
||||||
|
|
||||||
for x, y in tcod.los.bresenham(tuple(start_point), tuple(corner)).tolist():
|
for x, y in tcod.los.bresenham(tuple(start_point), tuple(corner)).tolist():
|
||||||
tiles[x, y] = Floor
|
tiles[x, y] = Floor
|
||||||
for x, y in tcod.los.bresenham(tuple(corner), tuple(end_point)).tolist():
|
for x, y in tcod.los.bresenham(tuple(corner), tuple(end_point)).tolist():
|
||||||
tiles[x, y] = Floor
|
tiles[x, y] = Floor
|
||||||
else:
|
else:
|
||||||
LOG.debug('%s (room) %s', node_bounds, node)
|
log.MAP.debug('%s (room) %s', node_bounds, node)
|
||||||
|
|
||||||
# Generate a room size between minimum_room_size and maximum_room_size. The minimum value is
|
# Generate a room size between minimum_room_size and maximum_room_size. The minimum value is
|
||||||
# straight-forward, but the maximum value needs to be clamped between minimum_room_size and the size of
|
# straight-forward, but the maximum value needs to be clamped between minimum_room_size and the size of
|
||||||
|
@ -162,7 +160,7 @@ class RoomsAndCorridorsGenerator(MapGenerator):
|
||||||
node.y + self.rng.randint(1, max(1, node.height - size.height - 1)))
|
node.y + self.rng.randint(1, max(1, node.height - size.height - 1)))
|
||||||
bounds = Rect(origin, size)
|
bounds = Rect(origin, size)
|
||||||
|
|
||||||
LOG.debug('`-> %s', bounds)
|
log.MAP.debug('`-> %s', bounds)
|
||||||
|
|
||||||
room = RectangularRoom(bounds)
|
room = RectangularRoom(bounds)
|
||||||
setattr(node, room_attrname, room)
|
setattr(node, room_attrname, room)
|
||||||
|
|
|
@ -15,30 +15,30 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"loggers": {
|
"loggers": {
|
||||||
"ai": {
|
"erynrl.ai": {
|
||||||
"level": "ERROR",
|
"level": "ERROR",
|
||||||
"handlers": ["console"],
|
"handlers": ["console"],
|
||||||
"propagate": false
|
"propagate": false
|
||||||
},
|
},
|
||||||
"actions": {
|
"erynrl.actions": {
|
||||||
"level": "INFO",
|
"level": "INFO",
|
||||||
"handlers": ["console"]
|
"handlers": ["console"]
|
||||||
},
|
},
|
||||||
"actions.movement": {
|
"erynrl.actions.movement": {
|
||||||
"level": "ERROR",
|
"level": "ERROR",
|
||||||
"handlers": ["console"]
|
"handlers": ["console"]
|
||||||
},
|
},
|
||||||
"actions.tree": {
|
"erynrl.actions.tree": {
|
||||||
"level": "INFO",
|
"level": "INFO",
|
||||||
"handlers": ["console"],
|
"handlers": ["console"],
|
||||||
"propagate": false
|
"propagate": false
|
||||||
},
|
},
|
||||||
"events": {
|
"erynrl.events": {
|
||||||
"level": "WARN",
|
"level": "WARN",
|
||||||
"handlers": ["console"],
|
"handlers": ["console"],
|
||||||
"propagate": false
|
"propagate": false
|
||||||
},
|
},
|
||||||
"visible": {
|
"erynrl.visible": {
|
||||||
"level": "DEBUG",
|
"level": "DEBUG",
|
||||||
"handlers": ["console"]
|
"handlers": ["console"]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue