Repository navigation
Conversation
## コア抽出(core/) - Pico/Web共通ロジック - core/coBroc_core.h/cpp: 全型・定数・ゲームロジック(合法判定/VM/AI採点) - core/model.h: YDFラッパー(main.hから移設、Pico非依存) - core/wasm_api.h/cpp: Web用C ABI(スナップショットJSON v1/base64シリアライズ) - core/test/core_test.cpp: ホスト決定論テスト(5シナリオ、FNV-1aハッシュ) - core/abi_test.cpp: ABI検証テスト - RNG: グローバル乱数→ProgramState.rng_seedに状態化。剰余法でクロスプラットフォーム決定論を保証 - AI予測: g_predictor_fn関数ポインタでPico(core1バッチ)/WASM(同期)を切替 ## Web版(web/) - WASMビルド(web/CMakeLists.txt): Emscripten 3.1.69, MODULARIZE+CoBrocModule - フロントエンド: Vite+TypeScript、Canvasフローチャート描画、操作UI - セーブ/ロード(localStorage)、リプレイ(操作ログの決定的再生) - E2Eテスト(web/e2e/): ヘッドレスChrome 15項目 - GitHub Pagesデプロイ(.github/workflows/web.yml) - 契約書(web/API_CONTRACT.md): C ABI/JSONスキーマ/シリアライズ形式 ## 主な修正 - main.cpp/main.h: コア参照にリファクタ。Pico依存(LVGL/赤外線)のみ保持 - Pico Debug/Releaseビルド維持 - パリティ検証: ネイティブ/WASMで全5シナリオ一致 (3BF544D8/F43A33F6/E01971F1/045744D7/8A0B3A3C) ## AIのEND全面禁止(TODO-Web07) - buildCandidatesでBlockType::Endをスキップ(AIは候補から完全除外) - performAITurnのEND抑制ブロックを削除。AI起因のゲーム終了は盤面満杯のみ - プレイヤー側の完成判定: ENDで閉じてdepth==0の場合のみ色選択へ - モック(mock.ts)もAI_PLAYABLEからENDを除外
Contributor
There was a problem hiding this comment.
Pull request overview
Pico版で動いていた coBroc のゲームロジックを core/ に抽出し、同一ロジックを Emscripten/WASM 経由で Web フロントエンド(Vite+TS+Canvas)から利用できるようにする移植PRです。あわせて AI の END 設置を全面禁止し、ネイティブ/WASM の決定論パリティ検証・E2E・Pages デプロイまでを揃えています。
Changes:
core/にゲームロジック・AI・VM・決定論テストを集約し、Pico側はハード/表示・予測ワーカー等の依存部に整理core/wasm_api.*とweb/CMakeLists.txtで Web 向け C ABI + JSON snapshot + base64 serialize/deserialize を実装web/に UI/ローダー/モック/セーブ/リプレイ/E2E を追加し、GitHub Pages へデプロイする workflow を追加
Reviewed changes
Copilot reviewed 27 out of 30 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| web/vite.config.ts | Vite ビルド/開発サーバ設定を追加 |
| web/tsconfig.json | Web 向け TypeScript 設定を追加 |
| web/src/wasm/types.ts | Snapshot/ABI/Replay の型と表示用定数を定義 |
| web/src/wasm/mock.ts | 実WASM不在時の契約準拠モックコアを実装 |
| web/src/wasm/loader.ts | WASM(実)優先・失敗時モックのローダー/ラッパーを実装 |
| web/src/ui/render.ts | Canvas 2D によるフローチャート/色選択/結果描画を実装 |
| web/src/storage.ts | localStorage オートセーブと JSON export/import を実装 |
| web/src/replay.ts | seed+操作ログによる決定的リプレイを実装 |
| web/src/main.ts | Web版メインループ/入力/ターン遷移/オートAIを実装 |
| web/package.json | Web ビルド/wasm/e2e スクリプトと依存を追加 |
| web/index.html | Web UI の DOM/スタイル/エントリポイントを追加 |
| web/e2e/run_e2e.mjs | dist 配信 + puppeteer 実行の E2E ランナーを追加 |
| web/e2e/e2e_test.mjs | ヘッドレスChromeで実ゲームフローを検証する E2E を追加 |
| web/CMakeLists.txt | Emscripten ビルド(コア+ABI)の CMake を追加 |
| web/API_CONTRACT.md | WASM/フロント並行開発向けの凍結契約(ABI/JSON/保存/リプレイ)を追加 |
| plan.md | WEB移植計画/検証内容/TODO を追記 |
| main.h | Pico側ヘッダを core 参照に整理 |
| main.cpp | Pico側を core 利用 + 予測ワーカー/ハードUI中心に整理し、完成判定/決定論対応を反映 |
| core/wasm_api.h | Web向け C ABI の公開ヘッダを追加 |
| core/wasm_api.cpp | C ABI 実装、snapshot JSON、base64 serialize/deserialize を追加 |
| core/test/core_test.cpp | ホスト決定論テスト(複数シナリオ+FNV-1a)を追加 |
| core/model.h | YDF ラッパーを core に移設 |
| core/coBroc_core.h | コアの型/定数/宣言を追加 |
| core/coBroc_core.cpp | コアロジック本体(AI/VM/決定論RNG等)を追加 |
| core/abi_test.cpp | C ABI のスモーク/ラウンドトリップ検証テストを追加 |
| CMakeLists.txt | ルートの Pico ビルドに core ソース/ヘッダを追加 |
| .gitignore | web のビルド成果物/WASM生成物等を追加で無視 |
| .github/workflows/web.yml | Emscripten+Vite でビルドして Pages にデプロイする workflow を追加 |
Files not reviewed (1)
- web/package-lock.json: Generated file
Suppressed comments (1)
web/src/wasm/loader.ts:69
toCStringallocatesstr.length + 1, which is not the UTF-8 byte size. UselengthBytesUTF8(str) + 1to size the buffer correctly before callingstringToUTF8.
function toCString(mod: EmscriptenModule, str: string): number {
const buf = mod._malloc(str.length + 1);
mod.stringToUTF8(str, buf, str.length + 1);
return buf;
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+3
to
+12
| export default defineConfig({ | ||
| root: '.', | ||
| build: { | ||
| outDir: 'dist', | ||
| target: 'es2022', | ||
| }, | ||
| server: { | ||
| port: 3000, | ||
| }, | ||
| }); |
Comment on lines
+30
to
+34
| _malloc(size: number): number; | ||
| _free(ptr: number): void; | ||
| UTF8ToString(ptr: number): string; | ||
| stringToUTF8(str: string, ptr: number, maxBytes: number): void; | ||
| } |
Comment on lines
+49
to
+63
| function injectScript(src: string): Promise<void> { | ||
| return new Promise((resolve, reject) => { | ||
| const existing = document.querySelector(`script[data-cobroc-wasm]`); | ||
| if (existing) { | ||
| resolve(); | ||
| return; | ||
| } | ||
| const script = document.createElement('script'); | ||
| script.src = src; | ||
| script.dataset.cobrocWasm = '1'; | ||
| script.onload = () => resolve(); | ||
| script.onerror = () => reject(new Error('failed to load ' + src)); | ||
| document.head.appendChild(script); | ||
| }); | ||
| } |
Comment on lines
+167
to
+188
| bool b64Decode(const char* in, std::vector<uint8_t>& out) { | ||
| const size_t len = std::strlen(in); | ||
| if (len % 4 != 0) return false; | ||
| out.clear(); | ||
| out.reserve((len / 4) * 3); | ||
| for (size_t i = 0; i < len; i += 4) { | ||
| int v[4]; | ||
| for (int k = 0; k < 4; k++) { | ||
| const char c = in[i + k]; | ||
| if (c == '=') v[k] = -2; | ||
| else v[k] = b64Value(c); | ||
| if (v[k] < 0 && !(c == '=' && k >= 2)) return false; | ||
| } | ||
| const uint32_t n = static_cast<uint32_t>( | ||
| (v[0] & 0x3F) << 18 | (v[1] & 0x3F) << 12 | | ||
| (v[2] > 0 ? v[2] : 0) << 6 | (v[3] > 0 ? v[3] : 0)); | ||
| out.push_back(static_cast<uint8_t>((n >> 16) & 0xFF)); | ||
| if (v[2] >= 0) out.push_back(static_cast<uint8_t>((n >> 8) & 0xFF)); | ||
| if (v[3] >= 0) out.push_back(static_cast<uint8_t>(n & 0xFF)); | ||
| } | ||
| return true; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
コア抽出(core/) - Pico/Web共通ロジック
Web版(web/)
主な修正
AIのEND全面禁止(TODO-Web07)