#include static PyObject* DumbevalError; static float x[122]; static const float wc[122] = { 5.6477, 6.316649999999999, 7.05515, 6.65315, 9.3171, 17.9777, 2.0235499999999993, 5.1129500000000005, 7.599200000000001, 9.68525, 3.1762, 8.05335, 16.153499999999998, 8.02445, 10.55345, 15.489600000000001, 10.525199999999998, 16.438850000000002, 12.27405, 9.6362, 12.7152, 13.2859, 1.6932499999999995, 26.79045, 10.521899999999999, 6.79635, 5.28135, 6.2059, 10.2306, 10.5485, 3.6000500000000004, 4.07825, 6.951700000000001, 4.413749999999999, 11.271450000000002, 12.9361, 11.087299999999999, 13.10085, 10.411999999999999, 8.084050000000001, 12.4893, 5.96055, 4.69195, 18.9482, 9.0946, 9.1954, 6.2592, 16.180300000000003, 8.3376, 23.24915, 14.32525, -2.6699000000000006, 19.156, 5.81445, 4.7214, 7.63055, 7.039, 5.88075, 2.00765, 14.596800000000002, 11.5208, -3.79, -3.8541000000000003, 5.358499999999999, 14.4516, 2.49015, 11.284799999999999, 14.1066, 16.2306, 5.82875, 9.34505, 16.13685, 8.1893, 2.93145, 7.83185, 12.86765, 6.90115, 20.07255, 8.93355, -0.12434999999999974, 12.0587, 11.83985, 6.34155, 7.1963, 10.571200000000001, 22.38365, 6.50745, 8.94595, 12.0434, 10.79885, 14.055800000000001, 0.022100000000000453, 10.39255, 4.088850000000001, 3.6421499999999996, 38.1298, 6.8957, 0.9804999999999997, 5.9599, 13.16055, 11.55305, 10.65015, 4.6673, 15.770999999999999, 27.700050000000005, 4.4329, 12.6349, 7.037800000000001, 3.4897, 18.91945, 10.239899999999999, 5.4625, 10.29705, 10.492799999999999, 8.850900000000001, -10.575999999999999, 10.6893, 15.30845, 17.8083, 31.88275, 11.225000000000001, 4.4806}; 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