def MakeInitRule(game_name, role, init_conds, fact_rules, min_success_score):
    sp = MakeTemplateProduction("init-%s" % game_name, "propose", "")
    sp.add_attrib(sp.get_state_id(), "superstate", "nil")
    sp.add_neg_attrib(sp.get_state_id(), "name", "")
    op_id = sp.add_operator_prop("init-%s" % game_name, "+ >")

    asp = MakeApplyRule(sp)

    asp.add_create_constant(asp.get_state_id(), 'name', game_name)
    asp.add_create_constant(asp.get_state_id(), 'next-action', '0')

    asp.add_create_id(asp.get_state_id(), 'desired')

    gs_id = asp.add_create_id(asp.get_state_id(), 'gs')
    fact_id = asp.add_create_id(asp.get_state_id(), 'facts')
    #	game_elabs_var = state_action.add_id_wme_action("elaborations")
    asp.add_create_constant(gs_id, 'action-counter', '0')

    if role == "":
        print "Warning: No role defined"
    else:
        asp.add_create_constant(gs_id, 'role', role)

    var_map = GDLSoarVarMapper(UniqueNameGenerator())
    for ic in init_conds:
        ic.head().make_soar_actions(asp, var_map)

    for f in fact_rules:
        f.head().make_soar_actions(asp, var_map)
    return [sp, asp]
    def __init__(self, name, state_name):
        #		if name == 'apply*remove-_next__holding__std_soar_var0__':
        #			pdb.set_trace()
        self.__name = name
        self.__state_name = state_name
        self.__name_gen = UniqueNameGenerator()
        self.__state_id = self.__name_gen.get_name("s")

        self.__top_conj = Conjunction.MakeTopConjunction(
            self.__state_id, self.__name_gen)
        if state_name != '':
            self.__top_conj.add_attrib(self.__state_id, "name", state_name)
        self.__curr_conj = self.__top_conj

        self.__create_id_actions = {}  # id -> [(attrib, id, prefs)]
        self.__actions = {}  # id -> [(attrib, rhs, action)]
        self.__new_ids = []  # ids created by actions
        self.__rhs_funcs = []
	def __init__(self, name, state_name):
#		if name == 'apply*remove-_next__holding__std_soar_var0__':
#			pdb.set_trace()
		self.__name = name
		self.__state_name = state_name
		self.__name_gen = UniqueNameGenerator()
		self.__state_id = self.__name_gen.get_name("s")
		
		self.__top_conj = Conjunction.MakeTopConjunction(self.__state_id, self.__name_gen)
		if state_name != '':
			self.__top_conj.add_attrib(self.__state_id, "name", state_name)
		self.__curr_conj = self.__top_conj

		self.__create_id_actions = {} # id -> [(attrib, id, prefs)]
		self.__actions = {} # id -> [(attrib, rhs, action)]
		self.__new_ids = [] # ids created by actions
		self.__rhs_funcs = []
class SoarProd:
    def __init__(self, name, state_name):
        #		if name == 'apply*remove-_next__holding__std_soar_var0__':
        #			pdb.set_trace()
        self.__name = name
        self.__state_name = state_name
        self.__name_gen = UniqueNameGenerator()
        self.__state_id = self.__name_gen.get_name("s")

        self.__top_conj = Conjunction.MakeTopConjunction(
            self.__state_id, self.__name_gen)
        if state_name != '':
            self.__top_conj.add_attrib(self.__state_id, "name", state_name)
        self.__curr_conj = self.__top_conj

        self.__create_id_actions = {}  # id -> [(attrib, id, prefs)]
        self.__actions = {}  # id -> [(attrib, rhs, action)]
        self.__new_ids = []  # ids created by actions
        self.__rhs_funcs = []

    def copy(self, name):
        c = SoarProd(name, self.__state_name)
        c.__name_gen = self.__name_gen.copy()
        c.__state_id = self.__state_id
        c.__top_conj = self.__top_conj.copy(None, c.__name_gen)
        c.__curr_conj = c.__top_conj  # dangerous?

        for id, id_actions in self.__create_id_actions:
            c.__create_id_actions[id] = id_actions[:]
        for id, actions in self.__actions:
            c.__actions[id] = actions[:]

        c.__new_ids = self.__new_ids[:]
        c.__rhs_funcs = self.__rhs_funcs[:]

        return c

    def get_name(self):
        return self.__name

    def get_state_id(self):
        return self.__state_id

    def get_state_name(self):
        return self.__state_name

    def get_name_gen(self):
        return self.__name_gen

    def add_predicate(self, id, predicate, rhs):
        self.__curr_conj.add_predicate(id, predicate, rhs)

    def add_id_attrib(self, id, attrib, name=""):
        assert attrib[0] != '<', 'Use new system to add variable attributes'
        return self.__curr_conj.add_id_attrib(id, attrib, name)

    def add_id_var_attrib(self, id, var_attrib, name=""):
        return self.__curr_conj.add_id_var_attrib(id, var_attrib, name)

    def add_id_attrib_chain(self, id, attrib_chain):
        return self.__curr_conj.add_id_attrib_chain(id, attrib_chain)

    def get_ids(self, lhs_id, attrib):
        return self.__curr_conj.get_ids(lhs_id, attrib)

    def get_ids_by_chain(self, attrib_chain):
        return self.__top_conj.get_ids_by_chain(self.__state_id, attrib_chain)

    def get_or_make_id_chain(self, attrib_chain):
        return self.__top_conj.get_or_make_id_chain(self.__state_id,
                                                    attrib_chain)

    def get_or_make_id_chain_existing(self, attrib_chain):
        return self.__top_conj.get_or_make_id_chain_existing(
            self.__state_id, attrib_chain)

    def add_attrib(self, id, attrib, rhs):
        self.__curr_conj.add_attrib(id, attrib, rhs)

