Skip to content

Commit

Permalink
eradicate threefolds
Browse files Browse the repository at this point in the history
  • Loading branch information
schlawg committed Jan 6, 2025
1 parent ac74ec0 commit 293ad87
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 27 deletions.
32 changes: 20 additions & 12 deletions ui/local/src/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function score(pv: Line, depth: number = pv.scores.length - 1): number {
export class Bot implements BotInfo, MoveSource {
private openings: Promise<OpeningBook[]>;
private stats: { cplMoves: number; cpl: number };
private traces: string[] = [];
private traces: string[];
readonly uid: string;
readonly version: number = 0;
name: string;
Expand All @@ -44,6 +44,7 @@ export class Bot implements BotInfo, MoveSource {
// keep these from being stored or cloned with the bot
Object.defineProperties(this, {
stats: { value: { cplMoves: 0, cpl: 0 } },
traces: { value: [], writable: true },
openings: {
get: () => Promise.all(this.books?.flatMap(b => env.assets.getBook(b.key)) ?? []),
},
Expand Down Expand Up @@ -71,28 +72,34 @@ export class Bot implements BotInfo, MoveSource {
const { fish, zero } = this;

this.trace([` ${env.game.live.ply}. '${this.name}' at '${co.fen.makeFen(chess.toSetup())}'`]);

this.trace(
`[move] - ${args.avoid?.length ? 'avoid = [' + args.avoid.join(', ') + '], ' : ''}` +
`${args.cp ? `cp = ${args.cp?.toFixed(2)}, ` : ''}remaining = ${args.remaining}`,
);
const opening = await this.bookMove(chess);
args.thinkTime = this.thinkTime(args);

// i need a better way to handle thinkTime, we probably need to adjust it in chooseMove
if (opening) return { uci: opening, thinkTime: args.thinkTime };

const zeroSearch = zero
? {
nodes: zero.nodes,
multipv: Math.max(zero.multipv, args.avoid.length + 1),
net: {
key: this.name + '-' + zero.net,
fetch: () => env.assets.getNet(zero.net),
},
}
: undefined;
const { uci, cpl, thinkTime } = this.chooseMove(
await Promise.all([
fish && env.bot.zerofish.goFish(pos, fish),
zero &&
env.bot.zerofish.goZero(pos, {
nodes: zero.nodes,
multipv: Math.max(zero.multipv, args.avoid.length + 1),
net: {
key: this.name + '-' + zero.net,
fetch: () => env.assets.getNet(zero.net),
},
}),
zeroSearch && env.bot.zerofish.goZero(pos, zeroSearch),
]),
args,
);
if (zeroSearch) this.trace(`[move] - ${stringify(zeroSearch)}`);
if (cpl !== undefined && cpl < 1000) {
this.stats.cplMoves++; // debug stats
this.stats.cpl += cpl;
Expand Down Expand Up @@ -127,7 +134,8 @@ export class Bot implements BotInfo, MoveSource {
const variateMax = Math.min(remaining, increment + initial / pace);
const thinkTime = quickest + Math.random() * variateMax;
this.trace(
`[thinkTime] - thinktime = ${thinkTime.toFixed(1)}, pace = ${pace.toFixed(1)}, quickest = ${quickest.toFixed(1)}, variateMax = ${variateMax.toFixed(1)}`,
`[thinkTime] - remaining = ${remaining.toFixed(1)}s, thinktime = ${thinkTime.toFixed(1)}s, pace = ` +
`${pace.toFixed(1)}, quickest = ${quickest.toFixed(1)}s, variateMax = ${variateMax.toFixed(1)}`,
);
return thinkTime;
}
Expand Down
10 changes: 8 additions & 2 deletions ui/local/src/dev/devCtrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,16 @@ export class DevCtrl {
const fen = env.game.live.fen;
const turn = env.game.turn;
if (ply === 0) {
const white = env.game.nameOf('white');
const black = env.game.nameOf('black');
const stringify = (obj: any) =>
JSON.stringify(obj, (_, v) => (!obj ? '' : typeof v === 'number' ? v.toFixed(2) : v));
this.trace.push(
`\n${white} vs ${black} ${env.game.speed} ${env.game.initial ?? ''}` +
`${env.game.increment ? `-${env.game.increment}` : ''} ${env.game.initialFen}`,
);
this.trace.push(`\nWhite: '${env.game.nameOf('white')}' ${stringify(env.bot.white)}`);
this.trace.push(`Black: '${env.game.nameOf('black')}' ${stringify(env.bot.black)}\n`);
this.trace.push(`Black: '${env.game.nameOf('black')}' ${stringify(env.bot.black)}`);
}
if (ply % 2 === 0) this.trace.push(`\n ${'-'.repeat(64)} Move ${ply / 2 + 1} ${'-'.repeat(64)}`);
if (!env.bot[turn]) this.trace.push(` ${ply}. '${env.game.nameOf(turn)}' at '${fen}': '${uci}'`);
Expand All @@ -116,7 +122,7 @@ export class DevCtrl {
`${matchup} - ${turn} ${reason} - ${env.game.live.fen} ${env.game.live.moves.join(' ')}`;
const result =
`${matchup}: ` + `${winner ? `${env.game.nameOf(winner)} wins by` : ''} ${status.name} ${reason ?? ''}`;
this.trace.push(` ${error || result}`);
this.trace.push(`\n ${error || result}\n`);
this.trace.push('='.repeat(144));
this.traceDb(this.trace.join('\n'));
this.trace = [];
Expand Down
8 changes: 5 additions & 3 deletions ui/local/src/dev/rateBot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class RateBot implements BotInfo, MoveSource {
books: Book[] = [];
sounds = {};
filters = {};
traceMove = '';
traceMove: string;

constructor(readonly level: number) {
const rating = (this.level + 8) * 75;
Expand All @@ -32,6 +32,7 @@ export class RateBot implements BotInfo, MoveSource {
rapid: rating,
classical: rating,
};
Object.defineProperty(this, 'traceMove', { value: '', writable: true });
}

get uid(): string {
Expand All @@ -45,16 +46,17 @@ export class RateBot implements BotInfo, MoveSource {
}

get description(): string {
return `Stockfish UCI_Elo ${this.ratings.classical} depth ${this.depth}`;
return `Stockfish ${this.ratings.classical} Skill Level ${this.level - 10} Depth ${this.depth}`;
}

async move({ pos }: MoveArgs): Promise<MoveResult> {
const ply = env.game.live.ply;
const turn = env.game.live.turn;

Check warning on line 54 in ui/local/src/dev/rateBot.ts

View workflow job for this annotation

GitHub Actions / lint

'turn' is assigned a value but never used. Allowed unused vars must match /^_/u
const fen = pos.fen;
const uci = (
await env.bot.zerofish.goFish(pos, { multipv: 1, level: this.level, by: { depth: this.depth } })
).bestmove;
this.traceMove = ` ${ply}. '${this.name} ${this.ratings.classical}' at '${pos.fen}': '${uci}'`;
this.traceMove = ` ${ply}. '${this.name} ${this.ratings.classical}' at '${fen}': '${uci}'`;
return { uci, thinkTime: 0.2 };
}
}
Expand Down
20 changes: 10 additions & 10 deletions ui/local/src/localGame.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as co from 'chessops';
import { makeFen } from 'chessops/fen';
//import { makeFen } from 'chessops/fen';
import { normalizeMove } from 'chessops/chess';
import { makeSanAndPlay } from 'chessops/san';
//import { makeSanAndPlay } from 'chessops/san';
import { statusOf } from 'game/status';
import { Status } from 'game';
import { deepFreeze } from 'common/algo';
Expand Down Expand Up @@ -58,11 +58,11 @@ export class LocalGame {
return this.moveResultWith({
end: true,
uci: move.uci,
reason: `${this.turn} made illegal move ${move.uci} at ${makeFen(this.chess.toSetup())}`,
reason: `${this.turn} made illegal move ${move.uci} at ${co.fen.makeFen(this.chess.toSetup())}`,
status: statusOf('cheat'), // bots are sneaky
});
}
const san = makeSanAndPlay(this.chess, coMove);
const san = co.san.makeSanAndPlay(this.chess, coMove);
const clock = move.clock ? { white: move.clock.white, black: move.clock.black } : undefined;
this.moves.push({ uci, clock });
this.fifty(coMove);
Expand All @@ -85,8 +85,8 @@ export class LocalGame {
updateThreefold(): boolean {
const boardFen = this.fen.split('-')[0];
let fenCount = this.threefoldFens.get(boardFen) ?? 0;
this.threefoldFens.set(boardFen, ++fenCount);
return fenCount >= 3;
this.threefoldFens.set(boardFen, fenCount + 1);
return fenCount > 1;
}

finish(finishStatus: Omit<GameStatus, 'end' | 'turn'>): void {
Expand Down Expand Up @@ -153,11 +153,11 @@ export class LocalGame {
}

get isThreefold(): boolean {
return (this.threefoldFens.get(this.fen.split('-')[0]) ?? 0) >= 3;
return (this.threefoldFens.get(this.fen.split('-')[0]) ?? 0) > 2;
}

get fen(): string {
return makeFen(this.chess.toSetup());
return co.fen.makeFen(this.chess.toSetup());
}

get dests(): { [from: string]: string } {
Expand All @@ -175,8 +175,8 @@ export class LocalGame {
for (const to of dests) {
const chess = this.chess.clone();
chess.play({ from, to });
const moveFen = makeFen(chess.toSetup()).split('-')[0];
if (moveFen !== boardFen && (this.threefoldFens.get(moveFen) ?? 0 >= 2))
const moveFen = co.fen.makeFen(chess.toSetup()).split('-')[0];
if (moveFen !== boardFen && (this.threefoldFens.get(moveFen) ?? 0) > 1)
draws.push(co.makeUci({ from, to }));
}
}
Expand Down

0 comments on commit 293ad87

Please sign in to comment.