Skip to content

Commit

Permalink
chore: remove stores
Browse files Browse the repository at this point in the history
  • Loading branch information
loks0n committed Dec 25, 2024
1 parent e7cd892 commit 8ed7c3b
Show file tree
Hide file tree
Showing 8 changed files with 374 additions and 52 deletions.
29 changes: 14 additions & 15 deletions src/computer/alpha-beta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,18 @@ import {
} from './computer';
import { Bitboard, DraughtsEngine, DraughtsEngineMove } from '../core/engine';

export type AlphaBetaOptions<TBitboard extends Bitboard, TStore> = {
export type AlphaBetaOptions<TBitboard extends Bitboard> = {
maxDepth: number;
evaluationFunction: SearchEvaluationFunction<TBitboard, TStore>;
evaluationFunction: SearchEvaluationFunction<TBitboard>;
quiescence?: boolean;
};

export async function alphaBeta<TBitboard extends Bitboard, TStore>({
export async function alphaBeta<TBitboard extends Bitboard>({
options: { maxDepth, evaluationFunction, quiescence = true },
engine,
}: DraughtsComputerStrategyArgs<
TBitboard,
TStore,
AlphaBetaOptions<TBitboard, TStore>
AlphaBetaOptions<TBitboard>
>): Promise<DraughtsEngineMove<TBitboard>> {
let recordEvaluation = Number.NEGATIVE_INFINITY;
let recordMove: DraughtsEngineMove<TBitboard> | undefined;
Expand Down Expand Up @@ -47,20 +46,20 @@ export async function alphaBeta<TBitboard extends Bitboard, TStore>({
return recordMove;
}

type AlphaBetaSearchArguments<TBitboard extends Bitboard, TStore> = {
type AlphaBetaSearchArguments<TBitboard extends Bitboard> = {
data: {
engine: DraughtsEngine<TBitboard, TStore>;
engine: DraughtsEngine<TBitboard>;
alpha: number;
beta: number;
depth: number;
};
options: Omit<AlphaBetaOptions<TBitboard, TStore>, 'maxDepth'>;
options: Omit<AlphaBetaOptions<TBitboard>, 'maxDepth'>;
};

async function alphaBetaSearch<TBitboard extends Bitboard, TStore>({
async function alphaBetaSearch<TBitboard extends Bitboard>({
data: { engine, alpha, beta, depth },
options: { evaluationFunction, quiescence },
}: AlphaBetaSearchArguments<TBitboard, TStore>) {
}: AlphaBetaSearchArguments<TBitboard>) {
if (depth === 0)
return quiescence
? quiescenceSearch({
Expand Down Expand Up @@ -89,21 +88,21 @@ async function alphaBetaSearch<TBitboard extends Bitboard, TStore>({
return alpha;
}

interface QuiescenceSearchArguments<TBitboard extends Bitboard, TStore> {
interface QuiescenceSearchArguments<TBitboard extends Bitboard> {
data: {
engine: DraughtsEngine<TBitboard, TStore>;
engine: DraughtsEngine<TBitboard>;
alpha: number;
beta: number;
};
options: {
evaluationFunction: SearchEvaluationFunction<TBitboard, TStore>;
evaluationFunction: SearchEvaluationFunction<TBitboard>;
};
}

async function quiescenceSearch<TBitboard extends Bitboard, TStore>({
async function quiescenceSearch<TBitboard extends Bitboard>({
data: { engine, alpha, beta },
options: { evaluationFunction },
}: QuiescenceSearchArguments<TBitboard, TStore>) {
}: QuiescenceSearchArguments<TBitboard>) {
const evaluation = evaluationFunction(engine);
if (evaluation >= beta) return beta;
alpha = Math.max(evaluation, alpha);
Expand Down
24 changes: 10 additions & 14 deletions src/computer/computer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,49 +5,45 @@ import {
DraughtsMove1D,
} from '../core/game';

export type SearchEvaluationFunction<TBitboard extends Bitboard, TStore> = (
engine: DraughtsEngine<TBitboard, TStore>
export type SearchEvaluationFunction<TBitboard extends Bitboard> = (
engine: DraughtsEngine<TBitboard>
) => number;

export type DraughtsComputerStrategyArgs<
TBitboard extends Bitboard,
TStore,
TOptions,
> = {
options: TOptions;
engine: DraughtsEngine<TBitboard, TStore>;
engine: DraughtsEngine<TBitboard>;
};

export type DraughtsComputerStrategy<
TBitboard extends Bitboard,
TStore,
TOptions,
> = (
args: DraughtsComputerStrategyArgs<TBitboard, TStore, TOptions>
args: DraughtsComputerStrategyArgs<TBitboard, TOptions>
) => Promise<DraughtsEngineMove<TBitboard>>;

export type DraughtsComputer<TBitboard extends Bitboard, TStore> = (
game: DraughtsGame1D<TBitboard, TStore>
export type DraughtsComputer<TBitboard extends Bitboard> = (
game: DraughtsGame1D<TBitboard>
) => Promise<DraughtsMove1D>;

export type DraughtsComputerArguments<
TBitboard extends Bitboard,
TStore,
TOptions,
> = {
adapter: DraughtsAdapter1D<TBitboard>;
strategy: DraughtsComputerStrategy<TBitboard, TStore, TOptions>;
strategy: DraughtsComputerStrategy<TBitboard, TOptions>;
options: TOptions;
};

export const DraughtsComputerFactory = {
setup<TBitboard extends Bitboard, TStore, TOptions>({
setup<TBitboard extends Bitboard, TOptions>({
adapter,
strategy,
options,
}: DraughtsComputerArguments<TBitboard, TStore, TOptions>): DraughtsComputer<
TBitboard,
TStore
}: DraughtsComputerArguments<TBitboard, TOptions>): DraughtsComputer<
TBitboard
> {
return async (game) => {
const engineMove = await strategy({
Expand Down
4 changes: 2 additions & 2 deletions src/computer/random.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Bitboard, DraughtsEngineMove } from '../core/engine';
import { DraughtsComputerStrategyArgs } from './computer';

export async function random<TBitboard extends Bitboard, TStore>({
export async function random<TBitboard extends Bitboard>({
engine,
}: DraughtsComputerStrategyArgs<TBitboard, TStore, undefined>): Promise<
}: DraughtsComputerStrategyArgs<TBitboard, undefined>): Promise<
DraughtsEngineMove<TBitboard>
> {
if (engine.moves.length === 0) throw new Error('no valid moves');
Expand Down
26 changes: 9 additions & 17 deletions src/english/computer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
import { alphaBeta, AlphaBetaOptions } from '../computer/alpha-beta';
import { random } from '../computer/random';
import { DraughtsEngine, DraughtsPlayer, DraughtsStatus } from '../core/engine';
import { EnglishDraughtsEngineStore } from './engine';
import { EnglishDraughtsAdapter1D } from './game';
import { cardinality } from './utils';
import Mask from './mask';
Expand All @@ -19,13 +18,10 @@ const statusToPlayer = {
/**
* Evaluation function for the English Draughts game
*
* @param {DraughtsEngine<number, EnglishDraughtsEngineStore>} engine - The game engine
* @param {DraughtsEngine<number>} engine - The game engine
* @returns {number} - Evaluation score for the given position
*/
export const evaluate: SearchEvaluationFunction<
number,
EnglishDraughtsEngineStore
> = (engine: DraughtsEngine<number, EnglishDraughtsEngineStore>) => {
export const evaluate: SearchEvaluationFunction<number> = (engine: DraughtsEngine<number>) => {
const status = engine.status;
if (status !== DraughtsStatus.PLAYING) {
if (status === DraughtsStatus.DRAW) return Number.NEGATIVE_INFINITY;
Expand All @@ -43,7 +39,7 @@ const MIDDLE_TWO_RANK_FOUR_FILE_WEIGHT = 25;
const MIDDLE_FOUR_RANK_TWO_FILE_WEIGHT = 5;

function evaluateMiddlegame(
engine: DraughtsEngine<number, EnglishDraughtsEngineStore>
engine: DraughtsEngine<number>
): number {
const player =
engine.data.player === DraughtsPlayer.LIGHT
Expand Down Expand Up @@ -91,10 +87,7 @@ function evaluateMiddlegame(
);
}

export type EnglishDraughtsComputer = DraughtsComputer<
number,
EnglishDraughtsEngineStore
>;
export type EnglishDraughtsComputer = DraughtsComputer<number>;

export const EnglishDraughtsComputerFactory = {
/**
Expand All @@ -104,21 +97,20 @@ export const EnglishDraughtsComputerFactory = {
random(): EnglishDraughtsComputer {
return DraughtsComputerFactory.setup({
adapter: EnglishDraughtsAdapter1D,
strategy: random<number, EnglishDraughtsEngineStore>,
strategy: random<number>,
options: undefined,
});
},
/**
* Creates a computer opponent with an alpha-beta pruning strategy
* @param {Partial<AlphaBetaOptions<number, EnglishDraughtsEngineStore>>} options - Options for the alpha-beta pruning strategy
* @param {Partial<AlphaBetaOptions<number>>} options - Options for the alpha-beta pruning strategy
* @returns {EnglishDraughtsComputer} - A computer opponent with an alpha-beta pruning strategy
*/
alphaBeta(
options: Partial<AlphaBetaOptions<number, EnglishDraughtsEngineStore>>
options: Partial<AlphaBetaOptions<number>>
): EnglishDraughtsComputer {
const withDefaultOptions: AlphaBetaOptions<
number,
EnglishDraughtsEngineStore
number
> = {
maxDepth: options.maxDepth ?? 4,
quiescence: options.quiescence ?? true,
Expand All @@ -127,7 +119,7 @@ export const EnglishDraughtsComputerFactory = {

return DraughtsComputerFactory.setup({
adapter: EnglishDraughtsAdapter1D,
strategy: alphaBeta<number, EnglishDraughtsEngineStore>,
strategy: alphaBeta<number>,
options: withDefaultOptions,
});
},
Expand Down
6 changes: 2 additions & 4 deletions src/english/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
} from '../core/game';
import {
EnglishDraughtsEngineFactory,
EnglishDraughtsEngineStore,
} from './engine';

import { EnglishDraughtsBitSquare as S, decomposeBits } from './utils';
Expand Down Expand Up @@ -139,8 +138,7 @@ export const EnglishDraughtsDefaultHistory1D: DraughtsGameHistory1D = {
};

export type EnglishDraughtsGame = DraughtsGame1D<
number,
EnglishDraughtsEngineStore
number
>;

export const EnglishDraughts = {
Expand All @@ -151,7 +149,7 @@ export const EnglishDraughts = {
* @returns The new English Draughts game
*/
setup(
data?: Partial<DraughtsEngineData<number, EnglishDraughtsEngineStore>>,
data?: Partial<DraughtsEngineData<number>>,
history?: Partial<DraughtsGameHistory1D>
): EnglishDraughtsGame {
const engine = EnglishDraughtsEngineFactory.setup(data);
Expand Down
61 changes: 61 additions & 0 deletions src/international/mask.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import {
InternationalDraughtsBitSquare as S,
bitwiseOr as or,
} from './utils';

/* We use the following bitboard layout for International Draughts
*
* [57][58][59][60][61][62]
* [63] 00, 01, 02, 03, 04,
* 05, 06, 07, 08, 09, [10]
* [10] 11, 12, 13, 14, 15,
* 16, 17, 18, 19, 20, [21]
* [21] 22, 23, 24, 25, 26,
* 27, 28, 29, 30, 31, [32]
* [32] 33, 34, 35, 36, 37,
* 38, 39, 40, 41, 42, [43]
* [43] 44, 45, 46, 47, 48,
* 49, 50, 51, 52, 53, [54]
* [55][56][57][58][59][60]
*
* Access the uint32 value of a square with S[n]
*
* Squares encased in brackets, such as [57], are invalid.
* A move forward to the left is a rotate right 6 bits.
* A move forward to the right is a rotate right 5 bit.
*/

const RANK_9 = or(S[0], S[1], S[2], S[3], S[4]);
const RANK_8 = or(S[5], S[6], S[7], S[8], S[9]);
const RANK_7 = or(S[12], S[13], S[14], S[15], S[16]);
const RANK_6 = or(S[17], S[18], S[19], S[20], S[21]);
const RANK_5 = or(S[22], S[23], S[24], S[25], S[26]);
const RANK_4 = or(S[27], S[28], S[29], S[30], S[31]);
const RANK_3 = or(S[36], S[37], S[38], S[39], S[40]);
const RANK_2 = or(S[41], S[42], S[43], S[44], S[45]);
const RANK_1 = or(S[48], S[49], S[50], S[51], S[52]);
const RANK_0 = or(S[53], S[54], S[55], S[56], S[57]);

const BOARD = or(
RANK_9,
RANK_8,
RANK_7,
RANK_6,
RANK_5,
RANK_4,
RANK_3,
RANK_2,
RANK_1,
RANK_0
);

const DARK_START = or(RANK_0, RANK_1, RANK_2, RANK_3);
const LIGHT_START = or(RANK_6, RANK_7, RANK_8, RANK_9);

const Mask = {
BOARD,
LIGHT_START,
DARK_START,
};

export default Mask;
Loading

0 comments on commit 8ed7c3b

Please sign in to comment.