Skip to content

Patch 5.0.0 - #10

Closed
argrath wants to merge 57 commits into
jnhfrom
patch
Closed

argrath wants to merge 57 commits into
jnhfrom
patch

Conversation

@argrath

@argrath argrath commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

5.0.0化する

Summary by CodeRabbit

  • New Features

    • Added Japanese language support across many in-game messages, menus, status displays, item/artifact names, and command prompts.
    • Updated Windows release publishing to ship the newer build artifact.
  • Documentation

    • Added repository and Japanese-specific translation/style guidelines.
  • Bug Fixes

    • Improved text handling for Japanese strings, including name length limits and character-boundary-aware truncation.
    • Updated several default config and display strings for Japanese builds.

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

本PRはNetHackに日本語ローカライズ(JNetHack)を導入する変更です。新規に日本語処理ライブラリ(jlib.c/jconj.c)とパッチレベルヘッダを追加し、ヘッダファイルのデータ構造・マクロ・拡張宣言をJP条件分岐で拡張、多数のヘッダ/ソースファイルの表示文字列・データテーブルを英語から日本語へ置換しました。CIワークフローの成果物パスも更新されています。

Changes

JNetHack 日本語化

Layer / File(s) Summary
プロジェクトドキュメントとCI設定
.github/workflows/windows.yml, AGENTS.md, include/AGENTS.md
Windowsリリース成果物名を更新し、翻訳/コーディング規約を記載したAGENTS.mdを新規追加。
日本語処理基盤ライブラリ
japanese/jlib.c, japanese/jconj.c, japanese/jpatchlevel.h, include/decl.h, include/extern.h, include/config.h
文字コード変換・漢字判定・活用変換ユーティリティを新規実装し、対応するextern宣言とインクルードをヘッダに追加。
コア構造体/マクロのJP対応
include/hack.h, include/you.h
KILLED_SUFFIX定義、UNDEFINED_ROLE/RACE初期化のJP分岐化、RoleName/Race/Gender/Alignへのoptフィールド追加。
シンボル・オプションテーブルの日本語化
include/artilist.h, include/defsym.h, include/optlist.h, src/decl.c
アーティファクト名、記号説明、オプション説明、色/素材/共通文字列テーブルを日本語化。
ステータス表示・属性メッセージ
src/allmain.c, src/attrib.c, src/botl.c
起動通知、属性増減、ステータスライン、ハイライトメニューの文言を日本語化。
アーティファクト戦闘メッセージ
src/artifact.c
アーティファクト起動・命中・発見関連メッセージを日本語化。
ワールドインタラクションメッセージ
src/ball.c, src/bones.c, src/dbridge.c, src/detect.c, src/dig.c, src/do.c
鉄球、bones、跳ね橋、検出、掘削、落下/蘇生等の演出メッセージを日本語化。
命名・装備メッセージ
src/do_name.c, src/do_wear.c
命名処理・文字数制限(漢字境界考慮)、装備着脱メッセージを日本語化し、already_wearing()のシグネチャを変更。
コマンド/設定UIメッセージ
src/cfgfiles.c, src/cmd.c
デフォルト設定ファイル名変更、拡張コマンド/メニュー/プロンプト文言を日本語化。
ペットAIメッセージ
src/dog.c, src/dogmove.c
ペット/使い魔の行動・食事・追従メッセージを日本語化。

Estimated code review effort: 5 (Critical) | ~150 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SrcC as "src/*.c"
  participant jconj as jconj()/jcan()/jpast()
  participant jlib as jlib.c(str2ic/jbuffer)
  participant Output as 画面出力

  SrcC->>jconj: 動詞語幹とサフィックスを渡す
  jconj->>jconj: jconj_tabで活用種別を検索
  jconj-->>SrcC: 活用済み日本語文字列を返す
  SrcC->>jlib: str2ic/jputsで文字コード変換
  jlib-->>Output: 変換済み文字列を出力
Loading

関連Issue: 特になし

関連PR: 特になし

Suggested labels: localization, i18n, japanese

Suggested reviewers: jnethack開発チームのコアメンテナ

Poem:

ウサギは跳ねて、文字を変え
英語の呪文、和語に染め
掘って、纏って、名を呼んで
千行超えて、月夜に光る
JNetHackの旅、今始まる 🐰🌕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive 変更内容とは関連していますが、「Patch 5.0.0」だけでは具体的な変更点が分からず、やや抽象的です。 例: 「JNetHackを5.0.0版へ更新」など、主要変更が分かる具体的な題名にしてください。
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch patch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/do_wear.c (1)

3875-3901: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

src/potion.c:2878inaccessible_equipment() 呼び出しも日本語の動詞句に揃えてください

