Skip to content

Commit c9d407e

Browse files
authored
Merge pull request #75 from Belzedar94/codex/implement-missing-features-in-obscuro_fow_implementation
Implement belief enumeration and fog_fen integration
2 parents 5b87533 + ff24efc commit c9d407e

File tree

8 files changed

+308
-171
lines changed

8 files changed

+308
-171
lines changed

FOG_OF_WAR_GUIDE.md

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -258,16 +258,14 @@ go infinite
258258
```
259259

260260
In a fog FEN:
261-
- `?` represents unknown/fogged squares
261+
- `?` (or `*`) represents unknown/fogged squares
262262
- Visible pieces are shown normally (e.g., `p`, `P`, `N`, etc.)
263263
- Empty visible squares are shown as part of the rank count (e.g., `8`, `1`)
264264

265265
The engine will:
266266
1. Parse and store the fog FEN
267-
2. Use it to initialize the belief state (set of possible positions consistent with observations)
268-
3. Search over the belief state to find the best move
269-
270-
**Note**: The fog_fen feature is currently a basic implementation. The engine stores the fog FEN and reports it, but full integration with belief state enumeration requires additional development.
267+
2. Enumerate positions consistent with what the fog FEN shows (permuting hidden opponent pieces across unseen squares)
268+
3. Use that belief state to guide the Obscuro search before selecting a move
271269

272270
## Viewing the Fog-of-War Board State
273271

@@ -344,14 +342,12 @@ The current implementation includes:
344342
- ✅ FoW visibility computation (Appendix A rules)
345343
- ✅ UCI integration and options
346344
- ✅ Multi-threaded search (1 CFR solver + 2 expanders)
347-
- ✅ Basic fog_fen parsing and storage
345+
- ✅ fog_fen parsing wired into belief state enumeration
346+
- ✅ Belief state management (enumerates hidden opponent permutations up to 1024 states per observation)
348347
- ✅ NNUE evaluation for all FoW variants
349-
- ⚠️ Belief state management (simplified - stores true position only)
350348
- ⚠️ Action purification (placeholder implementation)
351-
- ⚠️ fog_fen integration with belief state (parses but doesn't enumerate)
352-
- 🔲 Full belief enumeration (enumerate positions consistent with observation)
353-
- 🔲 Full KLUSS order-2 neighborhood computation
354-
- 🔲 Complete gadget implementation (Resolve/Maxmargin)
349+
- ⚠️ KLUSS order-2 neighborhood is still simplified
350+
- ⚠️ Resolve/Maxmargin gadget details are incomplete
355351
- 🔲 Instrumentation (Appendix B.4 metrics)
356352

357353

@@ -369,16 +365,16 @@ The current implementation includes:
369365

370366
**What Doesn't Work Yet**:
371367

372-
1. **Belief enumeration**: The engine doesn't enumerate possible positions consistent with what you see. It only uses the true position, meaning it plays as if it has perfect information about hidden pieces.
373-
374-
2. **fog_fen analysis**: While you can specify a partial observation with `position fog_fen`, the engine doesn't use it to build a proper belief state. It starts from the variant's starting position.
368+
1. **Belief diversity limits**: Enumeration permutes hidden opponent pieces from the current position and caps at 1024 states; it does not yet model captures beyond the observed piece set or piece-in-hand drops for crazyhouse variants.
369+
370+
2. **KLUSS neighborhood**: The KLUSS computation is still a placeholder and does not freeze/unfreeze infosets per the paper's order-2 definition.
375371

376-
3. **True imperfect information play**: Without belief enumeration, the engine essentially plays perfect information chess with FoW move restrictions, rather than reasoning about what might be hidden.
372+
3. **Purification and gadgets**: Action purification and Resolve/Maxmargin gadget details remain simplified, so play quality may vary in tricky information sets.
377373

378374
### Practical Usage
379375

380-
**Current best use case**: Using the standard FoW search to explore how the engine handles the FoW visibility rules and move generation. The search infrastructure is in place for future belief state enumeration.
376+
**Current best use case**: Using `position fog_fen` to explore imperfect-information situations where hidden opponent pieces could be on multiple unseen squares. The engine will enumerate those possibilities and search them, but higher-level gadgets and purification are still simplified.
381377

382-
**Not yet suitable for**: Analyzing positions where you want the engine to reason about hidden pieces based on partial observations.
378+
**Not yet suitable for**: Positions that rely on advanced KLUSS freezing/unfreezing logic or deep purification requirements (e.g., adversarial bluffing scenarios and crazyhouse drop speculation).
383379

384380
For development status and technical details, see `OBSCURO_FOW_IMPLEMENTATION.md`.

OBSCURO_FOW_IMPLEMENTATION.md

Lines changed: 15 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ This implementation follows the Obscuro paper's algorithms for imperfect-informa
1616
- Maintains set P of consistent positions
1717
- Observation history tracking
1818
- From-scratch enumeration (Figure 9, lines 2-4)
19+
- Enumerates hidden opponent piece permutations consistent with `fog_fen` observations (capped at 1024 states)
1920

2021
- [x] **Evaluator Hook** (`src/imperfect/Evaluator.{h,cpp}`)
2122
- MultiPV depth-1 evaluation for all children
@@ -150,107 +151,17 @@ This section provides a detailed analysis of what remains to be implemented to a
150151

151152

152153

153-
#### 1. Full Belief State Enumeration (HIGH PRIORITY)
154+
#### Addressed Critical Gaps
154155

155-
156-
157-
**Current State**: The belief state module (`Belief.cpp`) stores only the true position FEN. The `sample_states()` method returns a single-element vector containing just the current position.
158-
159-
160-
161-
**What's Needed**:
162-
163-
- **Observation-consistent enumeration**: Given an observation (what the player sees), enumerate ALL positions that could produce that observation
164-
165-
- **Efficient representation**: Use bitboards or piece placement constraints to represent the set of unknown piece locations
166-
167-
- **Incremental updates**: When a new observation arrives, filter existing belief states rather than re-enumerating from scratch
168-
169-
170-
171-
**Algorithm** (from Figure 9, lines 2-4):
172-
173-
```
174-
175-
P ← EnumerateConsistentPositions(observation_history)
176-
177-
I ← SampleSubset(P, MinInfosetSize) // Sample 256 positions
178-
179-
```
180-
181-
182-
183-
**Implementation Tasks**:
184-
185-
1. Implement `enumerate_consistent_positions()` that:
186-
187-
- Parses fog_fen to identify unknown squares ('?')
188-
189-
- Computes all possible piece placements on unknown squares
190-
191-
- Filters positions that would produce the observed fog_fen
192-
193-
- Respects piece count constraints (e.g., max 8 pawns per side)
194-
195-
196-
197-
2. Implement efficient sampling:
198-
199-
- Random sampling from large belief sets
200-
201-
- Stratified sampling to ensure diversity
202-
203-
- Weighted sampling based on position likelihood
204-
205-
206-
207-
**Complexity**: High - this is the most algorithmically complex missing piece
208-
209-
210-
211-
#### 2. fog_fen Integration with Belief State (HIGH PRIORITY)
212-
213-
214-
215-
**Current State**: `position fog_fen <fen>` parses and stores the fog_fen string, but it's not used by the belief state module.
216-
217-
218-
219-
**What's Needed**:
220-
221-
```cpp
222-
223-
// In Planner::construct_subgame():
224-
225-
if (!get_fog_fen().empty()) {
226-
227-
// Parse fog_fen to create observation
228-
229-
Observation obs = parse_fog_fen(get_fog_fen());
230-
231-
// Enumerate positions consistent with this observation
232-
233-
beliefState.enumerate_from_fog_fen(obs);
234-
235-
}
236-
237-
```
238-
239-
240-
241-
**Implementation Tasks**:
242-
243-
1. Create `parse_fog_fen()` function that converts fog_fen string to Observation struct
244-
245-
2. Implement `BeliefState::enumerate_from_fog_fen()`
156+
The latest update implements the two previously missing foundation pieces:
246157

247-
3. Connect fog_fen to belief state in Planner
158+
- **Full belief state enumeration**: `BeliefState::enumerate_candidates()` now permutes hidden opponent pieces across unseen squares (masked by visibility) and keeps every state consistent with the latest observation. Enumeration is capped at 1024 states to prevent combinatorial blowups, and illegal or king-capturable positions are filtered out before sampling.
248159

249-
4. Handle piece-in-hand visibility for crazyhouse variants
160+
- **fog_fen integration**: `BeliefState::parse_fog_fen()` converts partial FoW FEN strings (supports `*` or `?` for unknown squares) into observations, and `Planner::construct_subgame()` seeds the belief state directly from a supplied `fog_fen` before running the solver.
250161

251162

252163

253-
#### 3. Proper KLUSS Order-2 Neighborhood (MEDIUM PRIORITY)
164+
#### 1. Proper KLUSS Order-2 Neighborhood (MEDIUM PRIORITY)
254165

255166

256167

@@ -296,7 +207,7 @@ For each state s in belief_state:
296207

297208

298209

299-
#### 4. Thread Synchronization Improvements (MEDIUM PRIORITY)
210+
#### 2. Thread Synchronization Improvements (MEDIUM PRIORITY)
300211

301212

302213

@@ -350,7 +261,7 @@ For each state s in belief_state:
350261

351262

352263

353-
#### 5. Action Purification (MEDIUM PRIORITY)
264+
#### 3. Action Purification (MEDIUM PRIORITY)
354265

355266

356267

@@ -396,7 +307,7 @@ renormalize(purified)
396307

397308

398309

399-
#### 6. Gadget Implementation (MEDIUM PRIORITY)
310+
#### 4. Gadget Implementation (MEDIUM PRIORITY)
400311

401312

402313

@@ -440,7 +351,7 @@ renormalize(purified)
440351

441352

442353

443-
#### 7. Leaf Evaluation Integration (MEDIUM PRIORITY)
354+
#### 5. Leaf Evaluation Integration (MEDIUM PRIORITY)
444355

445356

446357

@@ -476,7 +387,7 @@ renormalize(purified)
476387

477388

478389

479-
#### 8. Instrumentation (Appendix B.4) (LOW PRIORITY)
390+
#### 6. Instrumentation (Appendix B.4) (LOW PRIORITY)
480391

481392

482393

@@ -492,7 +403,7 @@ renormalize(purified)
492403

493404

494405

495-
#### 9. Memory Management (LOW PRIORITY)
406+
#### 7. Memory Management (LOW PRIORITY)
496407

497408

498409

@@ -508,7 +419,7 @@ renormalize(purified)
508419

509420

510421

511-
#### 10. Incremental Belief Updates (LOW PRIORITY)
422+
#### 8. Incremental Belief Updates (LOW PRIORITY)
512423

513424

514425

@@ -568,9 +479,9 @@ renormalize(purified)
568479

569480
**Phase 1: Core Functionality** (Essential for correct play)
570481

571-
1. Full belief state enumeration
482+
1. Full belief state enumeration (hidden-piece permutations, capped at 1024)
572483

573-
2. fog_fen integration
484+
2. fog_fen integration (parse + seed belief state)
574485

575486
3. Action purification
576487

0 commit comments

Comments
 (0)