void tableinit(GameTable* const gameStat) { for (int i = 0; i < Players; ++i) { // 代走させる処理 if (gameStat->Player[i].ConnectionLost) { EnvTable::Instantiate()->PlayerDat[i].RemotePlayerFlag = 0; gameStat->Player[i].ConnectionLost = false; } } init_ai(gameStat); inittable(gameStat); // 局の開始で同期する。1.7系列まではこのとき落ち戻りが可能(落ち戻り機能は1.8で廃止されました) statsync(gameStat, mihajong_socket::protocol::Server_StartRound_Signature, [](GameTable* const gameStat, int ReceivedMsg) -> bool { if (ReceivedMsg == mihajong_socket::protocol::Server_StartRound_Signature) { return true; } else if (ReceivedMsg == 1023) { // 回線が切れてたら EnvTable::Instantiate()->GameMode = EnvTable::Standalone; for (int i = 0; i < Players; ++i) EnvTable::Instantiate()->PlayerDat[i].RemotePlayerFlag = 0; return true; } else { return false; } }); // 牌譜バッファの初期化 haifu::haifuinit(); /* 卓の情報を同期 */ syncTableStat(gameStat); // BGMを鳴らす choosebgm(gameStat); // 画面の準備 screen(gameStat); // 洗牌 tileshuffle(gameStat); // 賽を振る bool doraFlag = rolldice(gameStat, false, 0); #ifndef GUOBIAO if (RuleData::chkRule("dice_roll", "roll_twice")) #endif /* GUOBIAO */ (void)rolldice(gameStat, doraFlag, 2); // 二度振りの2回目 // 配牌 haipai(gameStat); return; }
int mahjong(unsigned seed) { Taku taku; rng_init(seed); init_taku(&taku); taku.chicha = rng_next() % N_PLAYER; while (taku.kyoku < 8) { taku_wo_miseru(&taku); shipai(&taku); taku_wo_miseru(&taku); kaimen(&taku); taku_wo_miseru(&taku); haipai(&taku); taku_wo_miseru(&taku); taku.teban = oya(&taku); while (rest_tsumo(&taku.yama)) { unsigned pai; unsigned info; unsigned action; unsigned nakite; Kawa *kawa; pai = tsumo_from_yama(&taku.yama); taku.current = taku.yama.narabi + taku.yama.tsumo_idx; after_tsumo: taku_wo_miseru(&taku); info = tsumo_select_action(&taku, pai); action = info_to_action(info); kawa = &taku.kawa[taku.teban]; switch (action) { case ACTION_KAKAN: pai = info_to_pai(info); info = chankan_select_action_all(&taku, pai); nakite = info_to_player(info); if (taku.teban != nakite) { taku.teban = nakite; goto after_hohra; } case ACTION_ANKAN: pai = tsumo_from_rinshan(&taku.yama); goto after_tsumo; case ACTION_RIICHI: taku.tenbo[taku.teban] -= 1000; taku.riichibo++; kawa->riichi_idx = kawa->sute_idx; case ACTION_SUTE: pai = info_to_pai(info); taku.current = kawa->narabi + kawa->sute_idx; kawa->narabi[kawa->sute_idx++] = pai; goto after_sute; case ACTION_TSUMO: goto after_hohra; } after_sute: taku_wo_miseru(&taku); if (is_sufurenda(&taku)) goto after_ryukyoku; info = furo_select_action_all(&taku, pai); nakite = info_to_player(info); action = info_to_action(info); if (action == ACTION_SANCHAHOH) goto after_ryukyoku; if (taku.teban != nakite) { taku.teban = nakite; kawa = &taku.kawa[taku.teban]; switch (action) { case ACTION_RON: goto after_hohra; case ACTION_CHI: case ACTION_PON: case ACTION_MINKAN: info = furo_sute_action(&taku, info); pai = info_to_pai(info); taku.current = kawa->narabi + kawa->sute_idx; kawa->narabi[kawa->sute_idx++] = pai; goto after_sute; case ACTION_THROUGH: break; } } if (is_suchariichi(&taku)) goto after_ryukyoku; if (is_sukaikan(&taku)) goto after_ryukyoku; taku.teban = (taku.teban + 1) % N_PLAYER; } after_ryukyoku: taku_wo_miseru(&taku); if (ryukyoku(&taku)) taku.kyoku++; else taku.tsumibo++; continue; after_hohra: taku_wo_miseru(&taku); if (hohra(&taku)) taku.kyoku++; else taku.tsumibo++; } return 0; }