Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,20 +84,20 @@ You need a pipenv and python 3.10+

Clone this repository, install requrements and run with either:

- `python main.py -l '<log url>'`
- `python main.py -l '<log url>' -p <seat number 0-3>`
- `python main.py '<log url>'`
- `python main.py '<log url>' -p <seat number 0-3>`

where 0 = East, 1 = South, 2 = West, 3 = North.

Outputs injustices to console.

To output skills use `-m skill`:
- `python main.py -l '<log url>' -m skill`
- `python main.py -l '<log url>' -p <seat number 0-3> -m skill`
- `python main.py '<log url>' -m skill`
- `python main.py '<log url>' -p <seat number 0-3> -m skill`

To output both skills and injustice use `-m both`:
- `python main.py -l '<log url>' -m both`
- `python main.py -l '<log url>' -p <seat number 0-3> -m both`
- `python main.py '<log url>' -m both`
- `python main.py '<log url>' -p <seat number 0-3> -m both`

## Usage (library)

Expand Down
2 changes: 1 addition & 1 deletion injustice_judge/classes2.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ class Kyoku:
def get_starting_score(self) -> int:
return (sum(self.start_scores) + self.rules.riichi_value*self.riichi_sticks) // self.num_players
def get_visible_tiles(self) -> List[int]:
"""Get all the currently visible tiles, used for ukeire calculations"""
"""Get all the currently visible tiles on the board, used for ukeire calculations"""
pond_tiles = [tile for seat in range(self.num_players) for tile in self.pond[seat]]
dora_indicators = [to_dora_indicator(dora, self.num_players) for dora in self.doras if dora not in {51,52,53}][:self.num_dora_indicators_visible]
def get_undiscarded_part(call):
Expand Down
6 changes: 3 additions & 3 deletions injustice_judge/fetch/majsoul.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ async def call(self, name: str, **fields: Any) -> Message:
assert method is not None, f"couldn't find method {name}"

# prepare the payload (req) and a place to store the response (res)
req: Message = pb.reflection.MakeClass(method.input_type)(**fields) # type: ignore[attr-defined]
res: Message = pb.reflection.MakeClass(method.output_type)() # type: ignore[attr-defined]
req: Message = pb.message_factory.GetMessageClass(method.input_type)(**fields) # type: ignore[attr-defined]
res: Message = pb.message_factory.GetMessageClass(method.output_type)() # type: ignore[attr-defined]
# the Res* response must have an error field
assert hasattr(res, "error"), f"Got non-Res object: {res}\n\nfrom request: {req}"

Expand Down Expand Up @@ -132,7 +132,7 @@ def parse_wrapped_bytes(data: bytes) -> Tuple[str, Message]:
wrapper.ParseFromString(data)
name = wrapper.name.strip(f'.{proto.DESCRIPTOR.package}')
try:
msg = pb.reflection.MakeClass(proto.DESCRIPTOR.message_types_by_name[name])() # type: ignore[attr-defined]
msg = pb.message_factory.GetMessageClass(proto.DESCRIPTOR.message_types_by_name[name])() # type: ignore[attr-defined]
msg.ParseFromString(wrapper.data)
except KeyError as e:
raise Exception(f"Failed to find message name {name}")
Expand Down
9 changes: 4 additions & 5 deletions injustice_judge/flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -736,8 +736,8 @@ def process_tenpai(self, i: int, seat: int, event_type: str,
# if no calls, use tsumo score. else, get ron score
calls_present = len(get_yaku_args["hand"].calls) > 0 # type: ignore[attr-defined]
all_scores = get_yaku(**get_yaku_args, check_rons = calls_present, check_tsumos = not calls_present) # type: ignore[arg-type]
visible_tiles = self.kyoku.get_visible_tiles()
formatted_scores = [(score, wait) for wait, score in all_scores.items() if visible_tiles.count(wait) > 0]
normalized_visible_tiles = list(normalize_red_fives(self.kyoku.get_visible_tiles() + list(hand.closed_part)))
formatted_scores = [(score, wait) for wait, score in all_scores.items() if normalized_visible_tiles.count(wait) < 4]
if len(formatted_scores) > 0: # if wait is not dead
best_score, takame = max(formatted_scores)
han = best_score.han
Expand All @@ -748,7 +748,7 @@ def process_tenpai(self, i: int, seat: int, event_type: str,
recalculate = han in {7, 9, 10, 12} or is_mangan(han-1, fu)
if recalculate and not calls_present:
ron_scores = get_yaku(**get_yaku_args, check_rons = True, check_tsumos = False) # type: ignore[arg-type]
formatted_ron_scores = [(score, wait) for wait, score in ron_scores.items() if visible_tiles.count(wait) > 0]
formatted_ron_scores = [(score, wait) for wait, score in ron_scores.items() if normalized_visible_tiles.count(wait) < 4]
if len(formatted_ron_scores) > 0: # if wait is not dead
best_ron_score, ron_takame = max(formatted_ron_scores)
ron_han = best_score.han
Expand All @@ -772,8 +772,7 @@ def process_tenpai(self, i: int, seat: int, event_type: str,
# first, do standard yakuman, otherwise, try kazoe yakuman
yakuman_waits: List[Tuple[str, Set[int]]] = [(y, get_yakuman_waits(self.at[seat].hand, y)) for y in get_yakuman_tenpais(self.at[seat].hand)]
# only report the yakuman if the waits are not dead
visible = self.get_visible_tiles()
yakuman_types: Set[str] = {t for t, waits in yakuman_waits if not all(visible.count(wait) == 4 for wait in waits)}
yakuman_types: Set[str] = {t for t, waits in yakuman_waits if not all(normalized_visible_tiles.count(wait) == 4 for wait in waits)}
if len(yakuman_types) > 0:
self.add_flag(seat, Flags.YOU_REACHED_YAKUMAN_TENPAI, {"hand": self.at[seat].hand, "types": yakuman_types, "waits": yakuman_waits})
elif han >= 13 and not any(y in YAKUMAN for y, _ in best_score.yaku):
Expand Down