From 3dc5097c22cb5f0f20fd9342659663b83dc84901 Mon Sep 17 00:00:00 2001 From: Elias Pschernig Date: Tue, 25 Jul 2006 17:45:32 +0000 Subject: [PATCH] Fixed two bugs in Python AI: User input was ignored during the AI's turn, and after the Python AI won a game, no more python games could be played. --- src/ai_python.cpp | 33 ++++++++++++++++++++++++++------- src/ai_python.hpp | 2 ++ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/ai_python.cpp b/src/ai_python.cpp index d4c2c1de908..d4a239b7ca6 100644 --- a/src/ai_python.cpp +++ b/src/ai_python.cpp @@ -1358,7 +1358,17 @@ PyObject* python_ai::wrapper_move_unit(PyObject* /*self*/, PyObject* args) return NULL; } - PyObject* loc = wrap_location(running_instance->move_unit_partial(*from->location_,*to->location_,running_instance->possible_moves_)); + location location; + try { + location = running_instance->move_unit_partial( + *from->location_, *to->location_, running_instance->possible_moves_); + } + catch(end_level_exception& e) { + running_instance->exception = e; + PyErr_SetString(PyExc_RuntimeError, "Game aborted!"); + return NULL; + } + PyObject* loc = wrap_location(location); running_instance->src_dst_.clear(); running_instance->dst_src_.clear(); running_instance->possible_moves_.clear(); @@ -1403,7 +1413,8 @@ PyObject* python_ai::wrapper_attack_unit(PyObject* /*self*/, PyObject* args) bc.get_attacker_stats().attack_num, bc.get_defender_stats().attack_num); } - catch(end_level_exception&) { + catch(end_level_exception& e) { + running_instance->exception = e; PyErr_SetString(PyExc_RuntimeError, "Game is won!"); return NULL; } @@ -1641,7 +1652,7 @@ static PyMethodDef wesnoth_python_methods[] = { PyObject* pyob = reinterpret_cast(type); \ PyModule_AddObject(module, const_cast(n), pyob); } -python_ai::python_ai(ai_interface::info& info) : ai_interface(info) +python_ai::python_ai(ai_interface::info& info) : ai_interface(info), exception(QUIT) { running_instance = this; if ( !init_ ) @@ -1680,6 +1691,8 @@ void python_ai::play_turn() std::string script = get_binary_file_location("data", "ais/" + script_name); PyObject* file = PyFile_FromString((char*)script.c_str(),"rt"); + PyErr_Clear(); + PyObject* dict = PyDict_New(); PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins()); @@ -1692,20 +1705,26 @@ void python_ai::play_turn() import_modules += "'" + *i + "ais', "; } import_modules += "])\n"; + std::cout << import_modules << std::endl; PyObject* pre = PyRun_String(import_modules.c_str(), Py_file_input, dict, dict); // Now execute the actual python AI. PyObject* ret = PyRun_File(PyFile_AsFile(file), script.c_str(), Py_file_input, dict, dict); + Py_XDECREF(pre); + Py_XDECREF(ret); + Py_DECREF(dict); + Py_DECREF(file); + if (PyErr_Occurred()) { // RuntimeError is the game-won exception, no need to print it if (!PyErr_ExceptionMatches(PyExc_RuntimeError)) PyErr_Print(); + // Otherwise, re-throw the exception here, so it will get handled + // properly further up. + else + throw exception; } - Py_XDECREF(pre); - Py_XDECREF(ret); - Py_DECREF(dict); - Py_DECREF(file); } // Finds all python AI scripts available in the current binary path. diff --git a/src/ai_python.hpp b/src/ai_python.hpp index 7ce91fc785e..29c0fbf49be 100644 --- a/src/ai_python.hpp +++ b/src/ai_python.hpp @@ -2,6 +2,7 @@ #define AI_PYTHON_HPP_INCLUDED #include "ai_interface.hpp" +#include "menu_events.hpp" #include typedef struct { @@ -62,6 +63,7 @@ public: protected: static bool init_; static PyObject* python_error_; + end_level_exception exception; ai_interface::move_map src_dst_; ai_interface::move_map dst_src_; std::map possible_moves_;