diff --git a/SanityCheck.jar b/SanityCheck.jar
new file mode 100644
index 0000000000000000000000000000000000000000..bebdf1da3e6277f966e8fff78ea96d884fe27b0b
Binary files /dev/null and b/SanityCheck.jar differ
diff --git a/devTools/javaSanityCheck/excluded b/devTools/javaSanityCheck/excluded
new file mode 100644
index 0000000000000000000000000000000000000000..28ff834dcbab00ca86653880aa605a6a64163fd2
--- /dev/null
+++ b/devTools/javaSanityCheck/excluded
@@ -0,0 +1,16 @@
+#Add files or folders to be excluded.
+#empty lines will match on ALL paths, so if you need one do it like this:
+#
+src/art/
+src/gui/svgFilters.tw
+#
+#excluded to reduce false positives until better solution:
+src/pregmod/basenationalitiesControls.tw
+src/pregmod/editGenetics.tw
+src/pregmod/widgets/bodySwapReaction.tw
+src/uncategorized/costsBudget.tw
+src/uncategorized/initRules.tw
+src/uncategorized/slaveAssignmentsReport.tw
+src/uncategorized/storyCaption.tw
+src/cheats/
+src/pregmod/customizeSlaveTrade.tw
diff --git a/devTools/javaSanityCheck/htmlTags b/devTools/javaSanityCheck/htmlTags
new file mode 100644
index 0000000000000000000000000000000000000000..751b084ff5822f4162e3f79ea622b91f60c5472b
--- /dev/null
+++ b/devTools/javaSanityCheck/htmlTags
@@ -0,0 +1,45 @@
+#Allowed HTML tags
+#Effectively everything that is allowed in a these statements like this:
+#<tag> or <tag ???>
+#when ;1 is specified it expects a matching closing tag like this: </tag>
+#Do not add Twine Tags here.
+#Characters outside of ASCII scope are not supported.
+#
+#included to reduce false positives until better solution
+!--
+http://www.gnu.org/licenses/
+#html tags
+a;1
+b;1
+blockquote;1
+body;1
+br;0
+button;1
+caption;1
+center;1
+dd;1
+div;1
+dl;1
+dt;1
+h1;1
+h2;1
+h3;1
+h4;1
+hr;0
+html;1
+i;1
+img;1
+input;0
+li;1
+option;1
+script;1
+select;1
+span;1
+strong;1
+style;1
+table;1
+td;1
+th;1
+tr;1
+tt;1
+ul;1
diff --git a/devTools/javaSanityCheck/src/DisallowedTagException.java b/devTools/javaSanityCheck/src/DisallowedTagException.java
new file mode 100644
index 0000000000000000000000000000000000000000..f4cc75e736b162192a5f18bbc55a10edb21eaa38
--- /dev/null
+++ b/devTools/javaSanityCheck/src/DisallowedTagException.java
@@ -0,0 +1,8 @@
+package org.arkerthan.sanityCheck;
+
+public class DisallowedTagException extends RuntimeException {
+
+    public DisallowedTagException(String tag) {
+        super(tag);
+    }
+}
diff --git a/devTools/javaSanityCheck/src/Main.java b/devTools/javaSanityCheck/src/Main.java
new file mode 100644
index 0000000000000000000000000000000000000000..eea3a4ff611203b0025cd29ce1fe431447f80e1c
--- /dev/null
+++ b/devTools/javaSanityCheck/src/Main.java
@@ -0,0 +1,319 @@
+package org.arkerthan.sanityCheck;
+
+import org.arkerthan.sanityCheck.element.AngleBracketElement;
+import org.arkerthan.sanityCheck.element.CommentElement;
+import org.arkerthan.sanityCheck.element.Element;
+import org.arkerthan.sanityCheck.element.KnownElement;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+
+public class Main {
+
+    public static TagSearchTree<Tag> htmlTags, twineTags;
+    private static String currentFile;
+    private static int currentLine, currentPosition;
+    private static Stack<Element> stack;
+    private static List<SyntaxError> errors = new LinkedList<>();
+    private static String[] excluded;
+
+    public static void main(String[] args) {
+        //setup
+        setupExclude();
+        setupHtmlTags();
+        setupTwineTags();
+        Path workingDir = Paths.get("").toAbsolutePath();
+
+        //actual sanityCheck
+        runSanityCheckInDirectory(workingDir, new File("src/"));
+
+        //handle errors
+        for (SyntaxError e :
+                errors) {
+            System.out.println(e.getError());
+        }
+    }
+
+
+    /**
+     * Goes through the whole directory including subdirectories and runs
+     * sanityCheck() on all .tw files
+     *
+     * @param dir to be checked
+     */
+    private static void runSanityCheckInDirectory(Path workingDir, File dir) {
+        //subdirectories are checked recursively
+
+        try {
+            for (File file : dir.listFiles()) {
+                if (file.isFile()) { //run sanityCheck if file is a .tw file
+                    String path = file.getAbsolutePath();
+                    if (path.endsWith(".tw")) {
+                        sanityCheck(workingDir.relativize(file.toPath()));
+                    }
+                } else if (file.isDirectory()) {
+                    runSanityCheckInDirectory(workingDir, file.getAbsoluteFile());
+                }
+            }
+        } catch (NullPointerException e) {
+            e.printStackTrace();
+            System.err.println("Couldn't find directory " + currentFile);
+            System.exit(-1);
+        }
+    }
+
+    /**
+     * Runs the sanity check for one file. Does not run if file is excluded.
+     *
+     * @param path file to be checked
+     */
+    private static void sanityCheck(Path path) {
+        File file = path.toFile();
+
+        // replace this with a known encoding if possible
+        Charset encoding = Charset.defaultCharset();
+
+        if (!excluded(file.getPath())) {
+            try {
+                currentFile = file.getPath();
+                currentLine = 1;
+                stack = new Stack<>();
+
+                //actually opening and reading the file
+                try (InputStream in = new FileInputStream(file);
+                     Reader reader = new InputStreamReader(in, encoding);
+                     // buffer for efficiency
+                     Reader buffer = new BufferedReader(reader)) {
+                    handleCharacters(buffer);
+                }
+            } catch (IOException e) {
+                System.err.println("Couldn't read " + file);
+            }
+        }
+    }
+
+    /**
+     * sets up the alphabetical search tree for fast access of HTML tags later
+     */
+    private static void setupHtmlTags() {
+        //load HTML tags into a list
+        List<Tag> TagsList = new LinkedList<>();
+        try {
+
+            Files.lines(new File("devTools/javaSanityCheck/htmlTags").toPath()).map(String::trim)
+                    .filter(s -> !s.startsWith("#"))
+                    .forEach(s -> TagsList.add(parseTag(s)));
+        } catch (IOException e) {
+            System.err.println("Couldn't read devTools/javaSanityCheck/htmlTags");
+        }
+
+        //turn List into alphabetical search tree
+        try {
+            htmlTags = new TagSearchTree(TagsList);
+        } catch (ArrayIndexOutOfBoundsException e) {
+            System.err.println("Illegal Character in devTools/javaSanityCheck/htmlTags");
+            System.exit(-1);
+        }
+    }
+
+    /**
+     * sets up the alphabetical search tree for fast access of twine tags later
+     */
+    private static void setupTwineTags() {
+        //load twine tags into a list
+        List<Tag> TagsList = new LinkedList<>();
+        try {
+
+            Files.lines(new File("devTools/javaSanityCheck/twineTags").toPath()).map(String::trim)
+                    .filter(s -> !s.startsWith("#"))
+                    .forEach(s -> TagsList.add(parseTag(s)));
+        } catch (IOException e) {
+            System.err.println("Couldn't read devTools/javaSanityCheck/twineTags");
+        }
+
+        //turn List into alphabetical search tree
+        try {
+            twineTags = new TagSearchTree(TagsList);
+        } catch (ArrayIndexOutOfBoundsException e) {
+            System.err.println("Illegal Character in devTools/javaSanityCheck/twineTags");
+            System.exit(-1);
+        }
+    }
+
+    /**
+     * Turns a string into a Tag
+     * ";1" at the end of the String indicates that the tag needs to be closed later
+     *
+     * @param s tag as String
+     * @return tag as Tag
+     */
+    private static Tag parseTag(String s) {
+        String[] st = s.split(";");
+        if (st.length > 1 && st[1].equals("1")) {
+            return new Tag(st[0], false);
+        }
+        return new Tag(st[0], true);
+    }
+
+    /**
+     * sets up the excluded array.
+     */
+    private static void setupExclude() {
+        //load excluded files
+        List<String> excludedList = new ArrayList<>();
+        try {
+            Files.lines(new File("devTools/javaSanityCheck/excluded").toPath()).map(String::trim)
+                    .filter(s -> !s.startsWith("#"))
+                    .forEach(excludedList::add);
+        } catch (IOException e) {
+            System.err.println("Couldn't read devTools/javaSanityCheck/excluded");
+        }
+
+        //turn excluded files into an array and change them to windows style if needed
+        if (isWindows()) {
+            excluded = new String[excludedList.size()];
+            int i = 0;
+            for (String s :
+                    excludedList) {
+                excluded[i++] = s.replaceAll("/", "\\\\");
+            }
+        } else {
+            excluded = excludedList.toArray(new String[0]);
+        }
+    }
+
+    /**
+     * @return whether OS is Windows or not
+     */
+    private static boolean isWindows() {
+        return (System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("windows"));
+    }
+
+    /**
+     * checks if a file or directory is excluded from the sanity check
+     *
+     * @param s file/directory to be checked
+     * @return whether it is excluded or not
+     */
+    private static boolean excluded(String s) {
+        for (String ex :
+                excluded) {
+            if (s.startsWith(ex)) return true;
+        }
+        return false;
+    }
+
+    /**
+     * Reads the file character by character.
+     *
+     * @param reader reader that is read
+     * @throws IOException thrown if the file can't be read
+     */
+    private static void handleCharacters(Reader reader) throws IOException {
+        int r;
+        while ((r = reader.read()) != -1) {
+            char c = (char) r;
+            handleCharacter(c);
+        }
+    }
+
+    /**
+     * Handles a single character
+     *
+     * @param c next character
+     */
+    private static void handleCharacter(char c) {
+        //updating position
+        currentPosition++;
+        if (c == '\n') {
+            currentLine++;
+            currentPosition = 1;
+        }
+
+        //try applying to the innermost element
+        if (!stack.empty()) {
+            int change;
+            try {
+                change = stack.peek().handleChar(c);
+            } catch (SyntaxError e) {
+                change = e.getChange();
+                addError(e);
+            }
+
+            //change greater 0 means the innermost element did some work
+            if (change > 0) {
+                //2 means the Element is complete
+                if (change == 2) {
+                    //remove the topmost element from stack since it is complete
+                    stack.pop();
+                    return;
+                }
+                //3 means the Element is complete and part of a two tag system
+                if (change == 3) {
+                    //remove the topmost element from stack since it is complete
+                    KnownElement k = stack.pop().getKnownElement();
+                    /*if (k.isOpening()) {
+                        stack.push(k);
+                    } else */
+                    if (k.isClosing()) {
+                        if (stack.empty()) {
+                            addError(new SyntaxError("Closed tag " + k.getShortDescription() + " without having any open tags.", -2));
+                        } else if (stack.peek() instanceof KnownElement) {
+                            KnownElement kFirst = (KnownElement) stack.pop();
+                            if (!kFirst.isMatchingElement(k)) {
+                                addError(new SyntaxError("Opening tag " + kFirst.getShortDescription() +
+                                        " does not match closing tag " + k.getShortDescription() + ".", -2));
+                            }
+                            //stack.pop();
+                        } else {
+                            addError(new SyntaxError("Closing tag " + k.getShortDescription() + " inside " +
+                                    "another tag: " + stack.peek().getShortDescription(), -2, true));
+                        }
+                    }
+                    if (k.isOpening()) {
+                        stack.push(k);
+                    }
+                    return;
+                }
+                if (change == 4) {
+                    stack.pop();
+                } else {
+                    return;
+                }
+            }
+        }
+
+
+        //innermost element was uninterested, trying to find matching element
+        switch (c) {
+            //case '@':
+            //  stack.push(new AtElement(currentLine, currentPosition));
+            //break;
+            case '<':
+                stack.push(new AngleBracketElement(currentLine, currentPosition));
+                break;
+            //case '>':
+            //addError(new SyntaxError("Dangling \">\", current innermost: " + (stack.empty() ? "null" : stack.peek().getShortDescription()), -2));
+            //break;
+            case '/':
+                stack.push(new CommentElement(currentLine, currentPosition));
+                break;
+        }
+    }
+
+    /**
+     * add an error to the error list
+     *
+     * @param e new error
+     */
+    private static void addError(SyntaxError e) {
+        e.setFile(currentFile);
+        e.setLine(currentLine);
+        e.setPosition(currentPosition);
+        errors.add(e);
+    }
+}
diff --git a/devTools/javaSanityCheck/src/SyntaxError.java b/devTools/javaSanityCheck/src/SyntaxError.java
new file mode 100644
index 0000000000000000000000000000000000000000..150f2bd449b8c318b5a05884868a71538554ec67
--- /dev/null
+++ b/devTools/javaSanityCheck/src/SyntaxError.java
@@ -0,0 +1,40 @@
+package org.arkerthan.sanityCheck;
+
+public class SyntaxError extends Exception {
+    private String file;
+    private int line, position;
+    private String description;
+    private int change; //see Element for values; -2 means not thrown
+    private boolean warning = false;
+
+    public SyntaxError(String description, int change) {
+        this.description = description;
+        this.change = change;
+    }
+
+    public SyntaxError(String description, int change, boolean warning) {
+        this(description, change);
+        this.warning = warning;
+    }
+
+    public void setFile(String file) {
+        this.file = file;
+    }
+
+    public void setLine(int line) {
+        this.line = line;
+    }
+
+    public void setPosition(int position) {
+        this.position = position;
+    }
+
+    public String getError() {
+        String s = warning ? "Warning: " : "Error: ";
+        return s + file + ": " + line + ":" + position + " : "+ description;
+    }
+
+    public int getChange() {
+        return change;
+    }
+}
diff --git a/devTools/javaSanityCheck/src/Tag.java b/devTools/javaSanityCheck/src/Tag.java
new file mode 100644
index 0000000000000000000000000000000000000000..8a13ee4f7a178399db3eaf626b693e8a12ae71df
--- /dev/null
+++ b/devTools/javaSanityCheck/src/Tag.java
@@ -0,0 +1,11 @@
+package org.arkerthan.sanityCheck;
+
+public class Tag {
+    public final String tag;
+    public final boolean single;
+
+    public Tag(String tag, boolean single) {
+        this.tag = tag;
+        this.single = single;
+    }
+}
diff --git a/devTools/javaSanityCheck/src/TagSearchTree.java b/devTools/javaSanityCheck/src/TagSearchTree.java
new file mode 100644
index 0000000000000000000000000000000000000000..dde49df879a346f124d15647cfeb821d0e0735fb
--- /dev/null
+++ b/devTools/javaSanityCheck/src/TagSearchTree.java
@@ -0,0 +1,80 @@
+package org.arkerthan.sanityCheck;
+
+import java.util.List;
+
+/**
+ * Tag SearchTree stores Tags in an alphabetical search tree.
+ * Once created the search tree can't be changed anymore.
+ *
+ * @param <E> Tag class to be stored
+ */
+public class TagSearchTree<E extends Tag> {
+    private static final int SIZE = 128;
+    private final TagSearchTree<E>[] branches;
+    private E element = null;
+    private String path;
+
+    /**
+     * creates a new empty TagSearchTree
+     */
+    private TagSearchTree() {
+        branches = new TagSearchTree[SIZE];
+    }
+
+    /**
+     * Creates a new filled TagSearchTree
+     *
+     * @param list Tags to be inserted
+     */
+    public TagSearchTree(List<E> list) {
+        this();
+        for (E e : list) {
+            this.add(e, 0);
+        }
+    }
+
+    /**
+     * adds a new Tag to the TagSearchTree
+     *
+     * @param e     Tag to be stored
+     * @param index index of relevant char for adding in tag
+     */
+    private void add(E e, int index) {
+        //set the path to here
+        path = e.tag.substring(0, index);
+        //checks if tag has to be stored here or further down
+        if (e.tag.length() == index) {
+            element = e;
+        } else {
+            //store tag in correct branch
+            char c = e.tag.charAt(index);
+            if (branches[c] == null) {
+                branches[c] = new TagSearchTree<>();
+            }
+            branches[c].add(e, index + 1);
+        }
+    }
+
+    /**
+     * @param c character of branch needed
+     * @return branch or null if branch doesn't exist
+     */
+    public TagSearchTree<E> getBranch(char c) {
+        if (c >= SIZE) return null;
+        return branches[c];
+    }
+
+    /**
+     * @return stored Tag, null if empty
+     */
+    public E getElement() {
+        return element;
+    }
+
+    /**
+     * @return path inside full tree to get to this Branch
+     */
+    public String getPath() {
+        return path;
+    }
+}
diff --git a/devTools/javaSanityCheck/src/UnknownStateException.java b/devTools/javaSanityCheck/src/UnknownStateException.java
new file mode 100644
index 0000000000000000000000000000000000000000..dceb35bc3d5b57fa3d710e9e61d3ce427a3499c3
--- /dev/null
+++ b/devTools/javaSanityCheck/src/UnknownStateException.java
@@ -0,0 +1,8 @@
+package org.arkerthan.sanityCheck;
+
+public class UnknownStateException extends RuntimeException {
+
+    public UnknownStateException(int state) {
+        super(String.valueOf(state));
+    }
+}
diff --git a/devTools/javaSanityCheck/src/element/AngleBracketElement.java b/devTools/javaSanityCheck/src/element/AngleBracketElement.java
new file mode 100644
index 0000000000000000000000000000000000000000..e4819ba37ea48e4924dc944827d651fa14e02ad1
--- /dev/null
+++ b/devTools/javaSanityCheck/src/element/AngleBracketElement.java
@@ -0,0 +1,360 @@
+package org.arkerthan.sanityCheck.element;
+
+import org.arkerthan.sanityCheck.*;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class AngleBracketElement extends Element {
+    private static final List<String> logicTags = Arrays.asList("if", "elseif", "else", "switch", "case", "default");
+    private int state = 0;
+    /*
+     0 - initial: <
+     TWINE
+     1 - <<
+    -1 - <</
+     2 - trying to complete twine tag: <<tag ???>>
+    -2 - trying to complete twine tag: <</tag>>
+     3 - waiting for >>
+    -3 - expecting > from 3
+     4 - waiting for >> with KnownElement
+    -4 - expecting > from 4
+     5 - expecting >>
+    -5 - expecting >
+     6 - expecting > with KnownElement opening; comparison?
+    -6 - expecting > with KnownElement closing
+
+     HTML
+    -9 - </
+    10 - trying to complete HTML tag: <tag ???>
+   -10 - trying to complete HTML tag: </tag>
+    11 - waiting for >
+   -11 - expecting >
+    12 - waiting for > with KnownElement
+     */
+
+    private TagSearchTree<Tag> tree;
+
+    public AngleBracketElement(int line, int pos) {
+        super(line, pos);
+    }
+
+    @Override
+    public int handleChar(char c) throws SyntaxError {
+        switch (state) {
+            case 0:
+                switch (c) {
+                    case '<':
+                        state = 1;
+                        return 1;
+                    case '>':
+                        throw new SyntaxError("Empty Statement?", 2);
+                    case '/':
+                        state = -9;
+                        return 1;
+                    case ' ':// assume comparison
+                    case '=':// "
+                        return 2;
+                    case '3'://a heart: <3
+                        return 2;
+                    default:
+                        try {
+                            state = 10;
+                            tree = Main.htmlTags;
+                            return handleOpeningHTML(c);
+                        } catch (SyntaxError e) {
+                            state = 1;
+                            throw new SyntaxError("Opening \"<\" missing, found " + c + " [debug:initialCase]", 1);
+                        }
+                }
+            case 1:
+                if (c == '<') {
+                    throw new SyntaxError("Too many \"<\".", 1);
+                } else if (c == '>') {
+                    state = 3;
+                    throw new SyntaxError("Empty Statement?", 1);
+                } else if (c == '/') {
+                    state = -1;
+                    return 1;
+                }
+                state = 2;
+                tree = Main.twineTags;
+                return handleOpeningTwine(c);
+            case -1:
+                if (c == '>') {
+                    throw new SyntaxError("Empty Statement?", 2, true);
+                }
+                state = -2;
+                tree = Main.twineTags;
+                return handleClosingTwine(c);
+
+            case 2:
+                return handleOpeningTwine(c);
+            case -2:
+                return handleClosingTwine(c);
+            case 3:
+                if (c == '>') {
+                    state = -3;
+                    return 1;
+                }
+                break;
+            case -3:
+                if (c == '>') {
+                    return 2;
+                } else if (c == ' ' || c == '=') { // assuming comparison
+                    state = 3;
+                    return 1;
+                } else {
+                    throw new SyntaxError("Closing \">\" missing, opened [" + line + ":" + pos + "]", 2);
+                }
+            case 4:
+                if (c == '>') {
+                    state = -4;
+                    return 1;
+                }
+                break;
+            case -4:
+                if (c == '>') {
+                    return 3;
+                } else if (c == ' ' || c == '=') { // assuming comparison
+                    state = 4;
+                    return 1;
+                } else {
+                    throw new SyntaxError("Closing \">\" missing, opened [" + line + ":" + pos + "]", 2);
+                }
+            case 5:
+                if (c == '>') {
+                    state = -5;
+                    return 1;
+                } else {
+                    throw new SyntaxError("Closing \">\" missing, opened [" + line + ":" + pos + "]", 2);
+                }
+            case -5:
+                if (c == '>') {
+                    return 2;
+                }
+                throw new SyntaxError("Closing \">\" missing, opened [" + line + ":" + pos + "]", 2);
+            case 6:
+                if (c == '>') {
+                    return 3;
+                } else if (c == ' ' || c == '=') {
+                    state = 3;
+                    return 1;
+                } else {
+                    throw new SyntaxError("Closing \">\" missing, opened [" + line + ":" + pos + "]", 3);
+                }
+            case -6:
+                if (c == '>') {
+                    return 3;
+                }
+                throw new SyntaxError("Closing \">\" missing, opened [" + line + ":" + pos + "]", 3);
+
+            case -9:
+                if (c == '>') {
+                    throw new SyntaxError("Empty Statement?", 2, true);
+                }
+                state = -10;
+                tree = Main.htmlTags;
+                return handleClosingHTML(c);
+            case 10:
+                return handleOpeningHTML(c);
+            case -10:
+                return handleClosingHTML(c);
+            case 11:
+                if (c == '>')
+                    return 2;
+                if (c == '@') //@ inside HTML tags is allowed
+                    return 1;
+                break;
+            case -11:
+                if (c == '>')
+                    return 2;
+                throw new SyntaxError("Closing \">\" missing [2]", 2);
+            case 12:
+                if (c == '>')
+                    return 3;
+                if (c == '@') //@ inside HTML tags is allowed
+                    return 1;
+                break;
+            default:
+                throw new UnknownStateException(state);
+        }
+        return 0;
+    }
+
+    private int handleOpeningHTML(char c) throws SyntaxError {
+        if (c == ' ') {
+            state = 11;
+            if (tree.getElement() == null) {
+                throw new SyntaxError("Unknown HTML tag", 1);
+            }
+            if (!tree.getElement().single) {
+                k = new KnownHtmlElement(line, pos, true, tree.getElement().tag);
+                state = 12;
+                return 1;
+            }
+            return 1;
+        }
+        if (c == '>') {
+            if (tree.getElement() == null) {
+                throw new SyntaxError("Unknown HTML tag", 2);
+            }
+            if (!tree.getElement().single) {
+                k = new KnownHtmlElement(line, pos, true, tree.getElement().tag);
+                return 3;
+            }
+            return 2;
+        }
+
+        tree = tree.getBranch(c);
+        if (tree == null) {
+            state = 11;
+            throw new SyntaxError("Unknown HTML tag or closing \">\" missing, found " + c, 1);
+        }
+
+        return 1;
+    }
+
+    private int handleClosingHTML(char c) throws SyntaxError {
+        if (c == '>') {
+            if (tree.getElement() == null) {
+                throw new SyntaxError("Unknown HTML tag", 2);
+            }
+            if (tree.getElement().single) {
+                throw new SyntaxError("Single HTML tag used as closing Tag: " + tree.getElement().tag, 2);
+            }
+            k = new KnownHtmlElement(line, pos, false, tree.getElement().tag);
+            return 3;
+        }
+
+        tree = tree.getBranch(c);
+        if (tree == null) {
+            state = -11;
+            throw new SyntaxError("Unknown HTML tag or closing \">\" missing, found " + c, 1);
+        }
+
+        return 1;
+    }
+
+
+    private int handleOpeningTwine(char c) throws SyntaxError {
+        if (c == ' ') {
+            state = 3;
+            if (tree.getElement() == null) {
+                //assuming not listed means widget until better solution
+                return 1;
+                //throw new SyntaxError("Unknown Twine tag or closing \">>\" missing, found " + tree.getPath(), 1);
+            }
+            if (!tree.getElement().single) {
+                if (logicTags.contains(tree.getElement().tag)) {
+                    k = new KnownLogicElement(line, pos, tree.getElement().tag, false);
+                } else {
+                    k = new KnownTwineElement(line, pos, true, tree.getElement().tag);
+                }
+                state = 4;
+                return 1;
+            }
+            return 1;
+        }
+        if (c == '>') {
+            state = -5;
+            if (tree.getElement() == null) {
+                //assuming not listed means widget until better solution
+                //throw new SyntaxError("Unknown Twine tag or closing \">>\" missing, found " + tree.getPath(), 1);
+                return 1;
+            }
+            if (!tree.getElement().single) {
+                if (logicTags.contains(tree.getElement().tag)) {
+                    k = new KnownLogicElement(line, pos, tree.getElement().tag, false);
+                } else {
+                    k = new KnownTwineElement(line, pos, true, tree.getElement().tag);
+                }
+                state = 6;
+                return 1;
+            }
+            return 2;
+        }
+
+        tree = tree.getBranch(c);
+        if (tree == null) {
+            //assuming not listed means widget until better solution
+            state = 3;
+            //throw new SyntaxError("Unknown Twine tag or closing \">>\" missing, found " + c, 1);
+        }
+
+        return 1;
+    }
+
+    private int handleClosingTwine(char c) throws SyntaxError {
+        if (c == '>') {
+            if (tree.getElement() == null) {
+                throw new SyntaxError("Unknown Twine tag", 2);
+            }
+            if (tree.getElement().single) {
+                throw new SyntaxError("Single Twine tag used as closing Tag: " + tree.getElement().tag, 2);
+            }
+            if (logicTags.contains(tree.getElement().tag)) {
+                k = new KnownLogicElement(line, pos, tree.getElement().tag, true);
+            } else {
+                k = new KnownTwineElement(line, pos, false, tree.getElement().tag);
+            }
+            state = -6;
+            return 1;
+        }
+
+        tree = tree.getBranch(c);
+        if (tree == null) {
+            state = 3;
+            throw new SyntaxError("Unknown Twine closing tag or closing \">>\" missing, found " + c, 1);
+        }
+
+        return 1;
+    }
+
+    @Override
+    public String getShortDescription() {
+        StringBuilder builder = new StringBuilder();
+        builder.append('[').append(line).append(":").append(pos).append("] ");
+        switch (state) {
+            case 0:
+                builder.append("<");
+                break;
+            case 1:
+                builder.append("<<");
+                break;
+            case -1:
+                builder.append("<</");
+                break;
+            case 2:
+                builder.append("<<").append(tree.getPath());
+                break;
+            case -2:
+                builder.append("<</").append(tree.getPath());
+                break;
+            case 3:
+                builder.append("<<??? ???");
+                break;
+            case 4:
+                builder.append("<<?").append(tree.getPath()).append(" ???");
+                break;
+            case -3:
+                builder.append("<<??? ???>");
+                break;
+            case -4:
+                builder.append("<<?").append(tree.getPath()).append(" ???>");
+                break;
+            case 5:
+                builder.append("<").append(tree.getPath()).append(" ???");
+                break;
+            case -5:
+                builder.append("</").append(tree.getPath());
+                break;
+            case 6:
+                builder.append("<").append(tree.getPath()).append(" ???");
+                break;
+            default:
+                //throw new UnknownStateException(state);
+        }
+        return builder.toString();
+    }
+}
diff --git a/devTools/javaSanityCheck/src/element/AtElement.java b/devTools/javaSanityCheck/src/element/AtElement.java
new file mode 100644
index 0000000000000000000000000000000000000000..0dad04247c50f2a9a77bb9ce584ded8de0377ed2
--- /dev/null
+++ b/devTools/javaSanityCheck/src/element/AtElement.java
@@ -0,0 +1,105 @@
+package org.arkerthan.sanityCheck.element;
+
+import org.arkerthan.sanityCheck.SyntaxError;
+import org.arkerthan.sanityCheck.UnknownStateException;
+
+public class AtElement extends Element {
+    private int state = 0;
+    // 0 = @
+    // 1 = @@
+    // 2 = @@.
+    // 3 = @@.a -- @@.ab -- @@.abc
+    // 4 = @@.abc;abc
+    // 5 = @@.abc;abc@
+
+    // example: @@.red;some text@@
+
+    public AtElement(int line, int pos) {
+        super(line, pos);
+    }
+
+    @Override
+    public int handleChar(char c) throws SyntaxError {
+        switch (state) {
+            case 0:
+                state = 1;
+                if (c == '@') {
+                    return 1;
+                } else {
+                    if (c == '.') {
+                        state = 2;
+                    }
+                    throw new SyntaxError("Opening \"@\" missing.", 1);
+                }
+            case 1:
+                if (c == '.') {
+                    state = 2;
+                    return 1;
+                } else {
+                    state = 4;
+                    throw new SyntaxError("\".\" missing, found \"" + c + "\". This might also indicate a " +
+                            "missing closure in the previous color code.", 0, true);
+                }
+            case 2:
+                state = 3;
+                if (Character.isAlphabetic(c)) {
+                    return 1;
+                } else {
+                    throw new SyntaxError("Identifier might be wrong.", 1, true);
+                }
+            case 3:
+                if (c == ';') {
+                    state = 4;
+                    return 1;
+                } else if (c == ' ') {
+                    state = 4;
+                    throw new SyntaxError("\";\" missing or wrong space.", 1);
+                }
+                break;
+            case 4:
+                if (c == '@') {
+                    state = 5;
+                    return 1;
+                }
+                break;
+            case 5:
+                if (c == '@') {
+                    return 2;
+                } else {
+                    throw new SyntaxError("Closing \"@\" missing.", 2);
+                }
+            default:
+                throw new UnknownStateException(state);
+        }
+        return 0;
+    }
+
+    @Override
+    public String getShortDescription() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(line).append(":").append(pos).append(" ");
+        switch (state) {
+            case 0:
+                builder.append("@");
+                break;
+            case 1:
+                builder.append("@@");
+                break;
+            case 2:
+                builder.append("@@.");
+                break;
+            case 3:
+                builder.append("@@.???");
+                break;
+            case 4:
+                builder.append("@@???");
+                break;
+            case 5:
+                builder.append("@@???@");
+                break;
+            default:
+                throw new UnknownStateException(state);
+        }
+        return builder.toString();
+    }
+}
diff --git a/devTools/javaSanityCheck/src/element/CommentElement.java b/devTools/javaSanityCheck/src/element/CommentElement.java
new file mode 100644
index 0000000000000000000000000000000000000000..3a3cc12aff9f3c2e4b06cc7240d14824575cc96e
--- /dev/null
+++ b/devTools/javaSanityCheck/src/element/CommentElement.java
@@ -0,0 +1,66 @@
+package org.arkerthan.sanityCheck.element;
+
+import org.arkerthan.sanityCheck.SyntaxError;
+import org.arkerthan.sanityCheck.UnknownStateException;
+
+public class CommentElement extends Element {
+    int state = 0;
+    /*
+    0 - /
+    1 - /*???
+    2 - /*???*
+    3 - /%???
+    4 - /%???%
+     */
+
+    public CommentElement(int line, int pos) {
+        super(line, pos);
+    }
+
+    @Override
+    public int handleChar(char c) throws SyntaxError {
+        switch (state) {
+            case 0:
+                if (c == '*') {
+                    state = 1;
+                } else if (c == '%') {
+                    state = 3;
+                } else if (c == '>') {
+                    throw new SyntaxError("XHTML style closure", 4, true);
+                } else {
+                    return 4;
+                }
+                break;
+            case 1:
+                if (c == '*') {
+                    state = 2;
+                }
+                break;
+            case 2:
+                if (c == '/') {
+                    return 2;
+                }
+                state = 1;
+                break;
+            case 3:
+                if (c == '%') {
+                    state = 4;
+                }
+                break;
+            case 4:
+                if (c == '/') {
+                    return 2;
+                }
+                state = 3;
+                break;
+            default:
+                throw new UnknownStateException(state);
+        }
+        return 1;
+    }
+
+    @Override
+    public String getShortDescription() {
+        return null;
+    }
+}
diff --git a/devTools/javaSanityCheck/src/element/Element.java b/devTools/javaSanityCheck/src/element/Element.java
new file mode 100644
index 0000000000000000000000000000000000000000..b0f99fa904f66a6a9ebcecb5ffdfb7040493b08b
--- /dev/null
+++ b/devTools/javaSanityCheck/src/element/Element.java
@@ -0,0 +1,40 @@
+package org.arkerthan.sanityCheck.element;
+
+import org.arkerthan.sanityCheck.SyntaxError;
+
+public abstract class Element {
+    protected KnownElement k;
+    protected int line, pos;
+
+    /**
+     * @param line Line the instance was created
+     * @param pos  Position in line the instance was created
+     */
+    protected Element(int line, int pos) {
+        this.line = line;
+        this.pos = pos;
+    }
+
+    /**
+     * Parses a Char and returns an int depending on the state of the element
+     * 0 - the Element did nothing
+     * 1 - the Element changed state
+     * 2 - the Element is finished
+     * 3 - the Element is finished and a KnownHtmlElement was generated
+     * 4 - the Element is finished and the char is still open for use
+     *
+     * @param c
+     * @return
+     * @throws Error
+     */
+    public abstract int handleChar(char c) throws SyntaxError;
+
+    public KnownElement getKnownElement() {
+        return k;
+    }
+
+    /**
+     * @return a short description usually based on state and position of the Element
+     */
+    public abstract String getShortDescription();
+}
diff --git a/devTools/javaSanityCheck/src/element/KnownElement.java b/devTools/javaSanityCheck/src/element/KnownElement.java
new file mode 100644
index 0000000000000000000000000000000000000000..305be2fe65210b191d96ead352487b35e448ce39
--- /dev/null
+++ b/devTools/javaSanityCheck/src/element/KnownElement.java
@@ -0,0 +1,31 @@
+package org.arkerthan.sanityCheck.element;
+
+import org.arkerthan.sanityCheck.SyntaxError;
+
+public abstract class KnownElement extends Element {
+
+    public KnownElement(int line, int pos) {
+        super(line, pos);
+    }
+
+    /**
+     * @return true, if it needs another Known Element to close it.
+     */
+    public abstract boolean isOpening();
+
+    /**
+     * @return true if it closes another Element.
+     */
+    public abstract boolean isClosing();
+
+    /**
+     * @param k Element to be checked
+     * @return true if given Element closes Element
+     */
+    public abstract boolean isMatchingElement(KnownElement k);
+
+    @Override
+    public int handleChar(char c) throws SyntaxError {
+        return 0;
+    }
+}
diff --git a/devTools/javaSanityCheck/src/element/KnownHtmlElement.java b/devTools/javaSanityCheck/src/element/KnownHtmlElement.java
new file mode 100644
index 0000000000000000000000000000000000000000..d086a74bc547a0aa90520e50c4398f5cf6dc365e
--- /dev/null
+++ b/devTools/javaSanityCheck/src/element/KnownHtmlElement.java
@@ -0,0 +1,41 @@
+package org.arkerthan.sanityCheck.element;
+
+public class KnownHtmlElement extends KnownElement {
+
+    private boolean opening;
+    private String statement;
+
+    public KnownHtmlElement(int line, int pos, boolean opening, String statement) {
+        super(line, pos);
+        this.opening = opening;
+        this.statement = statement;
+    }
+
+    @Override
+    public String getShortDescription() {
+        StringBuilder builder = new StringBuilder();
+        builder.append('[').append(line).append(":").append(pos).append("] <");
+        if (!opening) {
+            builder.append("/");
+        }
+        return builder.append(statement).append(">").toString();
+    }
+
+    @Override
+    public boolean isOpening() {
+        return opening;
+    }
+
+    @Override
+    public boolean isClosing() {
+        return !opening;
+    }
+
+    @Override
+    public boolean isMatchingElement(KnownElement k) {
+        if (k instanceof KnownHtmlElement) {
+            return ((KnownHtmlElement) k).statement.equals(this.statement);
+        }
+        return false;
+    }
+}
diff --git a/devTools/javaSanityCheck/src/element/KnownLogicElement.java b/devTools/javaSanityCheck/src/element/KnownLogicElement.java
new file mode 100644
index 0000000000000000000000000000000000000000..502abde93a296c3dffb2391b75b08893aeecd2c5
--- /dev/null
+++ b/devTools/javaSanityCheck/src/element/KnownLogicElement.java
@@ -0,0 +1,117 @@
+package org.arkerthan.sanityCheck.element;
+
+import org.arkerthan.sanityCheck.DisallowedTagException;
+import org.arkerthan.sanityCheck.UnknownStateException;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class KnownLogicElement extends KnownElement {
+    private static final List<String> allowedTags = Arrays.asList("if", "elseif", "else");
+    private final int state;
+    private boolean last;
+    /*
+    0 - if
+    1 - elseif
+    2 - else
+    3 - switch
+    4 - case
+    5 - default
+     */
+
+    public KnownLogicElement(int line, int pos, String tag, boolean last) {
+        this(line, pos, tag);
+        this.last = last;
+    }
+
+    public KnownLogicElement(int line, int pos, String tag) {
+        super(line, pos);
+        switch (tag) {
+            case "if":
+                state = 0;
+                break;
+            case "elseif":
+                state = 1;
+                break;
+            case "else":
+                state = 2;
+                break;
+            case "switch":
+                state = 3;
+                break;
+            case "case":
+                state = 4;
+                break;
+            case "default":
+                state = 5;
+                break;
+            default:
+                throw new DisallowedTagException(tag);
+        }
+        last = false;
+    }
+
+    @Override
+    public boolean isOpening() {
+        return !last;
+    }
+
+    @Override
+    public boolean isClosing() {
+        return (state != 0 && state != 3) || last;
+    }
+
+    @Override
+    public boolean isMatchingElement(KnownElement k) {
+        if (!(k instanceof KnownLogicElement)) {
+            return false;
+        }
+        KnownLogicElement l = (KnownLogicElement) k;
+        switch (state) {
+            case 0:
+            case 1:
+                return l.state == 1 || l.state == 2 || (l.state == 0 && l.last);
+            case 2:
+                return l.state == 0 && l.last;
+            case 3:
+            case 4:
+                return l.state == 3 || l.state == 4;
+            case 5:
+                return l.state == 3 && l.last;
+            default:
+                throw new UnknownStateException(state);
+        }
+    }
+
+    @Override
+    public String getShortDescription() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("[").append(line).append(":").append(pos).append("] <<");
+        if (last) {
+            builder.append('/');
+        }
+        switch (state) {
+            case 0:
+                builder.append("if");
+                break;
+            case 1:
+                builder.append("elseif");
+                break;
+            case 2:
+                builder.append("else");
+                break;
+            case 3:
+                builder.append("switch");
+                break;
+            case 4:
+                builder.append("case");
+                break;
+            case 5:
+                builder.append("default");
+                break;
+            default:
+                throw new UnknownStateException(state);
+        }
+        return builder.append(">>").toString();
+    }
+}
diff --git a/devTools/javaSanityCheck/src/element/KnownTwineElement.java b/devTools/javaSanityCheck/src/element/KnownTwineElement.java
new file mode 100644
index 0000000000000000000000000000000000000000..24003fd00be0bb79aa6a01b2fbd2d9a91439ac6a
--- /dev/null
+++ b/devTools/javaSanityCheck/src/element/KnownTwineElement.java
@@ -0,0 +1,41 @@
+package org.arkerthan.sanityCheck.element;
+
+public class KnownTwineElement extends KnownElement {
+
+    private boolean opening;
+    private String statement;
+
+    public KnownTwineElement(int line, int pos, boolean opening, String statement) {
+        super(line, pos);
+        this.opening = opening;
+        this.statement = statement;
+    }
+
+    @Override
+    public String getShortDescription() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("[").append(line).append(":").append(pos).append("] <<");
+        if (!opening) {
+            builder.append("/");
+        }
+        return builder.append(statement).append(">>").toString();
+    }
+
+    @Override
+    public boolean isOpening() {
+        return opening;
+    }
+
+    @Override
+    public boolean isClosing() {
+        return !opening;
+    }
+
+    @Override
+    public boolean isMatchingElement(KnownElement k) {
+        if (k instanceof KnownTwineElement) {
+            return ((KnownTwineElement) k).statement.equals(this.statement);
+        }
+        return false;
+    }
+}
diff --git a/devTools/javaSanityCheck/twineTags b/devTools/javaSanityCheck/twineTags
new file mode 100644
index 0000000000000000000000000000000000000000..e1dea71621bd818041d6aad43d7b3053b2c78132
--- /dev/null
+++ b/devTools/javaSanityCheck/twineTags
@@ -0,0 +1,39 @@
+#Allowed twine tags
+#Effectively everything that is allowed in a statements like this:
+#<<tag>> or <<tag ???>>
+#when ;1 is specified it expects a matching closing tag like this: <</tag>>
+#Everything belonging to if and switch statements is hard coded and does not
+#need to be included here.
+#Do not add HTML Tags here.
+#Characters outside of ASCII scope are not supported.
+#
+#twine tags
+capture;1
+continue;0
+for;1
+#does foreach really exist?
+foreach;1
+goto;0
+htag;1
+include;0
+link;1
+nobr;1
+print;0
+replace;1
+run;0
+script;1
+set;0
+silently;1
+textbox;0
+timed;1
+unset;0
+widget;1
+=;0
+#
+# Twine logic ### DO NOT TOUCH ###
+if;1
+elseif;1
+else;1
+switch;1
+case;1
+default;
diff --git a/sanityCheck-java b/sanityCheck-java
new file mode 100755
index 0000000000000000000000000000000000000000..455bbfbc243ec664f5aac2daa2ad74903d104962
--- /dev/null
+++ b/sanityCheck-java
@@ -0,0 +1 @@
+java -jar SanityCheck.jar
diff --git a/sanityCheck-java.bat b/sanityCheck-java.bat
new file mode 100644
index 0000000000000000000000000000000000000000..455bbfbc243ec664f5aac2daa2ad74903d104962
--- /dev/null
+++ b/sanityCheck-java.bat
@@ -0,0 +1 @@
+java -jar SanityCheck.jar
diff --git a/src/events/intro/introSummary.tw b/src/events/intro/introSummary.tw
index a91ccd914ba27167096a8773aceab38be01fde46..afcb75c701b1d1a4e1e2482a37af243c95366380 100644
--- a/src/events/intro/introSummary.tw
+++ b/src/events/intro/introSummary.tw
@@ -112,7 +112,7 @@ You are using standardized slave trading channels. [[Customize the slave trade|C
 	<<if ndef $nationalitiescheck>> /* NGP: regenerate $nationalitiescheck from previous game's $nationalities array */
 		<<silently>><<include "Customize Slave Trade">><</silently>>
 	<</if>>
-	<br style="clear:both" /><hr style="margin:0">
+	<br style="clear:both"><hr style="margin:0">
 	<<set _len = Object.keys($nationalitiescheck).length>>
 	<<set _j = 0>>
 	<<for _nation, _i range $nationalitiescheck>>
@@ -120,7 +120,7 @@ You are using standardized slave trading channels. [[Customize the slave trade|C
 		<<set _j++>>
 		<<if _j < _len>> | <</if>>
 	<</for>>
-	<br style="clear:both" /><hr style="margin:0">
+	<br style="clear:both"><hr style="margin:0">
 <</if>> /* closes $customVariety is defined */
 
 /* Accordion 000-250-006 */
diff --git a/src/facilities/farmyard/farmyard.tw b/src/facilities/farmyard/farmyard.tw
index 84c46326557d1a0e48a88b846e0610fedf7e9e83..b44ac1f37449d5c9c73970c43d2728e1ae0fcbd5 100644
--- a/src/facilities/farmyard/farmyard.tw
+++ b/src/facilities/farmyard/farmyard.tw
@@ -105,7 +105,7 @@ $farmyardNameCaps is an oasis of growth in the midst of the jungle of steel and
 <br>It can support $farmyard farmhands. Currently there <<if $farmyardSlaves == 1>>is<<else>>are<</if>> $farmyardSlaves farmhand<<if $farmyardSlaves != 1>>s<</if>> at $farmyardName.
 [[Expand the farmyard|Farmyard][cashX(forceNeg(_Tmult0), "capEx"), $farmyard += 5, $PC.engineering += .1]] //Costs <<print cashFormat(_Tmult0)>> and will increase upkeep costs//
 
-<span id="menials"
+<span id="menials">
 <br><br><br>
 <<if $farmMenials > 0>>
 	Assigned here are $farmMenials slaves working to produce as much food as possible.
diff --git a/src/facilities/nursery/childSummary.tw b/src/facilities/nursery/childSummary.tw
index 760106b9eeeed54014ee3ca43e64014d387b4169..78449006c71ef6d6c5753beb58d866e9c3b713cb 100644
--- a/src/facilities/nursery/childSummary.tw
+++ b/src/facilities/nursery/childSummary.tw
@@ -31,7 +31,7 @@
 		<<if (/Select/i.test(_Pass))>>
 			<<set _offset = -25>>
 		<</if>>
-		<br />
+		<br>
 		<<set _tableCount = _tableCount || 0>>
 		<<set _tableCount++>>
 		/*
@@ -104,7 +104,7 @@
 		<<set _chosenClothes = saChoosesOwnClothes(_Child)>>
 		<<set $cribs[_csi].devotion = _oldDevotion, _Child = $cribs[_csi]>> /* restore devotion value so repeatedly changing clothes isn't an exploit */
 	<</if>>
-	<br style="clear:both" /><<if $lineSeparations == 0>><br><<else>><hr style="margin:0"><</if>><<if ($seeImages == 1) && ($seeSummaryImages == 1)>><div class="imageRef smlImg"><<SlaveArt _Child 1>></div><</if>>
+	<br style="clear:both"><<if $lineSeparations == 0>><br><<else>><hr style="margin:0"><</if>><<if ($seeImages == 1) && ($seeSummaryImages == 1)>><div class="imageRef smlImg"><<SlaveArt _Child 1>></div><</if>>
 	<<if "be your Head Girl" == _Child.assignment>>''@@.lightcoral;HG@@''
 	<<elseif "recruit girls" == _Child.assignment>>''@@.lightcoral;RC@@''
 	<<elseif "guard you" == _Child.assignment>>''@@.lightcoral;BG@@''
@@ -114,7 +114,7 @@
 
 /* TODO: will the PC be able to give children PA? */
 <<case "Personal Attention Select">>
-	<br style="clear:both" /><<if $lineSeparations == 0>><br><<else>><hr style="margin:0"><</if>><<if ($seeImages == 1) && ($seeSummaryImages == 1)>><div class="imageRef smlImg"><<SlaveArt _Child 1>></div><</if>>
+	<br style="clear:both"><<if $lineSeparations == 0>><br><<else>><hr style="margin:0"><</if>><<if ($seeImages == 1) && ($seeSummaryImages == 1)>><div class="imageRef smlImg"><<SlaveArt _Child 1>></div><</if>>
 	<<link _childName>>
 		<<if !Array.isArray($personalAttention)>> /* first PA target */
 			<<set $personalAttention = [{ID: $cribs[_csi].ID, trainingRegimen: "undecided"}]>>
diff --git a/src/uncategorized/RESS.tw b/src/uncategorized/RESS.tw
index 40c313b72694a50904f2f50fb66a54938c0fa806..148413175ddb56d90efdfe5a1e2160c41695cc73 100644
--- a/src/uncategorized/RESS.tw
+++ b/src/uncategorized/RESS.tw
@@ -18470,7 +18470,7 @@ You tell $him kindly that you understand, and that $he'll be trained to address
 		<<case "be the Schoolteacher">>($his office in $schoolroomName, where $he'll decide today's lesson),
 		<<case "be the Stewardess">>($his office in $servantsQuartersName, where $he'll divvy out today's tasks),
 		<<case "be the Milkmaid">>($dairyName, to check on the cattle),
-		<<case "be the Farmer">><<($farmyardName, to tend to the crops),
+		<<case "be the Farmer">>($farmyardName, to tend to the crops),
 		<<case "be the Wardeness">>($cellblockName, to oversee the inmates),
 		<<case "be your Concubine">>(your bed),
 		<<case "be the Nurse">>($clinicName, to check on the patients),
diff --git a/src/uncategorized/costsReport.tw b/src/uncategorized/costsReport.tw
index 71acb6f942c242ce81e7ef69fd797dc0d9050f71..18fac0b47ff03305456796fa86ea478344ea1ae3 100644
--- a/src/uncategorized/costsReport.tw
+++ b/src/uncategorized/costsReport.tw
@@ -817,7 +817,7 @@ $nursery > 0 || $masterSuiteUpgradePregnancy > 0 || $incubator > 0 ||
 <<set _total = 0>> <<set _SL = $slaves.length>>
 <<for $i = 0; $i < _SL; $i++>>
 	<<capture $i>>
-	<br style="clear:both" /><<if $lineSeparations == 0>><br><<else>><hr style="margin:0"><</if>>
+	<br style="clear:both"><<if $lineSeparations == 0>><br><<else>><hr style="margin:0"><</if>>
 	[[$slaves[$i].slaveName|Slave Interact][$activeSlave = $slaves[$i]]] will $slaves[$i].assignment.
 	<<SlaveExpenses $slaves[$i]>>
 	<</capture>>
diff --git a/src/uncategorized/costsReportSlaves.tw b/src/uncategorized/costsReportSlaves.tw
index 68276158fa87dfcb7adb8d0ab89bb9287d745226..3399fecd92dfe8a6509c01412263bd4e8a05718d 100644
--- a/src/uncategorized/costsReportSlaves.tw
+++ b/src/uncategorized/costsReportSlaves.tw
@@ -6,7 +6,7 @@
 <<set _total = 0>> <<set _SL = $slaves.length>>
 <<for $i = 0; $i < _SL; $i++>>
 	<<capture $i>>
-	<br style="clear:both" /><<if $lineSeparations == 0>><br><<else>><hr style="margin:0"><</if>>
+	<br style="clear:both"><<if $lineSeparations == 0>><br><<else>><hr style="margin:0"><</if>>
 	[[$slaves[$i].slaveName|Slave Interact][$activeSlave = $slaves[$i]]] will $slaves[$i].assignment.
 	<<SlaveExpenses $slaves[$i]>>
 	<</capture>>
diff --git a/src/uncategorized/matchmaking.tw b/src/uncategorized/matchmaking.tw
index b10c5694b3e965c9f6986216ff474d51b5121702..dd884f98f2f89e5d5ab15c90e087add69e27bc40 100644
--- a/src/uncategorized/matchmaking.tw
+++ b/src/uncategorized/matchmaking.tw
@@ -378,7 +378,7 @@ Despite $his devotion and trust, $he is still a slave, and probably knows that $
 <</if>>
 */
 
-<<if $seeImages == 1>><br style="clear:both" /><</if>>
+<<if $seeImages == 1>><br style="clear:both"><</if>>
 
 <br><br>__Put $him with another worshipful <<if $eventSlave.relationship == -2>>emotionally bonded slave<<else>>emotional slut<</if>>:__
 <<set $Flag = 1>>
diff --git a/src/uncategorized/options.tw b/src/uncategorized/options.tw
index 1c7c4fb5bbe624165e3cbd59ce83926c2c93674d..dde2ff781bdf5821fd11a45ddc39a616e08159b7 100644
--- a/src/uncategorized/options.tw
+++ b/src/uncategorized/options.tw
@@ -196,7 +196,7 @@ Main menu slave tabs are
 	<</if>>
 <</if>>
 
-<br />
+<br>
 
 The slave Quick list in-page scroll-to is
 <<if $useSlaveListInPageJSNavigation != 1>>
@@ -254,7 +254,7 @@ Master Suite report details such as slave changes are
 <</if>>
 
 /* Accordion 000-250-006 */
-<br />
+<br>
 	Accordion effects on weekly reports are
 <<if ($useAccordion != 1)>>
 	@@.red;DISABLED.@@ [[Enable|Options][$useAccordion = 1]]
diff --git a/src/uncategorized/repBudget.tw b/src/uncategorized/repBudget.tw
index f539894bc0a2fa5cbd32f5e4658d66364d92e83b..6f86fe8de1ebfc179d8e8b4123e6c7793b98adae 100644
--- a/src/uncategorized/repBudget.tw
+++ b/src/uncategorized/repBudget.tw
@@ -14,7 +14,7 @@
 <br>
 //Reputation is a difficult thing to quantify, <<= properTitle()>>.  Here you see an overview of topics that interest people in the arcology, and in turn, reflect on your own reputation.  The more symbols you see in a category, the more impact that category is having on your reputation lately.//
 
-<br style="clear:both" /><<if $lineSeparations == 0>><br><<else>><hr style="margin:0"><</if>>
+<br style="clear:both"><<if $lineSeparations == 0>><br><<else>><hr style="margin:0"><</if>>
 <br>
 //Your weekly reputation changes are as follows://
 
diff --git a/src/uncategorized/seRetirement.tw b/src/uncategorized/seRetirement.tw
index 1e7675c756ae94c3146d47e68ec00a4433543e28..1ecab00f1cff96ed80a9cac3b81db3777390212a 100644
--- a/src/uncategorized/seRetirement.tw
+++ b/src/uncategorized/seRetirement.tw
@@ -210,7 +210,7 @@ Your arcology has gained a well-off citizen.
 	<</if>>
 	<</replace>>
 <</link>>
-<br />
+<br>
 <<if _clonedSlave.relationship >= 4>>
 <<link "Send $his _girl2 into retirement with $him">>
 	<<replace "#artFrame">>
diff --git a/src/utility/descriptionWidgetsStyle.tw b/src/utility/descriptionWidgetsStyle.tw
index 332c39fd64a2c10ea4c1dfdb09e46041161a8585..2b0b582edda330f37207b01447bd35e48c6a45e8 100644
--- a/src/utility/descriptionWidgetsStyle.tw
+++ b/src/utility/descriptionWidgetsStyle.tw
@@ -2532,7 +2532,7 @@ $His
 		<<case "a string bikini" "cutoffs and a t-shirt" "a schoolgirl outfit" "a slutty maid outfit" "striped panties">>
 			is curled into long flowing locks secured by hair ties with plastic buttons, bearing the garish inscription
 			<<InscripDesc>>
-		<<case "a scalemail bikini"
+		<<case "a scalemail bikini">>
 			is curled into long flowing locks, and topped by a gold headband.
 		<<case "battledress">>
 			is curled into floor-length locks secured by paracord.
@@ -2606,7 +2606,7 @@ $His
 		<<case "a string bikini" "cutoffs and a t-shirt" "a schoolgirl outfit" "a slutty maid outfit" "striped panties">>
 			is curled into long locks secured by hair ties with plastic buttons, bearing the garish inscription
 			<<InscripDesc>>
-		<<case "a scalemail bikini"
+		<<case "a scalemail bikini">>
 			is curled into long flowing locks, and topped by a gold headband.
 		<<case "battledress">>
 			is curled into long locks, secured by paracord.
@@ -2680,7 +2680,7 @@ $His
 		<<case "a string bikini" "cutoffs and a t-shirt" "a schoolgirl outfit" "a slutty maid outfit" "striped panties">>
 			is curled into short locks secured by hair ties with plastic buttons, bearing the garish inscription
 			<<InscripDesc>>
-		<<case "a scalemail bikini"
+		<<case "a scalemail bikini">>
 			is curled into short flowing locks, and topped by a gold headband.
 		<<case "battledress">>
 			is curled into short locks secured by paracord.