539d5ff4 |
from __future__ import division
|
b9c8e0f9 |
import collections
|
1d2d26d2 |
import os.path
import glob
import yaml
|
539d5ff4 |
|
76408e86 |
import libtcodpy as libtcod
import game
import objects
import utilities
import monsters
import random
|
1d2d26d2 |
from main import Game
|
76408e86 |
class Item(object):
|
70928ad3 |
stack_limit = 5
|
b9c8e0f9 |
potency = None
item_class = None
distance = None
probability = 1
|
1d2d26d2 |
def __init__(self, stackable=False):
|
b9c8e0f9 |
self.mods = collections.defaultdict(set)
|
1d2d26d2 |
|
76408e86 |
def __new__(*args):
res = object.__new__(*args)
return res
|
1d2d26d2 |
def bind_game(self, game):
self.game = game
def bind_user(self, user):
self.user = user
return self.owner
def free_user(self):
self.user = None
return self.owner
|
b9c8e0f9 |
def modify(self, mod):
undo = mod.modify(self)
self.mods[mod.name].add(mod)
self.owner.name = self.name
def unmodify(self, mod):
if hasattr(mod, 'upper'):
mods = self.mods[mod]
else:
mods = self.mods[mod.name]
if mods != set():
mod = mods.pop()
mod.revert(self)
self.owner.name = self.name
if mods == set():
self.mods.pop(mod.name)
print 'self.mods', self.mods
|
1d2d26d2 |
class ItemLoader(object):
def __init__(self, dir):
self.dir = dir
def load_items(self):
for fn in glob.glob(os.path.join(self.dir,'*.yml')):
print 'fn', fn
for doc in yaml.safe_load_all(file(fn)):
self.load_item(doc)
def load_item(self, doc):
|
b9c8e0f9 |
if doc is None: return
|
1d2d26d2 |
_color = doc.get('color', None)
if _color is None:
_color = libtcod.green
elif hasattr(_color, 'upper'):
_color = getattr(libtcod, _color)
else:
_color = libtcod.Color(*_color)
item_class = doc['item_class']
module, clas = item_class.rsplit('.',1)
module = __import__(module)
item_class = getattr(module, clas)
print 'item class:', item_class
print 'loading', doc
@Game.register_item_type(doc['spawn_chance'])
class LoadedItem(item_class):
name = doc.get('item_description')
char = doc.get('char', '!')
color = _color
|
70928ad3 |
stack_limit = doc.get('stack_limit', Item.stack_limit)
|
b9c8e0f9 |
potency = doc.get('potency')
distance = doc.get('distance')
|
1d2d26d2 |
|
76408e86 |
|
2dda4cb6 |
@Game.register_item_type(10)
|
76408e86 |
class HealingPotion(Item):
name = 'Healing potion'
char = '\x03'
color = libtcod.violet
|
2dda4cb6 |
potency = 15
|
b9c8e0f9 |
item_class = 'healing'
|
76408e86 |
def use(self):
fighter = self.user.fighter
result = True
if fighter.hp == fighter.max_hp:
|
b9c8e0f9 |
self.game.message('Full health, can\'t heal', libtcod.red)
|
76408e86 |
result = False
else:
|
1d2d26d2 |
self.game.message('Healing...')
|
b9c8e0f9 |
fighter.heal(self.potency)
|
76408e86 |
return result
|
2dda4cb6 |
@Game.register_item_type(7)
|
76408e86 |
class SuperHealingPotion(Item):
name = 'Super healing potion'
char = '\x03'
color = libtcod.yellow
|
b9c8e0f9 |
probability = .5
potency = 10
item_class = 'healing'
|
76408e86 |
def use(self):
fighter = self.user.fighter
|
b9c8e0f9 |
if random.random() < self.probability:
fighter.max_hp += self.potency
fighter.heal(self.potency)
|
76408e86 |
return True
@Game.register_item_type(1)
class Confusion(Item):
name = 'Confusion'
char = 'c'
color=libtcod.dark_chartreuse
|
b9c8e0f9 |
item_class = 'monster defense'
|
76408e86 |
def use(self):
monster = monsters.get_closest_monster(self.user)
result = False
if monster is not None:
|
1d2d26d2 |
self.game.message('%s becomes confused' % monster.name)
|
76408e86 |
monsters.ConfusedMonster(random.randrange(10,18)).attach(
monster
)
result = True
return result
@Game.register_item_type(4)
class Strengthen(Item):
name = 'Strengthen'
char = 's'
color = libtcod.chartreuse
|
b9c8e0f9 |
item_class = 'attack'
potency = 20
|
76408e86 |
def use(self):
if self.user.fighter:
|
1d2d26d2 |
self.game.message('%s feels a surge of strength' % self.user.name)
|
b9c8e0f9 |
self.user.fighter.stat_adjust(self.potency, self.adj)
|
76408e86 |
return True
def adj(self, owner):
return (
|
1d2d26d2 |
lambda _: self.game.message('The surge of strength has subsided'),
|
76408e86 |
owner.fighter.defense,
owner.fighter.power+3
)
@Game.register_item_type(4)
class Protect(Item):
name = 'Protect'
char = 'p'
color = libtcod.chartreuse
|
b9c8e0f9 |
item_class = 'defense'
potency = 15
|
76408e86 |
def use(self):
if self.user.fighter:
|
1d2d26d2 |
self.game.message('%s is surrounded by a protecting aura' % self.user.name)
|
b9c8e0f9 |
self.user.fighter.stat_adjust(self.potency, self.adj)
|
76408e86 |
return True
def adj(self, owner):
return (
|
1d2d26d2 |
lambda _: self.game.message('The protecting aura dissipates'),
|
76408e86 |
owner.fighter.defense+6,
owner.fighter.power
)
@Game.register_item_type(2)
class LightningBolt(Item):
name = 'Lightning Bolt'
char = 'z'
color = libtcod.darkest_red
|
b9c8e0f9 |
item_class = 'attack'
potency = 13
|
76408e86 |
def use(self):
monster = monsters.get_closest_monster(self.user)
result = False
if monster and self.user.can_see(monster.x, monster.y):
|
1d2d26d2 |
self.game.message('Monster %s has been struck by lightning' % monster.name)
|
b9c8e0f9 |
monster.fighter.take_damage(self.potency)
|
76408e86 |
result = True
else:
|
1d2d26d2 |
self.game.message('No target')
|
76408e86 |
return result
|
539d5ff4 |
@Game.register_item_type(5)
class Jump(Item):
name = 'Jump'
char = 'j'
color= libtcod.dark_green
|
b9c8e0f9 |
distance = 3
item_class = 'movement'
|
539d5ff4 |
def use(self):
|
1d2d26d2 |
self.game.select(self.jump)
|
539d5ff4 |
return True
def jump(self, x,y):
dist = self.user.distance(x,y)
|
b9c8e0f9 |
if dist <= self.distance:
|
539d5ff4 |
self.user.x, self.user.y = x,y
|
1d2d26d2 |
self.game.message('you are transported to a new place')
|
b9c8e0f9 |
elif random.random() < self.distance/dist:
|
539d5ff4 |
self.user.x, self.user.y = x,y
|
1d2d26d2 |
self.game.message('you strain all your power to move %d squares' % int(dist))
|
539d5ff4 |
else:
|
1d2d26d2 |
self.game.message('you didn\'t make it')
|
b9c8e0f9 |
self.user.fighter.take_damage( int(round(2 * dist/self.distance)) )
|
539d5ff4 |
@Game.register_item_type(3)
class Acquire(Item):
name = 'Acquire'
char = 'a'
color= libtcod.dark_green
effect_distance = 5
|
b9c8e0f9 |
item_class = 'pickup'
|
539d5ff4 |
def use(self):
|
1d2d26d2 |
self.game.message('what do you want?')
self.game.select(self.get)
|
539d5ff4 |
return True
def get(self, x,y):
if self.user.distance(x,y) < self.effect_distance:
self.user.pick_up(self.user.object_at(x,y))
|
76408e86 |
@Game.register_item_type(1)
class Smite(Item):
name = 'Smite'
char = '\x0f'
color = libtcod.red
|
b9c8e0f9 |
item_class = 'attack'
potency = 10
|
76408e86 |
def use(self):
|
1d2d26d2 |
self.game.select(self.smite)
|
76408e86 |
return True
def smite(self, x,y):
monster = monsters.monster_at(x,y)
if monster:
|
b9c8e0f9 |
monster.fighter.take_damage(self.potency)
|
76408e86 |
if monster.fighter:
|
1d2d26d2 |
self.game.message('%s is smitten, he only retains %s hp' % (monster.name, monster.fighter.hp))
|
539d5ff4 |
else:
|
1d2d26d2 |
self.game.message('%s thought it better to go elsewhere' % monster.name)
|
76408e86 |
|
539d5ff4 |
@Game.register_item_type(2)
|
76408e86 |
class Fireball(Item):
name = 'Fireball'
char = '*'
color = libtcod.darker_red
|
05dddf7e |
effect_radius = 5
|
b9c8e0f9 |
potency = (20,6)
item_class = 'splash attack'
|
76408e86 |
def use(self):
|
1d2d26d2 |
self.game.select(self.smite)
|
76408e86 |
return True
def smite(self, x,y):
|
539d5ff4 |
if random.random() < .1:
|
b9c8e0f9 |
self.game.message('the fireball is amazingly effective', libtcod.green)
|
539d5ff4 |
self.effect_radius *= 2
|
b9c8e0f9 |
direct_damage, splash_damage = self.potency
|
76408e86 |
strikes = []
for obj in self.owner.level.objects:
if obj.fighter and obj is not self.user:
if (obj.x, obj.y) == (x,y):
|
1d2d26d2 |
self.game.message('%s takes a direct hit from the fireball' % obj.name)
|
b9c8e0f9 |
obj.fighter.take_damage(direct_damage)
|
76408e86 |
elif obj.distance(x,y) < self.effect_radius:
|
b9c8e0f9 |
obj.fighter.take_damage(splash_damage)
|
76408e86 |
if obj.fighter:
strikes.append('%s %s' % (obj.name, obj.fighter.hp))
else:
strikes.append('%s dead' % obj.name)
|
1d2d26d2 |
self.game.message('The names of those who were to close for comfort: %s' % ', '.join(strikes))
|
76408e86 |
|