mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-10 20:06:28 +00:00
Converted more wesnoth module functions to release the GIL.
Added comment to bruteforce_unsafe.py about memoize caveat and maps which can change during gameplay.
This commit is contained in:
parent
8cac0e5e82
commit
cbba09d4e0
@ -220,7 +220,8 @@ class memoized( object ):
|
|||||||
def stats( self ):
|
def stats( self ):
|
||||||
return float(self.__cacheHits) / self.__calls
|
return float(self.__cacheHits) / self.__calls
|
||||||
|
|
||||||
|
# If AI is playing on a map where can pysically change during the AI's turn,
|
||||||
|
# this redefinition must be commented out.
|
||||||
wesnoth.get_location = memoized( wesnoth.get_location )
|
wesnoth.get_location = memoized( wesnoth.get_location )
|
||||||
|
|
||||||
|
|
||||||
|
@ -424,15 +424,20 @@ static PyObject* wrap_attacktype(const attack_type& type)
|
|||||||
|
|
||||||
bool python_ai::is_unit_valid(const unit* unit)
|
bool python_ai::is_unit_valid(const unit* unit)
|
||||||
{
|
{
|
||||||
if (!unit)
|
bool ret = false ;
|
||||||
{
|
if (unit) {
|
||||||
return false;
|
Py_BEGIN_ALLOW_THREADS
|
||||||
}
|
for(unit_map::const_iterator i = running_instance->get_info().units.begin(); \
|
||||||
for(unit_map::const_iterator i = running_instance->get_info().units.begin(); i != running_instance->get_info().units.end(); ++i) {
|
i != running_instance->get_info().units.end(); ++i) {
|
||||||
if (unit == &i->second)
|
if (unit == &i->second) {
|
||||||
return true;
|
ret = true ;
|
||||||
}
|
break ;
|
||||||
return false;
|
}
|
||||||
|
}
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret ;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject* unit_get_name(wesnoth_unit* unit, void* /*closure*/)
|
static PyObject* unit_get_name(wesnoth_unit* unit, void* /*closure*/)
|
||||||
@ -535,6 +540,7 @@ static PyObject* unit_stoned(wesnoth_unit* unit, void* /*closure*/)
|
|||||||
// version below which does not actually return a boolean value.
|
// version below which does not actually return a boolean value.
|
||||||
static PyObject* unit_query_valid(wesnoth_unit* unit, void* /*closure*/)
|
static PyObject* unit_query_valid(wesnoth_unit* unit, void* /*closure*/)
|
||||||
{
|
{
|
||||||
|
u_check ;
|
||||||
// if( running_instance->is_unit_valid(unit->unit_) )
|
// if( running_instance->is_unit_valid(unit->unit_) )
|
||||||
// Py_RETURN_TRUE ;
|
// Py_RETURN_TRUE ;
|
||||||
|
|
||||||
@ -841,6 +847,7 @@ static PyObject *wrap_location(const gamemap::location& loc)
|
|||||||
|
|
||||||
void recalculate_movemaps()
|
void recalculate_movemaps()
|
||||||
{
|
{
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
python_ai *ai = running_instance;
|
python_ai *ai = running_instance;
|
||||||
ai->src_dst_.clear();
|
ai->src_dst_.clear();
|
||||||
ai->dst_src_.clear();
|
ai->dst_src_.clear();
|
||||||
@ -853,6 +860,7 @@ void recalculate_movemaps()
|
|||||||
ai->enemy_possible_moves_.clear();
|
ai->enemy_possible_moves_.clear();
|
||||||
ai->calculate_possible_moves(ai->enemy_possible_moves_,
|
ai->calculate_possible_moves(ai->enemy_possible_moves_,
|
||||||
ai->enemy_src_dst_, ai->enemy_dst_src_, true);
|
ai->enemy_src_dst_, ai->enemy_dst_src_, true);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject* wrapper_location_adjacent_to( wesnoth_location* left, PyObject* args )
|
static PyObject* wrapper_location_adjacent_to( wesnoth_location* left, PyObject* args )
|
||||||
@ -923,8 +931,11 @@ static PyObject* wrapper_getmap_is_border( wesnoth_gamemap* map, PyObject* args
|
|||||||
bool on_board, on_board_without_borders;
|
bool on_board, on_board_without_borders;
|
||||||
if ( !PyArg_ParseTuple( args, OBVALUE, &wesnoth_location_type, &location ) )
|
if ( !PyArg_ParseTuple( args, OBVALUE, &wesnoth_location_type, &location ) )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
on_board = map->map_->on_board_with_border(*location->location_);
|
on_board = map->map_->on_board_with_border(*location->location_);
|
||||||
on_board_without_borders = map->map_->on_board(*location->location_);
|
on_board_without_borders = map->map_->on_board(*location->location_);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
return Py_BuildValue(INTVALUE, on_board && !on_board_without_borders ? 1 : 0);
|
return Py_BuildValue(INTVALUE, on_board && !on_board_without_borders ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1038,12 +1049,15 @@ static PyObject* wrapper_team_is_enemy(wesnoth_team* team, void* /*closure*/)
|
|||||||
static PyObject* wrapper_team_side(wesnoth_team* team, void* /*closure*/)
|
static PyObject* wrapper_team_side(wesnoth_team* team, void* /*closure*/)
|
||||||
{
|
{
|
||||||
int side = 0;
|
int side = 0;
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
for (size_t t = 0; t < running_instance->get_teams().size(); t++) {
|
for (size_t t = 0; t < running_instance->get_teams().size(); t++) {
|
||||||
if (team->team_ == &running_instance->get_teams()[t]) {
|
if (team->team_ == &running_instance->get_teams()[t]) {
|
||||||
side = 1 + t;
|
side = 1 + t;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
return Py_BuildValue(INTVALUE, side);
|
return Py_BuildValue(INTVALUE, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1188,6 +1202,7 @@ PyObject* python_ai::wrapper_unit_movement_cost( wesnoth_unit* unit, PyObject* a
|
|||||||
wesnoth_location* loc;
|
wesnoth_location* loc;
|
||||||
if ( !PyArg_ParseTuple( args, OBVALUE, &wesnoth_location_type, &loc ) )
|
if ( !PyArg_ParseTuple( args, OBVALUE, &wesnoth_location_type, &loc ) )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
u_check ;
|
||||||
return Py_BuildValue(INTVALUE,unit->unit_->movement_cost(map.get_terrain(*loc->location_)));
|
return Py_BuildValue(INTVALUE,unit->unit_->movement_cost(map.get_terrain(*loc->location_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1197,6 +1212,7 @@ PyObject* python_ai::wrapper_unit_defense_modifier( wesnoth_unit* unit, PyObject
|
|||||||
wesnoth_location* loc;
|
wesnoth_location* loc;
|
||||||
if ( !PyArg_ParseTuple( args, OBVALUE, &wesnoth_location_type, &loc ) )
|
if ( !PyArg_ParseTuple( args, OBVALUE, &wesnoth_location_type, &loc ) )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
u_check ;
|
||||||
return Py_BuildValue(INTVALUE,unit->unit_->defense_modifier(map.get_terrain(*loc->location_)));
|
return Py_BuildValue(INTVALUE,unit->unit_->defense_modifier(map.get_terrain(*loc->location_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1348,7 +1364,9 @@ PyObject* python_ai::wrapper_log_message(PyObject* /*self*/, PyObject* args)
|
|||||||
const char* msg;
|
const char* msg;
|
||||||
if ( !PyArg_ParseTuple( args, STRINGVALUE, &msg ) )
|
if ( !PyArg_ParseTuple( args, STRINGVALUE, &msg ) )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
running_instance->log_message(msg);
|
running_instance->log_message(msg);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
@ -1358,8 +1376,10 @@ PyObject* python_ai::wrapper_log(PyObject* /*self*/, PyObject* args)
|
|||||||
const char *msg;
|
const char *msg;
|
||||||
if (!PyArg_ParseTuple( args, STRINGVALUE, &msg))
|
if (!PyArg_ParseTuple( args, STRINGVALUE, &msg))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
LOG_AI << msg;
|
LOG_AI << msg;
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1467,6 +1487,7 @@ PyObject* python_ai::wrapper_move_unit(PyObject* /*self*/, PyObject* args)
|
|||||||
|
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
ai_interface::move_map::const_iterator pos;
|
ai_interface::move_map::const_iterator pos;
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
for (pos = running_instance->src_dst_.begin(); pos != running_instance->src_dst_.end(); pos++)
|
for (pos = running_instance->src_dst_.begin(); pos != running_instance->src_dst_.end(); pos++)
|
||||||
{
|
{
|
||||||
if ( pos->first == ( *from->location_ ) )
|
if ( pos->first == ( *from->location_ ) )
|
||||||
@ -1476,14 +1497,17 @@ PyObject* python_ai::wrapper_move_unit(PyObject* /*self*/, PyObject* args)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
if (!valid) Py_RETURN_NONE;
|
if (!valid) Py_RETURN_NONE;
|
||||||
if (pos == running_instance->src_dst_.end()) Py_RETURN_NONE;
|
if (pos == running_instance->src_dst_.end()) Py_RETURN_NONE;
|
||||||
|
|
||||||
location location;
|
location location;
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
wrap(
|
wrap(
|
||||||
location = running_instance->move_unit_partial(
|
location = running_instance->move_unit_partial(
|
||||||
*from->location_, *to->location_, running_instance->possible_moves_);
|
*from->location_, *to->location_, running_instance->possible_moves_);
|
||||||
)
|
)
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
PyObject* loc = wrap_location(location);
|
PyObject* loc = wrap_location(location);
|
||||||
|
|
||||||
@ -1598,12 +1622,16 @@ PyObject* python_ai::wrapper_unit_find_path(wesnoth_unit* self, PyObject* args)
|
|||||||
{
|
{
|
||||||
wesnoth_location* from;
|
wesnoth_location* from;
|
||||||
wesnoth_location* to;
|
wesnoth_location* to;
|
||||||
|
if( !running_instance->is_unit_valid(self->unit_) )
|
||||||
|
Py_RETURN_NONE ;
|
||||||
double max_cost = self->unit_->movement_left();
|
double max_cost = self->unit_->movement_left();
|
||||||
if ( !PyArg_ParseTuple( args, CC("O!O!|d"), &wesnoth_location_type, &from,
|
if ( !PyArg_ParseTuple( args, CC("O!O!|d"), &wesnoth_location_type, &from,
|
||||||
&wesnoth_location_type, &to, &max_cost ) )
|
&wesnoth_location_type, &to, &max_cost ) )
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!running_instance->is_unit_valid(self->unit_))
|
|
||||||
return NULL;
|
// Save thread state and release GIL
|
||||||
|
PyThreadState *_save;
|
||||||
|
Py_UNBLOCK_THREADS
|
||||||
|
|
||||||
info& inf = running_instance->get_info();
|
info& inf = running_instance->get_info();
|
||||||
|
|
||||||
@ -1619,6 +1647,9 @@ PyObject* python_ai::wrapper_unit_find_path(wesnoth_unit* self, PyObject* args)
|
|||||||
for (size_t step = 0; step < route.steps.size(); step++)
|
for (size_t step = 0; step < route.steps.size(); step++)
|
||||||
PyList_SetItem(steps,step,wrap_location(route.steps[step]));
|
PyList_SetItem(steps,step,wrap_location(route.steps[step]));
|
||||||
|
|
||||||
|
// Lock the GIL again
|
||||||
|
Py_BLOCK_THREADS
|
||||||
|
|
||||||
return steps;
|
return steps;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1641,6 +1672,8 @@ PyObject* python_ai::wrapper_unit_attack_statistics(wesnoth_unit* self, PyObject
|
|||||||
|
|
||||||
// We need to temporarily move our unit to where the attack calculation
|
// We need to temporarily move our unit to where the attack calculation
|
||||||
// is supposed to take place.
|
// is supposed to take place.
|
||||||
|
PyThreadState *_save;
|
||||||
|
Py_UNBLOCK_THREADS
|
||||||
std::pair<gamemap::location,unit> *temp = inf.units.extract(*from->location_);
|
std::pair<gamemap::location,unit> *temp = inf.units.extract(*from->location_);
|
||||||
std::pair<gamemap::location,unit> *backup = temp;
|
std::pair<gamemap::location,unit> *backup = temp;
|
||||||
std::pair<gamemap::location,unit> replace(*from->location_,*self->unit_);
|
std::pair<gamemap::location,unit> replace(*from->location_,*self->unit_);
|
||||||
@ -1657,6 +1690,8 @@ PyObject* python_ai::wrapper_unit_attack_statistics(wesnoth_unit* self, PyObject
|
|||||||
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
std::vector<double>attacker = bc.get_attacker_combatant().hp_dist;
|
std::vector<double>attacker = bc.get_attacker_combatant().hp_dist;
|
||||||
|
Py_BLOCK_THREADS
|
||||||
|
|
||||||
PyObject* adict = PyDict_New();
|
PyObject* adict = PyDict_New();
|
||||||
for (i = 0; i < attacker.size(); i++) {
|
for (i = 0; i < attacker.size(); i++) {
|
||||||
if (attacker[i] > 0)
|
if (attacker[i] > 0)
|
||||||
@ -1671,13 +1706,13 @@ PyObject* python_ai::wrapper_unit_attack_statistics(wesnoth_unit* self, PyObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Restore old position again
|
// Restore old position again
|
||||||
|
Py_UNBLOCK_THREADS
|
||||||
temp = inf.units.extract(*from->location_);
|
temp = inf.units.extract(*from->location_);
|
||||||
if (backup)
|
if (backup)
|
||||||
inf.units.add(backup);
|
inf.units.add(backup);
|
||||||
|
Py_BLOCK_THREADS
|
||||||
|
|
||||||
PyObject *ret = Py_BuildValue(CC("(OO)"), adict, ddict);
|
return Py_BuildValue(CC("(OO)"), adict, ddict);
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* python_ai::wrapper_set_variable(PyObject* /*self*/, PyObject* args)
|
PyObject* python_ai::wrapper_set_variable(PyObject* /*self*/, PyObject* args)
|
||||||
@ -1686,8 +1721,13 @@ PyObject* python_ai::wrapper_set_variable(PyObject* /*self*/, PyObject* args)
|
|||||||
PyObject *value;
|
PyObject *value;
|
||||||
if (!PyArg_ParseTuple(args, CC("sO"), &variable, &value))
|
if (!PyArg_ParseTuple(args, CC("sO"), &variable, &value))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
PyThreadState *_save ;
|
||||||
|
Py_UNBLOCK_THREADS ;
|
||||||
config const &old_memory = running_instance->current_team().ai_memory();
|
config const &old_memory = running_instance->current_team().ai_memory();
|
||||||
config new_memory(old_memory);
|
config new_memory(old_memory);
|
||||||
|
Py_BLOCK_THREADS ;
|
||||||
|
|
||||||
PyObject *so = PyMarshal_WriteObjectToString(value, Py_MARSHAL_VERSION);
|
PyObject *so = PyMarshal_WriteObjectToString(value, Py_MARSHAL_VERSION);
|
||||||
if (so)
|
if (so)
|
||||||
{
|
{
|
||||||
@ -1695,7 +1735,7 @@ PyObject* python_ai::wrapper_set_variable(PyObject* /*self*/, PyObject* args)
|
|||||||
Py_ssize_t len;
|
Py_ssize_t len;
|
||||||
PyString_AsStringAndSize(so, &cs, &len);
|
PyString_AsStringAndSize(so, &cs, &len);
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_UNBLOCK_THREADS ;
|
||||||
std::string s;
|
std::string s;
|
||||||
char const *digits[] = {
|
char const *digits[] = {
|
||||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||||
@ -1708,7 +1748,7 @@ PyObject* python_ai::wrapper_set_variable(PyObject* /*self*/, PyObject* args)
|
|||||||
}
|
}
|
||||||
new_memory[variable] = s;
|
new_memory[variable] = s;
|
||||||
running_instance->current_team().set_ai_memory(new_memory);
|
running_instance->current_team().set_ai_memory(new_memory);
|
||||||
Py_END_ALLOW_THREADS
|
Py_BLOCK_THREADS ;
|
||||||
|
|
||||||
Py_DECREF(so);
|
Py_DECREF(so);
|
||||||
} else {
|
} else {
|
||||||
@ -1733,24 +1773,29 @@ PyObject* python_ai::wrapper_get_variable(PyObject* /*self*/, PyObject* args)
|
|||||||
if (!PyArg_ParseTuple(args, CC("s|O"), &variable, &default_value))
|
if (!PyArg_ParseTuple(args, CC("s|O"), &variable, &default_value))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
PyThreadState *_save ;
|
||||||
|
Py_UNBLOCK_THREADS
|
||||||
config const &memory = running_instance->current_team().ai_memory();
|
config const &memory = running_instance->current_team().ai_memory();
|
||||||
char const *s = memory[variable].c_str();
|
char const *s = memory[variable].c_str();
|
||||||
|
Py_BLOCK_THREADS
|
||||||
|
|
||||||
if (s && s[0])
|
if (s && s[0])
|
||||||
{
|
{
|
||||||
int i;
|
Py_UNBLOCK_THREADS ;
|
||||||
int len = strlen(s);
|
|
||||||
char *data = new char[len / 2];
|
int i;
|
||||||
Py_BEGIN_ALLOW_THREADS
|
int len = strlen(s);
|
||||||
for (i = 0; i < len; i += 2)
|
char *data = new char[len / 2];
|
||||||
|
for (i = 0; i < len; i += 2)
|
||||||
{
|
{
|
||||||
int v1 = s[i] - '0';
|
int v1 = s[i] - '0';
|
||||||
int v2 = s[i + 1] - '0';
|
int v2 = s[i + 1] - '0';
|
||||||
if (v1 > 9) v1 += 10 + '0' - 'a';
|
if (v1 > 9) v1 += 10 + '0' - 'a';
|
||||||
if (v2 > 9) v2 += 10 + '0' - 'a';
|
if (v2 > 9) v2 += 10 + '0' - 'a';
|
||||||
char c = v1 * 16 + v2;
|
char c = v1 * 16 + v2;
|
||||||
data[i / 2] = c;
|
data[i / 2] = c;
|
||||||
}
|
}
|
||||||
Py_END_ALLOW_THREADS
|
Py_BLOCK_THREADS ;
|
||||||
|
|
||||||
Py_DECREF( default_value ) ;
|
Py_DECREF( default_value ) ;
|
||||||
PyObject *ret = PyMarshal_ReadObjectFromString(data, len / 2);
|
PyObject *ret = PyMarshal_ReadObjectFromString(data, len / 2);
|
||||||
@ -1812,6 +1857,8 @@ PyObject* python_ai::wrapper_test_move(PyObject* /*self*/, PyObject* args)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyThreadState *_save ;
|
||||||
|
Py_UNBLOCK_THREADS ;
|
||||||
info& inf = running_instance->get_info();
|
info& inf = running_instance->get_info();
|
||||||
|
|
||||||
unit_map::iterator u_it = inf.units.find(*from->location_);
|
unit_map::iterator u_it = inf.units.find(*from->location_);
|
||||||
@ -1836,6 +1883,7 @@ PyObject* python_ai::wrapper_test_move(PyObject* /*self*/, PyObject* args)
|
|||||||
inf.units.add(original);
|
inf.units.add(original);
|
||||||
if (backup)
|
if (backup)
|
||||||
inf.units.add(backup);
|
inf.units.add(backup);
|
||||||
|
Py_BLOCK_THREADS ;
|
||||||
|
|
||||||
PyObject* srcdst = wrap_move_map(test_src_dst);
|
PyObject* srcdst = wrap_move_map(test_src_dst);
|
||||||
PyObject* dstsrc = wrap_move_map(test_dst_src);
|
PyObject* dstsrc = wrap_move_map(test_dst_src);
|
||||||
@ -1852,7 +1900,7 @@ static PyMethodDef wesnoth_python_methods[] = {
|
|||||||
MDEF("log_message", python_ai::wrapper_log_message,
|
MDEF("log_message", python_ai::wrapper_log_message,
|
||||||
"Parameters: string\n"
|
"Parameters: string\n"
|
||||||
"Logs a message, displayed as a chat message, if debug is enabled." )
|
"Logs a message, displayed as a chat message, if debug is enabled." )
|
||||||
MDEF("log", python_ai::wrapper_log,
|
MDEF("log", python_ai::wrapper_log,
|
||||||
"Parameters: string\n"
|
"Parameters: string\n"
|
||||||
"Writes a debug message to the AI log. This should be used instead of "
|
"Writes a debug message to the AI log. This should be used instead of "
|
||||||
"print to not clutter stdout if AI logging is disabled.")
|
"print to not clutter stdout if AI logging is disabled.")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user