Coverage Report

Created: 2025-09-03 03:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/nix/store/i1aar97n7b4yf8rk94p66if25brfvvdx-gqvzl8a5pvrg3xj44q0msrndcripi8dk-source/src/statefunctions/gamestates/chi.cc
Line
Count
Source
1
#include <array>
2
#include <cstdint>
3
#include <iostream>
4
#include <memory>
5
#include <vector>
6
7
#include "statefunctions/router.h"
8
#include "statefunctions/stateutilities.h"
9
#include "types/event.h"
10
#include "types/gamestate.h"
11
#include "types/pieces.h"
12
#include "types/piecetype.h"
13
#include "types/sets.h"
14
#include "types/statefunction.h"
15
16
namespace mahjong {
17
namespace {
18
0
Piece GetChiStart(const GameState& state, int player) {
19
0
  if (CountPieces(state, player, state.pendingPiece - 2) > 0 &&
20
0
      CountPieces(state, player, state.pendingPiece - 1) > 0) {
21
0
    return state.pendingPiece - 2;
22
0
  }
23
0
  if (CountPieces(state, player, state.pendingPiece - 1) > 0 &&
24
0
      CountPieces(state, player, state.pendingPiece + 1) > 0) {
25
0
    return state.pendingPiece - 1;
26
0
  }
27
0
  if (CountPieces(state, player, state.pendingPiece + 1) > 0 &&
28
0
      CountPieces(state, player, state.pendingPiece + 2) > 0) {
29
0
    return state.pendingPiece;
30
0
  }
31
0
  return kError;
32
0
}
33
34
0
std::unique_ptr<GameState> Chi(std::unique_ptr<GameState> state) {
35
  // only gives a single one of the chis
36
  // ui oof
37
0
  const Piece chi_start = GetChiStart(*state, state->lastCaller);
38
0
  if (chi_start == kError) {
39
0
    std::cerr << "Failed to get start of Chi" << '\n';
40
0
    state->nextState = StateFunctionType::kError;
41
0
    return state;
42
0
  }
43
44
0
  if (state->hands.at(state->currentPlayer).riichi &&
45
0
      state->hands.at(state->currentPlayer).discards.size() ==
46
0
          state->hands.at(state->currentPlayer).riichiPieceDiscard) {
47
0
    state->hands.at(state->currentPlayer).riichiPieceDiscard++;
48
0
  }
49
50
0
  state->hands.at(state->lastCaller).open = true;
51
0
  state->currentPlayer = state->lastCaller;
52
53
0
  AlertPlayers(
54
0
      *state,
55
0
      Event{
56
0
          .type = Event::kChi,                                   // type
57
0
          .player = state->lastCaller,                           // player
58
0
          .piece = static_cast<int16_t>(chi_start.toUint8_t()),  // piece
59
0
          .decision = false,                                     // decision
60
0
      });
61
62
0
  state->hands.at(state->lastCaller).live.push_back(state->pendingPiece);
63
0
  state->hands.at(state->lastCaller).sort();
64
0
  state->lastCall = state->turnNum;
65
0
  state->concealedKan = false;
66
0
  state->turnNum++;
67
68
0
  if (RemovePieces(*state, state->lastCaller, chi_start, /*count=*/1) != 1 ||
69
0
      RemovePieces(*state, state->lastCaller, chi_start + 1, /*count=*/1) !=
70
0
          1 ||
71
0
      RemovePieces(*state, state->lastCaller, chi_start + 2, /*count=*/1) !=
72
0
          1) {
73
0
    std::cerr << "Not Enough Pieces to remove in Chi" << '\n';
74
0
    state->nextState = StateFunctionType::kError;
75
0
    return state;
76
0
  }
77
0
  state->hands.at(state->lastCaller)
78
0
      .melds.push_back({SetType::kChi, chi_start});
79
80
0
  state->pendingPiece = AskForDiscard(*state);
81
82
0
  state->nextState = StateFunctionType::kDiscard;
83
0
  return state;
84
0
}
85
}  // namespace
86
87
REGISTER_ROUTE(Chi, StateFunctionType::kChi);
88
}  // namespace mahjong