Skip to content

Commit

Permalink
Add game and board size affinity for bots
Browse files Browse the repository at this point in the history
  • Loading branch information
anoek committed Apr 17, 2023
1 parent 40f1a8e commit dba3f4b
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 18 deletions.
10 changes: 10 additions & 0 deletions src/Bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ export class Bot extends EventEmitter<Events> {
/** True if we are available for use by a Game. This flag is managed by the pool. */
available: boolean = true;

/* These are afinity fields used by our pool to try and select good bots to use */
last_game_id: number = -1;
last_width: number = -1;
last_height: number = -1;

log: (...arr: any[]) => any;
info: (...arr: any[]) => any;
trace: (...arr: any[]) => any;
Expand Down Expand Up @@ -561,6 +566,11 @@ export class Bot extends EventEmitter<Events> {
this.katafischer = false;
}

// Update our afinity fields
this.last_game_id = state.game_id;
this.last_width = state.width;
this.last_height = state.height;

if (state.width === state.height) {
await this.command(`boardsize ${state.width}`);
} else {
Expand Down
21 changes: 18 additions & 3 deletions src/Game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,11 +386,21 @@ export class Game extends EventEmitter<Events> {
config.opening_bot.number_of_opening_moves_to_play >= this.state.moves.length
) {
this.verbose("Acquiring opening bot instance");
this.bot = await bot_pools.opening.acquire(this.state.time_control.speed);
this.bot = await bot_pools.opening.acquire(
this.state.time_control.speed,
parseInt(this.state.width.toString()),
parseInt(this.state.height.toString()),
parseInt(this.state.game_id.toString()),
);
this.using_opening_bot = true;
} else {
this.verbose("Acquiring main bot instance");
this.bot = await bot_pools.main.acquire(this.state.time_control.speed);
this.bot = await bot_pools.main.acquire(
this.state.time_control.speed,
parseInt(this.state.width.toString()),
parseInt(this.state.height.toString()),
parseInt(this.state.game_id.toString()),
);
this.using_opening_bot = false;
}
this.bot.setGame(this);
Expand All @@ -415,7 +425,12 @@ export class Game extends EventEmitter<Events> {
`[game ${this.game_id}] Acquiring ending bot: ${this.state.moves.length} moves played out of ${move_to_start_checking_ending_bot} necessary to begin consulting ending bot`,
);

this.ending_bot = await bot_pools.ending.acquire(this.state.time_control.speed);
this.ending_bot = await bot_pools.ending.acquire(
this.state.time_control.speed,
parseInt(this.state.width.toString()),
parseInt(this.state.height.toString()),
parseInt(this.state.game_id.toString()),
);
this.ending_bot.verbose(`[game ${this.game_id}] Acquired resign bot instance`);
this.ending_bot.setGame(this);

Expand Down
53 changes: 38 additions & 15 deletions src/pools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class BotPool extends EventEmitter<Events> {
pool_name: string;
bot_config: BotConfig;
instances: Bot[] = [];
queue: [Speed, (bot: Bot) => void][] = [];
queue: [Speed, number, number, (bot: Bot) => void][] = [];
ready: Promise<string[]>;
log: (...arr: any[]) => any;
verbose: (...arr: any[]) => any;
Expand Down Expand Up @@ -70,18 +70,32 @@ export class BotPool extends EventEmitter<Events> {
});
}

async acquire(speed: Speed): Promise<Bot> {
async acquire(speed: Speed, width: number, height: number, game_id: number): Promise<Bot> {
trace.info(`Acquiring bot for ${speed} game`);
await this.ready;
for (let i = 0; i < this.instances.length; i++) {
const bot = this.instances[i];
if (bot.available) {
bot.available = false;
return bot;
for (const pass of ["game_id", "board_size", "any"]) {
for (let i = 0; i < this.instances.length; i++) {
const bot = this.instances[i];

/* We prioritize instances that have been playing this game, are already
* setup to play on this board size, or finally any that are available.
*/
const pass_check =
(pass === "game_id" && bot.last_game_id === game_id) ||
(pass === "board_size" &&
bot.last_width === width &&
bot.last_height === height) ||
pass === "any";

if (bot.available && pass_check) {
bot.available = false;
trace.info("Picked bot in " + pass + " pass");
return bot;
}
}
}
return new Promise((resolve) => {
this.queue.push([speed, resolve]);
this.queue.push([speed, width, height, resolve]);
});
}

Expand All @@ -92,13 +106,22 @@ export class BotPool extends EventEmitter<Events> {
release(bot: Bot): void {
bot.setGame(null);
if (this.queue.length > 0) {
for (const target_speed of ["blitz", "live", "correspondence"]) {
for (let i = 0; i < this.queue.length; i++) {
const [speed, resolve] = this.queue[i];
if (speed === target_speed) {
this.queue.splice(i, 1);
resolve(bot);
return;
for (const pass of ["board_size", "any"]) {
for (const target_speed of ["blitz", "live", "correspondence"]) {
for (let i = 0; i < this.queue.length; i++) {
const [speed, width, height, resolve] = this.queue[i];

const pass_check =
(pass === "board_size" &&
bot.last_width === width &&
bot.last_height === height) ||
pass === "any";

if (speed === target_speed && pass_check) {
this.queue.splice(i, 1);
resolve(bot);
return;
}
}
}
}
Expand Down

0 comments on commit dba3f4b

Please sign in to comment.