git.fiddlerwoaroof.com
Raw Blame History
import utilities
import math
import libtcodpy as libtcod
import maps

class Object(object):
	# FIXME: map argument unused, remove
	def __init__(self, map, con, x,y, char, name, color, blocks=False, level=None, fighter=None, ai=None, item=None):
		self.name = name
		self.x, self.y = x,y
		self.char = char
		self.color = color
		self.blocks = blocks
		self.con = con
		self.always_visible = False
#		self.map = map

		if level is not None:
			level.add_object(self)

		self.level = level


		if fighter is not None:
			fighter.owner = self
		self.fighter = fighter

		if ai is not None:
			ai.owner = self
			ai.init(self.level)
		self.ai = ai

		if item is not None:
			item.owner = self
		self.item = item

	@property
	def pos(self):
		return self.x, self.y

	def enter_level(self, level):
		self.level = level
		return self

	def move(self, dx, dy):
		if not self.level.is_blocked(self.x+dx,self.y+dy):
			self.x += dx
			self.y += dy
		else:
			dx,dy = 0,0
		return dx,dy

	def send_to_back(self):
		self.level.send_to_back(self)
		return self

	def distance_to(self, other):
		dx = other.x - self.x
		dy = other.y - self.y
		return math.sqrt(dx**2 + dy**2)

	def distance(self, x,y):
		dx = x - self.x
		dy = y - self.y
		return math.sqrt(dx**2 + dy**2)

	def get_step_towards(self, target_x, target_y):
		dx = target_x - self.x
		dy = target_y - self.y
		distance = math.sqrt(dx**2+dy**2)
		if distance == 0: distance = 1

		dx = int(round(dx/distance))
		dy = int(round(dy/distance))
		return dx,dy

	def move_towards(self, x,y):
		dx,dy = self.get_step_towards(x,y)
		return self.move(dx, dy)

	def draw(self, player=None):
		if player is None or self.always_visible or player.can_see(self.x, self.y):
			libtcod.console_set_default_foreground(self.con, self.color)
			libtcod.console_put_char(self.con, self.x,self.y, self.char, libtcod.BKGND_NONE)
		return self

	def clear(self):
		libtcod.console_put_char(self.con, self.x,self.y, ' ', libtcod.BKGND_NONE)


	def get_visible_objects(cls, fov_map, filter=lambda _: True):
		return [
			object for object in cls.objects
				if filter(object) and libtcod.map_is_in_fov(fov_map, object.x, object.y)
		]

	def get_closest_object(cls, char, *nots, **kwargs):
		filter = kwargs.pop('filter', lambda _: True)
		dist = 100
		cur = None
		for object in cls.level.iter_objects():
			if object is not char and object not in nots and filter(object):
				ndist = char.distance_to(object)
				if ndist < dist:
					dist = ndist
					cur = object
		return cur

	def object_at(self, x,y, filter=lambda _:True):
		for object in self.level.iter_objects():
			if (x,y) == (object.x, object.y) and filter(object):
				return object

	def choose_object(cls):
		names = [
			x.name for x in cls.level.iter_objects() if x is not game.Game.player and x.fighter
		]

		idx = game.menu('Which Monster?', names, max(len(x) for x in names)+10)
		return objects[idx]


import debug


class Fighter(object):
	def __init__(self, hp, defense, power, death_function = None):
		self.death_function = death_function
		self.max_hp = hp
		self.hp = hp
		self.defense = defense
		self.power = power
		self.timers = []

	def heal(self, amount):
		self.hp += amount
		if self.hp > self.max_hp:
			self.hp = self.max_hp

	def stat_adjust(self, time, adjustment_func):
		odefense, opower = self.defense, self.power
		cb, self.defense, self.power = adjustment_func(self.owner)
		self.timers.append(
			(time, self.defense-odefense, self.power-opower, cb)
		)

	def tick(self):
		timers = []
		for timer, ddef, dpow, cb in self.timers:
			timer -= 1
			if timer == 0:
				self.defense -= ddef
				self.power -= dpow
				cb(self.owner)
			else:
				timers.append( (timer,ddef,dpow,cb) )
		self.timers = timers

	def take_damage(self, damage):
		if damage > 0:
			self.hp -= damage

		if self.hp <= 0:
			function = self.death_function
			if function is not None:
				try:
					function(self.owner)
				except TypeError:
					function(self.owner.ai)

	def attack(self, target):
		damage = self.power - target.fighter.defense
		if damage > 0:
			game.message(
				'%s attacks %s for %s hitpoints' % (
					self.owner.name.capitalize(), target.name, str(damage)
				)
			)
			target.fighter.take_damage(damage)
		else:
			game.message(
				'%s attacks but it has no effect' % self.owner.name.capitalize()
			)

from player import Player
import game