apply.c 側は置き換わっていますが、dip_into() だけ verb"dip" を渡したままです。ここも "を浸す" にしないと、拒否メッセージに英語の動詞が混ざります。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/do_wear.c` around lines 3875 - 3901, The `dip_into()` path still passes
the English verb string to `inaccessible_equipment()`, so the refusal message
can mix English and Japanese. Update the call site in `dip_into()` to use the
localized Japanese verb phrase matching the rest of the `apply.c` changes, and
verify the message flow through `inaccessible_equipment()` uses the Japanese
action text consistently.
src/cmd.c (1)

841-842: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

extcmd_via_menu() の幅計算を表示幅ベースに置き換えてください。

strlen() はバイト数なので、日本語の ef_desc では biggest と実際の表示幅がずれ、# メニューの整列が崩れます。表示幅を返す共通処理に切り替えるか、この用途のヘルパーを追加してください。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cmd.c` around lines 841 - 842, `extcmd_via_menu()` の幅計算が strlen()
ベースになっており、`ef_desc` に日本語などのマルチバイト文字が含まれると `biggest`
が実表示幅とずれてメニュー整列が崩れます。`extcmd_via_menu()` 内の `ef_desc`
長さ取得を、表示幅を返す共通ヘルパー(既存のものがあればそれ)に置き換えるか、この用途専用の幅計算ヘルパーを追加して `biggest`
の更新に使ってください。
🧹 Nitpick comments (2)
src/dogmove.c (1)

1104-1113: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

既に#if 0で無効化された到達不能コードの翻訳

このブロックは外側の #if 0 /* [this is now handled in dochug()] */ ... #endif`` により既にコンパイル対象外です。実行されないコードにまで翻訳を適用する必要性は低く、レビュー・保守コストが増えるだけです。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/dogmove.c` around lines 1104 - 1113, This block is already disabled by
the surrounding `#if` 0 in dogmove.c and is unreachable, so the translation should
not be applied here. Remove the translated You() text from this dead code block
and keep the disabled comment block unchanged, using dochug() and
unstuck()/You() as the relevant symbols to locate the section.
src/do_name.c (1)

131-139: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

offset_in_kanji() の引数キャストを 136 行目と 159 行目でも統一

136/159 行目の char * 渡しも、454 行目と同じく (const unsigned char *) を付けておくと型が揃い、-Wpointer-sign 系の警告を避けやすいです。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/do_name.c` around lines 131 - 139, The offset_in_kanji() calls in
do_name.c should use the same pointer-sign cast consistently to avoid warning
mismatches. Update the call sites in the do_name logic (including the block
around the PL_PSIZ trimming code and the other matching call near the later
line) so the argument is passed as (const unsigned char *) instead of a plain
char *; keep the existing function name and surrounding outbuf handling
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@include/AGENTS.md`:
- Around line 6-8: `defsysm.h` is likely a typo for the actual file `defsym.h`,
and the guideline text should be aligned with the real filename. Update the
`include/AGENTS.md` exception list and any matching path-pattern references so
they consistently use `defsym.h`, keeping the other unique symbols
(`artilist.h`, `monsters.h`, `objects.h`, `optlist.h`) unchanged. Verify the
document no longer propagates the misspelling anywhere else in the coding
guidelines.

In `@include/extern.h`:
- Around line 712-715: Restore the extern declaration for monverbself in
extern.h by removing the `#if` 0 guard so the prototype is visible again to all
translation units. Keep the existing symbol signature and NONNULLARG123
annotation, since src/apply.c, src/muse.c, and src/steed.c still reference
monverbself and need the shared declaration.

In `@japanese/jlib.c`:
- Around line 190-227: str2ic() の IC == input_kcode で入る高速パスだけ境界チェックなしの strcpy
を使っており、静的バッファ buf をオーバーフローさせる可能性があります。str2ic() 内の他分岐と同様に、input_kcode でもコピー長を
sizeof(buf) - 1 に制限し、末尾の終端を保証するように修正してください。対象は str2ic() とその buf への代入処理です。
- Around line 296-311: The charlen function’s UTF-8 byte-length detection is
misclassifying 2-byte leading bytes as 3-byte characters because the thresholds
are ordered too broadly. Update the ICUTF8 branch in charlen to distinguish
0xC0-0xDF as 2 bytes, 0xE0-0xEF as 3 bytes, and 0xF0-0xF7 as 4 bytes, keeping
the fallback for 0x80+ and 1-byte values intact. Use the existing charlen logic
in japanese/jlib.c as the single place to correct the byte-length checks.
- Around line 481-524: split_japanese() currently relies on is_kanji1/is_kanji2,
which advance in 2-byte steps and will break UTF-8 by splitting multibyte
characters. Add a UTF-8-specific branch in split_japanese(), following the same
style as jrubout(), so that when IC == UTF8 it computes the split position using
UTF-8 character boundaries instead of the kanji helpers. Keep the existing
non-UTF-8 path unchanged and ensure the new branch uses the relevant split logic
in split_japanese() rather than modifying is_kanji1/is_kanji2.

In `@src/attrib.c`:
- Around line 1175-1192: The FAST branch in attrib.c still uses
ysimple_name(uarmf), which can introduce the unwanted “your/your...” wording
instead of matching the simplified naming used elsewhere. Update the FAST
handling inside the Very_fast block to use simpleonames(uarmf) so the message
text stays consistent with the other status-name formatting paths.

In `@src/botl.c`:
- Around line 570-576: The level label change in botl.c breaks the existing
Dlvl: replacement flow because dungeon.c still expects that exact token in
strsubst() for level-name formatting. Keep the Dlvl: prefix in the text produced
by the status display, or update both the botl.c output and the dungeon.c
strsubst(lbuf, "Dlvl:", "level "); logic together so the downstream substitution
still works from the relevant display path.

