Bug fixes: - Remove "TEMPORARY FIX" that stopped search after finding first suit - Add armor level as lowest-priority tiebreaker in scoring Scoring formula now: - Set completion: +1000 per complete set - Missing pieces: -200 penalty each - Crit damage: +10/20 per item - Damage rating (clothes): +10/20/30 - Spell coverage: +100 per fulfilled spell - Base item score: +5 per item - Armor level: +1 per 100 AL (tiebreaker) Updated design doc with audit findings - most features were already working correctly. The magsuitalgo.md analysis was outdated. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
224 lines
7.5 KiB
Markdown
224 lines
7.5 KiB
Markdown
# Suitbuilder Design Document
|
||
|
||
**Date:** 2026-01-30
|
||
**Status:** In Progress
|
||
**Reference:** `magsuitalgo.md` (detailed MagSuitBuilder algorithm analysis)
|
||
|
||
---
|
||
|
||
## Section 1: Problem Statement & Goals
|
||
|
||
### What is Suitbuilder?
|
||
|
||
Suitbuilder helps players find the best equipment combination from their inventory across multiple "mule" characters. In Asheron's Call, players have many characters storing thousands of armor pieces, jewelry, and accessories. Finding the optimal combination manually is impractical.
|
||
|
||
### Why is this hard?
|
||
|
||
The naive approach would check every possible combination: if you have 50 items per slot across 17 equipment slots, that's 50^17 combinations - more than atoms in the universe. MagSuitBuilder solved this with smart algorithms, and we're replicating that approach.
|
||
|
||
### Main Goal - Priority Order
|
||
|
||
Given user constraints, find equipment combinations that:
|
||
|
||
1. **Complete armor set bonuses** (5 pieces primary set + 4 pieces secondary set) - HIGHEST PRIORITY
|
||
2. **Cover all required spells/cantrips** without duplicates
|
||
3. **Maximize armor protection** - LOWEST PRIORITY (tiebreaker)
|
||
|
||
### Why we're doing this
|
||
|
||
The original MagSuitBuilder is a Windows desktop app. We want this functionality in our web-based Dereth Tracker so players can search their inventories from any browser.
|
||
|
||
---
|
||
|
||
## Section 2: Algorithm Overview
|
||
|
||
### The Bucket Approach
|
||
|
||
Instead of checking all item combinations, we organize items into "buckets" by equipment slot (Head, Chest, Hands, etc.). Then we search through buckets one at a time using recursion with backtracking.
|
||
|
||
### How it works
|
||
|
||
1. **Create buckets** - One bucket per equipment slot (11 armor slots + jewelry slots)
|
||
2. **Sort buckets** - Process smallest buckets first (fewer branches to explore)
|
||
3. **Recursive search** - Try each item in bucket 1, then recurse to bucket 2, etc.
|
||
4. **Backtrack** - When a branch fails constraints, undo and try next item
|
||
5. **Skip allowed** - Can skip a slot entirely (incomplete suit better than constraint violation)
|
||
|
||
### Why this is fast
|
||
|
||
- Bucket with 20 items × bucket with 15 items × bucket with 10 items = 3,000 combinations
|
||
- vs. checking every item against every other item = millions of combinations
|
||
|
||
### Two-Phase Search (from MagSuitBuilder)
|
||
|
||
1. **Phase 1 - ArmorSearcher**: Find optimal armor combinations (enforces set constraints)
|
||
2. **Phase 2 - AccessorySearcher**: Add jewelry to complete spell coverage
|
||
|
||
### Key Data Structures
|
||
|
||
- **Spell Bitmap**: 32-bit integer where each bit = one spell. Overlap detection is instant via bitwise OR
|
||
- **Coverage Mask**: Tracks which body areas are covered to prevent conflicts
|
||
- **Set Counter**: Tracks pieces per armor set (max 5 primary, 4 secondary)
|
||
|
||
---
|
||
|
||
## Section 3: Current Implementation State
|
||
|
||
**Updated after Task 1 Audit (2026-01-30)**
|
||
|
||
### What's Working ✅
|
||
|
||
| Feature | Location | Status |
|
||
|---------|----------|--------|
|
||
| Bucket creation (all 17 slots) | Lines 1006-1135 | ✅ Working |
|
||
| Bucket sorting (armor first, smallest first) | Lines 1127-1130 | ✅ Working |
|
||
| ItemPreFilter (surpassing logic) | Lines 503-583, used at 969 | ✅ Working |
|
||
| Item sorting (by spell count/ratings) | Lines 971-991 | ✅ Working |
|
||
| Spell bitmap system | SpellBitmapIndex class | ✅ Working |
|
||
| Set constraints (5+4 logic) | can_add_item() | ✅ Working |
|
||
| Coverage mask with reductions | Lines 1137-1240 | ✅ Working |
|
||
| API Endpoints | `/search`, `/characters`, `/sets` | ✅ Working |
|
||
| Streaming Results (SSE) | recursive_search() | ✅ Working |
|
||
| Frontend | `suitbuilder.html`, `suitbuilder.js` | ✅ Working |
|
||
|
||
### What's Broken ❌
|
||
|
||
| Bug | Location | Issue |
|
||
|-----|----------|-------|
|
||
| **Early termination** | Lines 1326-1329 | "TEMPORARY FIX" stops after finding 1 suit |
|
||
| **Armor level not scored** | `_calculate_score()` | Not included as tiebreaker |
|
||
|
||
### Current Scoring Formula
|
||
|
||
```
|
||
score = set_completion_bonus (1000 per complete set)
|
||
+ set_missing_penalty (-200 per missing piece)
|
||
+ crit_damage (10-20 per item)
|
||
+ damage_rating on clothes (10-30)
|
||
+ spell_coverage (100 per fulfilled spell)
|
||
+ base_item_score (5 per item)
|
||
|
||
MISSING: + armor_level as lowest-priority tiebreaker
|
||
```
|
||
|
||
### Code Structure
|
||
|
||
- `suitbuilder.py`: 1,847 lines
|
||
- Main solver class (`ConstraintSatisfactionSolver`): ~1,130 lines
|
||
|
||
### Note: magsuitalgo.md Analysis Was Outdated
|
||
|
||
The analysis document incorrectly stated:
|
||
- ❌ "Only creates 2 buckets" → Actually creates all 17
|
||
- ❌ "No item pre-filtering" → ItemPreFilter exists and is used
|
||
- ❌ "No item sorting" → Items are sorted by spell count/ratings
|
||
|
||
The code is in much better shape than documented. Only 2 bugs need fixing.
|
||
|
||
---
|
||
|
||
## Section 4: Implementation Plan
|
||
|
||
**Updated after audit - most tasks already done!**
|
||
|
||
---
|
||
|
||
### Task 1: Audit & Document Current Search Flow ✅ COMPLETE
|
||
|
||
**Findings:**
|
||
- Bucket creation: ✅ All 17 slots created correctly
|
||
- Pre-filtering: ✅ ItemPreFilter.remove_surpassed_items() used at line 969
|
||
- Sorting: ✅ Items sorted by spell count (armor/jewelry) and damage rating (clothes)
|
||
- Set constraints: ✅ 5+4 logic in can_add_item()
|
||
|
||
**Bugs Found:**
|
||
1. Early termination at lines 1326-1329 ("TEMPORARY FIX")
|
||
2. Armor level missing from scoring
|
||
|
||
---
|
||
|
||
### Task 2: Fix Bucket Creation ✅ ALREADY WORKING
|
||
|
||
No changes needed - all 17 slots are created at lines 1006-1135.
|
||
|
||
---
|
||
|
||
### Task 3: Fix Search Completion ✅ COMPLETE
|
||
|
||
**Goal:** Remove early termination so search finds multiple suits
|
||
|
||
**The Bug (was at lines 1326-1329):**
|
||
```python
|
||
# TEMPORARY FIX: Stop search after finding first suit to test completion
|
||
if len(self.best_suits) >= 1:
|
||
logger.info(f"[DEBUG] EARLY TERMINATION...")
|
||
return
|
||
```
|
||
|
||
**Fix Applied:** Removed this block entirely.
|
||
|
||
---
|
||
|
||
### Task 4: Add Item Sorting ✅ ALREADY WORKING
|
||
|
||
No changes needed - items sorted at lines 971-991.
|
||
|
||
---
|
||
|
||
### Task 5: Add Armor Level to Scoring ✅ COMPLETE
|
||
|
||
**Goal:** Add armor_level as lowest-priority tiebreaker
|
||
|
||
**Location:** `_calculate_score()` method
|
||
|
||
**Fix Applied:** Added armor level scoring after base item score:
|
||
```python
|
||
# 6. Armor level as tiebreaker (LOWEST PRIORITY)
|
||
# Scale down significantly so it only matters when other scores are equal
|
||
armor_score = state.total_armor // 100 # ~5 points per 500 AL
|
||
score += armor_score
|
||
```
|
||
|
||
---
|
||
|
||
### Task 6: Add Item Pre-Filtering ✅ ALREADY WORKING
|
||
|
||
No changes needed - ItemPreFilter used at line 969.
|
||
|
||
---
|
||
|
||
### Task 7: Add AccessorySearcher Phase (Future)
|
||
|
||
**Goal:** After armor search, optimize jewelry slots
|
||
|
||
**Scope:** Separate task, do after core search is verified working
|
||
|
||
---
|
||
|
||
## How to Use This Document
|
||
|
||
**For Claude (AI assistant):**
|
||
- Read this document at the start of each session
|
||
- Work on ONE task at a time
|
||
- Verify before moving to next task
|
||
- If confused, re-read the relevant section
|
||
- Do NOT make changes outside the current task scope
|
||
|
||
**For the developer:**
|
||
- Update "Status" at top when tasks complete
|
||
- Add notes under each task as we learn things
|
||
- Reference `magsuitalgo.md` for detailed algorithm explanations
|
||
|
||
---
|
||
|
||
## Progress Tracking
|
||
|
||
| Task | Status | Notes |
|
||
|------|--------|-------|
|
||
| Task 1: Audit Current Flow | ✅ Complete | Found 2 bugs, most features working |
|
||
| Task 2: Fix Bucket Creation | ✅ Already Working | No changes needed |
|
||
| Task 3: Fix Search Completion | ✅ Complete | Removed early termination at lines 1326-1329 |
|
||
| Task 4: Add Item Sorting | ✅ Already Working | No changes needed |
|
||
| Task 5: Add Armor Level Scoring | ✅ Complete | Added armor_score = total_armor // 100 |
|
||
| Task 6: Add Item Pre-Filtering | ✅ Already Working | No changes needed |
|
||
| Task 7: AccessorySearcher | Not Started | Future |
|