mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-16 18:31:32 +00:00
250 lines
7.9 KiB
Python
Executable File
250 lines
7.9 KiB
Python
Executable File
#!/usr/bin/env python
|
|
"""
|
|
wmlunits -- List unit names by race and level in either wikimedia or HTML tables
|
|
|
|
usage: wmlunits [-h] [-l lang]
|
|
|
|
-h = list as html
|
|
-l lang = specify language (as ISO country code)
|
|
"""
|
|
|
|
# Makes things faster on 32-bit systems
|
|
try: import psyco; psyco.full()
|
|
except ImportError: pass
|
|
|
|
import sys, os, re, glob
|
|
|
|
import wesnoth.wmldata as wmldata
|
|
import wesnoth.wmlparser as wmlparser
|
|
import wesnoth.wmltools as wmltools
|
|
|
|
def parse_core_macros_and_WML(text_to_parse):
|
|
# Create a new parser.
|
|
parser = wmlparser.Parser(datadir)
|
|
parser.do_preprocessor_logic = True
|
|
#parser.verbose = True
|
|
|
|
# Create a new WML object.
|
|
WML = wmldata.DataSub("WML")
|
|
|
|
# Parse some macros.
|
|
# TODO: Obviously, this is not ideal, e.g. we parse the macros multiple
|
|
# times. Could easily be fixed by keeping a reference to parser.macros
|
|
# and re-using it instead of re-parsing.
|
|
parser.parse_text("{core/macros/}\n")
|
|
parser.parse_top(None)
|
|
|
|
# Parse the actual WML.
|
|
parser.parse_text(text_to_parse)
|
|
parser.parse_top(WML)
|
|
|
|
return WML
|
|
|
|
class UnitList:
|
|
def __init__(self):
|
|
self.units_by_campaign = {}
|
|
|
|
def add(self, text_to_parse, campaign):
|
|
"Collect all units in the specified namespace, None = mainline."
|
|
|
|
WML = parse_core_macros_and_WML(text_to_parse)
|
|
#WML.debug()
|
|
|
|
# Collect unit data. First, we look for a [+units] section.
|
|
units = WML.get_first("+units")
|
|
# If no [+units] section, assume it is inside a [campaign].
|
|
if not units:
|
|
campaign = WML.get_first("campaign")
|
|
# Now we get the define - strange, but seems to be how Wesnoth
|
|
# works..
|
|
define = campaign.get_text_val("define")
|
|
|
|
# Re-parse, this time with the define defined.
|
|
WML = parse_core_macros_and_WML(
|
|
"#define %s\n#enddef\n%s" % (define, text_to_parse))
|
|
# This time, it oughta work.
|
|
units = WML.get_first("+units")
|
|
|
|
newunits = units.get_all("unit_type")
|
|
self.units_by_campaign[campaign] = []
|
|
for unit in newunits:
|
|
if unit.get_text_val("do_not_list", "no") == "no":
|
|
self.units_by_campaign[campaign].append(unit)
|
|
unit.campaign = campaign
|
|
|
|
def find_unit(self, unit_id):
|
|
"Find unit by id. Relies on IDs being unique."
|
|
for c in campaigns:
|
|
for u in self.units_by_campaign[c]:
|
|
if u.get_text_val("id") == unit_id:
|
|
return u
|
|
return None
|
|
|
|
def lookup(self, unit_id, attr):
|
|
"Get named attribute from unit, resolving [base_unit] references."
|
|
u = self.find_unit(unit_id)
|
|
firsttry = u.get_text_val(attr)
|
|
if firsttry:
|
|
return (firsttry, u.textdomain)
|
|
baseunit = u.get_first("base_unit")
|
|
if baseunit is None:
|
|
return None
|
|
print "*** Found baseunit %s while looking up (%s,%s)" \
|
|
% (baseunit, unit_id, attr)
|
|
# FIXME: lookup through baseunit doesn't work yet.
|
|
return None
|
|
|
|
def report_unit_names(campaign, unitlist, isocode):
|
|
tx = None
|
|
doubles = {}
|
|
races = {}
|
|
for u in unitlist:
|
|
# Fetch name of unit
|
|
name = u.get_text_val("name")
|
|
if name == None or name == "":
|
|
sys.stderr.write("Empty name detected! (id = %s)\n" %
|
|
u.get_text_val("id"))
|
|
continue
|
|
# Swap in the appropriate translation dictionary for this unit
|
|
if not u.textdomain:
|
|
sys.stderr.write("Unit %s has no textdomain (?)\n" % name)
|
|
continue
|
|
if tx == None or u.textdomain != tx.textdomain:
|
|
tx = wmltools.Translation(u.textdomain, isocode)
|
|
# Sanity check
|
|
if not name in tx:
|
|
# Hm...
|
|
sys.stderr.write("Unit %s has no translation (?)\n" % name)
|
|
if name in doubles:
|
|
sys.stderr.write("Unit %s found multiple times!\n" % name)
|
|
continue
|
|
doubles[name] = 1
|
|
|
|
r = u.get_text_val("race") or "unknown"
|
|
r = r[0].upper() + r[1:]
|
|
l = u.get_text_val("level")
|
|
levels = races.get(r, {})
|
|
ulist = levels.get(l, [])
|
|
ulist.append(u)
|
|
levels[l] = ulist
|
|
races[r] = levels
|
|
|
|
def poname(name):
|
|
return name[name.find("^") + 1:]
|
|
|
|
def place_units(race):
|
|
if use_html:
|
|
print "<font size=5>%s - %s</font>" % (race, campaign)
|
|
print "<table border=solid>"
|
|
else:
|
|
print '| colspan="6" | <font size=5>%s - %s</font>' % (race, campaign)
|
|
print '|-'
|
|
print '| level 0 || level 1 || level 2 || level 3 || level 4 || level 5'
|
|
levels = []
|
|
for i in range(6):
|
|
levels.append(races[race].get(str(i), []))
|
|
|
|
row = 0
|
|
while 1:
|
|
if use_html: print "<tr>"
|
|
else: print "|-"
|
|
ok = False
|
|
units = []
|
|
for i in range(6):
|
|
if row < len(levels[i]):
|
|
ok = True
|
|
if not ok: break
|
|
for i in range(6):
|
|
if use_html: print "<td>"
|
|
else: print "|",
|
|
if row < len(levels[i]):
|
|
u = levels[i][row]
|
|
name = u.get_text_val("name")
|
|
translated = tx.get(name, "?")
|
|
if use_html:
|
|
print "<b>%s</b>" % translated
|
|
print "<br>"
|
|
print poname(name)
|
|
else:
|
|
print "'''%s''' <br>" % translated,
|
|
print poname(name),
|
|
f = u.get_first("female")
|
|
if f:
|
|
name = f.get_text_val("name")
|
|
translated = tx.get(name, "?")
|
|
if use_html:
|
|
print "<br>"
|
|
print "<b>%s</b>" % translated
|
|
print "<br>"
|
|
print poname(name)
|
|
else:
|
|
print "<br>",
|
|
print "'''%s''' <br>" % translated,
|
|
print poname(name),
|
|
if use_html: print "</td>"
|
|
else: print
|
|
if use_html: print "</tr>"
|
|
else: print "|-"
|
|
row += 1
|
|
if use_html: print "</table>"
|
|
|
|
rlist = races.keys()
|
|
rlist.sort()
|
|
for race in rlist:
|
|
place_units(race)
|
|
|
|
if __name__ == '__main__':
|
|
import getopt
|
|
|
|
try:
|
|
(options, arguments) = getopt.getopt(sys.argv[1:], "hl:?", [
|
|
"html",
|
|
"lang=",
|
|
"usage",
|
|
])
|
|
except getopt.GetoptError:
|
|
help()
|
|
sys.exit(1)
|
|
isocode = "de"
|
|
use_html = False
|
|
for (switch, val) in options:
|
|
if switch in ('-h', '--html'):
|
|
html = True
|
|
elif switch in ('-l', '--lang'):
|
|
isocode = val
|
|
elif switch in ('-?', '--usage'):
|
|
print __doc__
|
|
sys.exit(1)
|
|
|
|
wmltools.pop_to_top("wmlunits")
|
|
datadir = os.getcwd() + "/data"
|
|
|
|
unitlist = UnitList()
|
|
|
|
# Parse all unit data
|
|
# This reads in units.cfg, giving us all the mainline units.
|
|
#unitlist.add("{units.cfg}", "mainline")
|
|
# Now we read each campaign in turn to get its units.
|
|
campaigns = glob.glob("data/campaigns/*")
|
|
for campaign in campaigns:
|
|
dirname = campaign[5:] # strip leading data/
|
|
if not dirname.startswith("campaigns/Under"): continue
|
|
description = dirname[10:].replace("_", " ")
|
|
unitlist.add("{%s}" % dirname, description)
|
|
|
|
# Report generation
|
|
if use_html:
|
|
print "<html><body>"
|
|
else:
|
|
print '{| border="solid"'
|
|
|
|
for (campaign, unitgroup) in unitlist.units_by_campaign.items():
|
|
report_unit_names(campaign, unitgroup, isocode)
|
|
|
|
if use_html:
|
|
print "</body></html>"
|
|
else:
|
|
print "|}"
|
|
|
|
|