root/hodgestar/PythonCode/DmTools/kintani-skills.py

Revision 551, 2.8 kB (checked in by hodgestar, 3 years ago)

Add xp calculator for Kintani Valley game.

  • Property svn:mime-type set to text/python-source
  • Property svn:eol-style set to native
Line 
1#!/usr/bin/env python
2
3"""Script for calculating XP spent on skills for Adrianna's
4   Kintani Valley campaign. Skills buying uses a two times
5   triangular XP cost structure:
6   
7   Rank 1: 2 xp
8   Rank 2: + 4 xp
9   Rank 3: + 6 xp
10   Rank 4: + 8 xp
11   Rank 5: + 10 xp
12   Rank 6: + 12 xp
13   Rank 7: + 14 xp
14   
15   In addition, emphasis must be bought at least every odd rank.
16   Emphasis are also bought using a two times triangular XP cost:
17   
18   First emphasis: 2 xp
19   Second emphasis: +4 xp
20   Third emphasis: +6 xp
21   """
22
23import re
24
25def twice_triangular(n):
26    """Calculate twice triangular XP cost for rank n."""
27    return n*(n+1)
28
29def skill_cost(ranks, emphasises):
30    """Total XP cost for a given skill rank and number of emphasises."""
31    return twice_triangular(ranks) + twice_triangular(emphasises)
32
33def zim_skill_parser(fIn):
34    """Parse a set of skills and emphasis from a ZimWiki file.
35
36       Results are yielded as (skill name, rank, list of emphases) tuples.
37       In the list of emphases names, free emphases are suffixed with an *.
38       The characters school skill is also suffixed with an *.
39       """
40    heading_re = re.compile(r'\s*([=]+)(?P<sec>.*)\1\s*')
41    skill_re = re.compile(r'(?P<linestart>[*/\s+]*)'
42        r'(?P<name>[^*/.]+)[*/\s]+'
43        r'(?P<rank>\d+)[*/\s]+'
44        r'\((?P<emphs>.*)\)\s*')
45
46    def process_emph(emph):
47        """Convert free emph to emph* notation."""
48        emph = emph.strip()
49        if emph.startswith('//'):
50            emph = emph.strip('/') + '*'
51        return emph
52
53    in_skills = False
54
55    for line in fIn:
56        match = heading_re.match(line)
57        if match:
58            sec = match.group('sec').strip()
59            if sec.lower() in ['skills', 'skill']:
60                in_skills = True
61            else:
62                in_skills = False
63            continue
64
65        if not in_skills:
66            continue
67
68        match = skill_re.match(line)
69        if match:
70            d = match.groupdict()
71            school_skill = d['linestart'].endswith('//')
72            name = d['name'].strip() + (school_skill and '*' or '')
73            rank = int(d['rank'])
74            emphs = [process_emph(x) for x in d['emphs'].split(',')]
75            # remove skill rank description
76            emphs = emphs[1:]
77            yield name, rank, emphs
78
79def main(fIn):
80    total = 0
81
82    print "[Skill]", "[Rank]", "[Emphases]", "[XP Cost]"
83    print "============================================"
84
85    for skill, rank, emphs in zim_skill_parser(fIn):
86        non_free_emphs = [x for x in emphs if not x.endswith('*')]
87        cost = skill_cost(rank, len(non_free_emphs))
88        total += cost
89        print skill, rank, "(" + ", ".join(emphs) + ")", cost
90
91    print "\nTotal XP:", total
92
93if __name__ == "__main__":
94    import sys
95    fIn = file(sys.argv[1], "rb")
96    main(fIn)
Note: See TracBrowser for help on using the browser.