/**
* @file アプリのエントリーポイントです。
*/
/*
* @author 市川雄二
* @copyright 2018 ICHIKAWA, Yuji (New 3 Rs)
* @license MIT
*/
/* global $ JGO i18n */
import { i18nSpeak } from './speech.js';
import { AZjsEngine } from './azjs_engine_client.js';
import { BoardController } from './board_controller.js';
import { PlayController } from './play_controller.js';
/**
* 指定された碁盤サイズとエンジンで対局を繰り返します。
* 手番と持ち時間は対極の都度受け付けます。
* @param {Integer} size
* @param {AZjsEngine} engine
*/
async function startGame(size, engine) {
const controller = await new Promise(function(res, rej) {
new BoardController(size, 0, 7.5, res);
});
const $startModal = $('#start-modal');
$startModal.modal('show');
// ユーザーが手番と持ち時間を決める間にニューラルネットワークのウェイトをダウンロードします。
try {
await engine.loadNN(); // 一度だけダウンロードし、次回は再利用します。
$('#loading-message').text(i18n.finishDownload);
$('#start-game').prop('disabled', false);
} catch(e) {
if (e === 'Error: No backend is available') {
if (/(Mac OS X 10_13|(iPad|iPhone|iPod); CPU OS 11).*Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent)) {
$('#loading-message').text(i18n.notSupport + i18n.safariWithoutWebgpu);
i18nSpeak(i18n.notSupport + i18n.safariWithoutWebgpu);
} else if (!i18nSpeak(i18n.notSupport)) {
$('#loading-message').text(i18n.notSupport);
alert(i18n.notSupport);
}
} else {
console.error(e);
}
return;
}
const condition = await new Promise(function(res, rej) {
const $conditionForm = $('#condition-form');
$conditionForm.one('submit', function(e) {
e.preventDefault();
$startModal.one('hidden.bs.modal', function(e) {
res({
color: $conditionForm[0]['color'].value,
timeRule: $conditionForm[0]['time'].value,
time: parseInt($conditionForm[0]['ai-byoyomi'].value),
mode: $conditionForm[0]['mode'].value
});
});
$startModal.modal('hide');
});
});
let mainTime;
let byoyomi;
switch (condition.timeRule) {
case 'ai-time':
mainTime = 0;
byoyomi = condition.time;
await engine.timeSettings(0, byoyomi);
break;
case 'igo-quest':
switch (size) {
case 9:
mainTime = 3 * 60;
byoyomi = 1;
break;
case 19:
mainTime = 7 * 60;
byoyomi = 3;
break;
default:
throw new Error('size is not supported');
}
await engine.timeSettings(mainTime, byoyomi);
break;
}
if (condition.color === 'W') {
controller.setOwnColor(JGO.WHITE);
if (controller.jboard.width === 9) {
controller.setKomi(6.5);
}
} else if (condition.color === 'B') {
controller.setOwnColor(JGO.BLACK);
if (controller.jboard.width === 9) {
controller.setKomi(6.5);
}
}
const isSelfPlay = condition.color === 'self-play';
if (isSelfPlay) {
controller.setOwnColor(null);
}
const $thumbsUp = $('#thumbs-up').parent();
if (condition.ponder && !isSelfPlay) {
$thumbsUp.show();
} else {
$thumbsUp.hide();
}
const observer = new PlayController(engine, controller, mainTime, byoyomi, condition.timeRule === 'igo-quest', condition.mode, isSelfPlay);
if (!isSelfPlay) {
i18nSpeak(i18n.startGreet);
}
observer.setIsSelfPlay(isSelfPlay);
controller.addObserver(observer);
$('#pass').on('click', function(event) {
observer.pass();
});
$('#resign').one('click', async function(event) {
observer.clearTimer();
await engine.stop();
i18nSpeak(i18n.endGreet);
$(document.body).addClass('end');
});
$('#retry').one('click', async function(event) {
$('#pass').off('click');
$('#resign').off('click');
controller.destroy();
engine.clear();
$(document.body).removeClass('end');
setTimeout(async function() {
await startGame(size, engine);
}, 0);
});
}
/**
* 碁盤サイズを受け付け、エンジンを生成し、対局を開始します。
* 碁盤サイズとエンジンは再対局の際に再利用します。
*/
async function main() {
const $sizeModal = $('#size-modal');
$sizeModal.modal('show');
const size = await new Promise(function(res, rej) {
$('.button-size').one('click', function(e) {
res(parseInt(e.currentTarget.dataset.value));
});
});
switch (size) {
case 9:
$('#size-9-rule').show();
break;
default:
$('#size-19-rule').show();
}
const engine = new AZjsEngine(size);
await startGame(size, engine);
}
main();