In previous part, we talked about unification algorithm and using logic statements as game states. However before we move on to the algorithm itself, we first need to lay the foundation. Here we will start with the **axiom**.

Axioms are units of logic that represent a single fact about the word. Following the example from the previous part, `cat(whiskers)`

is one of these facts. In this axiom “cat” is the **predicate** and “whiskers” is one and only **term**. As mentioned before meanings of these predicate-term coupling is determined by how you design your problem domain. This is not important for now. We must first understand rules of an axiom and how we will use them in Unity.

- An
**axiom**has a single**predicate**and at least one**term** - Terms can be primitives like int, float etc.
- Terms can be objects like string, GameObject etc.
- Terms can be unknown
**variables**. - Existence of an
**axiom**in the**game state**means that axiom is true. If a axiom is not in the game state, then it is false.

In a strict mathematical sense, axioms themselves are also terms but I am not interested in the correct nomenclature at this point. Lets start with our code.

public class Axiom { public readonly string Name; public readonly Term[] Terms; public readonly Type[] Types; public Axiom(string name, Type[] types, params object[] terms) { Name = name; Types = types; Terms = new Term[terms.Length]; for (int i=0; i<terms.Length; i++) { object termValue = terms[i]; Type ttt = typeof(Term<>).MakeGenericType (Types [i]); Terms [i] = (Term)Activator.CreateInstance ( typeof(Term<>).MakeGenericType( Types[i] ), termValue); } } public override string ToString () { string str = ""; Array.ForEach<Term> (Terms, delegate(Term obj) { str += obj + ", "; }); return string.Format ("{0} -> {1}", Name, str ); } }

In code above we have defined an axiom class that takes 3 parameters to its constructor. First parameter `name `

is actually the predicate. I have used a different wording since C# already has a Predicate class and I didn’t want that to confuse users. Second and third parameters are array of Types and their respective values. In other implementations like Prolog, terms are not strongly typed. I personally prefer to work on strongly typed code. You will see in next part in fact, I extend this axiom class to create strongly typed axiom definitions as well. Unification algorithm may work without strongly typed terms if you prefer to code it that way.

The constructor simply records the values given in readonly fields. I have made axioms immutable. These axioms will be passed around between various systems including realtime behaviours, AI solvers, persistent storage. Having mutable axioms can be an recipe for disaster as users may modify what they shouldn’t willy nilly.

You will see that there is a missing class Term used in the constructor. This is the class that manages Type of a term and whether that term is bound to a value or is an unbounded variable. Lets see what this class looks like.

public abstract class Term { public enum STATUS { UNBOUND, BOUND } public STATUS Status{ get{ return internalStatus; }} protected STATUS internalStatus; public readonly object ValueObject; public readonly Type ValueType; protected Term(Type valueType, object valueObject) { if (valueObject is Binding) { internalStatus = STATUS.UNBOUND; }else{ internalStatus = STATUS.BOUND; } ValueType = valueType; ValueObject = valueObject; } public override string ToString () { return ""+ValueObject; } } public class Term<T>:Term { public Term(IBindable<T> value):base(typeof(IBindable<T>), value) { } }

Here you can see that I have an abstract class for Term and an inherited class Term<T> with generic type T. This is part of my previous decision to implement a strongly typed system. Terms are immutable just like Axioms. So how do we work with them?

- Game State As Logic Statements [Part 1]
**Atoms of Logical Expressions [Part 2]**- Unification [Part 3]
- Test Cases [Part 4]
- Persistense [Part 5]