2018-03-27 00:26:15 +00:00
|
|
|
#include <Python.h>
|
|
|
|
|
|
|
|
static PyObject* DumbevalError;
|
|
|
|
|
|
|
|
static float x[122];
|
|
|
|
|
|
|
|
static const float wc[122] = {
|
2018-03-27 00:41:58 +00:00
|
|
|
1.5790816238841092, 1.6374860177130541, -1.7131823639980923, -0.9286186784962336, -1.0732080528763888,
|
|
|
|
-0.33851674519289876, 1.5798155080270462, 2.3161915581553414, 1.5625330782392322, 0.9397141260075461,
|
|
|
|
0.8386342522957442, 1.2380864901133144, -2.803703105809909, -1.6033863837759044, -1.9297462408169208,
|
|
|
|
2.804924084193149, 0.9270839975087402, 0.9877927467766145, -1.0075116465703597, -0.9456578829797895,
|
|
|
|
-2.592017567014881, 0.6309857231907587, 2.04590249003744, -0.7982917574924828, -1.4539868823698936,
|
|
|
|
1.0841407450630234, 0.45211788236898887, -1.2713606178159307, 0.8688872440724307, -0.6732738151904405,
|
|
|
|
2.2362742485632294, -0.6581729637609781, -1.7948051663967473, 2.1883788452643564, 2.1598171424723214,
|
|
|
|
0.40802272166662146, -0.9708789129385202, -0.28407011999124165, 1.132858480655588, 0.35009713673111253,
|
|
|
|
2.396877030228498, -2.9621397724422653, 1.607067798976531, 1.0644990486021744, 0.31954763526104113,
|
|
|
|
1.3044736141405133, -2.7454899725805606, -2.7379143210889545, -1.803990720175892, 0.46979843403681576,
|
|
|
|
-1.7142750941084806, -0.8151527229519924, -2.009462889335147, -0.3918389579023729, -1.2877598286852634,
|
|
|
|
2.555703689627613, 0.9185193346378826, -2.4440956502956404, -1.5557875467629176, 1.6171292628313898,
|
|
|
|
-0.7350519162308693, 2.9185129503030653, -0.02369662637182124, 0.9957404325370858, -0.6504711593915609,
|
|
|
|
2.6190546093943468, -0.36103491516117003, -0.5988376927918715, 0.16399156134136383, 0.3254074568551131,
|
|
|
|
-1.5638349190057885, 0.8561543642997189, -0.0880209333042492, 1.323918411026094, -0.9498883976797834,
|
|
|
|
2.3050169940592458, -2.859322940360703, 2.1798224505428836, 0.03769734441005257, 2.806706515762855,
|
|
|
|
-0.514728418369482, -2.7130236727731454, 1.343193402901159, -1.542350700154035, 1.1197565339573625,
|
|
|
|
-1.4498511795864624, 1.3472224178544003, 0.7044576479382245, -2.284211306571646, -1.7289596273930532,
|
|
|
|
-1.7276292685923906, -0.1945401442950634, 2.0338744133468643, 2.001064062247366, 1.9649901287717713,
|
|
|
|
1.5235253273336475, 0.40016636047698606, -1.3276206938801058, 0.8496121993449899, 1.054662320349336,
|
|
|
|
-1.1897996492934584, 0.49610727347392025, -1.8539475848522708, 0.4713599305742626, -2.8424352653158573,
|
|
|
|
-2.526691049928613, 2.1369664337786274, 1.0616438676464632, 1.9487914860665452, 2.822108017102477,
|
|
|
|
-0.3393405083020449, 2.787144781914554, -2.401723402781605, -1.1675562811241997, -1.1542961327714207,
|
|
|
|
0.18253192955355502, -2.418436664206371, 0.7423935287565309, 2.9903418274144666, -1.3503112004693552,
|
|
|
|
-2.649146174480099, -0.5447080156947952
|
|
|
|
};
|
2018-03-27 00:26:15 +00:00
|
|
|
|
|
|
|
static const float wr[122] = {
|
|
|
|
-0.7856, -0.50352, 0.12392, -1.00316, -2.46556, -0.1627, 0.18966, 0.0043, 0.0,
|
|
|
|
0.13681, 1.11245, 0.0, 0.0, -0.02781, -2.77982, 0.0, -0.91035, 0.60015,
|
|
|
|
-1.27266, 0.0, 0.0, 0.0, 0.0, -7.26713, -0.19412, -1.05121, 0.27448, -4.94251,
|
|
|
|
-0.06844, 0.37183, -3.66465, -0.8305, 0.09266, 0.07217, 0.0, 0.29906, -1.26062,
|
|
|
|
0.17405, 0.48302, 2.00366, 0.92321, -0.10839, 1.06349, 0.39521, 3.4204,
|
|
|
|
0.00576, 5.35, 3.8539, -0.09308, 0.17253, 0.13978, 0.2701, -0.52728, 0.88296,
|
|
|
|
0.2252, 0.0, 0.0, -0.12707, 3.05454, 0.31202, -0.88035, -0.01351, 0.0,
|
|
|
|
-3.40177, -0.22082, -0.13022, -0.09795, -2.29847, -12.32252, 0.0, -0.13597,
|
|
|
|
0.12039, 0.85631, 0.0, 0.0, -0.3424, 0.24855, 0.20178, 2.30052, 1.5068,
|
|
|
|
0.0, -0.07456, 5.16874, 0.01418, -1.3464, -1.29506, 0.0, 0.0, -1.40375,
|
|
|
|
0.0, -0.11696, 0.05281, -9.67677, 0.05685, -1.09167, 0.0, 0.0, -2.56906,
|
|
|
|
2.19605, 0.0, 0.68178, -0.08471, 0.0, -2.34631, 1.49549, -2.16183, 0.0,
|
|
|
|
1.16242, 1.08744, -0.1716, 0.25236, 0.13246, -0.37646, 0.0, -2.87401,
|
|
|
|
0.74427, 1.07274, -0.01591, -0.14818, -0.06285, 0.08302, -1.03508
|
|
|
|
};
|
|
|
|
|
|
|
|
void setx(int pos[])
|
|
|
|
{
|
|
|
|
/* sets input vector x[] given board position pos[] */
|
|
|
|
extern float x[];
|
|
|
|
int j, jm1, n;
|
|
|
|
/* initialize */
|
|
|
|
for(j=0;j<122;++j) x[j] = 0.0;
|
|
|
|
|
|
|
|
/* first encode board locations 24-1 */
|
|
|
|
for(j=1;j<=24;++j) {
|
|
|
|
jm1 = j - 1;
|
|
|
|
n = pos[25-j];
|
|
|
|
if(n!=0) {
|
|
|
|
if(n==-1) x[5*jm1+0] = 1.0;
|
|
|
|
if(n==1) x[5*jm1+1] = 1.0;
|
|
|
|
if(n>=2) x[5*jm1+2] = 1.0;
|
|
|
|
if(n==3) x[5*jm1+3] = 1.0;
|
|
|
|
if(n>=4) x[5*jm1+4] = (float)(n-3)/2.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* encode opponent barmen */
|
|
|
|
x[120] = -(float)(pos[0])/2.0;
|
|
|
|
/* encode computer's menoff */
|
|
|
|
x[121] = (float)(pos[26])/15.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
float dumbeval(int race, int pos[])
|
|
|
|
{
|
|
|
|
/* Backgammon move-selection evaluation function
|
|
|
|
for benchmark comparisons. Computes a linear
|
|
|
|
evaluation function: Score = W * X, where X is
|
|
|
|
an input vector encoding the board state (using
|
|
|
|
a raw encoding of the number of men at each location),
|
|
|
|
and W is a weight vector. Separate weight vectors
|
|
|
|
are used for racing positions and contact positions.
|
|
|
|
Makes lots of obvious mistakes, but provides a
|
|
|
|
decent level of play for benchmarking purposes. */
|
|
|
|
|
|
|
|
/* Provided as a public service to the backgammon
|
|
|
|
programming community by Gerry Tesauro, IBM Research.
|
|
|
|
(e-mail: tesauro@watson.ibm.com) */
|
|
|
|
|
|
|
|
/* The following inputs are needed for this routine:
|
|
|
|
|
|
|
|
race is an integer variable which should be set
|
|
|
|
based on the INITIAL position BEFORE the move.
|
|
|
|
Set race=1 if the position is a race (i.e. no contact)
|
|
|
|
and 0 if the position is a contact position.
|
|
|
|
|
|
|
|
pos[] is an integer array of dimension 28 which
|
|
|
|
should represent a legal final board state after
|
|
|
|
the move. Elements 1-24 correspond to board locations
|
|
|
|
1-24 from computer's point of view, i.e. computer's
|
|
|
|
men move in the negative direction from 24 to 1, and
|
|
|
|
opponent's men move in the positive direction from
|
|
|
|
1 to 24. Computer's men are represented by positive
|
|
|
|
integers, and opponent's men are represented by negative
|
|
|
|
integers. Element 25 represents computer's men on the
|
|
|
|
bar (positive integer), and element 0 represents opponent's
|
|
|
|
men on the bar (negative integer). Element 26 represents
|
|
|
|
computer's men off the board (positive integer), and
|
|
|
|
element 27 represents opponent's men off the board
|
|
|
|
(negative integer). */
|
|
|
|
|
|
|
|
/* Also, be sure to call rdwts() at the start of your
|
|
|
|
program to read in the weight values. Happy hacking] */
|
|
|
|
|
|
|
|
int i;
|
|
|
|
float score;
|
|
|
|
|
|
|
|
if(pos[26]==15) return(99999999.);
|
|
|
|
/* all men off, best possible move */
|
|
|
|
|
|
|
|
setx(pos); /* sets input array x[] */
|
|
|
|
score = 0.0;
|
|
|
|
if(race) { /* use race weights */
|
|
|
|
for(i=0;i<122;++i) score += wr[i]*x[i];
|
|
|
|
}
|
|
|
|
else { /* use contact weights */
|
|
|
|
for(i=0;i<122;++i) score += wc[i]*x[i];
|
|
|
|
}
|
|
|
|
return(score);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject*
|
|
|
|
dumbeval_eval(PyObject *self, PyObject *args) {
|
|
|
|
int race;
|
|
|
|
long numValues;
|
|
|
|
int board[28];
|
|
|
|
float eval_score;
|
|
|
|
|
|
|
|
PyObject* tuple_obj;
|
|
|
|
PyObject* val_obj;
|
|
|
|
|
|
|
|
if (! PyArg_ParseTuple(args, "pO!", &race, &PyTuple_Type, &tuple_obj))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
numValues = PyTuple_Size(tuple_obj);
|
|
|
|
|
|
|
|
if (numValues < 0) return NULL;
|
|
|
|
if (numValues != 28) {
|
|
|
|
PyErr_SetString(DumbevalError, "Tuple must have 28 entries");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Iterate over tuple to retreive positions
|
|
|
|
for (int i=0; i<numValues; i++) {
|
|
|
|
val_obj = PyTuple_GetItem(tuple_obj, i);
|
|
|
|
board[i] = PyLong_AsLong(val_obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
eval_score = dumbeval(race, board);
|
|
|
|
return Py_BuildValue("f", eval_score);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyMethodDef dumbeval_methods[] = {
|
|
|
|
{
|
|
|
|
"eval", dumbeval_eval, METH_VARARGS,
|
|
|
|
"Returns evaluation results for the given board position."
|
|
|
|
},
|
|
|
|
{NULL, NULL, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct PyModuleDef dumbeval_definition = {
|
|
|
|
PyModuleDef_HEAD_INIT,
|
|
|
|
"dumbeval",
|
|
|
|
"A Python module that implements Gerald Tesauro's dumbeval function for evaluation backgammon positions.",
|
|
|
|
-1,
|
|
|
|
dumbeval_methods
|
|
|
|
};
|
|
|
|
|
|
|
|
PyMODINIT_FUNC PyInit_dumbeval(void) {
|
|
|
|
PyObject* module;
|
|
|
|
|
|
|
|
module = PyModule_Create(&dumbeval_definition);
|
|
|
|
if (module == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
DumbevalError = PyErr_NewException("dumbeval.error", NULL, NULL);
|
|
|
|
Py_INCREF(DumbevalError);
|
|
|
|
PyModule_AddObject(module, "error", DumbevalError);
|
|
|
|
|
|
|
|
return module;
|
|
|
|
}
|