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