Esempio n. 1
0
/**
 * Gets all attribute names of an extended variable name. This is useful for tab completion.
 */
std::vector<std::string> lua_kernel_base::get_attribute_names(const std::string & input)
{
	std::vector<std::string> ret;
	std::string base_path = input;
	size_t last_dot = base_path.find_last_of('.');
	std::string partial_name = base_path.substr(last_dot + 1);
	base_path.erase(last_dot);
	std::string load = "return " + base_path;

	lua_State* L = mState;
	int save_stack = lua_gettop(L);
	int result = luaL_loadstring(L, load.c_str());
	if(result != LUA_OK) {
		// This isn't at error level because it's a really low priority error; it just means the user tried to tab-complete something that doesn't exist.
		LOG_LUA << "Error when attempting tab completion:\n";
		LOG_LUA << luaL_checkstring(L, -1) << '\n';
		// Just return an empty list; no matches were found
		lua_settop(L, save_stack);
		return ret;
	}

	luaW_pcall(L, 0, 1);
	if(lua_istable(L, -1) || lua_isuserdata(L, -1)) {
		int top = lua_gettop(L);
		int obj = lua_absindex(L, -1);
		if(luaL_getmetafield(L, obj, "__tab_enum") == LUA_TFUNCTION) {
			lua_pushvalue(L, obj);
			lua_pushlstring(L, partial_name.c_str(), partial_name.size());
			luaW_pcall(L, 2, 1);
			ret = lua_check<std::vector<std::string>>(L, -1);
		} else {
			lua_settop(L, top);
			// Metafunction not found, so use lua_next to enumerate the table
			for(lua_pushnil(L); lua_next(L, obj); lua_pop(L, 1)) {
				if(lua_isstring(L, -2)) {
					std::string attr = lua_tostring(L, -2);
					if(attr.empty()) {
						continue;
					}
					if(!isalpha(attr[0]) && attr[0] != '_') {
						continue;
					}
					if(std::any_of(attr.begin(), attr.end(), [](char c){
						return !isalpha(c) && !isdigit(c) && c != '_';
					})) {
						continue;
					}
					if(attr.substr(0, partial_name.size()) == partial_name) {
						ret.push_back(base_path + "." + attr);
					}
				}
			}
		}
	}
	lua_settop(L, save_stack);
	return ret;
}
Esempio n. 2
0
lua_ai_context* lua_ai_context::create(lua_State *L, char const *code, ai::engine_lua *engine)
{
	int res_ai = luaL_loadstring(L, code);//stack size is now 1 [ -1: ai_context]
	if (res_ai)
	{

		char const *m = lua_tostring(L, -1);
		ERR_LUA << "error while initializing ai:  " <<m << '\n';
		lua_pop(L, 2);//return with stack size 0 []
		return NULL;
	}
	//push data table here
	generate_and_push_ai_table(L, engine);

	//compile the ai as a closure
	if (!luaW_pcall(L, 1, 1, true)) {
		return NULL;//return with stack size 0 []
	}

	// Retrieve the ai elements table from the registry.
	lua_pushlightuserdata(L, static_cast<void *>(const_cast<char *>(&aisKey)));
	lua_rawget(L, LUA_REGISTRYINDEX);   //stack size is now 2  [-1: ais_table -2: f]
	// Push the function in the table so that it is not collected.
	size_t length_ai = lua_rawlen(L, -1);//length of ais_table
	lua_pushvalue(L, -2); //stack size is now 3: [-1: ai_context  -2: ais_table  -3: ai_context]
	lua_rawseti(L, -2, length_ai + 1);// ais_table[length+1]=ai_context.  stack size is now 2 [-1: ais_table  -2: ai_context]
	lua_pop(L, 2);
	return new lua_ai_context(L, length_ai + 1, engine->get_readonly_context().get_side());
}
Esempio n. 3
0
void lua_ai_action_handler::handle(config &cfg, bool configOut, lua_object_ptr l_obj)
{
	int initial_top = lua_gettop(L);//get the old stack size

	// Load the user function from the registry.
	lua_pushlightuserdata(L, static_cast<void *>(const_cast<char *>(&aisKey)));//stack size is now 1 [-1: ais_table key]
	lua_rawget(L, LUA_REGISTRYINDEX);//stack size is still 1 [-1: ais_table]
	lua_rawgeti(L, -1, num_);//stack size is 2 [-1: ai_action  -2: ais_table]
	lua_remove(L, -2);//stack size is 1 [-1: ai_action]
	//load the lua ai context as a parameter
	context_.load();//stack size is 2 [-1: ai_context -2: ai_action]

	if (!configOut)
	{
		luaW_pushconfig(L, cfg);
		luaW_pcall(L, 2, 0, true);
	}
	else if (luaW_pcall(L, 1, 5, true)) // @note for Crab: how much nrets should we actually have here
	{				    // there were 2 initially, but aspects like recruitment pattern
		l_obj->store(L, initial_top + 1); // return a lot of results
	}

	lua_settop(L, initial_top);//empty stack
}
Esempio n. 4
0
lua_ai_context* lua_ai_context::create(lua_State *L, char const *code, ai::engine_lua *engine)
{
	int res_ai = luaL_loadstring(L, code);//stack size is now 1 [ -1: ai_context]
	if (res_ai)
	{

		char const *m = lua_tostring(L, -1);
		ERR_LUA << "error while initializing ai:  " <<m << '\n';
		lua_pop(L, 2);//return with stack size 0 []
		return NULL;
	}
	//push data table here
	lua_newtable(L);// stack size is 2 [ -1: new table, -2: ai as string ]
	lua_pushinteger(L, engine->get_readonly_context().get_side());

	lua_setfield(L, -2, "side");//stack size is 2 [- 1: new table; -2 ai as string]

	static luaL_Reg const callbacks[] = {
		{ "attack", 			&cfun_ai_execute_attack			},
		// Move maps
		{ "get_new_dst_src", 		&cfun_ai_get_dstsrc			},
		{ "get_new_src_dst", 		&cfun_ai_get_srcdst			},
		{ "get_new_enemy_dst_src", 	&cfun_ai_get_enemy_dstsrc		},
		{ "get_new_enemy_src_dst", 	&cfun_ai_get_enemy_srcdst		},
		{ "recalculate_move_maps",	&cfun_ai_recalculate_move_maps		},
		{ "recalculate_enemy_move_maps",&cfun_ai_recalculate_move_maps_enemy	},
		// End of move maps
		// Goals and targets
		{ "get_targets",		&cfun_ai_get_targets			},
		// End of G & T
		// Aspects
		{ "get_aggression", 		&cfun_ai_get_aggression           	},
		{ "get_avoid", 			&cfun_ai_get_avoid			},
		{ "get_attack_depth",		&cfun_ai_get_attack_depth		},
		{ "get_attacks",		&cfun_ai_get_attacks			},
		{ "get_caution", 		&cfun_ai_get_caution			},
		{ "get_grouping",		&cfun_ai_get_grouping			},
		{ "get_leader_aggression", 	&cfun_ai_get_leader_aggression		},
		{ "get_leader_goal", 		&cfun_ai_get_leader_goal		},
		{ "get_leader_ignores_keep", &cfun_ai_get_leader_ignores_keep},
		{ "get_leader_value", 		&cfun_ai_get_leader_value		},
		{ "get_number_of_possible_recruits_to_force_recruit", &cfun_ai_get_number_of_possible_recruits_to_force_recruit},
		{ "get_passive_leader", 	&cfun_ai_get_passive_leader		},
		{ "get_passive_leader_shares_keep", &cfun_ai_get_passive_leader_shares_keep},
		{ "get_recruitment_ignore_bad_combat", &cfun_ai_get_recruitment_ignore_bad_combat},
		{ "get_recruitment_ignore_bad_movement", &cfun_ai_get_recruitment_ignore_bad_movement},
		{ "get_recruitment_pattern", 	&cfun_ai_get_recruitment_pattern 	},
		{ "get_scout_village_targeting", &cfun_ai_get_scout_village_targeting	},
		{ "get_simple_targeting", 	&cfun_ai_get_simple_targeting		},
		{ "get_support_villages",	&cfun_ai_get_support_villages		},
		{ "get_village_value",		&cfun_ai_get_village_value		},
		{ "get_villages_per_scout",	&cfun_ai_get_villages_per_scout		},
		// End of aspects
		// Validation/cache functions
		{ "is_dst_src_valid",		&cfun_ai_is_dst_src_valid		},
		{ "is_enemy_dst_src_valid",	&cfun_ai_is_dst_src_enemy_valid		},
		{ "is_src_dst_valid",		&cfun_ai_is_src_dst_valid		},
		{ "is_enemy_src_dst_valid",	&cfun_ai_is_src_dst_enemy_valid		},
		// End of validation functions
		{ "move",             		&cfun_ai_execute_move_partial		},
		{ "move_full",        		&cfun_ai_execute_move_full        	},
		{ "recall",          		&cfun_ai_execute_recall           	},
		{ "recruit",          		&cfun_ai_execute_recruit         	},
		{ "stopunit_all",     		&cfun_ai_execute_stopunit_all     	},
		{ "stopunit_attacks",		&cfun_ai_execute_stopunit_attacks 	},
		{ "stopunit_moves",   		&cfun_ai_execute_stopunit_moves 	},
		{ "suitable_keep",   		&cfun_ai_get_suitable_keep		},
		{ "check_recall",		&cfun_ai_check_recall			},
		{ "check_move",			&cfun_ai_check_move			},
		{ "check_stopunit",		&cfun_ai_check_stopunit			},
		{ "check_attack",		&cfun_ai_check_attack			},
		{ "check_recruit",		&cfun_ai_check_recruit			},
		//{ "",},
		//{ "",},
		{ NULL, NULL }
	};

	for (const luaL_Reg *p = callbacks; p->name; ++p) {
		lua_pushlightuserdata(L, engine);
		lua_pushcclosure(L, p->func, 1);
		lua_setfield(L, -2, p->name);
	}

	//compile the ai as a closure
	if (!luaW_pcall(L, 1, 1, true)) {
		return NULL;//return with stack size 0 []
	}

	// Retrieve the ai elements table from the registry.
	lua_pushlightuserdata(L, static_cast<void *>(const_cast<char *>(&aisKey)));
	lua_rawget(L, LUA_REGISTRYINDEX);   //stack size is now 2  [-1: ais_table -2: f]
	// Push the function in the table so that it is not collected.
	size_t length_ai = lua_rawlen(L, -1);//length of ais_table
	lua_pushvalue(L, -2); //stack size is now 3: [-1: ai_context  -2: ais_table  -3: ai_context]
	lua_rawseti(L, -2, length_ai + 1);// ais_table[length+1]=ai_context.  stack size is now 2 [-1: ais_table  -2: ai_context]
	lua_pop(L, 2);
	return new lua_ai_context(L, length_ai + 1, engine->get_readonly_context().get_side());
}