# 機能設計書 32-ゲージ管理

## 概要

本ドキュメントは、K-Shoot MANIAのゲームプレイにおけるゲージ管理機能の設計を記述する。通常ゲージ（Effective Rate）とHARDゲージ（ネガティブゲージ）の2種類のゲージ増減を管理し、クリア判定やゲージ0時の強制終了を制御する。

### 本機能の処理概要

**業務上の目的・背景**：音楽ゲームではプレイヤーの判定精度に応じてゲージが増減し、楽曲クリアの可否を決定する必要がある。通常ゲージとHARDゲージの2種類を用意することで、初心者から上級者まで多様なプレイスタイルに対応する。

**機能の利用シーン**：ゲームプレイ中に各ノートの判定結果に応じてリアルタイムにゲージが増減し、ゲージバーとして画面に表示される。HARDゲージモードではゲージが0になった時点で楽曲が強制終了する。コースモードでは各曲を通してゲージが継続する。

**主要な処理内容**：
1. 判定結果に応じたゲージ増加（addgauge関数）：CRITICAL/NEAR判定時にゲージタイプに応じた量を加算
2. 判定ミス時のゲージ減少（subgauge関数）：ERROR判定時にゲージタイプに応じた量を減算
3. HARDゲージモードでのゲージ0時の強制終了判定
4. コースモード時のゲージ継続管理（初期値100%、通常とは異なる増減量）

**関連システム・外部連携**：結果画面でのクリア判定（gauge/1000 > 70で通常クリア）に使用。

**権限による制御**：ゲージタイプ（effratetype）設定により処理内容が変わる。effratetype=0（通常）、effratetype=-1（Easy）、effratetype>0（HARD）。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | ゲームプレイ画面 | 主画面 | 通常ゲージとHARD(ネガティブ)ゲージの2種類のゲージ増減管理 |
| 6 | リザルト画面 | 結果表示画面 | ゲージパーセンテージ・クリア判定・メダルの表示 |

## 機能種別

計算処理 / バリデーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| effratetype | int | Yes | ゲージタイプ（0=通常, -1=Easy, >0=HARD） | -1以上の整数 |
| iscourse | int | Yes | コースモードフラグ（0=通常, 1=コース） | 0または1 |
| gauge | int | Yes | 現在のゲージ値（0〜gaugemax、内部値は1000倍） | 0以上の整数 |
| gaugemax | int | Yes | ゲージ最大値 | 通常モード: 可変、コース: 100000 |
| a | int | Yes | ゲージ加算時の基本倍率 | addgauge関数の第1引数 |
| b | int | Yes | 判定種別（0=CRITICAL, 1=NEAR/ERROR） | addgauge関数の第2引数 |

### 入力データソース

BT/FXノート判定（processButtonNoteJudgment）、レーザーノート判定（processLaserNoteJudgment）から呼び出される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| gauge | int | 更新後のゲージ値（内部値、1000で割るとパーセンテージ） |
| unlimited_gauge | int | 上限なしゲージ値（通常ゲージの参考値） |
| endfl | int | 強制終了フラグ（HARDゲージ0時に1） |

### 出力先

- 画面表示: ゲームプレイ画面のゲージバー（play_draw_frame.hsp）
- 結果画面: リザルト画面のゲージ表示・クリア判定（result.hsp）

## 処理フロー

### 処理シーケンス

```
1. ゲージ増加処理（addgauge）
   ├─ 通常モード（iscourse=0）
   │   ├─ effratetype=0（通常）: gauge += a*50, 上限=gaugemax
   │   ├─ effratetype=-1（Easy）: gauge += a*55, 上限=gaugemax
   │   └─ effratetype>0（HARD）: b=0のみ gauge += a*30, 上限=100000
   └─ コースモード（iscourse=1）
       ├─ effratetype=0（通常）: gauge += 100000*(a*50)/2/gaugemax, 上限=100000
       ├─ effratetype=-1（Easy）: gauge += 100000*(a*55)/2/gaugemax, 上限=100000
       └─ effratetype>0（HARD）: b=0のみ gauge += a*20, 上限=100000

2. ゲージ減少処理（subgauge）
   ├─ 通常モード（iscourse=0）
   │   ├─ effratetype=0（通常）: gauge -= a*gaugemax/200
   │   ├─ effratetype=-1（Easy）: gauge -= gaugemax*a*0.375/100
   │   └─ effratetype>0（HARD）: gauge -= a*2250*(100-41*(gauge<=30%))/100
   └─ コースモード（iscourse=1）
       ├─ effratetype=0/1（通常/Easy）: gauge -= a*100000*(17-7*(gauge<=30%))/10/200
       └─ effratetype>0（HARD）: gauge -= a*3037.5*(100-41*(gauge<=30%))/100

3. HARDゲージ0判定
   └─ gauge/1000<=0 かつ mendt=-1 → endfl=1, 強制終了SE再生
```