# actions

    def add_action(self, id, attrib, rhs, action):
        assert id in self.__top_conj.get_all_ids(
        ) or id in self.__new_ids, "Unknown identifier %s" % id
        self.__actions.setdefault(id, []).append((attrib, rhs, action))

    def add_create_id(self, id, attrib, name="", prefs=""):
        assert id in self.__top_conj.get_all_ids(
        ) or id in self.__new_ids, "Unknown identifier %s" % id
        if name != "":
            assert name in self.__top_conj.get_all_ids(
            ) or id in self.__new_ids, "Unknown identifier %s" % id
            self.__create_id_actions.setdefault(id, []).append(
                (attrib, name, prefs))
            return name
        else:
            new_id = self.__name_gen.get_name(attrib[0])
            self.__create_id_actions.setdefault(id, []).append(
                (attrib, new_id, prefs))
            self.__new_ids.append(new_id)
            return new_id

    def get_new_ids_by_chain(self, lhs_id, attrib_chain):
        curr_ids = [lhs_id]
        for attrib in attrib_chain:
            next_ids = []
            for id in curr_ids:
                create_actions = self.__create_id_actions.get(id, [])
                for c_attrib, c_id, prefs in create_actions:
                    if c_attrib == attrib:
                        next_ids.append(c_id)
            if len(next_ids) == 0:
                return []
            curr_ids = next_ids
        return curr_ids

    def add_rhs_func_call(self, function):
        self.__rhs_funcs.append(function)

    def begin_negative_conjunction(self):
        self.__curr_conj = self.__curr_conj.add_child(True)

    def end_negative_conjunction(self):
        self.__curr_conj = self.__curr_conj.get_parent()

    # convenience functions
    def add_neg_id_attrib(self, id, attrib):
        self.begin_negative_conjunction()
        new_id = self.add_id_attrib(id, attrib)
        self.end_negative_conjunction()
        return new_id

    def add_neg_attrib(self, id, attrib, rhs):
        self.begin_negative_conjunction()
        new_id = self.add_attrib(id, attrib, rhs)
        self.end_negative_conjunction()
        return new_id

    def add_bound_id_attrib(self, lhs_id, attrib, rhs_id):
        assert self.__curr_conj.id_in_scope(rhs_id)
        self.add_attrib(lhs_id, attrib, '<%s>' % rhs_id)

    def add_id_predicate(self, lhs_id, predicate, rhs_id):
        self.__curr_conj.add_predicate(lhs_id, predicate, mvar(rhs_id))

    def add_destroy_id(self, lhs_id, attrib, rhs_id):
        self.add_action(lhs_id, attrib, mvar(rhs_id), '-')

    def add_create_bound_id(self, lhs_id, attrib, rhs_id):
        self.add_action(lhs_id, attrib, mvar(rhs_id), '')

    def add_create_constant(self, id, attrib, const):
        self.add_action(id, attrib, const, '')

    def add_destroy_constant(self, id, attrib, const):
        self.add_action(id, attrib, const, '-')

    def add_operator_pref(self, op_id, prefs):
        self.add_action(self.__state_id, "operator", mvar(op_id), prefs)

    def add_operator_prop(self, name, prefs='+'):
        op_id = self.add_create_id(self.__state_id, 'operator', prefs=prefs)
        self.add_create_constant(op_id, 'name', name)
        return op_id

    def add_operator_test(self, op_name):
        op_id = self.add_id_attrib(self.__state_id, 'operator')
        self.add_attrib(op_id, 'name', op_name)

    def get_proposed_op_names(self):
        op_names = []
        for attrib, op_id, pref in self.__create_id_actions.get(
                self.__state_id, []):
            if attrib == "operator" and '+' in pref:
                # find the name
                op_elabs = self.__actions[op_id]
                name_found = False
                for attrib2, rhs2, action2 in op_elabs:
                    if attrib2 == 'name':
                        op_names.append(rhs2)
                        name_found = True
                        break
                assert name_found, "Operator proposed without name"
        return op_names

    def __str__(self):
        indentstr = ' ' * 3
        s = "sp {%s\n" % self.__name
        s += self.__top_conj.to_str(0, self.__state_id) + "\n"
        s += "-->\n"

        for id, actions in self.__actions.items():
            s += indentstr + "(%s" % mvar(id)
            for attrib, rhs, act in actions:
                s += " ^%s %s %s" % (attrib, rhs, act)
            s += ")\n"

        for id, actions in self.__create_id_actions.items():
            s += indentstr + "(%s" % mvar(id)
            for attrib, rhs_id, pref in actions:
                s += " ^%s %s %s" % (attrib, mvar(rhs_id), pref)
            s += ")\n"

        for func in self.__rhs_funcs:
            s += indentstr + "(%s)\n" % func
        s += '}'
        return s
