Committed a patch by ivan_i:

- Added a command-line option to invoke wesnoth's built-in python
  interpreter in interactive mode.

- Exposed wesnoth's random number generator to python.
This commit is contained in:
Sergey Popov 2008-11-17 19:20:48 +00:00
parent c9ad39ddc1
commit 2709806eec
10 changed files with 94 additions and 16 deletions

View file

@ -1,7 +1,6 @@
#!WPY
import time
import wesnoth, random
import ai as wesnoth
## Copyright 2006 by Michael Schmahl
## This code is available under the latest version of the GNU Public License.
@ -282,7 +281,7 @@ class AI:
while 1:
# pick a random recruit in proportion to the weights
r = random.uniform(0,sumweights)
r = wesnoth.get_random(0,sumweights)
for recruit,weight in recruit_list:
r -= weight
if r < 0: break
@ -528,8 +527,14 @@ class AI:
return score
#import time
#st = time.time()
import sys
print "Running bruteforce ai."
print "Wesnoth", wesnoth.get_version()
print "Python", sys.version
st = time.time()
ai = AI()
ai.recruit()
while True:

View file

@ -161,7 +161,7 @@
## ** Overall 25-8-0 76 10 Wins, 1 Loss (91%)
import time
import wesnoth, random
import ai as wesnoth
assert not restricted, "Can only be run outside of restricted environment!"
try:
@ -343,7 +343,7 @@ class AI:
while 1:
# pick a random recruit in proportion to the weights
r = random.uniform(0,sumweights)
r = wesnoth.get_random(0,sumweights)
for recruit,weight in recruit_list:
r -= weight
if r < 0: break
@ -588,6 +588,11 @@ class AI:
return score
import sys
print "Running bruteforce unsafe ai."
print "Wesnoth", wesnoth.get_version()
print "Python", sys.version
st = time.time()
ai = AI()
ai.recruit()

View file

@ -8,7 +8,8 @@
from __future__ import with_statement
import time
import wail, random
import wail
import ai
## Copyright 2006 by Michael Schmahl
## This code is available under the latest version of the GNU Public License.
@ -289,7 +290,7 @@ class AI:
while 1:
# pick a random recruit in proportion to the weights
r = random.uniform(0,sumweights)
r = ai.get_random(0,sumweights)
for recruit,weight in recruit_list:
r -= weight
if r < 0: break
@ -535,6 +536,10 @@ class AI:
return score
import sys
print "Running bruteforce wail ai."
print "Wesnoth", wesnoth.get_version()
print "Python", sys.version
st = time.time()
ai = AI()

View file

@ -85,7 +85,7 @@ if __name__ == "__main__":
os.system("src/wesnoth --python-api")
else:
# If we are run as a python script, output the documentation to stdout.
import wesnoth
import ai as wesnoth
topics = []
myhelp("wesnoth", topics)
output(topics, 1)

View file

@ -1,6 +1,6 @@
import re, os, safe
whitelisted = [ "collections", "functools", "heapq", "math", "Queue", "random", "re", "sets", "string", "threading", "time", "wail", "wesnoth"]
whitelisted = ["ai", "collections", "functools", "heapq", "math", "Queue", "re", "sets", "string", "threading", "time", "wail", "wesnoth"]
rex = re.compile(r"^import\s+(.*)", re.M)
modules = {}

View file

@ -2,7 +2,8 @@
"""This is a rather simple minded example of a python AI."""
import wesnoth, heapq, random
import ai as wesnoth
import heapq
def pos(location):
"""Just a helper function for printing positions in debug messages."""
@ -277,7 +278,7 @@ class AI:
v *= v * v
total_v += v
heapq.heappush(heap, (-v, r[0]))
r = random.uniform(0, total_v)
r = wesnoth.get_random(0, total_v)
while 1:
v, recruit = heapq.heappop(heap)
debug("%d %d" % (r, v))
@ -393,4 +394,9 @@ class AI:
return location
return location
import sys
print "Running sample ai."
print "Wesnoth", wesnoth.get_version()
print "Python", sys.version
AI()

View file

@ -1,5 +1,5 @@
#!WPY
import wesnoth
import ai as wesnoth
class AI:
def __init__(self):
@ -65,4 +65,4 @@ class AI:
return location
return location
AI()
AI()

View file

