32
32
* along with this program; if not, write to the Free Software
33
33
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35
* $Id: positionid.c,v 1.9 2001/04/24 12:35:50 thyssen Exp $
35
* $Id: positionid.c,v 1.33 2006/09/21 22:24:06 Superfly_Jon Exp $
38
39
#include <assert.h>
40
43
#include "positionid.h"
43
#if defined( __GNUC__ )
47
addBits(unsigned char auchKey[10], int bitPos, int nBits)
46
addBits(unsigned char auchKey[10], int const bitPos, int const nBits)
49
48
int const k = bitPos / 8;
50
49
int const r = (bitPos & 0x7);
87
extern char *PositionIDFromKey( unsigned char auchKey[ 10 ] ) {
86
extern char *PositionIDFromKey( const unsigned char auchKey[ 10 ] ) {
89
unsigned char *puch = auchKey;
88
const unsigned char *puch = auchKey;
90
89
static char szID[ 15 ];
92
static char aszBase64[ 64 ] =
91
static char aszBase64[ 65 ] =
93
92
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
121
120
return PositionIDFromKey( auch );
125
extern int CheckPosition( int anBoard[ 2 ][ 25 ] ) {
124
CheckPosition( int anBoard[ 2 ][ 25 ] )
128
/* Check for a point with a negative number of chequers */
129
for( i = 0; i < 25; i++ )
130
if( anBoard[ 0 ][ i ] < 0 ||
131
anBoard[ 1 ][ i ] < 0 ) {
129
136
/* Check for a player with over 15 chequers */
130
137
for( i = ac[ 0 ] = ac[ 1 ] = 0; i < 25; i++ )
131
138
if( ( ac[ 0 ] += anBoard[ 0 ][ i ] ) > 15 ||
132
139
( ac[ 1 ] += anBoard[ 1 ][ i ] ) > 15 ) {
137
144
/* Check for both players having chequers on the same point */
138
145
for( i = 0; i < 24; i++ )
139
146
if( anBoard[ 0 ][ i ] && anBoard[ 1 ][ 23 - i ] ) {
144
151
/* Check for both players on the bar against closed boards */
145
152
for( i = 0; i < 6; i++ )
146
153
if( anBoard[ 0 ][ i ] < 2 || anBoard[ 1 ][ i ] < 2 )
149
156
if( !anBoard[ 0 ][ 24 ] || !anBoard[ 1 ][ 24 ] )
163
extern void ClosestLegalPosition( int anBoard[ 2 ][ 25 ] ) {
165
int i, j, ac[ 2 ] = { 15, 15 };
167
/* Force a non-negative number of chequers on all points */
168
for( i = 0; i < 2; i++ )
169
for( j = 0; j < 25; j++ )
170
if( anBoard[ i ][ j ] < 0 )
171
anBoard[ i ][ j ] = 0;
173
/* Limit each player to 15 chequers */
174
for( i = 0; i < 2; i++ )
175
for( j = 0; j < 25; j++ )
176
if( ( ac[ i ] -= anBoard[ i ][ j ] ) < 0 ) {
177
anBoard[ i ][ j ] += ac[ i ];
181
/* Forbid both players having a chequer on the same point */
182
for( i = 0; i < 24; i++ )
183
if( anBoard[ 0 ][ i ] )
184
anBoard[ 1 ][ 23 - i ] = 0;
186
/* If both players have closed boards, let at least one of them off
188
for( i = 0; i < 6; i++ )
189
if( anBoard[ 0 ][ i ] < 2 || anBoard[ 1 ][ i ] < 2 )
193
if( anBoard[ 0 ][ 24 ] )
194
anBoard[ 1 ][ 24 ] = 0;
157
PositionFromKey(int anBoard[2][25], unsigned char* pauch)
198
PositionFromKey(int anBoard[2][25], const unsigned char* pauch)
159
200
int i = 0, j = 0, k;
201
const unsigned char* a;
162
203
memset(anBoard[0], 0, sizeof(anBoard[0]));
163
204
memset(anBoard[1], 0, sizeof(anBoard[1]));
199
extern int PositionFromID( int anBoard[ 2 ][ 25 ], char *pchEnc ) {
246
PositionFromID(int anBoard[ 2 ][ 25 ], const char* pchEnc)
201
248
unsigned char auchKey[ 10 ], ach[ 15 ], *pch = ach, *puch = auchKey;
251
memset ( ach, 0, 15 );
204
253
for( i = 0; i < 14 && pchEnc[ i ]; i++ )
205
pch[ i ] = Base64( pchEnc[ i ] );
254
pch[ i ] = (unsigned char)Base64( pchEnc[ i ] );
209
256
for( i = 0; i < 3; i++ ) {
210
257
*puch++ = ( pch[ 0 ] << 2 ) | ( pch[ 1 ] >> 4 );
211
258
*puch++ = ( pch[ 1 ] << 4 ) | ( pch[ 2 ] >> 2 );
247
static int anCombination[ 21 ][ 6 ], fCalculated = 0;
298
static int anCombination[ MAX_N ][ MAX_R ], fCalculated = 0;
249
300
static int InitCombination( void ) {
253
for( i = 0; i < 21; i++ )
304
for( i = 0; i < MAX_N; i++ )
254
305
anCombination[ i ][ 0 ] = i + 1;
256
for( j = 1; j < 6; j++ )
307
for( j = 1; j < MAX_R; j++ )
257
308
anCombination[ 0 ][ j ] = 0;
259
for( i = 1; i < 21; i++ )
260
for( j = 1; j < 6; j++ )
310
for( i = 1; i < MAX_N; i++ )
311
for( j = 1; j < MAX_R; j++ )
261
312
anCombination[ i ][ j ] = anCombination[ i - 1 ][ j - 1 ] +
262
313
anCombination[ i - 1 ][ j ];
269
static int Combination( int n, int r ) {
320
extern int Combination( const int n, const int r ) {
324
assert( n <= MAX_N );
325
assert( r <= MAX_R );
276
327
if( !fCalculated )
277
328
InitCombination();
279
330
return anCombination[ n - 1 ][ r - 1 ];
282
static int PositionF( int fBits, int n, int r ) {
333
static int PositionF( const int fBits, const int n, const int r ) {
288
339
PositionF( fBits, n - 1, r - 1 ) : PositionF( fBits, n - 1, r );
291
extern unsigned short PositionBearoff( int anBoard[ 6 ] ) {
343
unsigned int PositionBearoff( const int anBoard[],
295
for( j = 5, i = 0; i < 6; i++ )
349
for( j = nPoints - 1, i = 0; i < nPoints; i++ )
296
350
j += anBoard[ i ];
300
for( i = 0; i < 6; i++ ) {
354
for( i = 0; i < nPoints; i++ ) {
301
355
j -= anBoard[ i ] + 1;
302
356
fBits |= ( 1 << j );
305
return PositionF( fBits, 21, 6 );
360
return PositionF( fBits, nChequers + nPoints, nPoints );
308
363
static int PositionInv( int nID, int n, int r ) {
320
375
PositionInv( nID - nC, n - 1, r - 1 ) : PositionInv( nID, n - 1, r );
323
extern void PositionFromBearoff( int anBoard[ 6 ], unsigned short usID ) {
378
extern void PositionFromBearoff( int anBoard[], unsigned int usID,
379
int nPoints, int nChequers ) {
325
int fBits = PositionInv( usID, 21, 6 );
381
int fBits = PositionInv( usID, nChequers + nPoints, nPoints );
328
for( i = 0; i < 6; i++ )
384
for( i = 0; i < nPoints; i++ )
329
385
anBoard[ i ] = 0;
331
for( j = 5, i = 0; j >= 0 && i < 21; i++ ) {
387
for( j = nPoints - 1, i = 0; j >= 0 && i < ( nChequers + nPoints ); i++ ) {
332
388
if( fBits & ( 1 << i ) )
395
extern unsigned short
396
PositionIndex(int g, int anBoard[6])
401
for(i = 0; i < g; i++ )
406
for(i = 0; i < g; i++) {
407
j -= anBoard[ i ] + 1;
411
/* FIXME: 15 should be replaced by nChequers, but the function is
412
only called from bearoffgammon, so this should be fine. */
413
return (unsigned short)PositionF( fBits, 15, g );