from UniqueNameGen import UniqueNameGenerator
from SoarProd import *
from ElementGGP import ElementGGP as ElemGGP
from GGPRule import GGPRule
from GGPSentence import GGPSentence
import re
import ElementGGP
import pdb
from Comparison import Comparison

name_gen = UniqueNameGenerator()

rule_index = 0


def SentenceIsComp(sentence):
    Comparison_Ops = ['distinct', '<', '>', '>=']
    return sentence.name() in Comparison_Ops


def same_signature(sent1, sent2):
    if sent1.name() != sent2.name():
        return False

    if sent1.num_terms() != sent2.num_terms():
        return False

    for i in range(sent1.num_terms()):
        if (sent1.term(i).type() == 'function') ^ (sent2.term(i).type()
                                                   == 'function'):
            return False
class SoarProd:
	def __init__(self, name, state_name):
#		if name == 'apply*remove-_next__holding__std_soar_var0__':
#			pdb.set_trace()
		self.__name = name
		self.__state_name = state_name
		self.__name_gen = UniqueNameGenerator()
		self.__state_id = self.__name_gen.get_name("s")
		
		self.__top_conj = Conjunction.MakeTopConjunction(self.__state_id, self.__name_gen)
		if state_name != '':
			self.__top_conj.add_attrib(self.__state_id, "name", state_name)
		self.__curr_conj = self.__top_conj

		self.__create_id_actions = {} # id -> [(attrib, id, prefs)]
		self.__actions = {} # id -> [(attrib, rhs, action)]
		self.__new_ids = [] # ids created by actions
		self.__rhs_funcs = []
	
	def copy(self, name):
		c = SoarProd(name, self.__state_name)
		c.__name_gen = self.__name_gen.copy()
		c.__state_id = self.__state_id
		c.__top_conj = self.__top_conj.copy(None, c.__name_gen)
		c.__curr_conj = c.__top_conj # dangerous?

		for id, id_actions in self.__create_id_actions:
			c.__create_id_actions[id] = id_actions[:]
		for id, actions in self.__actions:
			c.__actions[id] = actions[:]

		c.__new_ids = self.__new_ids[:]
		c.__rhs_funcs = self.__rhs_funcs[:]

		return c

	def get_name(self):
		return self.__name

	def get_state_id(self):
		return self.__state_id

	def get_state_name(self):
		return self.__state_name

	def get_name_gen(self):
		return self.__name_gen

	def add_predicate(self, id, predicate, rhs):
		self.__curr_conj.add_predicate(id, predicate, rhs)
	
	def add_id_attrib(self, id, attrib, name = ""):
		assert attrib[0] != '<', 'Use new system to add variable attributes'
		return self.__curr_conj.add_id_attrib(id, attrib, name)

	def add_id_var_attrib(self, id, var_attrib, name = ""):
		return self.__curr_conj.add_id_var_attrib(id, var_attrib, name)
	
	def add_id_attrib_chain(self, id, attrib_chain):
		return self.__curr_conj.add_id_attrib_chain(id, attrib_chain)
	
	def get_ids(self, lhs_id, attrib):
		return self.__curr_conj.get_ids(lhs_id, attrib)

	def get_ids_by_chain(self, attrib_chain):
		return self.__top_conj.get_ids_by_chain(self.__state_id, attrib_chain)

	def get_or_make_id_chain(self, attrib_chain):
		return self.__top_conj.get_or_make_id_chain(self.__state_id, attrib_chain)

	def get_or_make_id_chain_existing(self, attrib_chain):
		return self.__top_conj.get_or_make_id_chain_existing(self.__state_id, attrib_chain)

	def add_attrib(self, id, attrib, rhs):
		self.__curr_conj.add_attrib(id, attrib, rhs)

