battleman.py: Converted command parser to use the cmd module
This commit is contained in:
parent
796a26c3b3
commit
007b033bdd
427
battleman.py
427
battleman.py
|
@ -14,6 +14,7 @@ sys.path.append('lib/')
|
||||||
|
|
||||||
import cPickle as pickle
|
import cPickle as pickle
|
||||||
import argparse
|
import argparse
|
||||||
|
import cmd
|
||||||
import os.path
|
import os.path
|
||||||
import battle
|
import battle
|
||||||
from battle import CombatGroup
|
from battle import CombatGroup
|
||||||
|
@ -62,242 +63,294 @@ def main():
|
||||||
|
|
||||||
print btl
|
print btl
|
||||||
|
|
||||||
while True:
|
cmd_parser = CommandParser(btl, battle_pickle, BP_FILE)
|
||||||
do_prompt(btl, battle_pickle, bp_io_failed, BP_FILE)
|
cmd_parser.cmdloop()
|
||||||
|
|
||||||
|
|
||||||
def do_prompt(btl, battle_pickle, bp_io_failed, BP_FILE):
|
|
||||||
print ''
|
|
||||||
(comm, rdata) = easyinput.input_str('', default='n', show_default=False, prompt_str='>').partition(' ')[::2]
|
|
||||||
data = rdata.split(' ')
|
|
||||||
|
|
||||||
if data == ['']:
|
class CommandParser(cmd.Cmd):
|
||||||
data = []
|
"""Parse the commands from the command-line."""
|
||||||
|
|
||||||
if comm == '?':
|
def __init__(self, btl, battle_pickle, BP_FILE):
|
||||||
do_help() # fixme - add ability to get command-specific help
|
cmd.Cmd.__init__(self)
|
||||||
elif comm == 'a':
|
|
||||||
do_add_combatants(btl, data)
|
|
||||||
elif comm == 'p':
|
|
||||||
do_print_combatant_info(btl, data)
|
|
||||||
elif comm == 'l':
|
|
||||||
print btl.format_combatants()
|
|
||||||
elif comm == 'b':
|
|
||||||
btl.begin()
|
|
||||||
elif comm == 'd':
|
|
||||||
do_damage(btl, data)
|
|
||||||
elif comm == 'h':
|
|
||||||
do_heal(btl, data)
|
|
||||||
elif comm == 't':
|
|
||||||
do_add_temp_hp(btl, data)
|
|
||||||
elif comm == 'T':
|
|
||||||
do_remove_temp_hp(btl, data)
|
|
||||||
elif comm == 's':
|
|
||||||
do_surge(btl, data)
|
|
||||||
elif comm == 'so':
|
|
||||||
do_surge(btl, data, heal=False)
|
|
||||||
elif comm == 'sw':
|
|
||||||
do_second_wind(btl, data)
|
|
||||||
elif comm == 'c':
|
|
||||||
do_add_condition(btl, data)
|
|
||||||
elif comm == 'C':
|
|
||||||
do_remove_condition(btl, data)
|
|
||||||
elif comm == 'n':
|
|
||||||
btl.next_combatant()
|
|
||||||
elif comm == 'r':
|
|
||||||
do_use_recharge_power(btl, data)
|
|
||||||
elif comm == 'w':
|
|
||||||
do_wait(btl, data)
|
|
||||||
elif comm == 'W':
|
|
||||||
do_unwait(btl, data)
|
|
||||||
elif comm == 'x':
|
|
||||||
do_stub()
|
|
||||||
elif comm == 'q':
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
# Re-pickle and write if changed after every query. It's cheap
|
self.btl = btl
|
||||||
# and we only have to run at user-speed anyway
|
self.battle_pickle = battle_pickle
|
||||||
old_bp = battle_pickle
|
self.BP_FILE = BP_FILE
|
||||||
battle_pickle = pickle.dumps(btl)
|
self.prompt = '\n> '
|
||||||
|
|
||||||
if old_bp != battle_pickle:
|
|
||||||
try:
|
|
||||||
with open(BP_FILE, 'w') as f:
|
|
||||||
f.write(battle_pickle)
|
|
||||||
except:
|
|
||||||
if not bp_io_failed:
|
|
||||||
print("Warning: can't write the battle pickle. Resuming later will fail.")
|
|
||||||
bp_io_failed = True
|
|
||||||
|
|
||||||
|
|
||||||
def do_help():
|
def postloop(self):
|
||||||
print("""Possible commands:
|
# Re-pickle and write if changed after every query. It's cheap
|
||||||
? - print this help menu (yay, you already figured that one out)
|
# and we only have to run at user-speed anyway
|
||||||
a - add more combatants (works during battle)
|
old_bp = self.battle_pickle
|
||||||
b - begin the battle
|
self.battle_pickle = pickle.dumps(btl)
|
||||||
l - list combatants
|
|
||||||
p - print info for combatant/group with initiative
|
if old_bp != self.battle_pickle:
|
||||||
d - deal damage to someone
|
try:
|
||||||
h - heal someone
|
with open(self.BP_FILE, 'w') as f:
|
||||||
t - add temporary hit points
|
f.write(self.battle_pickle)
|
||||||
T - remove temporary hit points [stub]
|
except Exception:
|
||||||
s - use a healing surge
|
if not self.bp_io_failed:
|
||||||
so - use a healing surge, but don't regain hit points
|
print("Warning: can't write the battle pickle. Resuming later will fail.")
|
||||||
sw - use a second wind
|
self.bp_io_failed = True
|
||||||
c/C - apply / remove a condition
|
|
||||||
r - use a rechargable power
|
|
||||||
n - next (end the current combat group's turn)
|
|
||||||
w/W - wait / unwait (remove a combatant from the initiative order and into a separate pool, then put them back) [stub]
|
|
||||||
x - force save the progress to the current battle cache (for use with --resume) [stub]
|
|
||||||
q - quit""")
|
|
||||||
|
|
||||||
|
|
||||||
# Core data parsing functions
|
# a
|
||||||
|
def do_add(self, line):
|
||||||
|
"""add [N]
|
||||||
|
Add the specified number of groups"""
|
||||||
|
|
||||||
def do_add_combatants(btl, data):
|
data = line.split(' ')
|
||||||
if len(data) >= 1:
|
|
||||||
ngroups = int(data[0])
|
|
||||||
else:
|
|
||||||
ngroups = easyinput.input_int('number of groups')
|
|
||||||
|
|
||||||
for i in range(1, ngroups+1):
|
if len(data) >= 1:
|
||||||
print "Adding group {}".format(i)
|
num_groups = int(data[0])
|
||||||
btl.add_group(CombatGroup.from_input())
|
|
||||||
|
|
||||||
|
|
||||||
def do_print_combatant_info(btl, data):
|
|
||||||
if len(data) >= 1:
|
|
||||||
c = btl.get_combatant(int(data[0]))
|
|
||||||
if not c:
|
|
||||||
print('Error: Invalid combatant index.')
|
|
||||||
else:
|
else:
|
||||||
print c.format_full_info()
|
num_groups = easyinput.input_int('number of groups')
|
||||||
else:
|
|
||||||
print btl.format_current_group()
|
for i in range(1, num_groups+1):
|
||||||
|
print "Adding group {}".format(i)
|
||||||
|
self.btl.add_group(CombatGroup.from_input())
|
||||||
|
|
||||||
|
|
||||||
def do_damage(btl, data):
|
# b
|
||||||
c = do_combatant_select(btl, data)
|
def do_begin(self, line):
|
||||||
if not c:
|
"""begin
|
||||||
return
|
Begins the battle. Rolls initiative for NPCs and prompts for PCs"""
|
||||||
|
|
||||||
if len(data) >= 2:
|
self.btl.begin()
|
||||||
amount = int(data[1])
|
|
||||||
else:
|
|
||||||
amount = easyinput.input_int('damage')
|
|
||||||
|
|
||||||
c.damage(amount)
|
|
||||||
|
|
||||||
|
|
||||||
def do_heal(btl, data):
|
# p
|
||||||
c = do_combatant_select(btl, data)
|
def do_print(self, line):
|
||||||
if not c:
|
"""print [index]
|
||||||
return
|
Print detailed info for combatant with index, or combatant or group with initiative"""
|
||||||
|
|
||||||
if len(data) >= 2:
|
data = line.split(' ')
|
||||||
amount = int(data[1])
|
|
||||||
else:
|
|
||||||
amount = easyinput.input_int('amount')
|
|
||||||
|
|
||||||
c.heal(amount)
|
if len(data) >= 1:
|
||||||
|
c = self.btl.get_combatant(int(data[0]))
|
||||||
|
if not c:
|
||||||
|
print 'Error: Invalid combatant index.'
|
||||||
|
else:
|
||||||
|
print c.format_full_info()
|
||||||
|
else:
|
||||||
|
print self.btl.format_current_group()
|
||||||
|
|
||||||
|
|
||||||
def do_add_temp_hp(btl, data):
|
# l
|
||||||
c = do_combatant_select(btl, data)
|
def do_list(self, line):
|
||||||
if not c:
|
"""list
|
||||||
return
|
Lists a summary of all of the combat groups and their members"""
|
||||||
|
|
||||||
if len(data) >= 2:
|
print self.btl.format_combatants()
|
||||||
amount = int(data[1])
|
|
||||||
else:
|
|
||||||
amount = easyinput.input_int('amount')
|
|
||||||
|
|
||||||
c.add_temp_hp(amount)
|
|
||||||
|
|
||||||
|
|
||||||
def do_remove_temp_hp(btl, data):
|
# d
|
||||||
do_stub()
|
def do_damage(self, line):
|
||||||
|
"""damage [index] [amount]
|
||||||
|
Deals damage to the specified combatant"""
|
||||||
|
|
||||||
|
data = line.split(' ')
|
||||||
|
|
||||||
|
c = battle.do_combatant_select(self.btl, data)
|
||||||
|
if not c:
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(data) >= 2:
|
||||||
|
amount = int(data[1])
|
||||||
|
else:
|
||||||
|
amount = easyinput.input_int('damage')
|
||||||
|
|
||||||
|
c.damage(amount)
|
||||||
|
|
||||||
|
|
||||||
def do_surge(btl, data, heal=True):
|
# h
|
||||||
c = do_combatant_select(btl, data)
|
def do_heal(self, line):
|
||||||
if not c:
|
"""heal [index] [amount]
|
||||||
return
|
Heal hit points for the specified combatant"""
|
||||||
c.use_surge(heal)
|
|
||||||
|
data = line.split(' ')
|
||||||
|
|
||||||
|
c = battle.do_combatant_select(self.btl, data)
|
||||||
|
if not c:
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(data) >= 2:
|
||||||
|
amount = int(data[1])
|
||||||
|
else:
|
||||||
|
amount = easyinput.input_int('amount')
|
||||||
|
|
||||||
|
c.heal(amount)
|
||||||
|
|
||||||
|
|
||||||
def do_second_wind(btl, data):
|
# t
|
||||||
c = do_combatant_select(btl, data)
|
def do_temp(self, line):
|
||||||
if not c:
|
"""temp [index] [amount]
|
||||||
return
|
Add temporary hit points to the specified combatant"""
|
||||||
c.use_second_wind()
|
|
||||||
|
data = line.split(' ')
|
||||||
|
|
||||||
|
c = battle.do_combatant_select(self.btl, data)
|
||||||
|
if not c:
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(data) >= 2:
|
||||||
|
amount = int(data[1])
|
||||||
|
else:
|
||||||
|
amount = easyinput.input_int('amount')
|
||||||
|
|
||||||
|
c.add_temp_hp(amount)
|
||||||
|
|
||||||
|
|
||||||
def do_add_condition(btl, data):
|
# T
|
||||||
duration = None
|
def do_rmtemp(self, line):
|
||||||
end_type = 'e'
|
"""rmtemp [index] [amount]
|
||||||
|
Remove temporary hit points from the specified combatant"""
|
||||||
|
|
||||||
c = do_combatant_select(btl, data)
|
do_stub()
|
||||||
if not c:
|
|
||||||
return
|
|
||||||
|
|
||||||
name = easyinput.do_data_input_str(data, 1, 'condition name')
|
|
||||||
ctype = easyinput.do_data_input_str(data, 2, 'condition type', default='s', show_default=True)
|
|
||||||
|
|
||||||
if ctype == 't':
|
|
||||||
duration = easyinput.do_data_input_int(data, 3, 'duration')
|
|
||||||
end_type = easyinput.do_data_input_str(data, 4, '(s)tart|(e)nd', default='e', show_default=True)
|
|
||||||
|
|
||||||
c.add_condition(name, ctype, duration, end_type)
|
|
||||||
|
|
||||||
|
|
||||||
def do_remove_condition(btl, data):
|
# s, so
|
||||||
c = do_combatant_select(btl, data)
|
def do_surge(self, line):
|
||||||
if not c:
|
"""surge [index] [heal]
|
||||||
return
|
Combatant with index uses a healing surge. If heal is 0, don't heal the combatant"""
|
||||||
|
|
||||||
if len(data) >= 2:
|
data = line.split(' ')
|
||||||
index = int(data[1])
|
|
||||||
else:
|
|
||||||
cond = c.choose_condition()
|
|
||||||
index = None
|
|
||||||
if cond:
|
|
||||||
index = cond['index']
|
|
||||||
|
|
||||||
if index != None:
|
c = battle.do_combatant_select(self.btl, data)
|
||||||
c.remove_condition(index)
|
if not c:
|
||||||
|
return
|
||||||
|
|
||||||
|
heal = True
|
||||||
|
if len(data) >= 2 and data[1] == '0':
|
||||||
|
heal = False
|
||||||
|
c.use_surge(heal)
|
||||||
|
|
||||||
|
|
||||||
def do_use_recharge_power(btl, data):
|
# sw
|
||||||
c = do_combatant_select(btl, data)
|
def do_wind(self, line):
|
||||||
if not c:
|
"""wind [index]
|
||||||
return
|
Use Second Wind for combatant"""
|
||||||
|
|
||||||
if len(data) >= 2:
|
data = line.split(' ')
|
||||||
index = int(data[1])
|
|
||||||
else:
|
|
||||||
r = c.choose_recharge_power()
|
|
||||||
index = None
|
|
||||||
if r:
|
|
||||||
index = r['index']
|
|
||||||
|
|
||||||
if index != None:
|
c = battle.do_combatant_select(self.btl, data)
|
||||||
c.use_recharge_power(index)
|
if not c:
|
||||||
|
return
|
||||||
|
c.use_second_wind()
|
||||||
|
|
||||||
|
|
||||||
def do_wait(btl, data):
|
# c
|
||||||
do_stub()
|
def do_cond(self, line):
|
||||||
|
"""cond [index] [name] [type] [duration] [start|end]
|
||||||
|
Add a temporary condition to a combatant, optionally specifying the condition name, type (s or t), duration and what phase of the combatant's turn it expires on"""
|
||||||
|
|
||||||
|
data = line.split(' ')
|
||||||
|
|
||||||
|
duration = None
|
||||||
|
end_type = 'e'
|
||||||
|
|
||||||
|
c = battle.do_combatant_select(self.btl, data)
|
||||||
|
if not c:
|
||||||
|
return
|
||||||
|
|
||||||
|
name = easyinput.do_data_input_str(data, 1, 'condition name')
|
||||||
|
ctype = easyinput.do_data_input_str(data, 2, 'condition type', default='s', show_default=True)
|
||||||
|
|
||||||
|
if ctype == 't':
|
||||||
|
duration = easyinput.do_data_input_int(data, 3, 'duration')
|
||||||
|
end_type = easyinput.do_data_input_str(data, 4, '(s)tart|(e)nd', default='e', show_default=True)
|
||||||
|
|
||||||
|
c.add_condition(name, ctype, duration, end_type)
|
||||||
|
|
||||||
|
|
||||||
def do_unwait(btl, data):
|
# C
|
||||||
do_stub()
|
def do_rmcond(self, line):
|
||||||
|
"""rmcond [index] [condition_index]
|
||||||
|
Remove a condition from a combatant early."""
|
||||||
|
|
||||||
|
data = line.split(' ')
|
||||||
|
|
||||||
|
c = battle.do_combatant_select(self.btl, data)
|
||||||
|
if not c:
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(data) >= 2:
|
||||||
|
index = int(data[1])
|
||||||
|
else:
|
||||||
|
cond = c.choose_condition()
|
||||||
|
index = None
|
||||||
|
if cond:
|
||||||
|
index = cond['index']
|
||||||
|
|
||||||
|
if index != None:
|
||||||
|
c.remove_condition(index)
|
||||||
|
|
||||||
|
|
||||||
|
# r
|
||||||
|
def do_recharge(self, line):
|
||||||
|
"""recharge [index] [recharge_index]
|
||||||
|
Use a rechargable power"""
|
||||||
|
|
||||||
|
data = line.split(' ')
|
||||||
|
|
||||||
|
c = battle.do_combatant_select(self.btl, data)
|
||||||
|
if not c:
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(data) >= 2:
|
||||||
|
index = int(data[1])
|
||||||
|
else:
|
||||||
|
r = c.choose_recharge_power()
|
||||||
|
index = None
|
||||||
|
if r:
|
||||||
|
index = r['index']
|
||||||
|
|
||||||
|
if index != None:
|
||||||
|
c.use_recharge_power(index)
|
||||||
|
|
||||||
|
|
||||||
|
# w
|
||||||
|
def do_wait(self, line):
|
||||||
|
"""wait
|
||||||
|
This function is still a stub"""
|
||||||
|
|
||||||
|
do_stub()
|
||||||
|
|
||||||
|
|
||||||
|
# W
|
||||||
|
def do_unwait(self, line):
|
||||||
|
"""unwait
|
||||||
|
This function is still a stub"""
|
||||||
|
|
||||||
|
do_stub()
|
||||||
|
|
||||||
|
|
||||||
|
# x
|
||||||
|
def do_sync(self, line):
|
||||||
|
"""sync
|
||||||
|
This function is still a stub"""
|
||||||
|
|
||||||
|
do_stub()
|
||||||
|
|
||||||
|
|
||||||
|
def do_EOF(self, line):
|
||||||
|
self.do_quit(line)
|
||||||
|
|
||||||
|
|
||||||
|
# q
|
||||||
|
def do_quit(self, line):
|
||||||
|
"""quit
|
||||||
|
Exits the program. If a battle is in progress, it is temporarily saved and can be resumed by running the program with --resume next time."""
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
def do_stub():
|
def do_stub():
|
||||||
print "Sorry, this is a stub function"
|
print "Sorry, this is a stub function"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
parser = argparse.ArgumentParser(description='Command-line interface to manage battle data for D&D 4e', formatter_class=argparse.RawTextHelpFormatter)
|
parser = argparse.ArgumentParser(description='Command-line interface to manage battle data for D&D 4e', formatter_class=argparse.RawTextHelpFormatter)
|
||||||
parser.add_argument('--resume', '-r', action='store_true', help='Resume the battle from the last run of the program')
|
parser.add_argument('--resume', '-r', action='store_true', help='Resume the battle from the last run of the program')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user