Permalink
Browse files

Code shuffle/cleanup/rewriting for better code consistency

  • Loading branch information...
1 parent d5d0bc7 commit 9b47e750485202d1342266d800f91f01f432e379 @helgefmi committed Jun 10, 2011
View
6 .gitignore
@@ -1,5 +1,5 @@
-lib
-logs/*
+/lib
+/logs/*
+/savegames
*.pyc
.*.swp
-savegames
View
9 ohno/ai/pathing.py
@@ -75,17 +75,12 @@ def _search(self):
# Investigate each tile once
if self.previous[neighbor.idx]:
continue
- # TODO: This is obviously a hack
- if neighbor.in_shop:
- continue
# Don't search past two unexplored tiles in a direction
if not current.explored and not neighbor.explored:
continue
- # TODO: Remove can_walk_diagonally and is_open_door and put the
- # logic in here.
# We can't move diagonally through an open door
- can_diagonal = (current.can_walk_diagonally() and
- neighbor.can_walk_diagonally())
+ can_diagonal = (not current.is_open_door() and
+ not neighbor.is_open_door())
if (not can_diagonal and
abs(neighbor.idx - current.idx) not in (1, 80)):
continue
View
2 ohno/ai/strategy/explore.py
@@ -22,7 +22,7 @@ def _closed_doors(self):
self.ohno.logger.strategy('[explore] found closed door at %r' % tile)
assert tile.walkable == False
- assert tile.feature_is_a('Door')
+ assert tile.feature_isa('Door')
if tile in self.ohno.dungeon.curtile.adjacent():
if tile.feature.locked:
View
16 ohno/appearance.py
@@ -8,10 +8,6 @@ def __init__(self, glyph, color):
self._fg = color['fg']
self._bold = color['bold']
- glyph = property(lambda self:self._glyph)
- fg = property(lambda self:self._fg)
- bold = property(lambda self:self._bold)
-
def __eq__(self, other):
return hash(self) == hash(other)
@@ -28,6 +24,18 @@ def __str__(self):
def __hash__(self):
return hash(str(self))
+ @property
+ def glyph(self):
+ return self._glyph
+
+ @property
+ def fg(self):
+ return self._fg
+
+ @property
+ def bold(self):
+ return self._bold
+
STAIRCASE_DOWN = Appearance('>', {'fg': 37, 'bold': False})
STAIRCASE_UP = Appearance('<', {'fg': 37, 'bold': False})
OPEN_DOOR = Appearance('-', {'fg': 33, 'bold': False})
View
18 ohno/dungeon/dungeon.py
@@ -10,16 +10,17 @@ def __init__(self, ohno):
def update(self):
"""
- 1. Check if we're on a new level, and make on if we are
- 2. Set self.curlevel and self.curtile, and update the current level
+ 1. Check if we're on a new level, and make on if we are.
+ 2. Set self.curlevel and self.curtile
+ 3. Update the current level.
"""
# TODO: Branches. We need to know which branch we are in and which
# levels are in which branch.
# This should probably be done inside this function, while
# the detection code should be in Level.
dlvl = self.ohno.hero.dlvl
if dlvl not in self.levels:
- self.ohno.logger.dungeon('Found new level (dlvl %d)!' % dlvl)
+ self.ohno.logger.dungeon('Found dlvl %d!' % dlvl)
self.levels[dlvl] = Level(self.ohno, dlvl)
newlevel = self.levels[dlvl]
@@ -34,16 +35,19 @@ def update(self):
MessageEvent.unsubscribe(self.curlevel.on_message)
MessageEvent.subscribe(newlevel.on_message)
self.curlevel = newlevel
- newlevel.update()
idx = self.ohno.hero.get_position_idx()
self.curtile = self.curlevel.tiles[idx]
- self.ohno.logger.dungeon('Current tile is %r' % self.curtile)
+ self.ohno.logger.dungeon(
+ 'curtile before updating level: %r' % self.curtile
+ )
+ self.curlevel.update()
+ self.ohno.logger.dungeon(
+ 'curtile after updating level: %r' % self.curtile
+ )
# Some sanity checks
assert self.curtile.idx == idx
assert self.curtile.appearance == self.ohno.hero.appearance
assert self.curtile.monster is None
-
- self.curlevel.farlook_monsters()
View
7 ohno/dungeon/item/item.py
@@ -7,7 +7,6 @@ def __init__(self, ohno, appearance):
self.ohno = ohno
self.appearance = appearance
- @staticmethod
- def create(ohno, appearance):
- """Checks `appearance` for which item to create"""
- return Item(ohno, appearance)
+def create(ohno, appearance):
+ """Checks `appearance` for which item to create"""
+ return Item(ohno, appearance)
View
78 ohno/dungeon/level.py
@@ -17,61 +17,63 @@ class Level(object):
def __init__(self, ohno, dlvl):
self.ohno = ohno
self.dlvl = dlvl
+ # Tiles should only mutate, never be replaced by new ones.
self.tiles = tuple(Tile(self, x) for x in xrange(21 * 80))
self.monsters = []
self.max_searched = 12
def __str__(self):
return '<Level %s>' % self.dlvl
+ __repr__ = __str__
- @queryable
- def tiles_where(self):
- return self.tiles
+ def _farlook_monsters(self):
+ # Check to see if there's a monster on this level that we're not sure
+ # what is yet.
+ for monster in self.monsters:
+ if not (len(monster.spoilers) > 1 or
+ (monster.peaceful is None and not monster.is_peaceful)):
+ continue
+
+ self.ohno.logger.level('Doing farlook on %s (%s)' % (
+ monster.tile, monster
+ ))
+ message = self.ohno.farlook(monster.tile)
+ self.ohno.logger.level('Got message: %s' % message)
+ info = Level.inspectname.search(message).groupdict()
+ self.ohno.logger.level('Parsed: %s' % info)
+ monster.monster_info(info)
def update(self):
+ """
+ This will update the current level.
+ 1. Make changes to the tiles of this level.
+ 2. Update newly explored tiles as explored.
+ 3. Farlook interesting monsters.
+ """
self.ohno.logger.level('Updating level..')
maptiles = self.ohno.framebuffer.get_maptiles()
- for (i, tile) in enumerate(self.tiles):
+ for i, tile in enumerate(self.tiles):
maptile = maptiles[i]
# No point in updating a tile that didn't change since last time.
if tile.appearance != maptile:
- #self.ohno.logger.level('Updating %d: %r' % (i, tile))
tile.set(maptile)
- #self.ohno.logger.level('RESULT: %d: %r' % (i, tile))
- curtile = self.tiles[self.ohno.hero.get_position_idx()]
- self.ohno.logger.level('Curtile after level update %r' % curtile)
- curtile.explored = True
+ self.ohno.dungeon.curtile.explored = True
# Since empty spaces might both be walkable and not, the only way to
# find out (well.. at this point anyway) is to stand adjacent to the
# square and see if it lights up (see if the glyph changes or not).
# If it doesn't, we need to set the tile to not walkable.
if not self.ohno.hero.blind:
- for tile in curtile.adjacent():
+ for tile in self.ohno.dungeon.curtile.adjacent():
if not tile.items:
tile.explored = True
if tile.appearance.glyph == ' ':
tile._walkable = False
- def farlook_monsters(self):
- # Check to see if there's a monster on this level that we're not sure
- # what is yet.
- for monster in self.monsters:
- do_farlook = (len(monster.spoilers) > 1 or
- (monster.peaceful is None and
- not monster.is_peaceful))
-
- if do_farlook:
- self.ohno.logger.level('Doing farlook on %s (%s)' % (
- monster.tile, monster
- ))
- message = self.ohno.farlook(monster.tile)
- self.ohno.logger.level('Got message: %s' % message)
- info = Level.inspectname.search(message).groupdict()
- monster.monster_info(info)
-
+ self._farlook_monsters()
+
def explored_progress(self):
"""
How much of the level do we think is explored?
@@ -85,8 +87,8 @@ def explored_progress(self):
# algorithms for normal levels and mine levels.
# TODO: Normal levels should count rooms as well as check the amount of
# walkable tiles.
- num_walkable_tiles = sum(
- 1 for x in self.tiles_where(walkable=True, explored=True)
+ num_walkable_tiles = len(
+ list(self.tiles_where(walkable=True, explored=True))
)
# Let's try 300 as the value of explored walkable tiles a level has on
@@ -95,9 +97,11 @@ def explored_progress(self):
def on_message(self, event):
curtile = self.ohno.dungeon.curtile
+
if event.msgtype == 'locked_door':
+ assert self.ohno.last_action.isa('Open')
tile = self.ohno.last_action.tile
- assert tile.feature_is_a('Door')
+ assert tile.feature_isa('Door')
self.ohno.logger.level('Locking %r@%s' % (tile, self))
tile.feature.lock()
@@ -113,23 +117,21 @@ def on_message(self, event):
self.ohno.logger.level('Setting %s to an open door' % curtile)
curtile.set_feature(appearance.OPEN_DOOR)
- #if event.msgtype == 'found_shop':
- # shop_tiles = [tile for tile in curtile.adjacent(walkable=True)
- # if tile.appearance != '#']
- # self.ohno.logger.level('shop_tiles: %s' % map(str, shop_tiles))
- # for tile in shop_tiles:
- # tile.set_in_shop()
-
if event.msgtype == 'kicked_door':
assert self.ohno.last_action.isa('Kick')
+ tile = self.ohno.last_action.tile
self.ohno.logger.level(
'Setting %s to floor.' % self.ohno.last_action.tile
)
- self.ohno.last_action.tile.set_feature(appearance.FLOOR)
+ tile.set_feature(appearance.FLOOR)
if event.msgtype == 'opened_door':
assert self.ohno.last_action.isa('Open')
self.ohno.logger.level(
'Setting %s to floor.' % self.ohno.last_action.tile
)
self.ohno.last_action.tile.set_feature(appearance.OPEN_DOOR)
+
+ @queryable
+ def tiles_where(self):
+ return self.tiles
View
26 ohno/dungeon/monster.py
@@ -6,22 +6,24 @@ class Monster(object):
Represents a monster on a tile.
"""
- @staticmethod
- def create(ohno, maptile):
- """Checks `maptile` for which monster to create"""
- return Monster(ohno, maptile)
-
def __init__(self, tile, maptile):
self.ohno = tile.ohno
self.tile = tile
self.appearance = maptile
+ # Means we haven't explicitly checked yet.
+ self.peaceful = None
self.spoilers = monsters.by_appearance[maptile]
- if str(maptile) != 'I7': # Invisible monster
+ self.ohno.logger.monster('Found spoiler: %s' % self.spoilers)
+
+ if str(maptile) not in ['I7', 'X7']:
assert self.spoilers, maptile
- self.ohno.logger.monster('Found spoiler: %s' % self.spoilers)
- self.peaceful = None # Means we haven't explicitly checked yet.
+ def __str__(self):
+ return '<Monster S=%s P=%s>' % (
+ self.spoilers, self.peaceful
+ )
+ __repr__ = __str__
def monster_info(self, info):
self.peaceful = bool(info['peaceful'])
@@ -43,8 +45,6 @@ def is_peaceful(self):
return self.peaceful
return all(x.is_peaceful() for x in self.spoilers)
- def __str__(self):
- return '<Monster S=%s P=%s>' % (
- self.spoilers, self.peaceful
- )
- __repr__ = __str__
+def create(ohno, maptile):
+ """Checks `maptile` for which monster to create"""
+ return Monster(ohno, maptile)
View
82 ohno/dungeon/tile.py
@@ -1,11 +1,10 @@
import string
-from ohno.dungeon.item.item import Item
-from ohno.dungeon.monster import Monster
+from queryable import queryable
+from ohno.dungeon import monster
from ohno.dungeon.feature import feature
-
-from queryable import queryable
+from ohno.dungeon.item import item
_tile_is_feature = lambda t: t.glyph in '.}{#_<>]^|-~ \\' or str(t) == 'm4'
_tile_is_item = lambda t: t.glyph in '`0*$[%)(/?!"=+'
@@ -27,13 +26,24 @@ def __init__(self, level, idx):
self.items = []
self.monster = None
self.has_hero = None
- self.in_shop = False
self._adjacent = None
self._orthogonal = None
self._horizontal = None
self._vertical = None
+ def __str__(self):
+ return '<Tile %d G=%s E=%d W=%d S=%d D=%f>' % (
+ self.idx,
+ self.appearance.glyph if self.appearance else ' ',
+ self.explored,
+ int(self.walkable or 0),
+ self.searched,
+ self.distance_from_hero() if self.ohno.ai.pathing.is_uptodate()
+ else -1
+ )
+ __repr__ = __str__
+
def set(self, appearance):
"""
Will be called by `ohno.dungeon.level.update` if the current glyph or
@@ -47,11 +57,12 @@ def set(self, appearance):
self.explored = self.explored or appearance.glyph != ' '
# If it's the first time we're seeing the feature of this tile or if
# it has changed (i.e. water can spread to nearby floortiles).
- if (not self.feature) or self.feature.appearance != appearance:
+ if not self.feature or self.feature.appearance != appearance:
self.set_feature(appearance)
self.items = []
self.has_hero = False
self.set_monster(None)
+
elif _tile_is_item(appearance):
self.ohno.logger.tile('Itemtile! %r' % self)
self._walkable = True
@@ -65,26 +76,25 @@ def set(self, appearance):
# If it stays the same, we'll simply assume nothing has changed.
if not self.items or self.items[-1].appearance != appearance:
self.ohno.logger.tile('New item!')
- self.items = [Item.create(self, appearance)]
+ self.items = [item.create(self, appearance)]
# Since this tile might have new information,
# we set explored to False. That way, it'll be easier for our AI
# to know this square is interesting.
self.explored = False
self.ohno.logger.tile('Itemtile is now %r' % self)
- elif self.idx == self.ohno.hero.get_position_idx():
+
+ elif self == self.ohno.dungeon.curtile:
self.ohno.logger.tile('Herotile! %r' % self)
assert not self.has_hero
self._walkable = True
self.has_hero = True
self.set_monster(None)
if self.ohno.hero.appearance != appearance:
- self.ohno.logger.tile('New hero! A was %s, now is %s' % (
- self.ohno.hero.appearance, appearance
- ))
# Not sure if we need this, but this seems like a good place to
# check if we're polymorphed.
self.ohno.hero.set_appearance(appearance)
self.ohno.logger.tile('Herotile is now %r' % self)
+
elif _tile_is_monster(appearance):
# TODO: Might not be true if this is a stone giant standing on a
# boulder.
@@ -93,16 +103,20 @@ def set(self, appearance):
self._walkable = True
if (not self.monster) or self.monster.appearance != appearance:
self.ohno.logger.tile('New monster!')
- self.set_monster(Monster.create(self, appearance))
+ self.set_monster(appearance)
self.ohno.logger.tile('Monstertile is now %r' % self)
def set_feature(self, appearance):
self.feature = feature.create(self, appearance)
self._walkable = (self.is_open_door() or
_tile_is_walkable(appearance))
- def set_monster(self, new_monster):
+ def set_monster(self, appearance):
"""Sets self.monster and updates Levle.monsters"""
+ new_monster = None
+ if appearance is not None:
+ new_monster = monster.create(self, appearance)
+
if new_monster == self.monster:
return
@@ -114,9 +128,6 @@ def set_monster(self, new_monster):
self.monster = new_monster
- def set_in_shop(self):
- self.in_shop = True
-
@property
def appearance(self):
"""What does this tile look like right now?"""
@@ -141,6 +152,14 @@ def distance_from_hero(self):
assert self.ohno.ai.pathing.tick == self.ohno.tick
return self.ohno.ai.pathing.dists[self.idx]
+ def feature_isa(self, class_name):
+ return self.feature_name == class_name
+
+ def is_open_door(self):
+ return (self.feature and
+ self.feature.appearance.glyph in '-|' and
+ self.feature.appearance.fg == 33)
+
# Methods for iterating neighbors
@queryable
def adjacent(self):
@@ -211,49 +230,22 @@ def has_monster(self):
@property
def has_closed_door(self):
- return self.feature_is_a('Door') and self.feature.closed
+ return self.feature_isa('Door') and self.feature.closed
@property
def feature_name(self):
return self.feature.__class__.__name__ if self.feature else 'Unknown'
@property
def reachable(self):
+ assert self.ohno.ai.pathing.is_uptodate()
return self.distance_from_hero() != float('inf')
@property
def walkable(self):
- # TODO: The following is not true if we're currently a giant or have
- # the ability to fly (i think :)..
# This might be called before the tile is initialized, so make sure we
# consider the case where appearance is None
return (self.appearance and
self._walkable and
not self.monster and
self.appearance.glyph != '0')
-
- def feature_is_a(self, class_name):
- return self.feature_name == class_name
-
- def __str__(self):
- return '<Tile %d G=%s E=%d W=%d S=%d D=%f>' % (
- self.idx, self.appearance.glyph if self.appearance else ' ',
- self.explored, int(self.walkable or 0), self.searched,
- self.distance_from_hero() if self.ohno.ai.pathing.is_uptodate()
- else -1
- )
-
- def __repr__(self):
- return str(self)
-
- # TODO: Meh, move this to the pathing code.
- # I see no other uses for this function.
- def is_open_door(self):
- return (self.feature and
- self.feature.appearance.glyph in '-|' and
- self.feature.appearance.fg == 33)
-
- # TODO: Meh, move this to the pathing code.
- # I see no other uses for this function.
- def can_walk_diagonally(self):
- return not self.is_open_door()
View
1 ohno/hero.py
@@ -65,6 +65,7 @@ def __init__(self, ohno):
def __str__(self):
return '<Hero ' + (' '.join('%s=%s' % (key, getattr(self, key))
for key in self.__dict__) + '>')
+ __repr__ = __str__
def get_position_idx(self):
return self.position[0] * 80 + self.position[1]
View
3 ohno/ohno.py
@@ -65,8 +65,9 @@ def loop(self):
if not self.running:
break
- # Updates stats like hp, ac, hunger, score, dlvl
+ # Updates stats (bottomlines) and hero's position.
self.hero.update()
+
# Creates new level and/or updates the level with what we got from
# framebuffer.
self.dungeon.update()
View
7 ohno/ui/debugmode.py
@@ -20,6 +20,10 @@ def __init__(self, ohno):
}
self.ohno.paused = True
+ def __str__(self):
+ return 'debug'
+ __repr__ = __str__
+
def get_cursor_idx(self):
return self.cursor['y'] * 80 + self.cursor['x']
@@ -89,6 +93,3 @@ def second_botline(self):
hero.dlvl, hero.hp, hero.maxhp, hero.ac, hero.level, hero.turns,
hero.gold
)
-
- def __str__(self):
- return 'debug'
View
7 ohno/ui/normalmode.py
@@ -8,12 +8,13 @@ def __init__(self, ohno):
self.ohno = ohno
self.ohno.paused = False
+ def __str__(self):
+ return 'normal'
+ __repr__ = __str__
+
def on_input(self, input):
if input in '|sp':
return super(NormalMode, self).on_input(input)
elif input == 'd':
from ohno.ui.debugmode import DebugMode
return DebugMode
-
- def __str__(self):
- return 'normal'

0 comments on commit 9b47e75

Please sign in to comment.