@ -48,6 +48,7 @@
#include "attack_prediction.hpp"
#include "gamestatus.hpp"
#include "filesystem.hpp"
#include "random.hpp"
#include "log.hpp"
#include "map.hpp"
#include "menu_events.hpp"
@ -1949,6 +1950,15 @@ PyObject* python_ai::wrapper_test_move(PyObject* /*self*/, PyObject* args)
return ret;
}
PyObject* python_ai::wrapper_get_random(PyObject* /*self*/, PyObject* args)
{
int a, b, r;
if (!PyArg_ParseTuple(args, CC("ii"), &a, &b))
return NULL;
r = get_random() % (b-a+1) + a;
return Py_BuildValue(INTVALUE, r);
}
static PyMethodDef wesnoth_python_methods[] = {
MDEF("log_message", python_ai::wrapper_log_message,
"Parameters: string\n"
@ -1957,6 +1967,10 @@ static PyMethodDef wesnoth_python_methods[] = {
"Parameters: string\n"
"Writes a debug message to the AI log. This should be used instead of "
"print to not clutter stdout if AI logging is disabled.")
MDEF("get_random", python_ai::wrapper_get_random,
"Parameters: a, b\n"
"Returns: random number\n"
"Get random number in the range [a, b].")
MDEF("get_units", python_ai::wrapper_get_units,
"Returns: units\n"
"Returns a dictionary containing (location, unit) pairs.")
@ -2057,7 +2071,7 @@ void python_ai::initialize_python()
init_ = true;
Py_Initialize( );
PyObject* module = Py_InitModule3(CC("wesnoth"), wesnoth_python_methods,
PyObject* module = Py_InitModule3(CC("ai"), wesnoth_python_methods,
CC("This is the wesnoth AI module. "
"The python script will be executed once for each turn of the side with the "
"python AI using the script."));
@ -2095,6 +2109,44 @@ void python_ai::invoke(std::string name)
Py_DECREF(globals);
}
/***
* Invoke the Wesnoth's builtin interactive Python interpreter.
*/
int python_ai::run_shell()
{
initialize_python();
PyErr_Clear();
PyObject* globals = PyDict_New();
PyDict_SetItemString(globals, "__builtins__", PyEval_GetBuiltins());
std::string python_code;
// Inspired by Django shell command implementation.
python_code +=
"import sys\n"
"sys.path.append(\"" + game_config::path + "/data/ai/python\")\n"
"sys.path.append(\"" + game_config::path + "/data/tools/wesnoth\")\n"
"import code\n"
"imported_objects = {}\n"
"try: # Try activating rlcompleter, because it's handy.\n"
"\timport readline\n"
"except ImportError:\n"
"\tpass\n"
"else:\n"
"\timport rlcompleter\n"
"\treadline.set_completer(rlcompleter.Completer(imported_objects).complete)\n"
"\treadline.parse_and_bind('tab:complete')\n"
"code.interact(local=imported_objects)\n"
;
PyObject *ret = PyRun_String(python_code.c_str(), Py_file_input, globals,
globals);
if (PyErr_Occurred())
PyErr_Print();
int cret = (int)PyInt_AsLong(ret);
Py_XDECREF(ret);
Py_DECREF(globals);
return cret; //Py_Main(argc, argv);
}
python_ai::python_ai(ai_interface::info& info) :
ai_interface(info),
exception(QUIT),

View file

@ -72,6 +72,7 @@ public:
W(get_version);
W(raise_user_interact);
W(test_move);
W(get_random);
static PyObject* unittype_advances_to( wesnoth_unittype* type, PyObject* args );
static PyObject* wrapper_team_recruits( wesnoth_team* team, PyObject* args );
@ -82,6 +83,7 @@ public:
std::vector<team>& get_teams() { return get_info().teams; }
static void initialize_python();
static void invoke(std::string name);
static int run_shell();
friend void recalculate_movemaps();
private:

View file

@ -1804,8 +1804,11 @@ static int process_command_args(int argc, char** argv) {
return 0;
#ifdef HAVE_PYTHON
} else if(val == "--python-api") {
python_ai::invoke("documentation.py");
python_ai::invoke("documentation");
return 0;
} else if(val == "--python-shell") {
int ret = python_ai::run_shell();
return 0;
#endif
} else if(val == "--config-dir") {
if (argc <= ++arg)