### フローチャート

```mermaid
flowchart TD
    A[判定結果入力] --> B{判定種別}
    B -->|CRITICAL/NEAR成功| C[addgauge呼び出し]
    B -->|ERROR/失敗| D[subgauge呼び出し]
    C --> E{iscourse?}
    E -->|0:通常| F{effratetype?}
    E -->|1:コース| G{effratetype?}
    F -->|0| H["gauge += a*50"]
    F -->|-1| I["gauge += a*55"]
    F -->|>0| J["b=0: gauge += a*30"]
    G -->|0| K["gauge += 100000*(a*50)/2/gaugemax"]
    G -->|>0| L["b=0: gauge += a*20"]
    D --> M{effratetype?}
    M -->|0| N["gauge -= a*gaugemax/200"]
    M -->|>0| O["gauge -= a*2250*..."]
    O --> P{gauge/1000 <= 0?}
    P -->|Yes| Q[endfl=1, 強制終了]
    P -->|No| R[継続]
    H --> R
    I --> R
    J --> R
    K --> R
    L --> R
    N --> R
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-32-01 | 通常ゲージ初期値 | 通常モード・通常ゲージ時は初期値0から開始 | effratetype<=0, iscourse=0 |
| BR-32-02 | HARDゲージ初期値 | HARDゲージおよびコースモード時は初期値100%（100000）から開始 | effratetype>0 or iscourse=1 |
| BR-32-03 | HARD強制終了 | HARDゲージが0以下になった場合、楽曲を強制終了する | effratetype>0 and gauge/1000<=0 |
| BR-32-04 | ゲージ30%以下ペナルティ | HARDゲージ30%以下では減少量が41%軽減される | effratetype>0 and gauge/1000<=30 |
| BR-32-05 | NEAR非加算（HARD） | HARDゲージではNEAR判定時にゲージ増加しない（b=1では加算されない） | effratetype>0 and b=1 |
| BR-32-06 | コースゲージ正規化 | コースモードでは全曲通して100000が上限となるよう正規化 | iscourse=1 |

### 計算ロジック

```
// 通常モード・通常ゲージ (effratetype=0, iscourse=0)
addgauge: gauge += a * 50 (上限: gaugemax)
subgauge: gauge -= a * gaugemax / 200 (下限: 0)

// 通常モード・Easyゲージ (effratetype=-1, iscourse=0)
addgauge: gauge += a * 55 (上限: gaugemax)
subgauge: gauge -= gaugemax * a * 0.375 / 100 (下限: 0)

// 通常モード・HARDゲージ (effratetype>0, iscourse=0)
addgauge: gauge += a * 30 (CRITICAL時のみ, 上限: 100000)
subgauge: gauge -= a * 2250 * (100 - 41*(gauge/1000<=30)) / 100

// HARDゲージ0判定
if gauge/1000 <= 0 and mendt == -1:
    endfl = 1 (強制終了)
    hardfailedid SE再生
