電脳麻将 ver.2.0 で開発中の新機能「パラメータによるルールのカスタマイズ」で 終局判断 と ポイント計算 に関わるパラメータは以下の通り。
[20, 10, -10, -20]
。true
の場合、持ち点が0点未満の対局者が出た時点で終局とする。デフォルト値は true
。true
の場合、規定の最終局の親番の対局者が30,000点以上で持ち点最大で途中流局を除く連荘をした際に終局となる。デフォルト値は true
。クラス Majiang.Game
のメソッド last()
で以下のように終局判断している。
last() {
let model = this._model;
model.lunban = -1;
if (this._view) this._view.update();
/* 輪荘時は次の局に進む */
if (! this._lianzhuang) {
model.jushu++;
model.zhuangfeng += (model.jushu / 4)|0;
model.jushu = model.jushu % 4;
}
/* 持ち点30,000点以上で持ち点最大の対局者を guanjun に設定する。
持ち点同点の場合は起家に近い対局者を上位とする。 */
let jieju = false;
let guanjun = -1;
const defen = model.defen;
for (let i = 0; i < 4; i++) {
let id = (model.qijia + i) % 4;
if (defen[id] < 0 && this._rule['トビ終了あり']) jieju = true;
// トビ終了
if (defen[id] >= 30000
&& (guanjun < 0 || defen[id] > defen[guanjun])) guanjun = id;
}
let sum_jushu = model.zhuangfeng * 4 + model.jushu;
if (15 < sum_jushu) jieju = true;
//「返り東」には入らない
else if ((this._rule['場数'] + 1) * 4 - 1 < sum_jushu) jieju = true;
// 四局を超えた延長戦は行わない
else if (this._max_jushu < sum_jushu) { // 最終局を超えた場合
if (this._rule['延長戦方式'] == 0) jieju = true;
// 延長戦なしなら終局
else if (this._rule['場数'] == 0) jieju = true;
// 一局戦なら終局
else if (guanjun >= 0) jieju = true;
// 30,000点超えがいるなら終局
else { // さらに延長戦を続ける
this._max_jushu += this._rule['延長戦方式'] == 3 ? 4
// 4局固定延長の場合、最終局を
// 4局先に延ばす
: this._rule['延長戦方式'] == 2 ? 1
// 連荘優先サドンデスの場合、
// 1局先に延ばす
: 0;
// その他の場合、延長しない
}
}
else if (this._max_jushu == sum_jushu) { // 最終局の場合
if (this._rule['オーラス止めあり'] && guanjun == model.player_id[0]
&& this._lianzhuang && ! this._no_game) jieju = true;
// オーラス止めの条件を満たせば
// 終局
}
if (jieju) this.delay(()=>this.jieju(), 0);
else this.delay(()=>this.qipai(), 0);
}
クラス Majiang.Game
のメソッド jieju()
で順位を決定し、ポイント計算する。
jieju() {
let model = this._model;
/* 持ち点により順位を決定する。同点の場合は起家に近い方を上位とする。*/
let paiming = [];
const defen = model.defen;
for (let i = 0; i < 4; i++) {
let id = (model.qijia + i) % 4;
for (let j = 0; j < 4; j++) {
if (j == paiming.length || defen[id] > defen[paiming[j]]) {
paiming.splice(j, 0, id);
break;
}
}
}
defen[paiming[0]] += model.lizhibang * 1000; // 積み残しの供託リーチ棒は
// トップの点に加算する
this._paipu.defen = defen;
/* 牌譜に順位を反映する。*/
let rank = [0,0,0,0];
for (let i = 0; i < 4; i++) {
rank[paiming[i]] = i + 1;
}
this._paipu.rank = rank;
/* 順位点を加えポイントを決定する。
ポイントの端数(小数点以下)は四捨五入する。*/
let point = [0,0,0,0];
for (let i = 1; i < 4; i++) {
let id = paiming[i];
point[id] = Math.round((defen[id] - 30000) / 1000)
+ this._rule['順位点'][i];
point[paiming[0]] -= point[id];
}
this._paipu.point = point.map(p=>''+p);
let paipu = { jieju: this._paipu };
let msg = [];
for (let l = 0; l < 4; l++) {
msg[l] = JSON.parse(JSON.stringify(paipu));
}
this.call_players('jieju', msg);
if (this._view) this._view.summary(this._paipu);
}
現在はポイントの小数点以下を四捨五入しているが、将来的にはこれもカスタマイズ可能とするかも。