On Tue, 29 Jul 2014, Ian Shaw wrote:

As I was pondering how gnubg evaluates positions, I realised that most of the time, the opponent's board layout is the same whatever move the player makes. There are only likely to be a couple of changes, when chequers are hit. If the opponent fails to enter from the bar, the position could even repeat across moves.

The results of calculate_half_inputs for the opposing side could therefore be re-used for many positions, which could lead to a saving in processing if they are cached. Is this done at present? Or would checking for a cache entry itself take up too much time?

calculate_half_inputs is really :

CalculateHalfInputs(const unsigned int anBoard[25],
                    const unsigned int anBoardOpp[25],
                    float afInput[])

It depends on all the checkers, not just those from one side.

Now, many inputs depend on one side only, and if a few of them are expensive to compute it could be worthwhile to split it in two functions and somehow cache this part of the inputs.

I have attached a profile of this function in case someone wants to look at it.


Something that's probably worth to be cached is the position of each side's most backward checker. I think it is computed three times for each evaluation : in ClassifyPosition, then in CalculateHalfInputs, then again in SanityCheck. It could probably be found in the move generation and put in an additional "pseudo board point". Finding the number of checkers on the board or borne off is done more times than necessary as well.


Another wasteful thing in inputs computation is that all inputs but one (I_BACKBONE) are really integers that are normalized (by an expensive floating point division) before being multiplied by the first layer of weights.

If the neural net inputs were left as integers (that means replacing I_BACKBONE by an approximation and retraining, and applying the normalization to the weights), I think CalculateHalfInputs would be faster.

At a minimum, whe should just cast the inputs to floats and leave the division part to the loading of the first layer of weights.