```

## データベース操作仕様

本機能はデータベースを使用しない。ゲージ値はメモリ上の変数として管理される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ゲージ下限チェック | gauge < 0 | gauge = 0に補正（通常ゲージ時） |
| - | ゲージ上限チェック | gauge > gaugemax | gauge = gaugmaxに補正 |
| - | HARDゲージ0 | gauge/1000 <= 0（HARDモード） | 強制終了フラグ設定、失敗SE再生 |

### リトライ仕様

リトライは不要。

## トランザクション仕様

トランザクション管理は不要。メモリ上の変数操作のみ。

## パフォーマンス要件

ノート判定ごとに呼び出されるため高速処理が必要。整数演算が主体であり問題なし。

## セキュリティ考慮事項

特になし。

## 備考

- `gauge`変数は内部的に1000倍の値で管理されている（例: 70% = 70000）
- `unlimited_gauge`はHARDゲージの強制終了判定には使用されず、参考値として管理される
- コースモードでは曲間でゲージが引き継がれる（coursenow=0の初曲のみ初期化）
- ngauge変数は通常ゲージ用の別系統（非推奨ゲージ: 旧互換用）として存在する

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | play_game_logic.hsp | `src/scene/play/play_game_logic.hsp` | initGamePlayVariables関数（49-60行目）でゲージ初期値の設定ロジックを確認 |

**読解のコツ**: `effratetype`の値によって初期値が分岐する。effratetype<=0（通常/Easy）では`gauge=0`、それ以外では`gauge=100000`。コースモード時は`coursenow=0`（初曲）のみ初期化される。

#### Step 2: ゲージ増加ロジック（addgauge）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | play_utils.hsp | `src/scene/play/play_utils.hsp` | addgauge関数（292-334行目）の全分岐パターンを理解 |

**主要処理フロー**:
- **293-301行目**: 通常モード（iscourse=0）でのゲージ増加パターン3種
- **307-332行目**: コースモード（iscourse=1）でのゲージ増加パターン（正規化あり）
- **321-331行目**: HARDゲージのNEAR判定時の減算ロジック（`b=1`のケース）

#### Step 3: ゲージ減少ロジック（subgauge）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | play_utils.hsp | `src/scene/play/play_utils.hsp` | subgauge関数（336-380行目）の全分岐パターンを理解 |

**主要処理フロー**:
- **338-341行目**: 通常ゲージのERROR時減算（`gauge -= a*gaugemax/200`）
- **347-358行目**: HARDゲージのERROR時減算と0判定（hardfailedid SE再生含む）
- **360-379行目**: コースモードでのゲージ減算パターン

#### Step 4: ゲージ増減の呼び出し元を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | play_button_note.hsp | `src/scene/play/play_button_note.hsp` | CRITICAL判定時の`addgauge 4*note.7,0`やERROR時の`subgauge 4.0*(1.0+...)`の呼び出し |
| 4-2 | play_laser_note.hsp | `src/scene/play/play_laser_note.hsp` | レーザー判定時の`addgauge analoganj.cnt.5,0`やERROR時の`subgauge`呼び出し |

### プログラム呼び出し階層図

```
on_update_play (play_update.hsp)
    |
    +-- processButtonNoteJudgment (play_button_note.hsp)
    |       +-- CRITICAL判定 → addgauge 4*note.7, 0
    |       +-- NEAR判定   → addgauge note.7, 1
    |       +-- ERROR判定  → subgauge 4.0*(1.0+...)
    |
    +-- processLaserNoteJudgment (play_laser_note.hsp)
    |       +-- CRITICAL判定 → addgauge 4*analoganj.5, 0
    |       +-- ERROR判定  → subgauge 4.0*(1.0+...)
    |
    +-- addgauge (play_utils.hsp:292-334)
    |       +-- gauge増加（ゲージタイプ分岐）
    |       +-- unlimited_gauge同時更新
    |
    +-- subgauge (play_utils.hsp:336-380)
            +-- gauge減少（ゲージタイプ分岐）
            +-- HARDゲージ0判定 → endfl=1
```

### データフロー図

```
[入力]                    [処理]                        [出力]

判定結果(CRITICAL)  ──> addgauge(a, 0) ──> gauge増加 ──> ゲージバー表示
判定結果(NEAR)      ──> addgauge(a, 1) ──> gauge増加    (play_draw_frame.hsp)
判定結果(ERROR)     ──> subgauge(a)    ──> gauge減少 ──> endfl=1(HARD時)
                                            |
effratetype         ──> 分岐制御            └──> result.hsp(クリア判定)
iscourse            ──> 分岐制御
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| play_utils.hsp | `src/scene/play/play_utils.hsp` | ソース | addgauge関数・subgauge関数の実装 |
| play_game_logic.hsp | `src/scene/play/play_game_logic.hsp` | ソース | initGamePlayVariablesでのゲージ初期化 |
| play_button_note.hsp | `src/scene/play/play_button_note.hsp` | ソース | BT/FXノート判定からのaddgauge/subgauge呼び出し |
| play_laser_note.hsp | `src/scene/play/play_laser_note.hsp` | ソース | レーザーノート判定からのaddgauge/subgauge呼び出し |
| play_update.hsp | `src/scene/play/play_update.hsp` | ソース | メインループのオーケストレーション |
| play_draw_frame.hsp | `src/scene/play/play_draw_frame.hsp` | ソース | ゲージバーの描画 |
| result.hsp | `src/scene/result.hsp` | ソース | 結果画面でのクリア判定・ゲージ表示 |
