From f9af10c473480e6d582f350c2627e46168c53dc5 Mon Sep 17 00:00:00 2001 From: umbralOptimatum Date: Mon, 15 Dec 2025 14:43:10 -0500 Subject: [PATCH 1/3] Update README parameters description --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4a0d9bc..08829df 100644 --- a/README.md +++ b/README.md @@ -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 ''` -- `python main.py -l '' -p ` +- `python main.py ''` +- `python main.py '' -p ` where 0 = East, 1 = South, 2 = West, 3 = North. Outputs injustices to console. To output skills use `-m skill`: -- `python main.py -l '' -m skill` -- `python main.py -l '' -p -m skill` +- `python main.py '' -m skill` +- `python main.py '' -p -m skill` To output both skills and injustice use `-m both`: -- `python main.py -l '' -m both` -- `python main.py -l '' -p -m both` +- `python main.py '' -m both` +- `python main.py '' -p -m both` ## Usage (library) From 454182ec7c59d1b3549f8711fa8f5e910668bcf5 Mon Sep 17 00:00:00 2001 From: umbralOptimatum Date: Wed, 24 Dec 2025 14:09:17 -0500 Subject: [PATCH 2/3] Replace removed protobuf method --- injustice_judge/fetch/majsoul.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/injustice_judge/fetch/majsoul.py b/injustice_judge/fetch/majsoul.py index 7eb921d..a704bb6 100644 --- a/injustice_judge/fetch/majsoul.py +++ b/injustice_judge/fetch/majsoul.py @@ -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}" @@ -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}") From b0978ff6803d9148f53b5e81e5c0fbfb65417e10 Mon Sep 17 00:00:00 2001 From: umbralOptimatum Date: Wed, 24 Dec 2025 14:19:11 -0500 Subject: [PATCH 3/3] Fix limit tenpai flags calculation Flags.YOU_HAD_LIMIT_TENPAI and Flags.YOU_REACHED_YAKUMAN_TENPAI were supposed to check that their waits weren't dead. Instead they required that at least one tile from the wait was already visible on the board. --- injustice_judge/classes2.py | 2 +- injustice_judge/flags.py | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/injustice_judge/classes2.py b/injustice_judge/classes2.py index ace4bb5..e040cec 100644 --- a/injustice_judge/classes2.py +++ b/injustice_judge/classes2.py @@ -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): diff --git a/injustice_judge/flags.py b/injustice_judge/flags.py index 61eb033..948fc5e 100644 --- a/injustice_judge/flags.py +++ b/injustice_judge/flags.py @@ -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 @@ -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 @@ -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):