> For the complete documentation index, see [llms.txt](https://docs.cardz.game/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cardz.game/zh/yun-zuo-fang-shi/rng-yu-ke-yan-zheng-gong-ping-xing.md).

# RNG 與可驗證公平性

### 1. 介紹

Cardz.game 的結算引擎使用基於 SHA-256 密碼雜湊函式的決定性隨機數生成 (RNG) 演算法。這可確保任何機率事件（開包）的結果僅由事先提交的輸入導出，使結果不可更改且可驗證。

本文件定義將原始熵轉換為資產選取所使用的數學運算。

### 2. 輸入參數

生成器需要三個不同的輸入（種子）以最大化熵並確保使用者參與。

| **參數**     | **類型**    | **位元長度** | **說明**                              |
| ---------- | --------- | -------- | ----------------------------------- |
| 伺服器種子 (Ss) | 字串（16 進位） | 256 位元   | 由平台產生的密碼學安全隨機位元組。                   |
| 用戶種子 (Sc)  | 字串        | 可變       | 使用者提供的熵。預設為瀏覽器產生的 32 字元字串，但可由使用者自訂。 |
| 計數器 (N)    | 整數（u64）   | 64 位元    | 與該種子對關聯的單調遞增計數器。每次執行遞增 (N+1)。       |

### 3. 雜湊程序

原始熵透過串接與雜湊產生。

#### 3.1. 串接

輸入以嚴格的 UTF-8 字串方式串接：

明文

```
Raw = ServerSeed + ClientSeed + Nonce
```

#### 3.2. 摘要產生

串接後的字串經由 SHA-256 演算法處理以產生十六進位摘要 (H)：

明文

```
H = SHA256(Raw)
```

結果是一個 64 個字元的十六進位字串，代表 256 位元的熵。

> *範例 H：* `b56a4208e9104033...`

### 4. 結果決定（正規化）

為將十六進位雜湊 (H) 轉為可用的遊戲結果，我們採用均勻浮點轉換方法。此方法將雜湊映射到介於 0 與 1 之間的浮點數。

#### 4.1. 切片與整數轉換

我們取生成雜湊 (H) 的前 8 個字元（32 位元）。該子字串從 16 進位（hex）轉換為 10 進位（十進制）。

明文

```
I = HexToDecimal(H.substring(0, 8))
```

* I 的理論範圍： `0` 到 `4,294,967,295` (16^8 - 1)

#### 4.2. 浮點正規化

整數 `I` 被除以最大可能的 32 位元值以產生正規化的浮點數 (U)。

明文

```
U = I / 4,294,967,296
```

這會產生一個均勻分佈的浮點數，其 `0 <= U < 1`.

### 5. 資產選取（累積分佈函數映射）

浮點數 `U` 會與該包的掉落表的累積分佈函數（CDF）比較。

範例掉落表：

* 資產 A（普通）：50%（0.50）
* 資產 B（稀有）：30%（0.30）
* 資產 C（超稀有 SSR）：20%（0.20）

映射邏輯：

系統會遍歷累積權重。若 `U` 小於累積閾值，該資產即被選取。

1. 閾值 1： `0.50` （資產 A） -> 是否 `U < 0.50`?
2. 閾值 2： `0.80` （0.50 + 0.30） -> 是否 `U < 0.80`?
3. 閾值 3： `1.00` （0.80 + 0.20） -> 是否 `U < 1.00`?

*注意：對於 5 張卡包，該過程會重複 5 次。通常會遞增 Nonce 以從單一種子產生 5 個不同的數值。*

### 6. 參考實作（TypeScript）

下列程式片段複製生產邏輯以供驗證之用。

TypeScript

```
import { createHash } from 'crypto';

/**
 * 從種子產生正規化的浮點數。
 * @param serverSeed - 未雜湊的伺服器種子。
 * @param clientSeed - 使用者的用戶端種子。
 * @param nonce - 當前交易計數。
 * @returns 介於 0 與 1 之間的浮點數。
 */
function generateResult(serverSeed: string, clientSeed: string, nonce: number): number {
  // 1. 建構 Raw 字串
  const rawString = `${serverSeed}${clientSeed}${nonce}`;

  // 2. 產生 SHA-256 雜湊（十六進位輸出）
  const hash = createHash('sha256').update(rawString).digest('hex');

  // 3. 取前 8 個字元（32 位元）
  const hexSlice = hash.substring(0, 8);

  // 4. 轉為十進位整數
  const decimalValue = parseInt(hexSlice, 16);

  // 5. 正規化為浮點數 [0, 1)
  // 除數為 16^8（4,294,967,296）
  const result = decimalValue / 4294967296;

  return result;
}

// 範例用法
const outcome = generateResult("a1b2c3d4...", "user-seed-123", 1);
console.log(`RNG Result: ${outcome}`); // 例如：0.4812...
```

### 7. 邊界情況處理

#### 7.1. 精度限制

系統使用標準 IEEE 754 雙精度浮點運算。除數 `2^32` 確保結果解析度足以支援低至 `0.000000023%`.

#### 7.2. 避免模數偏差

我們嚴格避免對原始雜湊使用模（`%`）運算來決定結果，因為當鍵空間無法被結果數量整除時，模運算可能會引入些微的統計偏差。浮點正規化方法（`I / 2^32`）在統計上是中性且無偏的。
