def MakeApplyRule(sp):
    op_names = sp.get_proposed_op_names()

    assert len(op_names) > 0, "Operator doesn't propose any operators"
    assert len(op_names) == 1, "Proposing more than one operator with one rule"

    prod_name = sp.get_name().replace('propose', 'apply')
    ap = SoarProd(prod_name, sp.get_state_name())
    ap.add_operator_test(op_names[0])
    return ap
def MakeApplyRule(sp):
	op_names = sp.get_proposed_op_names()

	assert len(op_names) > 0, "Operator doesn't propose any operators"
	assert len(op_names) == 1, "Proposing more than one operator with one rule"

	prod_name = sp.get_name().replace('propose', 'apply')
	ap = SoarProd(prod_name, sp.get_state_name())
	ap.add_operator_test(op_names[0])
	return ap
def MakeTemplateProduction(name, type="", game_name='game'):
    if type != "":
        prod_name = name_gen.get_name("%s*%s" % (type, name))
    else:
        prod_name = name_gen.get_name(name)
    p = SoarProd(prod_name, game_name)
    return p
def HandleMath(maths, head, base_prod, var_map, rule_index, state_name):

    # build a map of result variables to the calculation index
    # that generated it
    result_vars = {}  # var -> index
    for i, m in enumerate(maths):
        assert m.num_terms(
        ) == 3, 'Math condition only has %d terms' % m.num_terms()
        rvar = m.term(2)
        assert rvar.type() == 'variable', 'Math result not variable'
        assert rvar not in result_vars, 'Two math results share the same variable'
        result_vars[rvar] = i

    # resolve interdependencies among calculations
    deps = {}  # index -> [index]
    for i, m in enumerate(maths):
        for t in [0, 1]:
            if m.term(t).type() == 'variable' and m.term(t) in result_vars:
                deps.setdefault(i, []).append(result_vars[m.term(t)])
            else:
                deps.setdefault(i, []).append(-1)

    # create intermediate productions
    int_prods = []
    for i, m in enumerate(maths):
        math_code = 'math-%d-%d' % (rule_index, i)
        # make a production to create the <s> ^math.math-x-y structure
        mk_struct_prod = SoarProd(
            name_gen.get_name('elaborate*%s-make-%s-struct' %
                              (SoarifyStr(str(head)), math_code)), state_name)
        math_id = mk_struct_prod.get_or_make_id_chain(['math'])[0]
        mk_struct_prod.add_create_id(math_id, math_code)
        int_prods.append(mk_struct_prod)

        # make the production for the actual operator
        prod_name = name_gen.get_name(base_prod.get_name() +
                                      SoarifyStr(str(m)))
        prod = base_prod.copy(prod_name)
        var_map1 = var_map.copy(prod.get_name_gen())
        # add conditions to bind the ids for the operands
        ops = []  # [(name, 0/1 (0 = constant, 1 = variable))]
        for j, d in enumerate(deps[i]):
            if d >= 0:
                # have to get this operand from an intermediate result
                ops.append((GetMathRes(maths, prod, var_map1, deps, d,
                                       rule_index), 1))
            else:
                if m.term(j).type() == 'variable':
                    # get this from a regular condition
                    assert m.term(j).name(
                    ) in var_map1, "There appears to be an unbound variable %s" % m.term(
                        j).name()
                    ops.append((var_map1.get_var(m.term(j).name()), 1))
                else:
                    # constant
                    ops.append((str(m.term(j)), 0))

        # make an action to put this op,op,result triplet on the state
        math_id = prod.get_or_make_id_chain_existing(['math', math_code])[0]
        query_id = prod.add_create_id(math_id, 'query-link')
        op_strs = []
        for j in [0, 1]:
            if ops[j][1] == 1:
                # id
                prod.add_create_bound_id(query_id, 'op%d' % j, ops[j][0])
                op_strs.append('<%s>' % ops[j][0])
            else:
                # const
                prod.add_create_constant(query_id, 'op%d' % j, ops[j][0])
                op_strs.append(ops[j][0])

        prod.add_create_constant(
            query_id, 'res', '(%s %s %s)' % (m.name(), op_strs[0], op_strs[1]))
        int_prods.append(prod)

    # modify body of base production to test for necessary calculations
    used = []
    for v, i in result_vars.items():
        GetMathRes(maths, base_prod, var_map, deps, i, rule_index, used)

    return int_prods
def HandleMath(maths, head, base_prod, var_map, rule_index, state_name):

	# build a map of result variables to the calculation index
	# that generated it
	result_vars = {} # var -> index
	for i, m in enumerate(maths):
		assert m.num_terms() == 3, 'Math condition only has %d terms' % m.num_terms()
		rvar = m.term(2)
		assert rvar.type() == 'variable', 'Math result not variable'
		assert rvar not in result_vars, 'Two math results share the same variable'
		result_vars[rvar] = i
	
	# resolve interdependencies among calculations
	deps = {} # index -> [index]
	for i, m in enumerate(maths):
		for t in [0,1]:
			if m.term(t).type() == 'variable' and m.term(t) in result_vars:
				deps.setdefault(i, []).append(result_vars[m.term(t)])
			else:
				deps.setdefault(i, []).append(-1)

	# create intermediate productions
	int_prods = []
	for i, m in enumerate(maths):
		math_code = 'math-%d-%d' % (rule_index, i)
		# make a production to create the <s> ^math.math-x-y structure
		mk_struct_prod = SoarProd(name_gen.get_name('elaborate*%s-make-%s-struct' % (SoarifyStr(str(head)), math_code)), state_name)
		math_id = mk_struct_prod.get_or_make_id_chain(['math'])[0]
		mk_struct_prod.add_create_id(math_id, math_code)
		int_prods.append(mk_struct_prod)
		
		# make the production for the actual operator
		prod_name = name_gen.get_name(base_prod.get_name() + SoarifyStr(str(m)))
		prod = base_prod.copy(prod_name)
		var_map1 = var_map.copy(prod.get_name_gen())
		# add conditions to bind the ids for the operands
		ops = [] # [(name, 0/1 (0 = constant, 1 = variable))]
		for j, d in enumerate(deps[i]):
			if d >= 0:
				# have to get this operand from an intermediate result
				ops.append((GetMathRes(maths, prod, var_map1, deps, d, rule_index), 1))
			else:
				if m.term(j).type() == 'variable':
					# get this from a regular condition
					assert m.term(j).name() in var_map1, "There appears to be an unbound variable %s" % m.term(j).name()
					ops.append((var_map1.get_var(m.term(j).name()), 1))
				else:
					# constant
					ops.append((str(m.term(j)), 0))

		# make an action to put this op,op,result triplet on the state
		math_id = prod.get_or_make_id_chain_existing(['math', math_code])[0]
		query_id = prod.add_create_id(math_id, 'query-link')
		op_strs = []
		for j in [0,1]:
			if ops[j][1] == 1:
				# id
				prod.add_create_bound_id(query_id, 'op%d' % j, ops[j][0])
				op_strs.append('<%s>' % ops[j][0])
			else:
				# const
				prod.add_create_constant(query_id, 'op%d' % j, ops[j][0])
				op_strs.append(ops[j][0])
				
		prod.add_create_constant(query_id, 'res', '(%s %s %s)' % (m.name(), op_strs[0], op_strs[1]))
		int_prods.append(prod)
	
	# modify body of base production to test for necessary calculations
	used = []
	for v, i in result_vars.items():
		GetMathRes(maths, base_prod, var_map, deps, i, rule_index, used)
	
	return int_prods