2017-04-25 08:10:14 -06:00
|
|
|
import { h } from 'snabbdom'
|
2017-07-09 04:28:57 -06:00
|
|
|
import { VNodeData } from 'snabbdom/vnode'
|
2017-07-09 04:15:42 -06:00
|
|
|
import { Hooks } from 'snabbdom/hooks'
|
2017-07-08 15:09:41 -06:00
|
|
|
import * as cg from 'chessground/types'
|
2017-07-09 04:35:23 -06:00
|
|
|
import { opposite } from 'chessground/util';
|
2020-07-07 06:16:00 -06:00
|
|
|
import { Redraw, EncodedDests, Dests, MaterialDiff, Step, CheckCount } from './interfaces';
|
2017-04-25 08:10:14 -06:00
|
|
|
|
2017-04-25 05:16:04 -06:00
|
|
|
const pieceScores = {
|
|
|
|
pawn: 1,
|
|
|
|
knight: 3,
|
|
|
|
bishop: 3,
|
|
|
|
rook: 5,
|
|
|
|
queen: 9,
|
|
|
|
king: 0
|
|
|
|
};
|
|
|
|
|
2017-07-09 04:28:57 -06:00
|
|
|
export function justIcon(icon: string): VNodeData {
|
2017-05-23 02:34:28 -06:00
|
|
|
return {
|
2017-07-09 04:28:57 -06:00
|
|
|
attrs: { 'data-icon': icon }
|
2017-05-23 02:34:28 -06:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-04-25 08:10:14 -06:00
|
|
|
export function uci2move(uci: string): cg.Key[] | undefined {
|
2017-04-25 05:16:04 -06:00
|
|
|
if (!uci) return undefined;
|
2017-04-25 08:10:14 -06:00
|
|
|
if (uci[1] === '@') return [uci.slice(2, 4) as cg.Key];
|
|
|
|
return [uci.slice(0, 2), uci.slice(2, 4)] as cg.Key[];
|
2017-07-09 04:23:43 -06:00
|
|
|
}
|
|
|
|
|
2019-03-07 23:09:04 -07:00
|
|
|
export function onInsert(f: (el: HTMLElement) => void): Hooks {
|
2017-04-25 08:10:14 -06:00
|
|
|
return {
|
2017-07-09 04:15:42 -06:00
|
|
|
insert(vnode) {
|
2019-03-07 23:09:04 -07:00
|
|
|
f(vnode.elm as HTMLElement);
|
2017-04-25 08:10:14 -06:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2017-07-09 04:23:43 -06:00
|
|
|
|
2019-07-10 16:38:21 -06:00
|
|
|
export function bind(eventName: string, f: (e: Event) => void, redraw?: Redraw, passive: boolean = true): Hooks {
|
2019-03-07 23:09:04 -07:00
|
|
|
return onInsert(el => {
|
2019-07-10 16:38:21 -06:00
|
|
|
el.addEventListener(eventName, !redraw ? f : e => {
|
2019-03-07 23:09:04 -07:00
|
|
|
const res = f(e);
|
2019-07-10 16:38:21 -06:00
|
|
|
redraw();
|
2019-03-07 23:09:04 -07:00
|
|
|
return res;
|
2019-07-10 16:38:21 -06:00
|
|
|
}, { passive });
|
2019-03-07 23:09:04 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-07-07 06:16:00 -06:00
|
|
|
export function parsePossibleMoves(dests?: EncodedDests): Dests {
|
|
|
|
const dec = new Map();
|
|
|
|
if (!dests) return dec;
|
2018-12-15 07:09:13 -07:00
|
|
|
if (typeof dests == 'string')
|
2020-07-07 06:16:00 -06:00
|
|
|
for (const ds of dests.split(' ')) {
|
|
|
|
dec.set(ds.slice(0,2), ds.slice(2).match(/.{2}/g) as cg.Key[]);
|
|
|
|
}
|
|
|
|
else for (const k in dests) dec.set(k, dests[k].match(/.{2}/g) as cg.Key[]);
|
2017-07-12 07:25:30 -06:00
|
|
|
return dec;
|
2017-07-09 04:23:43 -06:00
|
|
|
}
|
|
|
|
|
2017-04-25 05:16:04 -06:00
|
|
|
// {white: {pawn: 3 queen: 1}, black: {bishop: 2}}
|
2018-09-06 15:43:09 -06:00
|
|
|
export function getMaterialDiff(pieces: cg.Pieces): MaterialDiff {
|
|
|
|
const diff: MaterialDiff = {
|
2017-07-09 04:35:23 -06:00
|
|
|
white: { king: 0, queen: 0, rook: 0, bishop: 0, knight: 0, pawn: 0 },
|
|
|
|
black: { king: 0, queen: 0, rook: 0, bishop: 0, knight: 0, pawn: 0 },
|
2017-04-25 05:16:04 -06:00
|
|
|
};
|
2020-07-07 06:16:00 -06:00
|
|
|
for (const p of pieces.values()) {
|
|
|
|
const them = diff[opposite(p.color)];
|
2017-07-09 04:35:23 -06:00
|
|
|
if (them[p.role] > 0) them[p.role]--;
|
|
|
|
else diff[p.color][p.role]++;
|
2017-04-25 05:16:04 -06:00
|
|
|
}
|
|
|
|
return diff;
|
2017-07-09 04:23:43 -06:00
|
|
|
}
|
|
|
|
|
2017-07-08 15:09:41 -06:00
|
|
|
export function getScore(pieces: cg.Pieces): number {
|
2020-07-07 06:16:00 -06:00
|
|
|
let score = 0;
|
|
|
|
for (const p of pieces.values()) {
|
|
|
|
score += pieceScores[p.role] * (p.color === 'white' ? 1 : -1);
|
2017-04-25 05:16:04 -06:00
|
|
|
}
|
|
|
|
return score;
|
2017-07-09 04:23:43 -06:00
|
|
|
}
|
|
|
|
|
2019-02-01 17:34:02 -07:00
|
|
|
export const noChecks: CheckCount = {
|
|
|
|
white: 0,
|
|
|
|
black: 0
|
|
|
|
}
|
2018-12-22 13:21:17 -07:00
|
|
|
|
2019-02-01 17:34:02 -07:00
|
|
|
export function countChecks(steps: Step[], ply: Ply): CheckCount {
|
|
|
|
const checks: CheckCount = {...noChecks};
|
|
|
|
for (let step of steps) {
|
|
|
|
if (ply < step.ply) break;
|
|
|
|
if (step.check) {
|
|
|
|
if (step.ply % 2 === 1) checks.white++;
|
|
|
|
else checks.black++;
|
2018-12-22 13:21:17 -07:00
|
|
|
}
|
|
|
|
}
|
2019-02-01 17:34:02 -07:00
|
|
|
return checks;
|
2018-12-22 13:21:17 -07:00
|
|
|
}
|
|
|
|
|
2017-04-25 08:10:14 -06:00
|
|
|
export function spinner() {
|
2019-01-22 19:11:54 -07:00
|
|
|
return h('div.spinner', {
|
|
|
|
'aria-label': 'loading'
|
|
|
|
}, [
|
2017-04-25 08:10:14 -06:00
|
|
|
h('svg', { attrs: { viewBox: '0 0 40 40' } }, [
|
|
|
|
h('circle', {
|
|
|
|
attrs: { cx: 20, cy: 20, r: 18, fill: 'none' }
|
|
|
|
})])]);
|
|
|
|
}
|