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