#include static PyObject* DumbevalError; static float x[122]; /* With apologies to Gerry Tesauro */ /* Weights generated by weights.py */ static const float wc[122] = { -1.91222, 1.45979, 0.40657, -1.39159, 3.64558, -0.45381, -0.03157, 0.14539, 0.80232, 0.87558, 2.36202, -2.01887, -0.88918, 2.65871, -1.31587, 1.07476, 0.30491, -1.32892, 0.38018, -0.30714, -1.16178, 0.71481, -1.01334, -0.44373, 0.51255, -0.17171, -0.88886, 0.02071, -0.53279, -0.22139, -1.02436, 0.17948, 0.95697, 0.49272, 0.31848, -0.58293, 0.14484, 0.22063, 1.0336 , -1.90554, 1.10291, -2.05589, -0.16964, -0.82442, 1.27217, -1.24968, -0.90372, 0.05546, 0.2535 , -0.03533, -0.31773, 0.43704, 0.21699, 0.10519, 2.12775, -0.48196, -0.08445, -0.13156, -0.68362, 0.64765, 0.32537, 0.79493, 1.94577, -0.63827, 0.97057, -0.46039, 1.51801, -0.62955, -0.43632, 0.25876, -0.46623, -0.46963, 1.3532 , -0.07362, -1.53211, 0.69676, -0.92407, 0.07153, 0.67173, 0.27661, -0.51579, -0.49019, 1.06603, -0.97673, -1.21231, -1.54966, -0.07795, 0.32697, 0.02873, 1.38703, 0.41725, 0.78326, -0.7257 , 0.54165, 1.38882, 0.27304, 1.0739 , 0.74654, 1.35561, 1.18697, 1.09146, 0.17552, -0.30773, 0.27812, -1.674 , -0.31073, -0.40745, 0.51546, -1.10875, 2.0081 , -1.27931, -1.16321, 0.95652, 0.7487 , -0.2347 , 0.20324, -0.41417, 0.05929, 0.72632, -1.15223, 1.2745 , -0.15947 }; static const float wr[122] = { 0.13119, -0.13164, -1.2736 , 1.06352, -1.34749, -1.03086, -0.27417, -0.27762, 0.79454, -1.12623, 2.1134 , -0.7003 , 0.26056, -1.13518, -1.64548, -1.30828, -0.96589, -0.36258, -1.14323, -0.2006 , -1.00307, 0.57739, -0.62693, 0.29721, -0.36996, -0.17462, 0.96704, 0.08902, 1.4337 , -0.47107, 0.82156, 0.14988, 1.74034, 1.13313, -0.32083, -0.00048, -0.86622, 1.12808, 0.99875, 0.8049 , -0.16841, -0.42677, -1.9409 , -0.53565, -0.83708, 0.69603, 0.32079, 0.56942, 0.67965, 1.49328, -1.65885, 0.96284, 0.63196, -0.27504, 0.39174, 0.71225, -0.3614 , 0.88761, 1.12882, 0.77764, 1.02618, -0.20245, -0.39245, -1.56799, 1.04888, -1.20858, -0.24361, -1.85157, -0.16912, 0.50512, -2.93122, 0.70477, -0.93066, 1.74867, 0.23963, -0.00699, -1.27183, -0.30604, 1.71039, 0.82202, -1.36734, -1.08352, -1.25054, 0.49436, -1.5037 , -0.73143, 0.74189, 0.32365, 0.30539, -0.72169, 0.41088, -1.56632, -0.63526, 0.58779, -0.05653, 0.76713, -1.40898, -0.33683, 1.86802, 0.59773, 1.28668, -0.65817, 2.46829, -0.09331, 2.9034 , 1.04809, 0.73222, -0.44372, 0.53044, -1.9274 , -1.57183, -1.14068, 1.26036, -0.9296 , 0.06662, -0.26572, -0.30862, 0.72915, 0.98977, 0.63513, -1.43917, -0.12523 }; 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