git.fiddlerwoaroof.com
libs/overlay.py
b8f124a1
 from src import events
5f75058b
 import abc
ac4ad8e3
 import collections
dff12016
 from . import combat
5f75058b
 
 class Overlay(object):
dff12016
 	__metaclass__ = abc.ABCMeta
5f75058b
 
 	char = abc.abstractproperty()
 	color = (0,0,0)
 	blocks = False
 
 	@property
 	def pos(self):
 		return self.x, self.y
 	def __init__(self, x,y, map):
df36dce5
 		super(Overlay, self).__init__()
b8f124a1
 		print self.handled_events
ac4ad8e3
 		self.events = collections.OrderedDict()
5f75058b
 		self.x = x
 		self.y = y
 		self.map = map
ac4ad8e3
 		for key, value in self.handled_events.viewitems():
 			self.events.setdefault(key, []).extend(value)
 
86f3fea2
 	def draw(self):
 		self.map.add(self)
5f75058b
 
ac4ad8e3
 	def register_event(self, event, cb):
 		'''register a callback for an event
 
 		if the callback returns a false value besides None, execution will end after that event'''
 		self.events.setdefault(event, []).append(cb)
 
 	def trigger_event(self, event, *args, **kw):
df36dce5
 		for cb in self.events.get(event, []):
ac4ad8e3
 			result = cb(self, *args, **kw)
 			result = result is None or result # if the event returns a false value besides None, break
 			if result == False: break
 
b8f124a1
 	@staticmethod
 	def add_event(event,  cb_name):
 		def _inner(cls):
 			if not hasattr(cls,  'handled_events'):
 				cls.handled_events = {}
 				for base in cls.bases:
 					if hasattr(base,  'handled_events'):
 						cls.handled_events.update(base.handled_events)
 			cls.handled_events.setdefault(event,  []).append(getattr(cls,  cb_name))
 			return cls
ac4ad8e3
 		return _inner
 
b8f124a1
 	def tick(self):
 		pass
ac4ad8e3
 
5f75058b
 
b8f124a1
 @Overlay.add_event('attacked',  'attacked_by')
 @Overlay.add_event('bumped',  'bumped_by')
5f75058b
 class Actor(Overlay):
 	char = ord('@')
 	color = (255,0,0)
 	blocks = True
 
b8f124a1
 	handled_events = collections.OrderedDict()
5f75058b
 	@property
 	def pos(self):
 		return self.x, self.y
 
 	def __init__(self, x,y, map, adventurer=None):
ac4ad8e3
 		super(Actor, self).__init__(x,y, map)
 		self.inventory = []
dff12016
 		if adventurer is None:
 			adventurer = combat.Adventurer.randomize()
 		self.adventurer = adventurer
b8f124a1
 		self.repeated_actions = {}
5f75058b
 
b8f124a1
 	def add_repeated_action(self, time, action, *args, **kw):
 		print 'adding action', action, args, kw
 		self.repeated_actions.setdefault(time, []).append( (action, args, kw) )
 
 	def update_pos(self, dx,dy):
5f75058b
 		self.x += dx
 		self.y += dy
 
b8f124a1
 	def move(self, dx, dy):
 		print 'moving'
 		self.map.move(self, dx,dy, self.update_pos)
 
5f75058b
 	def tick(self):
86f3fea2
 		result = True
 		if self.adventurer.state >= 2:
 			result = False
 			self.char = ord('%')
 			self.blocks = False
b8f124a1
 		else:
df36dce5
 			self.act()
b8f124a1
 			ractions = {}
 			for nleft, actions in self.repeated_actions.items():
 				for (action,args,kwargs) in actions:
 					print action,args,kwargs
 					action(*args, **kwargs)
 					if nleft > 1:
 						ractions.setdefault(nleft-1, []).append( (action,args,kwargs) )
df36dce5
 				print ractions
b8f124a1
 			self.repeated_actions = ractions
86f3fea2
 		return result
5f75058b
 
df36dce5
 	def act(self): pass
 
dff12016
 	def ishostile(self, other):
ac4ad8e3
 		return self.adventurer.state < 2 #TODO: implement factions
dff12016
 
5f75058b
 	def bump(self, other):
 		print '%s bumped %s' % (type(self).__name__, type(other).__name__)
dff12016
 		if isinstance(other, Actor) and other.ishostile(self):
 			self.adventurer.attack(other.adventurer)
ac4ad8e3
 			other.trigger_event('attacked', self)
b8f124a1
 
 	def interact(self, other):
 		result = False
 		if isinstance(other, Object):
 			result = True
ac4ad8e3
 			self.pickup(other)
 			other.trigger_event('picked_up', self)
dff12016
 
ac4ad8e3
 		other.trigger_event('bumped', self)
b8f124a1
 		return result
 
 	def pickup(self, other):
 		self.inventory.append(other)
ac4ad8e3
 
dff12016
 	def attacked_by(self, other):
86f3fea2
 		if self.adventurer.skills.check('agility'):
dff12016
 			self.adventurer.attack(other.adventurer)
 
5f75058b
 	def bumped_by(self, other):
 		print '%s was bumped by %s' % (type(self).__name__, type(other).__name__)
 
df36dce5
 import random
 class AIActor(Actor):
 	def act(self):
 		print 'wiggly %s' % self.adventurer.name
 		self.move(random.choice([-1,0,1]), random.choice([-1,0,1]))
 
b8f124a1
 @Overlay.add_event('picked_up',  'picked_up_by')
 @Overlay.add_event('bumped',  'bumped_by')
5f75058b
 class Object(Overlay):
ac4ad8e3
 	item = None
b8f124a1
 	handled_events = collections.OrderedDict()
ac4ad8e3
 	def picked_up_by(self, other):
b8f124a1
 		events.EventHandler().trigger_event('msg', 'picked up a %s' % self)
ac4ad8e3
 		self.map.remove(self)
b8f124a1
 	def bumped_by(self, other): pass
5f75058b
 
ac4ad8e3
 class Weapon(Object):
 	item = None
5f75058b
 
 class Potion(Object):
 	char = ord('!')
b8f124a1
 	def __str__(self): return 'potion'
ac4ad8e3
 
5f75058b
 class Scroll(Object):
 	char = ord('!')
ac4ad8e3
 
 class Equipment(Object):
 	pass