summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/boxes.svg384
-rw-r--r--tools/cards.sh8
-rw-r--r--tools/crop.sh123
-rw-r--r--tools/genboxes.py73
-rw-r--r--tools/gencolors.js85
-rw-r--r--tools/genhex.js63
-rw-r--r--tools/map.sh7
-rw-r--r--tools/map.svg3
-rw-r--r--tools/render.sh36
9 files changed, 782 insertions, 0 deletions
diff --git a/tools/boxes.svg b/tools/boxes.svg
new file mode 100644
index 0000000..7e5f781
--- /dev/null
+++ b/tools/boxes.svg
@@ -0,0 +1,384 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="2550"
+ height="1650"
+ version="1.1"
+ id="svg4"
+ sodipodi:docname="boxes.svg"
+ inkscape:version="1.0.2 (e86c870879, 2021-01-15)">
+ <metadata
+ id="metadata10">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs8" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview6"
+ showgrid="true"
+ inkscape:zoom="1.7859922"
+ inkscape:cx="2122.3644"
+ inkscape:cy="944.53822"
+ inkscape:current-layer="svg4"
+ inkscape:document-rotation="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid14" />
+ </sodipodi:namedview>
+ <image
+ sodipodi:absref="/home/tor/src/rally/public/time-of-crisis/map75.png"
+ xlink:href="../map75.png"
+ sodipodi:insensitive="true"
+ id="image2"
+ height="1650"
+ width="2550"
+ style="display:inline;image-rendering:pixelated" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect873"
+ width="258"
+ height="52"
+ x="1502"
+ y="720"
+ ry="0.610479"
+ inkscape:label="Thracia Support" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect881"
+ width="258"
+ height="52"
+ x="2034"
+ y="1280"
+ ry="0.610479"
+ inkscape:label="Syria Support" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect871"
+ width="258"
+ height="53"
+ x="1154"
+ y="626"
+ ry="0.610479"
+ inkscape:label="Pannonia Support" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect875"
+ width="258"
+ height="53"
+ x="1384"
+ y="936"
+ ry="0.610479"
+ inkscape:label="Macedonia Support" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect887"
+ width="258"
+ height="53"
+ x="154"
+ y="980"
+ ry="0.610479"
+ inkscape:label="Hispania Support" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect869"
+ width="258"
+ height="53"
+ x="460"
+ y="507"
+ ry="0.610479"
+ inkscape:label="Gallia Support" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect879"
+ width="258"
+ height="53"
+ x="1954"
+ y="931"
+ ry="0.610479"
+ inkscape:label="Galatia Support" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect867"
+ width="258"
+ height="52"
+ x="231"
+ y="260"
+ ry="0.610479"
+ inkscape:label="Britannia Support" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect877"
+ width="258"
+ height="52"
+ x="1679"
+ y="1000"
+ ry="0.610479"
+ inkscape:label="Asia Support" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect885"
+ width="258"
+ height="53"
+ x="647"
+ y="1290"
+ ry="0.610479"
+ inkscape:label="Africa Support" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect883"
+ width="258"
+ height="53"
+ x="1700"
+ y="1468"
+ ry="0.610479"
+ inkscape:label="Aegyptus Support" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect891"
+ width="258"
+ height="52"
+ x="1054"
+ y="887"
+ ry="0.610479"
+ inkscape:label="Italia Support 2" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect889"
+ width="258"
+ height="52"
+ x="1028"
+ y="835"
+ ry="0.610479"
+ inkscape:label="Italia Support 1" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect845"
+ width="70"
+ height="70"
+ x="1594"
+ y="631"
+ ry="0.610479"
+ inkscape:label="Thracia Capital" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect853"
+ width="70"
+ height="70"
+ x="2174"
+ y="1193"
+ ry="0.610479"
+ inkscape:label="Syria Capital" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect843"
+ width="70"
+ height="70"
+ x="1214"
+ y="536"
+ ry="0.610479"
+ inkscape:label="Pannonia Capital" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect859"
+ width="70"
+ height="70"
+ x="1477"
+ y="850"
+ ry="0.610479"
+ inkscape:label="Macedonia Capital" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect861"
+ width="70"
+ height="70"
+ x="1038"
+ y="743"
+ ry="0.610479"
+ inkscape:label="Italia Capital" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect847"
+ width="70"
+ height="70"
+ x="249"
+ y="892"
+ ry="0.610479"
+ inkscape:label="Hispania Capital" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect841"
+ width="70"
+ height="70"
+ x="554"
+ y="418"
+ ry="0.610479"
+ inkscape:label="Gallia Capital" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect855"
+ width="70"
+ height="70"
+ x="2048"
+ y="842"
+ ry="0.610479"
+ inkscape:label="Galatia Capital" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect839"
+ width="70"
+ height="70"
+ x="325"
+ y="177"
+ ry="0.610479"
+ inkscape:label="Britannia Capital" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect857"
+ width="70"
+ height="70"
+ x="1790"
+ y="908"
+ ry="0.610479"
+ inkscape:label="Asia Capital" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect849"
+ width="70"
+ height="70"
+ x="741"
+ y="1204"
+ ry="0.610479"
+ inkscape:label="Africa Capital" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect851"
+ width="70"
+ height="70"
+ x="1793"
+ y="1380"
+ ry="0.610479"
+ inkscape:label="Aegyptus Capital" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect902"
+ width="130"
+ height="60"
+ x="1970"
+ y="620"
+ ry="0.610479"
+ inkscape:label="Pontus Euxinus XY" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect900"
+ width="100"
+ height="60"
+ x="1770"
+ y="1170"
+ ry="0.610479"
+ inkscape:label="Mare Orientale XY" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect898"
+ width="90"
+ height="60"
+ x="720"
+ y="890"
+ ry="0.610479"
+ inkscape:label="Mare Occidentale XY" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect893"
+ width="80"
+ height="50"
+ x="130"
+ y="495"
+ ry="0.610479"
+ inkscape:label="Oceanus Atlanticus XY" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect904"
+ width="165"
+ height="25"
+ x="705"
+ y="1495"
+ ry="0.610479"
+ inkscape:label="Nomads XY" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect906"
+ width="190"
+ height="25"
+ x="2295"
+ y="980"
+ ry="0.610479"
+ inkscape:label="Sassanids XY" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect912"
+ width="130"
+ height="15"
+ x="1840"
+ y="235"
+ ry="0.610479"
+ inkscape:label="Goths XY" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect910"
+ width="195"
+ height="15"
+ x="1370"
+ y="200"
+ ry="0.610479"
+ inkscape:label="Alamanni XY" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect908"
+ width="135"
+ height="15"
+ x="900"
+ y="200"
+ ry="0.610479"
+ inkscape:label="Franks XY" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect865"
+ width="2469"
+ height="80"
+ x="40"
+ y="40"
+ ry="0.610479"
+ inkscape:label="SCORE TRACK" />
+ <rect
+ style="fill:#e60000;fill-opacity:0.325203;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.581301"
+ id="rect863"
+ width="262"
+ height="326"
+ x="2195"
+ y="189"
+ ry="0.610479"
+ inkscape:label="CRISIS TABLE" />
+</svg>
diff --git a/tools/cards.sh b/tools/cards.sh
new file mode 100644
index 0000000..5601ad3
--- /dev/null
+++ b/tools/cards.sh
@@ -0,0 +1,8 @@
+mkdir -p cards.1x cards.2x
+for F in HIRES/render/event*.png HIRES/render/influence*
+do
+ B=$(basename $F)
+ echo SCALING $B
+ convert -colorspace RGB -gravity Center -crop 3000x4200+0+0 -resize 8.333333% -colorspace sRGB $F cards.1x/$B
+ convert -colorspace RGB -gravity Center -crop 3000x4200+0+0 -resize 16.666667% -colorspace sRGB $F cards.2x/$B
+done
diff --git a/tools/crop.sh b/tools/crop.sh
new file mode 100644
index 0000000..11ee84b
--- /dev/null
+++ b/tools/crop.sh
@@ -0,0 +1,123 @@
+#!/bin/bash
+
+mkdir -p /tmp/1x /tmp/2x /tmp/xx images
+
+HEX=800x924
+
+# - original size -
+# SQUARE=896x896
+# RECT=1488x752
+# CIRCLE=816x816
+# HEX=800x924
+
+# - trimmed 1px border -
+SQUARE=880x880
+RECT=1472x736
+CIRCLE=800x800
+
+# FILTER="-filter triangle
+# UNSHARP="-unsharp 0x1+0.5"
+
+function resize() {
+ B=$(basename $2)
+ echo $B
+ convert $2 -gravity Center -crop $1+0+0 +repage -colorspace RGB $FILTER -resize 12.5% $UNSHARP -colorspace sRGB images/$B
+}
+
+function crop_only() {
+ B=$(basename $2)
+ echo $B
+ convert tools/original/$B -gravity Center -crop $1+0+0 +repage /tmp/xx/$B
+}
+
+function resize_only() {
+ B=$(basename $1)
+ echo $B
+ convert $1 -colorspace RGB $FILTER -resize 12.5% $UNSHARP -colorspace sRGB images/$B
+}
+
+for F in tools/original/legion_full_*.png tools/original/legion_reduced_*.png
+do
+ crop_only $SQUARE $F
+done
+montage -mode concatenate -tile 9x /tmp/xx/legion_full_*.png tools/original/legion_full.png
+montage -mode concatenate -tile 9x /tmp/xx/legion_reduced_*.png tools/original/legion_reduced.png
+
+resize_only tools/original/legion_full.png
+resize_only tools/original/legion_reduced.png
+
+resize $RECT tools/original/amphitheater.png
+resize $RECT tools/original/basilica.png
+resize $RECT tools/original/limes.png
+
+resize $RECT tools/original/amphitheater_back.png
+resize $RECT tools/original/basilica_back.png
+resize $RECT tools/original/limes_back.png
+
+resize $SQUARE tools/original/alamanni_active.png
+resize $SQUARE tools/original/alamanni_inactive.png
+resize $SQUARE tools/original/ardashir.png
+resize $SQUARE tools/original/cniva.png
+resize $SQUARE tools/original/cniva_back.png
+resize $SQUARE tools/original/first_player.png
+resize $SQUARE tools/original/franks_active.png
+resize $SQUARE tools/original/franks_inactive.png
+resize $SQUARE tools/original/goths_active.png
+resize $SQUARE tools/original/goths_inactive.png
+resize $SQUARE tools/original/militia.png
+resize $SQUARE tools/original/no_place_governor.png
+resize $SQUARE tools/original/nomads_active.png
+resize $SQUARE tools/original/nomads_inactive.png
+resize $SQUARE tools/original/rival_back.png
+resize $SQUARE tools/original/rival_postumus.png
+resize $SQUARE tools/original/rival_priest_king.png
+resize $SQUARE tools/original/rival_zenobia.png
+resize $SQUARE tools/original/sassanids_active.png
+resize $SQUARE tools/original/sassanids_inactive.png
+resize $SQUARE tools/original/shapur.png
+resize $SQUARE tools/original/shapur_back.png
+resize $SQUARE tools/original/red_emperor_turns.png
+resize $SQUARE tools/original/red_general.png
+resize $SQUARE tools/original/blue_emperor_turns.png
+resize $SQUARE tools/original/blue_general.png
+resize $SQUARE tools/original/yellow_emperor_turns.png
+resize $SQUARE tools/original/yellow_general.png
+resize $SQUARE tools/original/green_emperor_turns.png
+resize $SQUARE tools/original/green_general.png
+
+resize $HEX tools/original/mob.png
+resize $HEX tools/original/mob_x2.png
+resize $HEX tools/original/castra.png
+resize $HEX tools/original/quaestor.png
+resize $HEX tools/original/red_breakaway.png
+resize $HEX tools/original/blue_breakaway.png
+resize $HEX tools/original/yellow_breakaway.png
+resize $HEX tools/original/green_breakaway.png
+resize $HEX tools/original/red_seat_of_power.png
+resize $HEX tools/original/blue_seat_of_power.png
+resize $HEX tools/original/yellow_seat_of_power.png
+resize $HEX tools/original/green_seat_of_power.png
+
+resize $CIRCLE tools/original/neutral_governor.png
+resize $CIRCLE tools/original/red_governor.png
+resize $CIRCLE tools/original/red_legacy.png
+resize $CIRCLE tools/original/red_legacy_40.png
+resize $CIRCLE tools/original/blue_governor.png
+resize $CIRCLE tools/original/blue_legacy.png
+resize $CIRCLE tools/original/blue_legacy_40.png
+resize $CIRCLE tools/original/yellow_governor.png
+resize $CIRCLE tools/original/yellow_legacy.png
+resize $CIRCLE tools/original/yellow_legacy_40.png
+resize $CIRCLE tools/original/green_governor.png
+resize $CIRCLE tools/original/green_legacy.png
+resize $CIRCLE tools/original/green_legacy_40.png
+
+resize $CIRCLE tools/original/blue_governor_emperor.png
+resize $CIRCLE tools/original/green_governor_emperor.png
+resize $CIRCLE tools/original/red_governor_emperor.png
+resize $CIRCLE tools/original/yellow_governor_emperor.png
+
+resize $SQUARE tools/original/blue_general_emperor.png
+resize $SQUARE tools/original/green_general_emperor.png
+resize $SQUARE tools/original/red_general_emperor.png
+resize $SQUARE tools/original/yellow_general_emperor.png
diff --git a/tools/genboxes.py b/tools/genboxes.py
new file mode 100644
index 0000000..650f625
--- /dev/null
+++ b/tools/genboxes.py
@@ -0,0 +1,73 @@
+mode = None
+
+list = []
+
+x = y = w = h = 0
+name = None
+
+def flush():
+ global x, y, w, h, name
+ if mode == 'rect':
+ list.append((x,y,w,h,'box',name))
+ if mode == 'circle':
+ x = cx - rx
+ y = cy - ry
+ w = rx * 2
+ h = ry * 2
+ list.append((x,y,w,h,'circle',name))
+ x = y = w = h = 0
+ name = None
+
+for line in open("tools/boxes.svg").readlines():
+ line = line.strip()
+ if line == "<rect":
+ flush()
+ mode = 'rect'
+ x = y = w = h = 0
+ elif line == "<ellipse":
+ flush()
+ mode = 'circle'
+ cx = cy = rx = ry = 0
+ if line.startswith('x="'): x = round(float(line.split('"')[1]))
+ if line.startswith('y="'): y = round(float(line.split('"')[1]))
+ if line.startswith('width="'): w = round(float(line.split('"')[1]))
+ if line.startswith('height="'): h = round(float(line.split('"')[1]))
+ if line.startswith('cx="'): cx = round(float(line.split('"')[1]))
+ if line.startswith('cy="'): cy = round(float(line.split('"')[1]))
+ if line.startswith('rx="'): rx = round(float(line.split('"')[1]))
+ if line.startswith('ry="'): ry = round(float(line.split('"')[1]))
+ if line.startswith('inkscape:label="'): name = line.split('"')[1]
+flush()
+
+def print_list():
+ print("const boxes = {")
+ for (x,y,w,h,c,name) in list:
+ print(f'"{name}": [{x},{y},{w},{h}],')
+ print("}")
+
+def print_list2():
+ print("const centers = {")
+ for (x,y,w,h,c,name) in list:
+ xc = round((x+w/2.0))
+ yc = round((y+h/2.0))
+ print(f'"{name}": [{xc},{yc}],')
+ print("}")
+
+def print_html():
+ # print('<html><style>')
+ # print('.box{position:absolute;background-color:#f008;border:2px solid blue;}')
+ # print('.circle{position:absolute;background-color:#0f08;border-radius:50%;border:2px solid blue;}')
+ # print('img{position:absolute;display:block}')
+ # print('</style>')
+ # print('<div style="position:relative;width:1275px;heigth:1650px;">')
+ # print('<img src="map75.png">')
+ for (x,y,w,h,c,name) in list:
+ x = round(x)
+ y = round(y)
+ w = round(w)
+ h = round(h)
+ print(f'<div class="{c}" style="top:{y}px;left:{x}px;width:{w}px;height:{h}px">{name}</div>')
+ # print('</div>')
+
+#print_html()
+print_list()
diff --git a/tools/gencolors.js b/tools/gencolors.js
new file mode 100644
index 0000000..fbcb36c
--- /dev/null
+++ b/tools/gencolors.js
@@ -0,0 +1,85 @@
+const { parse_hex, format_hex, lrgb_from_any, rgb_from_any, oklab_from_any } = require("../../common/colors.js")
+
+const white = "#ffffff"
+const black = "#000000"
+
+function lerp(a, b, n) {
+ return a + (b - a) * n
+}
+
+function blend(a, b, n) {
+ a = lrgb_from_any(parse_hex(a))
+ b = lrgb_from_any(parse_hex(b))
+ return format_hex({
+ mode: "lrgb",
+ r: lerp(a.r, b.r, n),
+ g: lerp(a.g, b.g, n),
+ b: lerp(a.b, b.b, n)
+ })
+}
+
+function multiply_luminance(hex, m) {
+ let oklab = oklab_from_any(parse_hex(hex))
+ oklab.l = Math.max(0, Math.min(1, oklab.l * m))
+ return format_hex(oklab)
+}
+
+function add_luminance(hex, m) {
+ let oklab = oklab_from_any(parse_hex(hex))
+ oklab.l = Math.max(0, Math.min(1, oklab.l + m))
+ return format_hex(oklab)
+}
+
+function make_3d_colors(base) {
+ return [
+ base,
+ multiply_luminance(base, 0.9),
+ multiply_luminance(base, 0.8),
+ multiply_luminance(base, 0.7),
+ multiply_luminance(base, 0.4)
+ ]
+}
+
+function make_2d_colors(base) {
+ return [
+ base,
+ multiply_luminance(base, 1.2),
+ multiply_luminance(base, 0.8),
+ multiply_luminance(base, 0.4)
+ ]
+}
+
+function make_2d_colors_add(base) {
+ return [
+ base,
+ add_luminance(base, 0.2),
+ add_luminance(base, -0.2),
+ add_luminance(base, -0.5),
+ ]
+}
+
+function print(x) {
+ console.log(x)
+}
+
+function gencss(color, sel) {
+ let [ bg, hi, lo, sh ] = make_2d_colors(color)
+ print(`${sel} { border-color: ${hi} ${lo} ${lo} ${hi}; box-shadow: 0 0 0 1px ${sh}, 1px 2px 4px #0008; }`)
+}
+
+gencss("#efebea", ".amphitheater, .basilica, .limes")
+gencss("#ed1b2f", ".red")
+gencss("#a0caec", ".blue")
+gencss("#ffe175", ".yellow")
+gencss("#80b563", ".green")
+gencss("#c3bc8e", ".alamanni")
+gencss("#9cb4be", ".franks")
+gencss("#3a9cd6", ".goths")
+gencss("#f99d1c", ".nomads")
+gencss("#8e5ca6", ".sassanids")
+gencss("#b8b996", ".rival")
+gencss("#e3dedc", ".neutral")
+gencss("#f0f0f0", ".militia")
+gencss("#f0f0f0", ".legion")
+gencss("#6e6e6e", ".no_place_governor")
+
diff --git a/tools/genhex.js b/tools/genhex.js
new file mode 100644
index 0000000..c0e8812
--- /dev/null
+++ b/tools/genhex.js
@@ -0,0 +1,63 @@
+// hexagonal counters with embedded image and outline
+
+const fs = require('fs')
+
+function print_hex(output, input, hi, lo, bd) {
+ let image = fs.readFileSync(input).toString('base64')
+ let svg = []
+
+ let img_w = 50
+ let img_h = 58 // 57.735
+
+ let svg_w = img_w + 4
+ let svg_h = img_h + 6
+
+ svg.push(`<svg xmlns="http://www.w3.org/2000/svg" width="${svg_w}" height="${svg_h}">`)
+
+ let iw = img_w / 2
+ let ih = iw / Math.sqrt(3)
+ let iy = (svg_h - ih * 4) / 2
+
+ let ow = img_w / 2 + 2
+ let oh = ow / Math.sqrt(3)
+ let oy = (svg_h - oh * 4) / 2
+
+ svg.push('<clipPath id="ic">')
+ svg.push(`<path d="M 1 ${iy} m 0 ${3*ih} v -${2*ih} l ${iw} -${ih} l ${iw} ${ih} v ${2*ih} l -${iw} ${ih} z"/>`)
+ svg.push('</clipPath>')
+
+ svg.push('<clipPath id="oc">')
+ svg.push(`<path d="M 0 ${oy} m 0 ${oh*3} v -${oh*2} l ${ow} -${oh} l ${ow} ${oh} z"/>`)
+ svg.push('</clipPath>')
+
+ svg.push(`<path fill="${bd}" d="M 0 ${oy} m 0 ${3*oh} v -${2*oh} l ${ow} -${oh} l ${ow} ${oh} v ${2*oh} l -${ow} ${oh} z"/>`)
+
+ svg.push(`<image x="2" y="3" width="${img_w}" height="${img_h}" clip-path="url(#ic)" href="data:image/png;base64,${image}"/>`)
+
+ svg.push(`<path fill="none" stroke="${lo}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"`)
+ svg.push(` d="M 2 ${iy} m ${2*iw} ${ih} v ${ih*2} l -${iw} ${ih} l -${iw} -${ih}"/>`)
+ svg.push(`<path fill="none" stroke="${hi}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" clip-path="url(#oc)"`)
+ svg.push(` d="M 2 ${iy} m 0 ${ih*3} v -${ih*2} l ${iw} -${ih} l ${iw} ${ih}"/>`)
+
+ svg.push('</svg>')
+
+ fs.writeFileSync(output, svg.join("\n") + "\n")
+}
+
+print_hex("images/castra.svg", "images/castra.png", "#ffffff", "#b2b2b2", "#434343")
+print_hex("images/quaestor.svg", "images/quaestor.png", "#ffffff", "#b2b2b2", "#434343")
+
+print_hex("images/mob.svg", "images/mob.png", "#eaebc7", "#888968", "#323214")
+print_hex("images/mob_x2.svg", "images/mob_x2.png", "#eaebc7", "#888968", "#323214")
+
+print_hex("images/blue_breakaway.svg", "images/blue_breakaway.png", "#d5ffff", "#6e96b6", "#113854")
+print_hex("images/blue_seat_of_power.svg", "images/blue_seat_of_power.png", "#d5ffff", "#6e96b6", "#113854")
+
+print_hex("images/green_breakaway.svg", "images/green_breakaway.png", "#ace48f", "#568837", "#033600")
+print_hex("images/green_seat_of_power.svg", "images/green_seat_of_power.png", "#ace48f", "#568837", "#033600")
+
+print_hex("images/red_breakaway.svg", "images/red_breakaway.png", "#ff5455", "#c00000", "#680000")
+print_hex("images/red_seat_of_power.svg", "images/red_seat_of_power.png", "#ff5455", "#c00000", "#680000")
+
+print_hex("images/yellow_breakaway.svg", "images/yellow_breakaway.png", "#fffe92", "#c3a634", "#553a00")
+print_hex("images/yellow_seat_of_power.svg", "images/yellow_seat_of_power.png", "#fffe92", "#c3a634", "#553a00")
diff --git a/tools/map.sh b/tools/map.sh
new file mode 100644
index 0000000..37b4eef
--- /dev/null
+++ b/tools/map.sh
@@ -0,0 +1,7 @@
+pngtopnm map600.png | pnmcut -left 300 -top 300 -width 20400 -height 13200 > map600.ppm
+cat map600.ppm | pnmdepth 65535 | pnmgamma -srgbramp -ungamma | pnmscale -reduce 4 | pnmgamma -srgbramp | pnmdepth 255 > map150.ppm
+cat map600.ppm | pnmdepth 65535 | pnmgamma -srgbramp -ungamma | pnmscale -reduce 8 | pnmgamma -srgbramp | pnmdepth 255 > map75.ppm
+cat overlay_2p_600.ppm | pnmdepth 65535 | pnmgamma -srgbramp -ungamma | pnmscale -reduce 4 | pnmgamma -srgbramp | pnmdepth 255 > overlay_2p_150.ppm
+cat overlay_2p_600.ppm | pnmdepth 65535 | pnmgamma -srgbramp -ungamma | pnmscale -reduce 8 | pnmgamma -srgbramp | pnmdepth 255 > overlay_2p_75.ppm
+cat overlay_3p_600.ppm | pnmdepth 65535 | pnmgamma -srgbramp -ungamma | pnmscale -reduce 4 | pnmgamma -srgbramp | pnmdepth 255 > overlay_3p_150.ppm
+cat overlay_3p_600.ppm | pnmdepth 65535 | pnmgamma -srgbramp -ungamma | pnmscale -reduce 8 | pnmgamma -srgbramp | pnmdepth 255 > overlay_3p_75.ppm
diff --git a/tools/map.svg b/tools/map.svg
new file mode 100644
index 0000000..c278b18
--- /dev/null
+++ b/tools/map.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="2550" height="1650">
+<image xlink:href="../map75.png" style="display:inline;image-rendering:pixelated" width="2550" height="1650"/>
+</svg>
diff --git a/tools/render.sh b/tools/render.sh
new file mode 100644
index 0000000..f18ba5d
--- /dev/null
+++ b/tools/render.sh
@@ -0,0 +1,36 @@
+mkdir -p HIRES/render
+gs -r1200 -sDEVICE=png16m -o HIRES/render/counters_1B.png HIRES/CLEAN/TOC-Counters-1B-nf.p1.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/counters_1F.png HIRES/CLEAN/TOC-Counters-1F-nf.p1.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/counters_2B.png HIRES/CLEAN/TOC-Counters-2B-nf.p1.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/counters_2F.png HIRES/CLEAN/TOC-Counters-2F-nf.p1.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/counters_3B.png HIRES/CLEAN/TOC-Counters-3B-nf.p1.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/counters_3F.png HIRES/CLEAN/TOC-Counters-3F-nf.p1.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/event_back.png HIRES/CLEAN/TOC_EVENT_BACK.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/event_01.png HIRES/CLEAN/TOC_EVENTcard-01-nf.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/event_02.png HIRES/CLEAN/TOC_EVENTcard-02-nf.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/event_03.png HIRES/CLEAN/TOC_EVENTcard-03-nf.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/event_04.png HIRES/CLEAN/TOC_EVENTcard-04-nf.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/event_05.png HIRES/CLEAN/TOC_EVENTcard-05-nf.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/event_06.png HIRES/CLEAN/TOC_EVENTcard-06-nf.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/event_07.png HIRES/CLEAN/TOC_EVENTcard-07-nf.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/event_08.png HIRES/CLEAN/TOC_EVENTcard-08-nf.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/event_09.png HIRES/CLEAN/TOC_EVENTcard-09-nf.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/event_10.png HIRES/CLEAN/TOC_EVENTcard-10-nf.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/event_11.png HIRES/CLEAN/TOC_EVENTcard-11-nf.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/event_12.png HIRES/CLEAN/TOC_EVENTcard-12-nf.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/event_13.png HIRES/CLEAN/TOC_EVENTcard-13-nf.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/event_14.png HIRES/CLEAN/TOC_EVENTcard-14-nf.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/event_15.png HIRES/CLEAN/TOC_EVENTcard-15-nf.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/influence_back.png HIRES/CLEAN/TOC_INFLUENCE_BACK.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/influence_m1.png HIRES/CLEAN/TOC_INFcards-M1nf-x12.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/influence_m2.png HIRES/CLEAN/TOC_INFcards-M2nf-x9.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/influence_m3.png HIRES/CLEAN/TOC_INFcards-M3nf-x8.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/influence_m4.png HIRES/CLEAN/TOC_INFcards-M4nf-x6.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/influence_p1.png HIRES/CLEAN/TOC_INFcards-P1nf-x12.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/influence_p2.png HIRES/CLEAN/TOC_INFcards-P2nf-x9.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/influence_p3.png HIRES/CLEAN/TOC_INFcards-P3nf-x8.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/influence_p4.png HIRES/CLEAN/TOC_INFcards-P4nf-x6.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/influence_s1.png HIRES/CLEAN/TOC_INFcards-S1nf-x12.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/influence_s2.png HIRES/CLEAN/TOC_INFcards-S2nf-x9.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/influence_s3.png HIRES/CLEAN/TOC_INFcards-S3nf-x8.pdf
+gs -r1200 -sDEVICE=png16m -o HIRES/render/influence_s4.png HIRES/CLEAN/TOC_INFcards-S4nf-x6.pdf