Files
Pierre MARTINandClaude Opus 5.5 792f6395bf Copie figée du cœur de GNU Backgammon (commit 14b6798)
Fichiers repris sans modification dans engine/gnubg/, poids et table
d'équité Kazaross-XG2 dans engine/data/, provenance détaillée dans
engine/gnubg/PROVENANCE.md. Le lint ne vérifie plus les espaces de ces
copies, pour qu'elles restent identiques à l'original.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 13:56:23 +01:00

284 lines
6.9 KiB
C

/*
* Copyright (C) 2002-2003 Joern Thyssen <jthyssen@dk.ibm.com>
* Copyright (C) 2004-2013 the AUTHORS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* $Id: matchid.c,v 1.30 2021/12/18 22:06:37 plm Exp $
*/
#include "config.h"
#include "backgammon.h"
#include "positionid.h"
#include "matchequity.h"
#include "matchid.h"
#include <string.h>
/*
* Calculate log2 of Cube value.
*
* Input:
* n: cube value
*
* Returns:
* log(n)/log(2)
*
*/
extern int
LogCube(int n)
{
int i = 0;
while (n >>= 1)
i++;
return i;
}
static void
SetBit(unsigned char *pc, unsigned int bitPos, int test, unsigned int iBit)
{
const unsigned int k = bitPos / 8;
const unsigned char rbit = (unsigned char) (0x1 << (bitPos % 8));
unsigned char c;
if (test & (0x1 << iBit))
c = rbit;
else
c = 0;
pc[k] = (pc[k] & (0xFF ^ rbit)) | c;
}
static void
SetBits(unsigned char *pc, unsigned int bitPos, unsigned int nBits, int iContent)
{
unsigned int i;
/* FIXME: rewrite SetBit, SetBits to be faster */
for (i = 0; i < nBits; i++) {
SetBit(pc, bitPos + i, iContent, i);
}
}
static void
GetBits(const unsigned char *pc, const unsigned int bitPos, const unsigned int nBits, int *piContent)
{
unsigned int i, j;
unsigned char c[2];
/* FIXME: rewrite GetBits to be faster */
c[0] = 0;
c[1] = 0;
for (i = 0, j = bitPos; i < nBits; i++, j++) {
unsigned int k, r;
k = j / 8;
r = j % 8;
SetBit(c, i, pc[k], r);
}
*piContent = c[0] | (c[1] << 8);
}
static char *
MatchIDFromKey(unsigned char auchKey[9])
{
unsigned char *puch = auchKey;
static char szID[L_MATCHID + 1];
char *pch = szID;
static const char aszBase64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int i;
for (i = 0; i < 3; i++) {
*pch++ = aszBase64[puch[0] >> 2];
*pch++ = aszBase64[((puch[0] & 0x03) << 4) | (puch[1] >> 4)];
*pch++ = aszBase64[((puch[1] & 0x0F) << 2) | (puch[2] >> 6)];
*pch++ = aszBase64[puch[2] & 0x3F];
puch += 3;
}
*pch = 0;
return szID;
}
extern char *
MatchID(const unsigned int anDice[2],
const int fTurn,
const int fResigned,
const int fDoubled,
const int fMove,
const int fCubeOwner, const int fCrawford, const int nMatchTo, const int anScore[2], const int nCube,
const int fJacobyInUse, const gamestate gs)
{
unsigned char auchKey[9];
memset(auchKey, 0, 9);
SetBits(auchKey, 0, 4, LogCube(nCube));
SetBits(auchKey, 4, 2, fCubeOwner & 0x3);
SetBits(auchKey, 6, 1, fMove);
SetBits(auchKey, 7, 1, fCrawford);
SetBits(auchKey, 8, 3, (int) gs);
SetBits(auchKey, 11, 1, fTurn);
SetBits(auchKey, 12, 1, fDoubled);
SetBits(auchKey, 13, 2, fResigned);
if (anDice[0] >= anDice[1]) {
SetBits(auchKey, 15, 3, anDice[0] & 0x7);
SetBits(auchKey, 18, 3, anDice[1] & 0x7);
} else {
SetBits(auchKey, 15, 3, anDice[1] & 0x7);
SetBits(auchKey, 18, 3, anDice[0] & 0x7);
}
SetBits(auchKey, 21, 15, nMatchTo & 0x7FFF);
SetBits(auchKey, 36, 15, anScore[0] & 0x7FFF);
SetBits(auchKey, 51, 15, anScore[1] & 0x7FFF);
SetBits(auchKey, 66, 1, (!fJacobyInUse));
return MatchIDFromKey(auchKey);
}
static int
MatchFromKey(int anDice[2],
int *pfTurn,
int *pfResigned,
int *pfDoubled,
int *pfMove, int *pfCubeOwner, int *pfCrawford, int *pnMatchTo, int anScore[2], int *pnCube,
int *pfJacoby, gamestate * pgs, const unsigned char *auchKey)
{
int temp;
GetBits(auchKey, 0, 4, pnCube);
*pnCube = 0x1 << *pnCube;
GetBits(auchKey, 4, 2, pfCubeOwner);
if (*pfCubeOwner && *pfCubeOwner != 1)
*pfCubeOwner = -1;
GetBits(auchKey, 6, 1, pfMove);
GetBits(auchKey, 7, 1, pfCrawford);
GetBits(auchKey, 8, 3, &temp);
*pgs = (gamestate) temp;
GetBits(auchKey, 11, 1, pfTurn);
GetBits(auchKey, 12, 1, pfDoubled);
GetBits(auchKey, 13, 2, pfResigned);
GetBits(auchKey, 15, 3, &anDice[0]);
GetBits(auchKey, 18, 3, &anDice[1]);
GetBits(auchKey, 21, 15, pnMatchTo);
GetBits(auchKey, 36, 15, &anScore[0]);
GetBits(auchKey, 51, 15, &anScore[1]);
GetBits(auchKey, 66, 1, pfJacoby);
*pfJacoby = !(*pfJacoby);
/* FIXME: implement a consistency check */
if (anDice[0] < 0 || anDice[0] > 6)
return -1;
if (anDice[1] < 0 || anDice[1] > 6)
return -1;
if (*pnMatchTo < 0 || *pnMatchTo > MAXSCORE)
return -1;
if (*pnMatchTo) {
if (anScore[0] < 0 || anScore[0] > *pnMatchTo)
return -1;
if (anScore[1] < 0 || anScore[1] > *pnMatchTo)
return -1;
} else {
/* money game */
if (*pfCrawford)
/* no Crawford game in money play */
return -1;
}
return 0;
}
extern int
MatchFromID(unsigned int anDice[2],
int *pfTurn,
int *pfResigned,
int *pfDoubled, int *pfMove, int *pfCubeOwner, int *pfCrawford, int *pnMatchTo, int anScore[2], int *pnCube,
int *pfJacoby, gamestate * pgs, const char *szMatchID)
{
unsigned char auchKey[9];
unsigned char *puch = auchKey;
unsigned char ach[L_MATCHID + 1];
unsigned char *pch = ach;
int i;
memset(ach, 0, sizeof(ach));
/* decode base64 into key */
for (i = 0; i < L_MATCHID && szMatchID[i]; i++)
pch[i] = Base64((unsigned char) szMatchID[i]);
for (i = 0; i < 3; i++) {
*puch++ = (unsigned char) (pch[0] << 2) | (pch[1] >> 4);
*puch++ = (unsigned char) (pch[1] << 4) | (pch[2] >> 2);
*puch++ = (unsigned char) (pch[2] << 6) | pch[3];
pch += 4;
}
/* get matchstate info from the key */
return MatchFromKey((int *) anDice, pfTurn, pfResigned, pfDoubled, pfMove, pfCubeOwner, pfCrawford, pnMatchTo,
(int *) anScore, pnCube, pfJacoby, pgs, auchKey);
}
/*
* Generate match ID from matchstate
*
* Input:
* pms: match state
*
*/
extern char *
MatchIDFromMatchState(const matchstate * pms)
{
return MatchID(pms->anDice,
pms->fTurn,
pms->fResigned,
pms->fDoubled, pms->fMove, pms->fCubeOwner, pms->fCrawford, pms->nMatchTo, pms->anScore, pms->nCube,
pms->fJacoby, pms->gs);
}