# -*- coding: utf-8 -*- # $Id: 33e672ada0beb012199dc62acd15361886a22b31 $ import sys import random try: import cStringIO as _StringIO except ImportError: import StringIO as _StringIO try: set, frozenset except NameError: from sets import Set as set, ImmutableSet as frozenset def pformat(skills): order = ['NAME', 'TYPE', 'SP', 'LV'] mmap = { 'NAME': 'name', 'TYPE': 'skilltype', 'SP': 'point', 'LV': 'level', } horiz = [[getattr(s, mmap[n])() for n in order] for s in skills] virt = zip(*horiz) sepnum = (len(order) * 3) - 1 fmt = ['|'] for i, t in enumerate(virt): num = max(len(str(n)) for n in list(t) + [order[i]]) sepnum += num if i < 2: fmt.append(' %%-%ds |' % num) else: fmt.append(' %%%ds |' % num) fmt = ''.join(fmt + ['\n']) sep = ''.join(['+', '-' * sepnum, '+', '\n']) io = _StringIO.StringIO() io.write(sep) io.write(fmt % tuple(order)) io.write(sep) for d in horiz: io.write(fmt % tuple(d)) io.write(sep) io.flush() return io.getvalue() class SkillType: def __init__(self, attacker): self.attacker = attacker def range(self): return 0 def selectable(self, warriors): return [] def efficiency(self): return 0 class HealType(SkillType): def range(self): return 1 def selectable(self, warriors): return [self.attacker] def efficiency(self): base = self.attacker.concentration() * 2 + 10 gosa = base / 2 return 0 - random.randint(base - gosa, base + gosa) class ResurrectionType(SkillType): def range(self): return 1 def selectable(self, warriors): loosers = [w for w in warriors if w.is_dead()] try: return [random.choice(loosers)] except IndexError: return [] def efficiency(self): base = self.attacker.concentration() + 10 gosa = base / 2 return 0 - random.randint(base - gosa, base + gosa) class SingleAttackType(SkillType): def range(self): return 1 def selectable(self, warriors): living = [w for w in warriors if not w.is_dead()] living.remove(self.attacker) return living def efficiency(self): base = int(self.attacker.concentration() * 2.5) gosa = base / 2 return random.randint(base - gosa, base + gosa) class RangeAttackType(SkillType): def range(self): return self.attacker.concentration() // 25 + 1 def selectable(self, warriors): living = [w for w in warriors if not w.is_dead()] living.remove(self.attacker) return living def efficiency(self): base = int(self.attacker.concentration() * 2.3) gosa = base / 2 return random.randint(base - gosa, base + gosa) class MultiAttackType(SkillType): def range(self): return sys.maxint def selectable(self, warriors): living = [w for w in warriors if not w.is_dead()] living.remove(self.attacker) return living def efficiency(self): base = int(self.attacker.concentration() * 1.7) gosa = base / 2 return random.randint(base - gosa, base + gosa) class SuicideAttackType(SkillType): def range(self): return sys.maxint def selectable(self, warriors): living = [w for w in warriors if not w.is_dead()] living.remove(self.attacker) return living + [self.attacker] def efficiency(self): return self.attacker.hitpoint() class Skill: def __init__(self, name, point, skilltype, level=1): self._name = name self._point = point self._skilltype = skilltype self._level = level def name(self): return self._name def point(self): return self._point def skilltype(self): return str(self._skilltype).split('.')[-1] def level(self): return self._level def range(self, attacker): return self._skilltype(attacker).range() def selectable(self, attacker, warriors): return self._skilltype(attacker).selectable(warriors) def invoke(self, attacker, targets, warriors): type_ = self._skilltype(attacker) if not targets: return [] if not warriors: return [] if attacker.skillpoint() < self.point(): return [] if type_.range() * (self._level // 2 + 1) < len(targets): return [] if not set(targets).issubset(set(warriors)): return [] attacker.spend(self.point()) return [(t, self._invoke_one(type_, t, targets), False, False) for t in targets] def _invoke_one(self, type_, t, targets): return t.damage(int(type_.efficiency() * self.level() / len(targets)))