電脳麻将 ver.2.0 で開発中の新機能「パラメータによるルールのカスタマイズ」で終局判断とポイント計算に関わるパラメータは以下の通り。
- 配給原点
- 順位点
- 場数
- トビ終了あり
- オーラス止めあり
- 延長戦方式
パラメータの意味
- 配給原点
- 対局開始時の各対局者の持ち点。デフォルト値は 25,000点。終局時には30,000点を「原点」とし、原点からの差を1,000点1ポイントに換算する。配給原点との差は「オカ」として着順トップの対局者のポイントとなる。
- 順位点
- 順位に応じて付加されるポイント数。デフォルト値は着順順に
[20, 10, -10, -20]
。 - 場数
- 一局戦: 0、東風戦: 1、東南戦: 2、一荘戦: 4。デフォルト値は 2。
- トビ終了あり
true
の場合、持ち点が0点未満の対局者が出た時点で終局とする。デフォルト値はtrue
。- オーラス止めあり
true
の場合、規定の最終局の親番の対局者が30,000点以上で持ち点最大で途中流局を除く連荘をした際に終局となる。デフォルト値はtrue
。- 延長戦方式
- 延長戦なし: 0、サドンデス: 1、連荘優先サドンデス: 2、4局固定: 3。デフォルト値は 1。0 以外の場合、場数 により定まる最終局を超えたときに持ち点が30,000点以上の対局者がいないと延長戦となる。1 の場合、各局終了時に持ち点30,000点以上の対局者が出た時点で終局とする。2 の場合、各局を最終局として オーラス止めあり も加味して終局判断を行う。3 の場合は延長戦4局目(東南戦なら西四局)に最終局を延長する。4局を超えた延長戦は行わない。また、場数 が 0 (一局戦)もしくは 4 (一荘戦)の場合は延長戦は行わない。
終局判断
クラス 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); }
現在はポイントの小数点以下を四捨五入しているが、将来的にはこれもカスタマイズ可能とするかも。*1