If the imputs were integers, checking if they are 0, 1 or something else on integers instead of floats may help in the neural net routines as well.
ROUTINE ====================== CalculateHalfInputs in 
/home/michel/src/gnubg-1.02.000/eval.c
 60175  67249 Total samples (flat / cumulative)
     .      .  720: 
     .      .  721: /* Calculates inputs for any contact position, for one 
player only. */
     .      .  722: 
     .      .  723: static void
     .      .  724: CalculateHalfInputs(const unsigned int anBoard[25], const 
unsigned int anBoardOpp[25], float afInput[])
---
    65     65  725: {
     .      .  726:     int i, j, k, l, nOppBack, n, aHit[39], nBoard;
     .      .  727: 
     .      .  728:     /* aanCombination[n] -
     .      .  729:      * How many ways to hit from a distance of n pips.
     .      .  730:      * Each number is an index into aIntermediate below. 
     .      .  731:      */
     .      .  732:     static const int aanCombination[24][5] = {
     .      .  733:         {0, -1, -1, -1, -1},    /*  1 */
     .      .  734:         {1, 2, -1, -1, -1},     /*  2 */
     .      .  735:         {3, 4, 5, -1, -1},      /*  3 */
     .      .  736:         {6, 7, 8, 9, -1},       /*  4 */
     .      .  737:         {10, 11, 12, -1, -1},   /*  5 */
     .      .  738:         {13, 14, 15, 16, 17},   /*  6 */
     .      .  739:         {18, 19, 20, -1, -1},   /*  7 */
     .      .  740:         {21, 22, 23, 24, -1},   /*  8 */
     .      .  741:         {25, 26, 27, -1, -1},   /*  9 */
     .      .  742:         {28, 29, -1, -1, -1},   /* 10 */
     .      .  743:         {30, -1, -1, -1, -1},   /* 11 */
     .      .  744:         {31, 32, 33, -1, -1},   /* 12 */
     .      .  745:         {-1, -1, -1, -1, -1},   /* 13 */
     .      .  746:         {-1, -1, -1, -1, -1},   /* 14 */
     .      .  747:         {34, -1, -1, -1, -1},   /* 15 */
     .      .  748:         {35, -1, -1, -1, -1},   /* 16 */
     .      .  749:         {-1, -1, -1, -1, -1},   /* 17 */
     .      .  750:         {36, -1, -1, -1, -1},   /* 18 */
     .      .  751:         {-1, -1, -1, -1, -1},   /* 19 */
     .      .  752:         {37, -1, -1, -1, -1},   /* 20 */
     .      .  753:         {-1, -1, -1, -1, -1},   /* 21 */
     .      .  754:         {-1, -1, -1, -1, -1},   /* 22 */
     .      .  755:         {-1, -1, -1, -1, -1},   /* 23 */
     .      .  756:         {38, -1, -1, -1, -1}    /* 24 */
     .      .  757:     };
     .      .  758: 
     .      .  759:     /* One way to hit */
     .      .  760:     typedef struct _Inter {
     .      .  761:         /* if true, all intermediate points (if any) are 
required;
     .      .  762:          * if false, one of two intermediate points are 
required.
     .      .  763:          * Set to true for a direct hit, but that can be 
checked with
     .      .  764:          * nFaces == 1,
     .      .  765:          */
     .      .  766:         int fAll;
     .      .  767: 
     .      .  768:         /* Intermediate points required */
     .      .  769:         int anIntermediate[3];
     .      .  770: 
     .      .  771:         /* Number of faces used in hit (1 to 4) */
     .      .  772:         int nFaces;
     .      .  773: 
     .      .  774:         /* Number of pips used to hit */
     .      .  775:         int nPips;
     .      .  776:     } Inter;
     .      .  777: 
     .      .  778:     const Inter *pi;
     .      .  779:     /* All ways to hit */
     .      .  780:     static const Inter aIntermediate[39] = {
     .      .  781:         {1, {0, 0, 0}, 1, 1},   /*  0: 1x hits 1 */
     .      .  782:         {1, {0, 0, 0}, 1, 2},   /*  1: 2x hits 2 */
     .      .  783:         {1, {1, 0, 0}, 2, 2},   /*  2: 11 hits 2 */
     .      .  784:         {1, {0, 0, 0}, 1, 3},   /*  3: 3x hits 3 */
     .      .  785:         {0, {1, 2, 0}, 2, 3},   /*  4: 21 hits 3 */
     .      .  786:         {1, {1, 2, 0}, 3, 3},   /*  5: 11 hits 3 */
     .      .  787:         {1, {0, 0, 0}, 1, 4},   /*  6: 4x hits 4 */
     .      .  788:         {0, {1, 3, 0}, 2, 4},   /*  7: 31 hits 4 */
     .      .  789:         {1, {2, 0, 0}, 2, 4},   /*  8: 22 hits 4 */
     .      .  790:         {1, {1, 2, 3}, 4, 4},   /*  9: 11 hits 4 */
     .      .  791:         {1, {0, 0, 0}, 1, 5},   /* 10: 5x hits 5 */
     .      .  792:         {0, {1, 4, 0}, 2, 5},   /* 11: 41 hits 5 */
     .      .  793:         {0, {2, 3, 0}, 2, 5},   /* 12: 32 hits 5 */
     .      .  794:         {1, {0, 0, 0}, 1, 6},   /* 13: 6x hits 6 */
     .      .  795:         {0, {1, 5, 0}, 2, 6},   /* 14: 51 hits 6 */
     .      .  796:         {0, {2, 4, 0}, 2, 6},   /* 15: 42 hits 6 */
     .      .  797:         {1, {3, 0, 0}, 2, 6},   /* 16: 33 hits 6 */
     .      .  798:         {1, {2, 4, 0}, 3, 6},   /* 17: 22 hits 6 */
     .      .  799:         {0, {1, 6, 0}, 2, 7},   /* 18: 61 hits 7 */
     .      .  800:         {0, {2, 5, 0}, 2, 7},   /* 19: 52 hits 7 */
     .      .  801:         {0, {3, 4, 0}, 2, 7},   /* 20: 43 hits 7 */
     .      .  802:         {0, {2, 6, 0}, 2, 8},   /* 21: 62 hits 8 */
     .      .  803:         {0, {3, 5, 0}, 2, 8},   /* 22: 53 hits 8 */
     .      .  804:         {1, {4, 0, 0}, 2, 8},   /* 23: 44 hits 8 */
     .      .  805:         {1, {2, 4, 6}, 4, 8},   /* 24: 22 hits 8 */
     .      .  806:         {0, {3, 6, 0}, 2, 9},   /* 25: 63 hits 9 */
     .      .  807:         {0, {4, 5, 0}, 2, 9},   /* 26: 54 hits 9 */
     .      .  808:         {1, {3, 6, 0}, 3, 9},   /* 27: 33 hits 9 */
     .      .  809:         {0, {4, 6, 0}, 2, 10},  /* 28: 64 hits 10 */
     .      .  810:         {1, {5, 0, 0}, 2, 10},  /* 29: 55 hits 10 */
     .      .  811:         {0, {5, 6, 0}, 2, 11},  /* 30: 65 hits 11 */
     .      .  812:         {1, {6, 0, 0}, 2, 12},  /* 31: 66 hits 12 */
     .      .  813:         {1, {4, 8, 0}, 3, 12},  /* 32: 44 hits 12 */
     .      .  814:         {1, {3, 6, 9}, 4, 12},  /* 33: 33 hits 12 */
     .      .  815:         {1, {5, 10, 0}, 3, 15}, /* 34: 55 hits 15 */
     .      .  816:         {1, {4, 8, 12}, 4, 16}, /* 35: 44 hits 16 */
     .      .  817:         {1, {6, 12, 0}, 3, 18}, /* 36: 66 hits 18 */
     .      .  818:         {1, {5, 10, 15}, 4, 20},        /* 37: 55 hits 20 */
     .      .  819:         {1, {6, 12, 18}, 4, 24} /* 38: 66 hits 24 */
     .      .  820:     };
     .      .  821: 
     .      .  822:     /* aaRoll[n] - All ways to hit with the n'th roll
     .      .  823:      * Each entry is an index into aIntermediate above.
     .      .  824:      */
     .      .  825: 
     .      .  826:     static const int aaRoll[21][4] = {
     .      .  827:         {0, 2, 5, 9},           /* 11 */
     .      .  828:         {0, 1, 4, -1},          /* 21 */
     .      .  829:         {1, 8, 17, 24},         /* 22 */
     .      .  830:         {0, 3, 7, -1},          /* 31 */
     .      .  831:         {1, 3, 12, -1},         /* 32 */
     .      .  832:         {3, 16, 27, 33},        /* 33 */
     .      .  833:         {0, 6, 11, -1},         /* 41 */
     .      .  834:         {1, 6, 15, -1},         /* 42 */
     .      .  835:         {3, 6, 20, -1},         /* 43 */
     .      .  836:         {6, 23, 32, 35},        /* 44 */
     .      .  837:         {0, 10, 14, -1},        /* 51 */
     .      .  838:         {1, 10, 19, -1},        /* 52 */
     .      .  839:         {3, 10, 22, -1},        /* 53 */
     .      .  840:         {6, 10, 26, -1},        /* 54 */
     .      .  841:         {10, 29, 34, 37},       /* 55 */
     .      .  842:         {0, 13, 18, -1},        /* 61 */
     .      .  843:         {1, 13, 21, -1},        /* 62 */
     .      .  844:         {3, 13, 25, -1},        /* 63 */
     .      .  845:         {6, 13, 28, -1},        /* 64 */
     .      .  846:         {10, 13, 30, -1},       /* 65 */
     .      .  847:         {13, 31, 36, 38}        /* 66 */
     .      .  848:     };
     .      .  849: 
     .      .  850:     /* One roll stat */
     .      .  851: 
     .      .  852:     struct {
     .      .  853:         /* count of pips this roll hits */
     .      .  854:         int nPips;
     .      .  855: 
     .      .  856:         /* number of chequers this roll hits */
     .      .  857:         int nChequers;
     .      .  858:     } aRoll[21];
     .      .  859: 
   213    213  860:     for (nOppBack = 24; nOppBack >= 0; --nOppBack) {
   177    177  861:         if (anBoardOpp[nOppBack]) {
     .      .  862:             break;
     .      .  863:         }
     .      .  864:     }
     .      .  865: 
   215    215  866:     nOppBack = 23 - nOppBack;
     .      .  867: 
     .      .  868:     n = 0;
   820    820  869:     for (i = nOppBack + 1; i < 25; i++)
   536    536  870:         if (anBoard[i])
  1350   1350  871:             n += (i + 1 - nOppBack) * anBoard[i];
     .      .  872: 
     .      .  873:     g_assert(n);
     .      .  874: 
     8      8  875:     afInput[I_BREAK_CONTACT] = n / (15 + 152.0f);
     .      .  876: 
     .      .  877:     {
     .      .  878:         unsigned int p = 0;
     .      .  879: 
   723    723  880:         for (i = 0; i < nOppBack; i++) {
   254    254  881:             if (anBoard[i])
   204    204  882:                 p += (i + 1) * anBoard[i];
     .      .  883:         }
     .      .  884: 
     7      7  885:         afInput[I_FREEPIP] = p / 100.0f;
     .      .  886:     }
     .      .  887: 
     .      .  888:     {
     .      .  889:         int t = 0;
     .      .  890: 
     .      .  891:         int no = 0;
     .      .  892: 
    60     60  893:         t += 24 * anBoard[24];
     9      9  894:         no += anBoard[24];
     .      .  895: 
   558    558  896:         for (i = 23; i >= 12 && i > nOppBack; --i) {
   375    375  897:             if (anBoard[i] && anBoard[i] != 2) {
   128    128  898:                 int n = ((anBoard[i] > 2) ? (anBoard[i] - 
2) : 1);
    47     47  899:                 no += n;
    40     40  900:                 t += i * n;
     .      .  901:             }
     .      .  902:         }
     .      .  903: 
   608    608  904:         for (; i >= 6; --i) {
   171    171  905:             if (anBoard[i]) {
     .      .  906:                 int n = anBoard[i];
    36     36  907:                 no += n;
   239    239  908:                 t += i * n;
     .      .  909:             }
     .      .  910:         }
     .      .  911: 
   382    382  912:         for (i = 5; i >= 0; --i) {
   232    232  913:             if (anBoard[i] > 2) {
   145    145  914:                 t += i * (anBoard[i] - 2);
    55     55  915:                 no += (anBoard[i] - 2);
   139    139  916:             } else if (anBoard[i] < 2) {
   207    207  917:                 int n = (2 - anBoard[i]);
     .      .  918: 
    20     20  919:                 if (no >= n) {
    25     25  920:                     t -= i * n;
     6      6  921:                     no -= n;
     .      .  922:                 }
     .      .  923:             }
     .      .  924:         }
     .      .  925: 
     .      .  926:         if (t < 0) {
     .      .  927:             t = 0;
     .      .  928:         }
     .      .  929: 
   635    635  930:         afInput[I_TIMING] = t / 100.0f;
     .      .  931:     }
     .      .  932: 
     .      .  933:     /* Back chequer */
     .      .  934: 
     .      .  935:     {
     .      .  936:         int nBack;
     .      .  937: 
   152    152  938:         for (nBack = 24; nBack >= 0; --nBack) {
    75     75  939:             if (anBoard[nBack]) {
     .      .  940:                 break;
     .      .  941:             }
     .      .  942:         }
     .      .  943: 
   330    330  944:         afInput[I_BACK_CHEQUER] = nBack / 24.0f;
     .      .  945: 
     .      .  946:         /* Back anchor */
     .      .  947: 
   161    161  948:         for (i = ((nBack == 24) ? 23 : nBack); i >= 0; --i) 
{
   442    442  949:             if (anBoard[i] >= 2) {
     4      4  950:                 break;
     .      .  951:             }
     .      .  952:         }
     .      .  953: 
    15     15  954:         afInput[I_BACK_ANCHOR] = i / 24.0f;
     .      .  955: 
     .      .  956:         /* Forward anchor */
     .      .  957: 
     .      .  958:         n = 0;
    48     48  959:         for (j = 18; j <= i; ++j) {
    20     20  960:             if (anBoard[j] >= 2) {
     6      6  961:                 n = 24 - j;
     .      .  962:                 break;
     .      .  963:             }
     .      .  964:         }
     .      .  965: 
    15     15  966:         if (n == 0) {
   129    129  967:             for (j = 17; j >= 12; --j) {
    53     53  968:                 if (anBoard[j] >= 2) {
    24     24  969:                     n = 24 - j;
     .      .  970:                     break;
     .      .  971:                 }
     .      .  972:             }
     .      .  973:         }
     .      .  974: 
   458    458  975:         afInput[I_FORWARD_ANCHOR] = n == 0 ? 2.0f : n / 
6.0f;
     .      .  976:     }
     .      .  977: 
     .      .  978: 
     .      .  979:     /* Piploss */
     .      .  980: 
     .      .  981:     nBoard = 0;
   167    167  982:     for (i = 0; i < 6; i++)
     .      .  983:         if (anBoard[i])
   180    180  984:             nBoard++;
     .      .  985: 
   143    143  986:     memset(aHit, 0, sizeof(aHit));
     .      .  987: 
     .      .  988:     /* for every point we'd consider hitting a blot on, */
     .      .  989: 
  1656   1656  990:     for (i = (nBoard > 2) ? 23 : 21; i >= 0; i--)
     .      .  991:         /* if there's a blot there, then */
     .      .  992: 
   646    646  993:         if (anBoardOpp[i] == 1)
     .      .  994:             /* for every point beyond */
     .      .  995: 
  1945   1945  996:             for (j = 24 - i; j < 25; j++)
     .      .  997:                 /* if we have a hitter and are willing to 
hit */
     .      .  998: 
  1275   1275  999:                 if (anBoard[j] && !(j < 6 && anBoard[j] == 
2))
     .      . 1000:                     /* for every roll that can hit from 
that point */
     .      . 1001: 
   159    159 1002:                     for (n = 0; n < 5; n++) {
   491    491 1003:                         if (aanCombination[j - 24 + i][n] 
== -1)
     .      . 1004:                             break;
     .      . 1005: 
     .      . 1006:                         /* find the intermediate points 
required to play */
     .      . 1007: 
   280    280 1008:                         pi = aIntermediate + 
aanCombination[j - 24 + i][n];
     .      . 1009: 
   364    364 1010:                         if (pi->fAll) {
     .      . 1011:                             /* if nFaces is 1, there are no 
intermediate points */
     .      . 1012: 
   396    396 1013:                             if (pi->nFaces > 1) {
     .      . 1014:                                 /* all the intermediate 
points are required */
     .      . 1015: 
   281    281 1016:                                 for (k = 0; k < 3 && 
pi->anIntermediate[k] > 0; k++)
   344    344 1017:                                     if (anBoardOpp[i - 
pi->anIntermediate[k]] > 1)
     .      . 1018:                                         /* point is 
blocked; look for other hits */
    43     43 1019:                                         goto cannot_hit;
     .      . 1020:                             }
     .      . 1021:                         } else {
     .      . 1022:                             /* either of two points are 
required */
     .      . 1023: 
   474    474 1024:                             if (anBoardOpp[i - 
pi->anIntermediate[0]] > 1 && anBoardOpp[i - pi->anIntermediate[1]] > 1) {
     .      . 1025:                                 /* both are blocked; look 
for other hits */
     .      . 1026:                                 goto cannot_hit;
     .      . 1027:                             }
     .      . 1028:                         }
     .      . 1029: 
     .      . 1030:                         /* enter this shot as available */
     .      . 1031: 
   325    325 1032:                         aHit[aanCombination[j - 24 + i][n]] 
|= 1 << j;
    95     95 1033:                       cannot_hit:;
     .      . 1034:                     }
     .      . 1035: 
   227    227 1036:     memset(aRoll, 0, sizeof(aRoll));
     .      . 1037: 
    35     35 1038:     if (!anBoard[24]) {
     .      . 1039:         /* we're not on the bar; for each roll, */
     .      . 1040: 
   406    406 1041:         for (i = 0; i < 21; i++) {
     .      . 1042:             n = -1;             /* (hitter used) */
     .      . 1043: 
     .      . 1044:             /* for each way that roll hits, */
  2919   2919 1045:             for (j = 0; j < 4; j++) {
   708    708 1046:                 int r = aaRoll[i][j];
     .      . 1047: 
  1061   1061 1048:                 if (r < 0)
     .      . 1049:                     break;
     .      . 1050: 
  1562   1562 1051:                 if (!aHit[r])
     .      . 1052:                     continue;
     .      . 1053: 
  1286   1286 1054:                 pi = aIntermediate + r;
     .      . 1055: 
   498    498 1056:                 if (pi->nFaces == 1) {
     .      . 1057:                     /* direct shot */
   936    936 1058:                     for (k = 23; k > 0; k--) {
  1295   1295 1059:                         if (aHit[r] & (1 << k)) {
     .      . 1060:                             /* select the most advanced 
blot; if we still have
     .      . 1061:                              * a chequer that can hit there 
*/
     .      . 1062: 
  1082   1082 1063:                             if (n != k || anBoard[k] > 1)
    93     93 1064:                                 aRoll[i].nChequers++;
     .      . 1065: 
     .      . 1066:                             n = k;
     .      . 1067: 
   340    340 1068:                             if (k - pi->nPips + 1 > 
aRoll[i].nPips)
    68     68 1069:                                 aRoll[i].nPips = k - 
pi->nPips + 1;
     .      . 1070: 
     .      . 1071:                             /* if rolling doubles, check 
for multiple
     .      . 1072:                              * direct shots */
     .      . 1073: 
   832    832 1074:                             if (aaRoll[i][3] >= 0 && 
aHit[r] & ~(1 << k))
    31     31 1075:                                 aRoll[i].nChequers++;
     .      . 1076: 
     .      . 1077:                             break;
     .      . 1078:                         }
     .      . 1079:                     }
     .      . 1080:                 } else {
     .      . 1081:                     /* indirect shot */
   273    273 1082:                     if (!aRoll[i].nChequers)
   175    175 1083:                         aRoll[i].nChequers = 1;
     .      . 1084: 
     .      . 1085:                     /* find the most advanced hitter */
     .      . 1086: 
   669    669 1087:                     for (k = 23; k >= 0; k--)
   583    583 1088:                         if (aHit[r] & (1 << k))
     .      . 1089:                             break;
     .      . 1090: 
   768    768 1091:                     if (k - pi->nPips + 1 > aRoll[i].nPips)
   178    178 1092:                         aRoll[i].nPips = k - pi->nPips + 1;
     .      . 1093: 
     .      . 1094:                     /* check for blots hit on intermediate 
points */
     .      . 1095: 
   846    846 1096:                     for (l = 0; l < 3 && 
pi->anIntermediate[l] > 0; l++)
   340    340 1097:                         if (anBoardOpp[23 - k + 
pi->anIntermediate[l]] == 1) {
     .      . 1098: 
    13     13 1099:                             aRoll[i].nChequers++;
    55     55 1100:                             break;
     .      . 1101:                         }
     .      . 1102:                 }
     .      . 1103:             }
     .      . 1104:         }
    10     10 1105:     } else if (anBoard[24] == 1) {
     .      . 1106:         /* we have one on the bar; for each roll, */
     .      . 1107: 
   321    321 1108:         for (i = 0; i < 21; i++) {
     .      . 1109:             n = 0;              /* (free to use either die 
to enter) */
     .      . 1110: 
   435    435 1111:             for (j = 0; j < 4; j++) {
   103    103 1112:                 int r = aaRoll[i][j];
     .      . 1113: 
   137    137 1114:                 if (r < 0)
     .      . 1115:                     break;
     .      . 1116: 
   168    168 1117:                 if (!aHit[r])
     .      . 1118:                     continue;
     .      . 1119: 
   217    217 1120:                 pi = aIntermediate + r;
     .      . 1121: 
   106    106 1122:                 if (pi->nFaces == 1) {
     .      . 1123:                     /* direct shot */
     .      . 1124: 
   359    359 1125:                     for (k = 24; k > 0; k--) {
   446    446 1126:                         if (aHit[r] & (1 << k)) {
     .      . 1127:                             /* if we need this die to 
enter, we can't hit elsewhere */
     .      . 1128: 
   344    344 1129:                             if (n && k != 24)
     .      . 1130:                                 break;
     .      . 1131: 
     .      . 1132:                             /* if this isn't a shot from 
the bar, the
     .      . 1133:                              * other die must be used to 
enter */
     .      . 1134: 
    22     22 1135:                             if (k != 24) {
     .      . 1136:                                 int npip = 
aIntermediate[aaRoll[i][1 - j]].nPips;
     .      . 1137: 
    67     67 1138:                                 if (anBoardOpp[npip - 1] > 
1)
     7      7 1139:                                     break;
     .      . 1140: 
     .      . 1141:                                 n = 1;
     .      . 1142:                             }
     .      . 1143: 
    66     66 1144:                             aRoll[i].nChequers++;
     .      . 1145: 
    59     59 1146:                             if (k - pi->nPips + 1 > 
aRoll[i].nPips)
     6      6 1147:                                 aRoll[i].nPips = k - 
pi->nPips + 1;
     .      . 1148:                         }
     .      . 1149:                     }
     .      . 1150:                 } else {
     .      . 1151:                     /* indirect shot -- consider from the 
bar only */
    73     73 1152:                     if (!(aHit[r] & (1 << 24)))
     .      . 1153:                         continue;
     .      . 1154: 
    33     33 1155:                     if (!aRoll[i].nChequers)
     3      3 1156:                         aRoll[i].nChequers = 1;
     .      . 1157: 
    23     23 1158:                     if (25 - pi->nPips > aRoll[i].nPips)
    12     12 1159:                         aRoll[i].nPips = 25 - pi->nPips;
     .      . 1160: 
     .      . 1161:                     /* check for blots hit on intermediate 
points */
    90     90 1162:                     for (k = 0; k < 3 && 
pi->anIntermediate[k] > 0; k++)
    19     19 1163:                         if 
(anBoardOpp[pi->anIntermediate[k] + 1] == 1) {
     .      . 1164: 
    15     15 1165:                             aRoll[i].nChequers++;
     6      6 1166:                             break;
     .      . 1167:                         }
     .      . 1168:                 }
     .      . 1169:             }
     .      . 1170:         }
     .      . 1171:     } else {
     .      . 1172:         /* we have more than one on the bar --
     .      . 1173:          * count only direct shots from point 24 */
     .      . 1174: 
   273    273 1175:         for (i = 0; i < 21; i++) {
     .      . 1176:             /* for the first two ways that hit from the bar 
*/
     .      . 1177: 
    20     20 1178:             for (j = 0; j < 2; j++) {
     1      1 1179:                 int r = aaRoll[i][j];
     .      . 1180: 
    18     18 1181:                 if (!(aHit[r] & (1 << 24)))
     .      . 1182:                     continue;
     .      . 1183: 
     7      7 1184:                 pi = aIntermediate + r;
     .      . 1185: 
     .      . 1186:                 /* only consider direct shots */
     .      . 1187: 
     2      2 1188:                 if (pi->nFaces != 1)
     .      . 1189:                     continue;
     .      . 1190: 
     .      . 1191:                 aRoll[i].nChequers++;
     .      . 1192: 
     2      2 1193:                 if (25 - pi->nPips > aRoll[i].nPips)
     1      1 1194:                     aRoll[i].nPips = 25 - pi->nPips;
     .      . 1195:             }
     .      . 1196:         }
     .      . 1197:     }
     .      . 1198: 
     .      . 1199:     {
     .      . 1200:         int np = 0;
     .      . 1201:         int n1 = 0;
     .      . 1202:         int n2 = 0;
     .      . 1203: 
   546    546 1204:         for (i = 0; i < 21; i++) {
   566    566 1205:             int w = aaRoll[i][3] > 0 ? 1 : 2;
   147    147 1206:             int nc = aRoll[i].nChequers;
     .      . 1207: 
   397    397 1208:             np += aRoll[i].nPips * w;
     .      . 1209: 
   485    485 1210:             if (nc > 0) {
    12     12 1211:                 n1 += w;
     .      . 1212: 
   365    365 1213:                 if (nc > 1) {
   237    237 1214:                     n2 += w;
     .      . 1215:                 }
     .      . 1216:             }
     .      . 1217:         }
     .      . 1218: 
   240    240 1219:         afInput[I_PIPLOSS] = np / (12.0f * 36.0f);
     .      . 1220: 
   219    219 1221:         afInput[I_P1] = n1 / 36.0f;
   245    245 1222:         afInput[I_P2] = n2 / 36.0f;
     .      . 1223:     }
     .      . 1224: 
   645   1126 1225:     afInput[I_BACKESCAPES] = Escapes(anBoard, 23 - 
nOppBack) / 36.0f;
     .      . 1226: 
   439   1016 1227:     afInput[I_BACKRESCAPES] = Escapes1(anBoard, 23 - 
nOppBack) / 36.0f;
     .      . 1228: 
  1008   1008 1229:     for (n = 36, i = 15; i < 24 - nOppBack; i++)
   299   2579 1230:         if ((j = Escapes(anBoard, i)) < n)
     .      . 1231:             n = j;
     .      . 1232: 
    11     11 1233:     afInput[I_ACONTAIN] = (36 - n) / 36.0f;
     5      5 1234:     afInput[I_ACONTAIN2] = afInput[I_ACONTAIN] * 
afInput[I_ACONTAIN];
     .      . 1235: 
    31     31 1236:     if (nOppBack < 0) {
     .      . 1237:         /* restart loop, point 24 should not be included */
     .      . 1238:         i = 15;
     .      . 1239:         n = 36;
     .      . 1240:     }
     .      . 1241: 
   873    873 1242:     for (; i < 24; i++)
   261   2156 1243:         if ((j = Escapes(anBoard, i)) < n)
     .      . 1244:             n = j;
     .      . 1245: 
     .      . 1246: 
     2      2 1247:     afInput[I_CONTAIN] = (36 - n) / 36.0f;
    16     16 1248:     afInput[I_CONTAIN2] = afInput[I_CONTAIN] * 
afInput[I_CONTAIN];
     .      . 1249: 
   935    935 1250:     for (n = 0, i = 6; i < 25; i++)
   505    505 1251:         if (anBoard[i])
   768   2609 1252:             n += (i - 5) * anBoard[i] * Escapes(anBoardOpp, 
i);
     .      . 1253: 
   512    512 1254:     afInput[I_MOBILITY] = n / 3600.0f;
     .      . 1255: 
     .      . 1256:     j = 0;
     .      . 1257:     n = 0;
   867    867 1258:     for (i = 0; i < 25; i++) {
   282    282 1259:         int ni = anBoard[i];
     .      . 1260: 
   172    172 1261:         if (ni) {
    50     50 1262:             j += ni;
   802    802 1263:             n += i * ni;
     .      . 1264:         }
     .      . 1265:     }
     .      . 1266: 
   190    190 1267:     if (j) {
   461    461 1268:         n = (n + j - 1) / j;
     .      . 1269:     }
     .      . 1270: 
     .      . 1271:     j = 0;
   160    160 1272:     for (k = 0, i = n + 1; i < 25; i++) {
    51     51 1273:         int ni = anBoard[i];
     .      . 1274: 
   175    175 1275:         if (ni) {
    47     47 1276:             j += ni;
  1003   1003 1277:             k += ni * (i - n) * (i - n);
     .      . 1278:         }
     .      . 1279:     }
     .      . 1280: 
   673    673 1281:     if (j) {
     .      . 1282:         k = (k + j - 1) / j;
     .      . 1283:     }
     .      . 1284: 
    19     19 1285:     afInput[I_MOMENT2] = k / 400.0f;
     .      . 1286: 
   308    308 1287:     if (anBoard[24] > 0) {
     .      . 1288:         int loss = 0;
     9      9 1289:         int two = anBoard[24] > 1;
     .      . 1290: 
     7      7 1291:         for (i = 0; i < 6; ++i) {
    30     30 1292:             if (anBoardOpp[i] > 1) {
     .      . 1293:                 /* any double loses */
     .      . 1294: 
    20     20 1295:                 loss += 4 * (i + 1);
     .      . 1296: 
    26     26 1297:                 for (j = i + 1; j < 6; ++j) {
     8      8 1298:                     if (anBoardOpp[j] > 1) {
     7      7 1299:                         loss += 2 * (i + j + 2);
     .      . 1300:                     } else {
    14     14 1301:                         if (two) {
    10     10 1302:                             loss += 2 * (i + 1);
     .      . 1303:                         }
     .      . 1304:                     }
     .      . 1305:                 }
     .      . 1306:             } else {
    20     20 1307:                 if (two) {
    19     19 1308:                     for (j = i + 1; j < 6; ++j) {
     7      7 1309:                         if (anBoardOpp[j] > 1) {
     4      4 1310:                             loss += 2 * (j + 1);
     .      . 1311:                         }
     .      . 1312:                     }
     .      . 1313:                 }
     .      . 1314:             }
     .      . 1315:         }
     .      . 1316: 
    69     69 1317:         afInput[I_ENTER] = loss / (36.0f * (49.0f / 6.0f));
     .      . 1318:     } else {
    23     23 1319:         afInput[I_ENTER] = 0.0f;
     .      . 1320:     }
     .      . 1321: 
     .      . 1322:     n = 0;
    24     24 1323:     for (i = 0; i < 6; i++) {
   203    203 1324:         n += anBoardOpp[i] > 1;
     .      . 1325:     }
     .      . 1326: 
   438    438 1327:     afInput[I_ENTER2] = (36 - (n - 6) * (n - 6)) / 36.0f;
     .      . 1328: 
     .      . 1329:     {
     .      . 1330:         int pa = -1;
     .      . 1331:         int w = 0;
     .      . 1332:         int tot = 0;
     .      . 1333:         int np;
     .      . 1334: 
   722    722 1335:         for (np = 23; np > 0; --np) {
   495    495 1336:             if (anBoard[np] >= 2) {
   526    526 1337:                 if (pa == -1) {
     .      . 1338:                     pa = np;
     .      . 1339:                     continue;
     .      . 1340:                 }
     .      . 1341: 
     .      . 1342:                 {
    37     37 1343:                     int d = pa - np;
     .      . 1344:                     int c = 0;
     .      . 1345: 
   141    141 1346:                     if (d <= 6) {
     .      . 1347:                         c = 11;
   191    191 1348:                     } else if (d <= 11) {
     .      . 1349:                         c = 13 - d;
     .      . 1350:                     }
     .      . 1351: 
   152    152 1352:                     w += c * anBoard[pa];
    85     85 1353:                     tot += anBoard[pa];
     .      . 1354:                 }
     .      . 1355:             }
     .      . 1356:         }
     .      . 1357: 
   194    194 1358:         if (tot) {
   439    439 1359:             afInput[I_BACKBONE] = 1 - (w / (tot * 11.0f));
     .      . 1360:         } else {
    56     56 1361:             afInput[I_BACKBONE] = 0;
     .      . 1362:         }
     .      . 1363:     }
     .      . 1364: 
     .      . 1365:     {
     .      . 1366:         unsigned int nAc = 0;
     .      . 1367: 
    12     12 1368:         for (i = 18; i < 24; ++i) {
     .      . 1369:             if (anBoard[i] > 1) {
   129    129 1370:                 ++nAc;
     .      . 1371:             }
     .      . 1372:         }
     .      . 1373: 
    57     57 1374:         afInput[I_BACKG] = 0.0;
    10     10 1375:         afInput[I_BACKG1] = 0.0;
     .      . 1376: 
    13     13 1377:         if (nAc >= 1) {
     .      . 1378:             unsigned int tot = 0;
    19     19 1379:             for (i = 18; i < 25; ++i) {
    44     44 1380:                 tot += anBoard[i];
     .      . 1381:             }
     .      . 1382: 
    54     54 1383:             if (nAc > 1) {
     .      . 1384:                 /* g_assert( tot >= 4 ); */
     .      . 1385: 
    31     31 1386:                 afInput[I_BACKG] = (tot - 3) / 4.0f;
     1      1 1387:             } else if (nAc == 1) {
   127    127 1388:                 afInput[I_BACKG1] = tot / 8.0f;
     .      . 1389:             }
     .      . 1390:         }
     .      . 1391:     }
    38     38 1392: }
---
     .      . 1393: 
     .      . 1394: 
     .      . 1395: extern void
     .      . 1396: CalculateRaceInputs(const TanBoard anBoard, float inputs[])
     .      . 1397: {
_______________________________________________
Bug-gnubg mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/bug-gnubg

Reply via email to