In `@src/cmd.c`:
- Around line 3205-3209: The branch handling extcmdlist lookup in cmd.c is
mismatched: it checks key2cmdbuf with STRNCMP2 against "接頭辞:" but still calls
strsubst with "prefix:", so the replacement never fires for this path. Update
the strsubst call in the same conditional block to use the same Japanese prefix
string as the matcher, and keep the reqmenu handling consistent with the
surrounding extcmdlist logic so the two-line display conversion runs correctly.

In `@src/dog.c`:
- Around line 872-878: The current JP translation wraps only part of a
multi-line original `pline` call with `/*JP */`, leaving `Monnam(mtmp));`
outside the preserved original text. Update the `dog.c` translation block around
`mon_has_amulet` / `canseemon` to use the full `#if 0 /*JP:T*/ ... `#else` ...
`#endif`` form, matching the nearby translated sections, so the entire original
multi-line statement is kept intact and only one complete translated version is
emitted.
- Around line 255-277: The petname assignments in the Role_if(PM_SAMURAI),
Role_if(PM_BARBARIAN), and Role_if(PM_RANGER) branches are single-line
independent changes, so replace the current `#if` 0 /*JP:T*/ ... `#else` ... `#endif`
blocks in dog.c with the single-line JP replacement form using the surrounding
petname assignment lines as the anchor.

In `@src/dogmove.c`:
- Around line 304-311: This change uses a multi-line `#if` 0 block for a one-line
independent substitution in the seeobj branch of dogmove.c, which violates the
single-line replacement guideline. Replace the existing pline statement and its
translated variant in the same spot with the single-line comment form using the
JP marker, so the original English line is kept as a comment and the translated
pline line is placed directly beneath it. Keep the change localized around the
seeobj handling and do not leave the `#if` 0 / `#else` / `#endif` wrapper in place.

---

Outside diff comments:
In `@src/cmd.c`:
- Around line 841-842: `extcmd_via_menu()` の幅計算が strlen() ベースになっており、`ef_desc`
に日本語などのマルチバイト文字が含まれると `biggest` が実表示幅とずれてメニュー整列が崩れます。`extcmd_via_menu()` 内の
`ef_desc` 長さ取得を、表示幅を返す共通ヘルパー(既存のものがあればそれ)に置き換えるか、この用途専用の幅計算ヘルパーを追加して `biggest`
の更新に使ってください。

In `@src/do_wear.c`:
- Around line 3875-3901: The `dip_into()` path still passes the English verb
string to `inaccessible_equipment()`, so the refusal message can mix English and
Japanese. Update the call site in `dip_into()` to use the localized Japanese
verb phrase matching the rest of the `apply.c` changes, and verify the message
flow through `inaccessible_equipment()` uses the Japanese action text
consistently.

---

Nitpick comments:
In `@src/do_name.c`:
- Around line 131-139: The offset_in_kanji() calls in do_name.c should use the
same pointer-sign cast consistently to avoid warning mismatches. Update the call
sites in the do_name logic (including the block around the PL_PSIZ trimming code
and the other matching call near the later line) so the argument is passed as
(const unsigned char *) instead of a plain char *; keep the existing function
name and surrounding outbuf handling unchanged.

In `@src/dogmove.c`:
- Around line 1104-1113: This block is already disabled by the surrounding `#if` 0
in dogmove.c and is unreachable, so the translation should not be applied here.
Remove the translated You() text from this dead code block and keep the disabled
comment block unchanged, using dochug() and unstuck()/You() as the relevant
symbols to locate the section.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: eee1f64f-c1de-47df-b99c-66da7780e50d

📥 Commits

Reviewing files that changed from the base of the PR and between 9c7ba6a and e3580f1.

