#!/usr/bin/env python # -*- coding: utf-8 -*- # $Id: d51d6cbc0b293385b0dccb6e8ed3bd1e15b285dc $ import os import sys import random import pycodebattler class DrawGame(Exception): pass class BattleProto: HANDLER_COMMAND = 0 def __init__(self, warriors, max_turn=sys.maxint - 1): self._warriors = warriors self._max_turn = max_turn self._handlers = {} self.register_handler(self.HANDLER_COMMAND, self._handle_command_random) def winner(self): living = [w for w in self._warriors if not w.is_dead()] if not living: raise DrawGame() if len(living) == 1: return living[0] return None def loosers(self): return [w for w in self._warriors if w.is_dead()] def battle(self): for i in xrange(1, self._max_turn + 1): if self.winner(): break yield self.turn() else: raise DrawGame() def turn(self): for attacker in self._sorted_by_agility(): if attacker in self.loosers(): continue targets = [w for w in self._warriors if w not in self.loosers() + [attacker]] yield self._call_handler(self.HANDLER_COMMAND, attacker, targets) if self.winner(): break def register_handler(self, id_, handler, *ext_args): self._handlers[id_] = (handler, ext_args) def _call_handler(self, id_, *args): handler, ext_args = self._handlers[id_] return handler(self, *(args + ext_args)) def _sorted_by_agility(self): def cmp_agility(w1, w2): agi1 = w1.agility() agi2 = w2.agility() agi1 += random.randint(0 - agi1 / 8, agi1 / 8) agi2 += random.randint(0 - agi2 / 8, agi2 / 8) return agi2 - agi1 return sorted(self._warriors, cmp=cmp_agility) @staticmethod def _handle_command_random(self, attacker, targets): target = random.choice(targets) try: skname = random.choice(attacker.skill_list()) except IndexError: skname = None if attacker.can_invoke(skname) and random.randint(1, 10) > 8: sk = attacker.skill(skname) tt = sk.selectable(attacker, self._warriors) if sk.skilltype() == 'SuicideAttackType': damages = attacker.invoke(skname, tt, self._warriors) return attacker, skname, damages if tt: r = min([len(tt), sk.range(attacker)]) t = random.sample(tt, random.randint(1, r)) damages = attacker.invoke(skname, t, self._warriors) return attacker, skname, damages dmg, miss, crit = attacker.attack_to(target) return attacker, None, [(target, dmg, miss, crit)] def _main_entry(): from optparse import OptionParser parser = OptionParser(usage='%prog [options] file1 file2 ...') parser.add_option('-C', action='store_true', help='no color output') parser.add_option('-W', action='store_true', help='no wait per each turn') options, args = parser.parse_args() if len(args) <= 1: parser.print_help() return pycodebattler.util.set_color_enable(not options.C) skills = [pycodebattler.skill.Skill(*sk) for sk in [ ['Chakra', 3, pycodebattler.skill.HealType, 1], ['Resurrection', 2, pycodebattler.skill.ResurrectionType, 1], ['Psychokinesis', 13, pycodebattler.skill.SingleAttackType, 2], ['Flame Radiation', 8, pycodebattler.skill.RangeAttackType, 1], ['Meltdown', 7, pycodebattler.skill.MultiAttackType, 1], ['Big Bang', 23, pycodebattler.skill.SuicideAttackType, 1], ]] players = [ pycodebattler.warrior.Warrior( pycodebattler.util.path2name(f), open(f), random.sample(skills, random.randint(1, len(skills))) ) for f in args ] proto = BattleProto(players) def print_warriors(warriors, all=False): print('Warriors:') print(pycodebattler.warrior.pformat(players)) if not all: return for w in warriors: print("%s's skill:" % w) print(pycodebattler.skill.pformat( [w.skill(n) for n in w.skill_list()])) def print_match_result(attacker, skname, damages): if skname: print("-> %s invokes %s!!!" % (attacker, pycodebattler.util.cyan(skname))) else: print("-> %s's attack!" % attacker) if not damages: print(' but no effect...\n') return for victim, damage, miss, critical in damages: if critical: print(' %s!!!' % pycodebattler.util.red('CRITICAL')) if miss: print(' ...but %s!! %s got no damage!' % (pycodebattler.util.green('MISS'), victim)) continue if damage < 0: print(' %s is %s cured!' % (victim, pycodebattler.util.green(0 - damage))) else: print(' %s got %s damage!' % (victim, pycodebattler.util.yellow(damage))) if victim.is_dead(): print(pycodebattler.util.red(' %s is DEAD...' % victim)) print('') try: print_warriors(players, True) if not options.W: raw_input('> Hit enter key... ') print('') num_turn = 1 for turn in proto.battle(): print(pycodebattler.util.green( '============= turn %d =============' % num_turn)) for attacker, skname, damages in turn: print_match_result(attacker, skname, damages) print_warriors(players) num_turn += 1 if not options.W: raw_input('> Hit enter key... ') print('') print('') print(pycodebattler.util.green( '>>> %s is WINNER!! <<<' % proto.winner())) except (KeyboardInterrupt, EOFError, DrawGame): print('\n') print(pycodebattler.util.green('>>> Draw Game! <<<')) print('') print_warriors(players) if __name__ == '__main__': _main_entry()