# actions

	def add_action(self, id, attrib, rhs, action):
		assert id in self.__top_conj.get_all_ids() or id in self.__new_ids, "Unknown identifier %s" % id
		self.__actions.setdefault(id, []).append((attrib, rhs, action))

	def add_create_id(self, id, attrib, name = "", prefs = ""):
		assert id in self.__top_conj.get_all_ids() or id in self.__new_ids, "Unknown identifier %s" % id
		if name != "":
			assert name in self.__top_conj.get_all_ids() or id in self.__new_ids, "Unknown identifier %s" % id
			self.__create_id_actions.setdefault(id, []).append((attrib, name, prefs))
			return name
		else:
			new_id = self.__name_gen.get_name(attrib[0])
			self.__create_id_actions.setdefault(id, []).append((attrib, new_id, prefs))
			self.__new_ids.append(new_id)
			return new_id

	def get_new_ids_by_chain(self, lhs_id, attrib_chain):
		curr_ids = [lhs_id]
		for attrib in attrib_chain:
			next_ids = []
			for id in curr_ids:
				create_actions = self.__create_id_actions.get(id, [])
				for c_attrib, c_id, prefs in create_actions:
					if c_attrib == attrib:
						next_ids.append(c_id)
			if len(next_ids) == 0:
				return []
			curr_ids = next_ids
		return curr_ids
	
	def add_rhs_func_call(self, function):
		self.__rhs_funcs.append(function)

	def begin_negative_conjunction(self):
		self.__curr_conj = self.__curr_conj.add_child(True)

	def end_negative_conjunction(self):
		self.__curr_conj = self.__curr_conj.get_parent()

	# convenience functions
	def add_neg_id_attrib(self, id, attrib):
		self.begin_negative_conjunction()
		new_id = self.add_id_attrib(id, attrib)
		self.end_negative_conjunction()
		return new_id

	def add_neg_attrib(self, id, attrib, rhs):
		self.begin_negative_conjunction()
		new_id = self.add_attrib(id, attrib, rhs)
		self.end_negative_conjunction()
		return new_id

	def add_bound_id_attrib(self, lhs_id, attrib, rhs_id):
		assert self.__curr_conj.id_in_scope(rhs_id)
		self.add_attrib(lhs_id, attrib, '<%s>' % rhs_id)

	def add_id_predicate(self, lhs_id, predicate, rhs_id):
		self.__curr_conj.add_predicate(lhs_id, predicate, mvar(rhs_id))

	def add_destroy_id(self, lhs_id, attrib, rhs_id):
		self.add_action(lhs_id, attrib, mvar(rhs_id), '-')
	
	def add_create_bound_id(self, lhs_id, attrib, rhs_id):
		self.add_action(lhs_id, attrib, mvar(rhs_id), '')

	def add_create_constant(self, id, attrib, const):
		self.add_action(id, attrib, const, '')

	def add_destroy_constant(self, id, attrib, const):
		self.add_action(id, attrib, const, '-')
	
	def add_operator_pref(self, op_id, prefs):
		self.add_action(self.__state_id, "operator", mvar(op_id), prefs)
	
	def add_operator_prop(self, name, prefs = '+'):
		op_id = self.add_create_id(self.__state_id, 'operator', prefs = prefs)
		self.add_create_constant(op_id, 'name', name)
		return op_id

	def add_operator_test(self, op_name):
		op_id = self.add_id_attrib(self.__state_id, 'operator')
		self.add_attrib(op_id, 'name', op_name)

	def get_proposed_op_names(self):
		op_names = []
		for attrib, op_id, pref in self.__create_id_actions.get(self.__state_id, []):
			if attrib == "operator" and '+' in pref:
				# find the name
				op_elabs = self.__actions[op_id]
				name_found = False
				for attrib2, rhs2, action2 in op_elabs:
					if attrib2 == 'name':
						op_names.append(rhs2)
						name_found = True
						break
				assert name_found, "Operator proposed without name"
		return op_names

	def __str__(self):
		indentstr = ' ' * 3
		s = "sp {%s\n" % self.__name
		s += self.__top_conj.to_str(0, self.__state_id) + "\n"
		s +="-->\n"

		for id, actions in self.__actions.items():
			s += indentstr + "(%s" % mvar(id)
			for attrib, rhs, act in actions:
				s += " ^%s %s %s" % ( attrib, rhs, act)
			s += ")\n"

		for id, actions in self.__create_id_actions.items():
			s += indentstr + "(%s" % mvar(id)
			for attrib, rhs_id, pref in actions:
				s += " ^%s %s %s" % ( attrib, mvar(rhs_id), pref)
			s += ")\n"

		for func in self.__rhs_funcs:
			s += indentstr + "(%s)\n" % func
		s += '}'
		return s