⛔ Files ignored due to path filters (116)
  • dat/Arc-fila.lua is excluded by !dat/**
  • dat/Arc-filb.lua is excluded by !dat/**
  • dat/Arc-goal.lua is excluded by !dat/**
  • dat/Arc-loca.lua is excluded by !dat/**
  • dat/Arc-strt.lua is excluded by !dat/**
  • dat/Bar-fila.lua is excluded by !dat/**
  • dat/Bar-filb.lua is excluded by !dat/**
  • dat/Bar-goal.lua is excluded by !dat/**
  • dat/Bar-loca.lua is excluded by !dat/**
  • dat/Bar-strt.lua is excluded by !dat/**
  • dat/Cav-fila.lua is excluded by !dat/**
  • dat/Cav-filb.lua is excluded by !dat/**
  • dat/Cav-goal.lua is excluded by !dat/**
  • dat/Cav-loca.lua is excluded by !dat/**
  • dat/Cav-strt.lua is excluded by !dat/**
  • dat/Hea-fila.lua is excluded by !dat/**
  • dat/Hea-filb.lua is excluded by !dat/**
  • dat/Hea-goal.lua is excluded by !dat/**
  • dat/Hea-loca.lua is excluded by !dat/**
  • dat/Hea-strt.lua is excluded by !dat/**
  • dat/Kni-fila.lua is excluded by !dat/**
  • dat/Kni-filb.lua is excluded by !dat/**
  • dat/Kni-goal.lua is excluded by !dat/**
  • dat/Kni-loca.lua is excluded by !dat/**
  • dat/Kni-strt.lua is excluded by !dat/**
  • dat/Mon-fila.lua is excluded by !dat/**
  • dat/Mon-filb.lua is excluded by !dat/**
  • dat/Mon-goal.lua is excluded by !dat/**
  • dat/Mon-loca.lua is excluded by !dat/**
  • dat/Mon-strt.lua is excluded by !dat/**
  • dat/Pri-fila.lua is excluded by !dat/**
  • dat/Pri-filb.lua is excluded by !dat/**
  • dat/Pri-goal.lua is excluded by !dat/**
  • dat/Pri-loca.lua is excluded by !dat/**
  • dat/Pri-strt.lua is excluded by !dat/**
  • dat/Ran-fila.lua is excluded by !dat/**
  • dat/Ran-filb.lua is excluded by !dat/**
  • dat/Ran-goal.lua is excluded by !dat/**
  • dat/Ran-loca.lua is excluded by !dat/**
  • dat/Ran-strt.lua is excluded by !dat/**
  • dat/Rog-fila.lua is excluded by !dat/**
  • dat/Rog-filb.lua is excluded by !dat/**
  • dat/Rog-goal.lua is excluded by !dat/**
  • dat/Rog-loca.lua is excluded by !dat/**
  • dat/Rog-strt.lua is excluded by !dat/**
  • dat/Sam-fila.lua is excluded by !dat/**
  • dat/Sam-filb.lua is excluded by !dat/**
  • dat/Sam-goal.lua is excluded by !dat/**
  • dat/Sam-loca.lua is excluded by !dat/**
  • dat/Sam-strt.lua is excluded by !dat/**
  • dat/Tou-fila.lua is excluded by !dat/**
  • dat/Tou-filb.lua is excluded by !dat/**
  • dat/Tou-goal.lua is excluded by !dat/**
  • dat/Tou-loca.lua is excluded by !dat/**
  • dat/Tou-strt.lua is excluded by !dat/**
  • dat/Val-fila.lua is excluded by !dat/**
  • dat/Val-filb.lua is excluded by !dat/**
  • dat/Val-goal.lua is excluded by !dat/**
  • dat/Val-loca.lua is excluded by !dat/**
  • dat/Val-strt.lua is excluded by !dat/**
  • dat/Wiz-fila.lua is excluded by !dat/**
  • dat/Wiz-filb.lua is excluded by !dat/**
  • dat/Wiz-goal.lua is excluded by !dat/**
  • dat/Wiz-loca.lua is excluded by !dat/**
  • dat/Wiz-strt.lua is excluded by !dat/**
  • dat/air.lua is excluded by !dat/**
  • dat/asmodeus.lua is excluded by !dat/**
  • dat/astral.lua is excluded by !dat/**
  • dat/baalz.lua is excluded by !dat/**
  • dat/bigrm-11.lua is excluded by !dat/**
  • dat/castle.lua is excluded by !dat/**
  • dat/earth.lua is excluded by !dat/**
  • dat/fakewiz1.lua is excluded by !dat/**
  • dat/fakewiz2.lua is excluded by !dat/**
  • dat/fire.lua is excluded by !dat/**
  • dat/hellfill.lua is excluded by !dat/**
  • dat/juiblex.lua is excluded by !dat/**
  • dat/knox.lua is excluded by !dat/**
  • dat/medusa-1.lua is excluded by !dat/**
  • dat/medusa-2.lua is excluded by !dat/**
  • dat/medusa-3.lua is excluded by !dat/**
  • dat/medusa-4.lua is excluded by !dat/**
  • dat/minefill.lua is excluded by !dat/**
  • dat/minend-1.lua is excluded by !dat/**
  • dat/minend-2.lua is excluded by !dat/**
  • dat/minend-3.lua is excluded by !dat/**
  • dat/minetn-1.lua is excluded by !dat/**
  • dat/minetn-2.lua is excluded by !dat/**
  • dat/minetn-3.lua is excluded by !dat/**
  • dat/minetn-4.lua is excluded by !dat/**
  • dat/minetn-5.lua is excluded by !dat/**
  • dat/minetn-6.lua is excluded by !dat/**
  • dat/minetn-7.lua is excluded by !dat/**
  • dat/nhlib.lua is excluded by !dat/**
  • dat/oracle.lua is excluded by !dat/**
  • dat/orcus.lua is excluded by !dat/**
  • dat/quest.lua is excluded by !dat/**
  • dat/sanctum.lua is excluded by !dat/**
  • dat/soko1-1.lua is excluded by !dat/**
  • dat/soko1-2.lua is excluded by !dat/**
  • dat/soko2-1.lua is excluded by !dat/**
  • dat/soko2-2.lua is excluded by !dat/**
  • dat/soko3-1.lua is excluded by !dat/**
  • dat/soko3-2.lua is excluded by !dat/**
  • dat/soko4-1.lua is excluded by !dat/**
  • dat/soko4-2.lua is excluded by !dat/**
  • dat/themerms.lua is excluded by !dat/**
  • dat/tower1.lua is excluded by !dat/**
  • dat/tower2.lua is excluded by !dat/**
  • dat/tower3.lua is excluded by !dat/**
  • dat/tut-1.lua is excluded by !dat/**
  • dat/valley.lua is excluded by !dat/**
  • dat/water.lua is excluded by !dat/**
  • dat/wizard1.lua is excluded by !dat/**
  • dat/wizard3.lua is excluded by !dat/**
  • rej.txt is excluded by !*.txt
📒 Files selected for processing (127)
  • .github/workflows/windows.yml
  • AGENTS.md
  • include/AGENTS.md
  • include/artilist.h
  • include/config.h
  • include/decl.h
  • include/defsym.h
  • include/extern.h
  • include/hack.h
  • include/monsters.h
  • include/objects.h
  • include/optlist.h
  • include/you.h
  • japanese/jconj.c
  • japanese/jlib.c
  • japanese/jpatchlevel.h
  • src/allmain.c
  • src/apply.c
  • src/artifact.c
  • src/attrib.c
  • src/ball.c
  • src/bones.c
  • src/botl.c
  • src/cfgfiles.c
  • src/cmd.c
  • src/dbridge.c
  • src/decl.c
  • src/detect.c
  • src/dig.c
  • src/do.c
  • src/do_name.c
  • src/do_wear.c
  • src/dog.c
  • src/dogmove.c
  • src/dokick.c
  • src/dothrow.c
  • src/drawing.c
  • src/dungeon.c
  • src/eat.c
  • src/end.c
  • src/engrave.c
  • src/exper.c
  • src/explode.c
  • src/files.c
  • src/fountain.c
  • src/getpos.c
  • src/hack.c
  • src/hacklib.c
  • src/insight.c
  • src/invent.c
  • src/light.c
  • src/lock.c
  • src/mail.c
  • src/makemon.c
  • src/mcastu.c
  • src/mdlib.c
  • src/mhitm.c
  • src/mhitu.c
  • src/minion.c
  • src/mklev.c
  • src/mkmaze.c
  • src/mkobj.c
  • src/mon.c
  • src/mondata.c
  • src/monmove.c
  • src/mplayer.c
  • src/mthrowu.c
  • src/muse.c
  • src/music.c
  • src/nhlua.c
  • src/o_init.c
  • src/objnam.c
  • src/options.c
  • src/pager.c
  • src/pickup.c
  • src/pline.c
  • src/polyself.c
  • src/potion.c
  • src/pray.c
  • src/priest.c
  • src/quest.c
  • src/questpgr.c
  • src/read.c
  • src/region.c
  • src/restore.c
  • src/rip.c
  • src/role.c
  • src/rumors.c
  • src/save.c
  • src/shk.c
  • src/shknam.c
  • src/sit.c
  • src/sounds.c
  • src/sp_lev.c
  • src/spell.c
  • src/steal.c
  • src/steed.c
  • src/symbols.c
  • src/teleport.c
  • src/timeout.c
  • src/topten.c
  • src/trap.c
  • src/uhitm.c
  • src/vault.c
  • src/version.c
  • src/weapon.c
  • src/were.c
  • src/wield.c
  • src/windows.c
  • src/wizard.c
  • src/wizcmds.c
  • src/worm.c
  • src/worn.c
  • src/write.c
  • src/zap.c
  • sys/windows/Makefile.nmake
  • sys/windows/consoletty.c
  • sys/windows/vs/NetHack/NetHack.vcxproj
  • sys/windows/windmain.c
  • sys/windows/windsys.c
  • util/makedefs.c
  • util/recover.c
  • win/share/tilemap.c
  • win/share/tiletext.c
  • win/tty/getline.c
  • win/tty/topl.c
  • win/tty/wintty.c

Comment thread include/AGENTS.md
Comment on lines +6 to +8
原則として*.cと同様に原文をコメントアウトして残しますが、例外として
artilist.h, defsysm.h, monsters.h, objects.h, optlist.h は
変更点が多いため原文を残さずに直接日本語に書き換えます。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

defsysm.hdefsym.h の誤記の可能性があります。

他レイヤーの変更サマリでは実際のファイルとして include/defsym.h が挙げられています。本ドキュメント(およびコーディングガイドラインのパスパターン)の綴りが実ファイル名と異なると、将来的にパスベースの設定・ツールがこのファイルにマッチしなくなる恐れがあります。

As per coding guidelines, include/**/{artilist.h,defsysm.h,monsters.h,objects.h,optlist.h} と同じ綴りが使われており、実ファイル名との不一致がドキュメント全体に伝播しています。

