keyboard move: play sound on illegal move

This commit is contained in:
Thibault Duplessis 2019-05-02 15:56:10 +07:00
parent 15712c6eb3
commit 552a2ba78e
3 changed files with 36 additions and 16 deletions

View file

@ -420,11 +420,11 @@ export default class RoundController {
else this.data.expiration.movedAt = Date.now();
}
this.redraw();
if (playing && playedColor === d.player.color) {
if (playing && playedColor == d.player.color) {
this.moveOn.next();
cevalSub.publish(d, o);
}
if (!this.replaying() && playedColor !== d.player.color) {
if (!this.replaying() && playedColor != d.player.color) {
// atrocious hack to prevent race condition
// with explosions and premoves
// https://github.com/ornicar/lila/issues/343
@ -438,7 +438,7 @@ export default class RoundController {
}
this.autoScroll();
this.onChange();
if (this.keyboardMove) this.keyboardMove.update(step);
if (this.keyboardMove) this.keyboardMove.update(step, playedColor != d.player.color);
if (this.music) this.music.jump(o);
speech.step(step);
};

View file

@ -8,7 +8,7 @@ import { valid as crazyValid } from './crazy/crazyCtrl';
import { sendPromotion } from './promotion'
import { onInsert } from './util'
export type KeyboardMoveHandler = (fen: Fen, dests?: cg.Dests) => void;
export type KeyboardMoveHandler = (fen: Fen, dests?: cg.Dests, yourMove?: boolean) => void;
interface SanMap {
[key: string]: cg.Role;
@ -17,7 +17,7 @@ interface SanMap {
export interface KeyboardMove {
drop(key: cg.Key, piece: string): void;
promote(orig: cg.Key, dest: cg.Key, piece: string): void;
update(step: Step): void;
update(step: Step, yourMove?: boolean): void;
registerHandler(h: KeyboardMoveHandler): void;
hasFocus(): boolean;
setFocus(v: boolean): void;
@ -61,8 +61,8 @@ export function ctrl(root: RoundController, step: Step, redraw: Redraw): Keyboar
root.chessground.cancelMove();
sendPromotion(root, orig, dest, role, {premove: false});
},
update(step) {
if (handler) handler(step.fen, cgState.movable.dests);
update(step, yourMove: boolean = false) {
if (handler) handler(step.fen, cgState.movable.dests, yourMove);
else preHandlerBuffer = step.fen;
},
registerHandler(h: KeyboardMoveHandler) {

View file

@ -7,21 +7,29 @@ const crazyhouseRegex = /^\w?@[a-h][1-8]$/;
const ambiguousPromotionCaptureRegex = /^([a-h]x?)?[a-h](1|8)$/;
const promotionRegex = /^([a-h]x?)?[a-h](1|8)=?[nbrq]$/;
interface SubmitOpts {
force?: boolean;
server?: boolean;
yourMove?: boolean;
}
type Submit = (v: string, submitOpts: SubmitOpts) => void;
window.lichess.keyboardMove = function(opts: any) {
if (opts.input.classList.contains('ready')) return;
opts.input.classList.add('ready');
let sans: any = null;
const submit = function(v: string, force?: boolean) {
const submit: Submit = function(v: string, submitOpts: SubmitOpts) {
// consider 0's as O's for castling
v = v.replace(/0/g, 'O');
const foundUci = v.length >= 2 && sans && sanToUci(v, sans);
if (foundUci) {
// ambiguous castle
if (v.toLowerCase() === 'o-o' && sans['O-O-O'] && !force) return;
if (v.toLowerCase() === 'o-o' && sans['O-O-O'] && !submitOpts.force) return;
// ambiguous UCI
if (v.match(keyRegex) && opts.ctrl.hasSelected()) opts.ctrl.select(v);
// ambiguous promotion (also check sans[v] here because bc8 could mean Bc8)
if (v.match(ambiguousPromotionCaptureRegex) && sans[v] && !force) return;
if (v.match(ambiguousPromotionCaptureRegex) && sans[v] && !submitOpts.force) return;
else opts.ctrl.san(foundUci.slice(0, 2), foundUci.slice(2));
clear();
} else if (sans && v.match(keyRegex)) {
@ -41,21 +49,31 @@ window.lichess.keyboardMove = function(opts: any) {
} else if (v.toLowerCase().startsWith('clock')) {
readClocks(opts.ctrl.clock());
clear();
} else
opts.input.classList.toggle('wrong', v.length && sans && !sanCandidates(v, sans).length);
} else if (submitOpts.yourMove && v.length > 1) {
setTimeout(window.lichess.sound.error, 500);
opts.input.value = '';
}
else {
const wrong = v.length && sans && !sanCandidates(v, sans).length;
if (wrong && !opts.input.classList.contains('wrong')) window.lichess.sound.error();
opts.input.classList.toggle('wrong', wrong);
}
};
const clear = function() {
opts.input.value = '';
opts.input.classList.remove('wrong');
};
makeBindings(opts, submit, clear);
return function(fen: string, dests: DecodedDests) {
return function(fen: string, dests: DecodedDests, yourMove: boolean) {
sans = dests && Object.keys(dests).length ? sanWriter(fen, destsToUcis(dests)) : null;
submit(opts.input.value);
submit(opts.input.value, {
server: true,
yourMove: yourMove
});
};
}
function makeBindings(opts: any, submit: Function, clear: Function) {
function makeBindings(opts: any, submit: Submit, clear: Function) {
window.Mousetrap.bind('enter', function() {
opts.input.focus();
});
@ -71,7 +89,9 @@ function makeBindings(opts: any, submit: Function, clear: Function) {
clear();
}
else if (v === '' && e.which == 13) opts.ctrl.confirmMove();
else submit(v, e.which === 13);
else submit(v, {
force: e.which === 13
});
});
opts.input.addEventListener('focus', function() {
opts.ctrl.setFocus(true);