✏️ 修正案
-artilist.h, defsysm.h, monsters.h, objects.h, optlist.h は
+artilist.h, defsym.h, monsters.h, objects.h, optlist.h は
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
原則として*.cと同様に原文をコメントアウトして残しますが、例外として
artilist.h, defsysm.h, monsters.h, objects.h, optlist.h は
変更点が多いため原文を残さずに直接日本語に書き換えます。
原則として*.cと同様に原文をコメントアウトして残しますが、例外として
artilist.h, defsym.h, monsters.h, objects.h, optlist.h は
変更点が多いため原文を残さずに直接日本語に書き換えます。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@include/AGENTS.md` around lines 6 - 8, `defsysm.h` is likely a typo for the
actual file `defsym.h`, and the guideline text should be aligned with the real
filename. Update the `include/AGENTS.md` exception list and any matching
path-pattern references so they consistently use `defsym.h`, keeping the other
unique symbols (`artilist.h`, `monsters.h`, `objects.h`, `optlist.h`) unchanged.
Verify the document no longer propagates the misspelling anywhere else in the
coding guidelines.

Source: Coding guidelines

Comment thread include/extern.h
Comment thread japanese/jlib.c
Comment on lines +190 to +227
const char *
str2ic(const char *s)
{
static unsigned char buf[1024];
const unsigned char *up;
unsigned char *p;

if(!s)
return s;

buf[0] = '\0';

if( IC==input_kcode ){
strcpy((char *)buf, s);
return (char *)buf;
}

p = buf;
#ifdef POSIX_ICONV
if (input_dsc) {
size_t src_len, dst_len;
up = (unsigned char *)s;
src_len = strlen(s);
dst_len = sizeof(buf) - 1;
if (iconv(input_dsc, (char**)&up, &src_len,
(char**)&p, &dst_len) == (size_t)-1){
strncpy((char *) buf, s, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
return (char *)buf;
}
*p = '\0';
return (char *)buf;
} else {
strncpy((char *) buf, s, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
return (char *)buf;
}
#else /*WIN32*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

str2ic()の高速パスで境界チェックなしのstrcpyが使われています。

IC == input_kcodeの場合(202-205行目)はstrcpy((char *)buf, s)を無制限に実行しますが、同じ関数の他の分岐(216-217行目、223-224行目)はstrncpysizeof(buf) - 1に制限しています。この分岐だけ境界チェックが抜けており、sが1024バイトを超えると静的バッファbufがオーバーフローします。

🛡️ 修正案
     if( IC==input_kcode ){
-        strcpy((char *)buf, s);
+        strncpy((char *)buf, s, sizeof(buf) - 1);
+        buf[sizeof(buf) - 1] = '\0';
         return (char *)buf;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const char *
str2ic(const char *s)
{
static unsigned char buf[1024];
const unsigned char *up;
unsigned char *p;
if(!s)
return s;
buf[0] = '\0';
if( IC==input_kcode ){
strcpy((char *)buf, s);
return (char *)buf;
}
p = buf;
#ifdef POSIX_ICONV
if (input_dsc) {
size_t src_len, dst_len;
up = (unsigned char *)s;
src_len = strlen(s);
dst_len = sizeof(buf) - 1;
if (iconv(input_dsc, (char**)&up, &src_len,
(char**)&p, &dst_len) == (size_t)-1){
strncpy((char *) buf, s, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
return (char *)buf;
}
*p = '\0';
return (char *)buf;
} else {
strncpy((char *) buf, s, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
return (char *)buf;
}
#else /*WIN32*/
const char *
str2ic(const char *s)
{
static unsigned char buf[1024];
const unsigned char *up;
unsigned char *p;
if(!s)
return s;
buf[0] = '\0';
if( IC==input_kcode ){
`#if` 0 /*JP*/
strcpy((char *)buf, s);
`#else`
strncpy((char *)buf, s, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
`#endif`
return (char *)buf;
}
p = buf;
`#ifdef` POSIX_ICONV
if (input_dsc) {
size_t src_len, dst_len;
up = (unsigned char *)s;
src_len = strlen(s);
dst_len = sizeof(buf) - 1;
if (iconv(input_dsc, (char**)&up, &src_len,
(char**)&p, &dst_len) == (size_t)-1){
strncpy((char *) buf, s, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
return (char *)buf;
}
*p = '\0';
return (char *)buf;
} else {
strncpy((char *) buf, s, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
return (char *)buf;
}
`#else` /*WIN32*/
🧰 Tools
🪛 ast-grep (0.44.0)

[error] 202-202: Use of an unbounded buffer function that can overflow the destination; use a size-bounded equivalent (fgets, strncpy/strlcpy, strncat/strlcat, snprintf).
Context: strcpy((char *)buf, s)
Note: [CWE-120] Buffer Copy without Checking Size of Input ('Classic Buffer Overflow').

(dangerous-buffer-functions-c)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@japanese/jlib.c` around lines 190 - 227, str2ic() の IC == input_kcode
で入る高速パスだけ境界チェックなしの strcpy を使っており、静的バッファ buf をオーバーフローさせる可能性があります。str2ic()
内の他分岐と同様に、input_kcode でもコピー長を sizeof(buf) - 1 に制限し、末尾の終端を保証するように修正してください。対象は
str2ic() とその buf への代入処理です。

Source: Linters/SAST tools

Comment thread japanese/jlib.c
Comment on lines +296 to +311
static int
charlen(unsigned int c)
{
#ifdef ICUTF8
if(c >= 0xf0){
return 4;
}
if(c >= 0xc0){
return 3;
}
#endif
if(c >= 0x80){
return 2;
}
return 1;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

UTF-8先頭バイト判定に誤りがあります。

0xC00xDF(本来2バイト文字の先頭バイト)がc >= 0xc0の条件に該当して3バイトと誤判定されます。UTF-8の正しい判定は 0xC0-0xDF→2バイト、0xE0-0xEF→3バイト、0xF0-0xF7→4バイト です。ひらがな・漢字(3バイト)自体は影響を受けませんが、ラテン拡張文字等の2バイト文字が混在すると後続バイト列がずれ、文字化けを引き起こします。

🐛 修正案
 static int
 charlen(unsigned int c)
 {
 `#ifdef` ICUTF8
     if(c >= 0xf0){
       return 4;
     }
-    if(c >= 0xc0){
+    if(c >= 0xe0){
       return 3;
     }
+    if(c >= 0xc0){
+      return 2;
+    }
 `#endif`
     if(c >= 0x80){
       return 2;
     }
     return 1;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
static int
charlen(unsigned int c)
{
#ifdef ICUTF8
if(c >= 0xf0){
return 4;
}
if(c >= 0xc0){
return 3;
}
#endif
if(c >= 0x80){
return 2;
}
return 1;
}
static int
charlen(unsigned int c)
{
`#ifdef` ICUTF8
`#if` 0 /*JP*/
if(c >= 0xf0){
return 4;
}
if(c >= 0xc0){
return 3;
}
`#else`
if(c >= 0xf0){
return 4;
}
if(c >= 0xe0){
return 3;
}
if(c >= 0xc0){
return 2;
}
`#endif`
`#endif`
if(c >= 0x80){
return 2;
}
return 1;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@japanese/jlib.c` around lines 296 - 311, The charlen function’s UTF-8
byte-length detection is misclassifying 2-byte leading bytes as 3-byte
characters because the thresholds are ordered too broadly. Update the ICUTF8
branch in charlen to distinguish 0xC0-0xDF as 2 bytes, 0xE0-0xEF as 3 bytes, and
0xF0-0xF7 as 4 bytes, keeping the fallback for 0x80+ and 1-byte values intact.
Use the existing charlen logic in japanese/jlib.c as the single place to correct
the byte-length checks.

Comment thread japanese/jlib.c
Comment on lines +481 to +524
int
is_kanji2(const char *s,int pos)
{
unsigned char *str;

str = (unsigned char *)s;
while(*str && pos>0){
if(is_kanji(*str)){
str+=2;
pos-=2;
}
else{
++str;
--pos;
}
}
if(pos<0)
return 1;
else
return 0;
}

int
is_kanji1(const char *s,int pos)
{
unsigned char *str;

str = (unsigned char *)s;
while(*str && pos>0){
if(is_kanji(*str)){
str+=2;
pos-=2;
}
else{
++str;
--pos;
}
}
if(!pos && is_kanji(*str))
return 1;
else
return 0;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

set -e
git ls-files japanese/jlib.c
printf '\n--- split_japanese / jrubout refs ---\n'
rg -n "split_japanese|jrubout|IC == UTF8|UTF8" japanese/jlib.c
printf '\n--- relevant sections ---\n'
sed -n '430,740p' japanese/jlib.c
printf '\n--- jrubout section ---\n'
sed -n '1340,1415p' japanese/jlib.c

Repository: jnethack/temp-370

Length of output: 8205


🏁 Script executed:

set -e
sed -n '430,740p' japanese/jlib.c | cat -n
printf '\n---\n'
sed -n '1340,1415p' japanese/jlib.c | cat -n
printf '\n--- search ---\n'
rg -n "split_japanese|jrubout|IC == UTF8|UTF8" japanese/jlib.c

Repository: jnethack/temp-370

Length of output: 10828


🏁 Script executed:

set -e
printf '%s\n' '--- split_japanese call sites ---'
rg -n "split_japanese\s*\(" -S .
printf '%s\n' '--- is_kanji definition ---'
rg -n "`#define`[[:space:]]+is_kanji|int[[:space:]]+is_kanji|is_kanji\(" japanese/jlib.c

Repository: jnethack/temp-370

Length of output: 763


🏁 Script executed:

set -e
sed -n '80,120p' japanese/jlib.c | cat -n
printf '\n--- topten context ---\n'
sed -n '1220,1265p' src/topten.c | cat -n
printf '\n--- topl context ---\n'
sed -n '235,275p' win/tty/topl.c | cat -n

Repository: jnethack/temp-370

Length of output: 4078


split_japanese() に UTF-8 専用の分岐を追加してください。
is_kanji1/2 は 2 バイト前提で進むため、IC == UTF8 では 3 バイト文字を途中で切ってしまいます。jrubout() と同様に UTF-8 では別経路で分割位置を決める必要があります。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@japanese/jlib.c` around lines 481 - 524, split_japanese() currently relies on
is_kanji1/is_kanji2, which advance in 2-byte steps and will break UTF-8 by
splitting multibyte characters. Add a UTF-8-specific branch in split_japanese(),
following the same style as jrubout(), so that when IC == UTF8 it computes the
split position using UTF-8 character boundaries instead of the kanji helpers.
Keep the existing non-UTF-8 path unchanged and ensure the new branch uses the
relevant split logic in split_japanese() rather than modifying
is_kanji1/is_kanji2.

Comment thread src/botl.c
Comment on lines +570 to +576
#if 0 /*JP:T*/
Sprintf(buf, "%s:%-2d", /* "Dlvl:n" (grep fodder) */
In_tutorial(&u.uz) ? "Tutorial" : "Dlvl", depth(&u.uz));
#else
Sprintf(buf, "%s:%-2d", /* "Dlvl:n" (grep fodder) */
In_tutorial(&u.uz) ? "説明" : "地下", depth(&u.uz));
#endif

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# "Dlvl:" 文字列への依存(grep等)がないか確認
rg -n 'Dlvl:' --type=c --type=cpp -g '!src/botl.c'
rg -n 'Dlvl' win/ sys/ 2>/dev/null

Repository: jnethack/temp-370

Length of output: 155


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '== exact string matches ==\n'
rg -n --hidden --glob '!.git' 'Dlvl:' . || true

printf '\n== broader Dlvl matches ==\n'
rg -n --hidden --glob '!.git' 'Dlvl' . || true

printf '\n== nearby botl.c context ==\n'
sed -n '560,585p' src/botl.c

Repository: jnethack/temp-370

Length of output: 3242


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '== src/dungeon.c around the substitution ==\n'
sed -n '2688,2706p' src/dungeon.c

printf '\n== win/tty/wintty.c around Dlvl shrinking ==\n'
sed -n '4400,4420p' win/tty/wintty.c
sed -n '5064,5084p' win/tty/wintty.c

printf '\n== win/curses/cursstat.c around Dlvl-N wording ==\n'
sed -n '1234,1250p' win/curses/cursstat.c

Repository: jnethack/temp-370

Length of output: 3406


Dlvl: の表記は維持するか、置換処理も合わせて修正してください
src/botl.c:570-576Dlvl:説明 / 地下 に変えると、src/dungeon.cstrsubst(lbuf, "Dlvl:", "level "); が効かなくなり、レベル名の整形が崩れます。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/botl.c` around lines 570 - 576, The level label change in botl.c breaks
the existing Dlvl: replacement flow because dungeon.c still expects that exact
token in strsubst() for level-name formatting. Keep the Dlvl: prefix in the text
produced by the status display, or update both the botl.c output and the
dungeon.c strsubst(lbuf, "Dlvl:", "level "); logic together so the downstream
substitution still works from the relevant display path.

Comment thread src/cmd.c
Comment on lines +3205 to +3209
#if 0 /*JP:T*/
if (!strncmpi(key2cmdbuf, "prefix:", 7) && !strcmpi(txt, "reqmenu"))
#else /* extcmdlistの文字列を見ている */
if (!STRNCMP2(key2cmdbuf, "接頭辞:") && !strcmpi(txt, "reqmenu"))
#endif

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# STRNCMP2 マクロの定義を検索
rg -n -C3 '\bSTRNCMP2\b' --type=c --type=h -g '*.h' -g '*.c'

Repository: jnethack/temp-370

Length of output: 155


🏁 Script executed:

#!/bin/bash
set -e

echo '--- STRNCMP2 search (entire repo) ---'
rg -n -C3 '\bSTRNCMP2\b' .

echo
echo '--- nearby context in src/cmd.c ---'
sed -n '3188,3220p' src/cmd.c

Repository: jnethack/temp-370

Length of output: 11154


🏁 Script executed:

#!/bin/bash
set -e

echo '--- search for related string-compare macros/functions ---'
rg -n -C2 '\b(STRNCMP2|STRN?CMP|strncmpi|strcmpi)\b' src include .

Repository: jnethack/temp-370

Length of output: 50374


strsubst の検索文字列を日本語に揃えてください (src/cmd.c:3208-3211)
STRNCMP2(key2cmdbuf, "接頭辞:") には入りますが、直後の strsubst(key2cmdbuf, "prefix:", ...) は一致せず、この分岐での2行表示変換が実行されません。"接頭辞:" に合わせてください。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cmd.c` around lines 3205 - 3209, The branch handling extcmdlist lookup in
cmd.c is mismatched: it checks key2cmdbuf with STRNCMP2 against "接頭辞:" but still
calls strsubst with "prefix:", so the replacement never fires for this path.
Update the strsubst call in the same conditional block to use the same Japanese
prefix string as the matcher, and keep the reqmenu handling consistent with the
surrounding extcmdlist logic so the two-line display conversion runs correctly.

Comment thread src/dog.c
Comment on lines +255 to +277
#if 0 /*JP:T*/
petname = "Slasher"; /* The Warrior */
#else
petname = "スラッシャー";
#endif
if (Role_if(PM_SAMURAI))
#if 0 /*JP:T*/
petname = "Hachi"; /* Shibuya Station */
#else
petname = "ハチ公";
#endif
if (Role_if(PM_BARBARIAN))
#if 0 /*JP:T*/
petname = "Idefix"; /* Obelix */
#else
petname = "イデフィクス";
#endif
if (Role_if(PM_RANGER))
#if 0 /*JP:T*/
petname = "Sirius"; /* Orion's dog */
#else
petname = "シリウス";
#endif

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

単一行の独立変更には #if 0ブロックではなく単一行形式を使うべき

petname = "..." は各行とも1行で完結し、周囲から独立した変更です。コーディングガイドラインでは「原文・変更後コードがともに1行に収まり、変更が独立している場合は単一行置換形式 /*JP ... */ を使う」とされています。ここでは複数行を要する #if 0 /*JP:T*/ ... #else...#endif`` ブロックが使われており、規約と一致しません。

♻️ 修正例(1件目のみ抜粋)
         if (Role_if(PM_CAVE_DWELLER))
-#if 0 /*JP:T*/
-            petname = "Slasher"; /* The Warrior */
-#else
-            petname = "スラッシャー";
-#endif
+/*JP
+            petname = "Slasher"; /* The Warrior */
+*/
+            petname = "スラッシャー";

As per coding guidelines: "If the original and changed code each fit on a single line and the change is independent, use the single-line replacement form /*JP ... */ followed by the replacement line."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/dog.c` around lines 255 - 277, The petname assignments in the
Role_if(PM_SAMURAI), Role_if(PM_BARBARIAN), and Role_if(PM_RANGER) branches are
single-line independent changes, so replace the current `#if` 0 /*JP:T*/ ... `#else`
... `#endif` blocks in dog.c with the single-line JP replacement form using the
surrounding petname assignment lines as the anchor.

Source: Coding guidelines

Comment thread src/dog.c
Comment thread src/dogmove.c
@argrath argrath closed this Jul 4, 2026
@argrath
argrath deleted the patch branch July 4, 2026 16:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants