Files
amethyst/docs/live-chess-implementation-status.md
T
nrobi144 c2f035acc0 docs: update chess implementation status
- Mark ChessViewModel, navigation, relay subscriptions as complete
- Update file structure to reflect KMP commons migration
- Update checklist with completed items
- Revise next steps to focus on FAB and badge display

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 12:10:39 +02:00

267 lines
10 KiB
Markdown

# Live Chess Implementation Status
## ✅ Completed Implementation
### 1. Chess Engine & Move Validation
- **kchesslib dependency** added to `quartz/build.gradle.kts:150`
- **ChessEngine** interface with expect/actual pattern:
- `ChessEngine.kt` (commonMain) - Platform-agnostic API
- `ChessEngine.jvmAndroid.kt` (jvmAndroid) - kchesslib implementation
- **Full move validation**: Legal moves, check/checkmate, castling, en passant, pawn promotion
- **FEN import/export**: Board state serialization
- **Move history tracking**: SAN notation
### 2. Interactive UI Components (commons/)
- **InteractiveChessBoard.kt**: Click-to-move with visual feedback
- Selected piece highlighting (green)
- Legal move indicators (circles/rings)
- Automatic move validation
- Callback system for move events
- **LiveChessGame.kt**: Complete game UI
- NewChessGameDialog (challenge creation)
- LiveChessGameScreen (full game interface)
- GameInfoHeader (turn indicator, game status)
- MoveHistoryDisplay (SAN move list)
- GameControls (Resign, Offer Draw)
### 3. Nostr Event Protocol (quartz/nip64Chess/)
**New Event Kinds:**
| Kind | Event | Purpose |
|------|-------|---------|
| 30064 | LiveChessGameChallengeEvent | Create/accept challenges |
| 30065 | LiveChessGameAcceptEvent | Accept challenge |
| 30066 | LiveChessMoveEvent | Individual moves (SAN + FEN) |
| 30067 | LiveChessGameEndEvent | Game result & termination |
**Event Factory Integration** (EventFactory.kt:190-193):
- All live chess events registered for automatic parsing
### 4. Game State Management
- **LiveChessGameState.kt**: Coordinates engine, Nostr, and UI
- Turn validation
- Move synchronization
- Automatic end detection (checkmate/stalemate)
- PGN generation
- Position mismatch recovery
### 5. ChessViewModel (amethyst/ui/screen/loggedIn/chess/)
- **ChessViewModel.kt**: Full game state management & event publishing
- `activeGames: StateFlow<Map<String, LiveChessGameState>>` - Active games by ID
- `challenges: StateFlow<List<Note>>` - Incoming/outgoing challenges
- `badgeCount: StateFlow<Int>` - Notification count
- `createChallenge()` - Create open or directed challenges
- `acceptChallenge()` - Accept challenge and start game
- `publishMove()` - Send moves to relays
- `resign()` / `offerDraw()` - End game actions
- **Relay subscriptions** via `LocalCache.live.newEventBundles`
- Auto-handles incoming moves, acceptances, endings, challenges
- **ChessViewModelFactory.kt**: ViewModel factory with Account injection
- **ChessGameScreen.kt**: Wrapper connecting ViewModel to LiveChessGameScreen UI
### 6. Feed Integration
**Chess Feed Filter** (TopNavFilterState.kt:130-142):
- Shows Kind 64 (completed games)
- Shows Kind 30064 (challenges - open & directed)
- Shows Kind 30067 (game endings)
- Excludes Kind 30066 (individual moves - too noisy)
**Event Rendering** (Chess.kt, NoteCompose.kt):
- `RenderChessGame()` - Completed PGN games (Kind 64)
- `RenderLiveChessChallenge()` - Challenge cards with visual states:
- 🔓 **Open challenges** (green border)
- 💌 **Incoming challenges** (orange border)
-**Sent challenges** (gray border)
- `RenderLiveChessGameEnd()` - Game results with PGN
## 🚧 Remaining Work
### Priority 1: FAB & Challenge Creation
**Files to modify:**
1. **HomeScreen.kt** or chess-specific screen
```kotlin
var showNewGameDialog by remember { mutableStateOf(false) }
Scaffold(
floatingActionButton = {
if (isChessFeed) {
FloatingActionButton(
onClick = { showNewGameDialog = true }
) {
Icon(Icons.Default.Add, "New Game")
}
}
}
)
if (showNewGameDialog) {
NewChessGameDialog(
onDismiss = { showNewGameDialog = false },
onCreateGame = { opponentPubkey, color ->
viewModel.createChallenge(opponentPubkey, color)
showNewGameDialog = false
}
)
}
```
### Priority 4: In-App Badges (Optional)
**Files to create:**
1. **BadgeProvider.kt** (commons/)
```kotlin
object ChessBadgeProvider {
fun getBadgeCount(
challenges: List<LiveChessGameChallengeEvent>,
activeGames: List<LiveChessGameState>,
userPubkey: String
): Int {
val incomingChallenges = challenges.count {
it.opponentPubkey() == userPubkey
}
val yourTurnGames = activeGames.count { it.isPlayerTurn() }
return incomingChallenges + yourTurnGames
}
}
```
2. **Badge Display** - Add to chess filter icon:
```kotlin
BadgedBox(badge = { Badge { Text("$count") } }) {
Icon(/* chess icon */)
}
```
## 📋 Implementation Checklist
### Phase 1: Basic Playability ✅ COMPLETE
- [x] Create ChessViewModel
- [x] Add navigation route for LiveChessGameScreen (Route.ChessGame exists)
- [x] Create ChessGameScreen wrapper
- [x] Wire up NewGameDialog → ViewModel.createChallenge()
- [x] Implement event publishing (challenges, moves, game end)
- [ ] Test: Create challenge, see it in feed
### Phase 2: Two-Player Functionality ✅ COMPLETE
- [x] Implement relay subscriptions for game events
- [x] Wire up move synchronization (publish/receive)
- [x] Handle challenge acceptance flow
- [ ] Test: Play complete game between two accounts
### Phase 3: Polish (IN PROGRESS)
- [ ] Add FAB to chess feed
- [ ] Implement badge counts display in nav
- [x] Add "Accept Challenge" button to incoming challenge cards
- [x] Add "View Game" navigation from challenge/game-end cards
- [ ] Handle edge cases (network errors, position desync, abandoned games)
### Phase 4: Persistence (Optional)
- [ ] Create Room entities for active games
- [ ] Store games locally for offline viewing
- [ ] Sync on app start
- [ ] Background service for "your turn" notifications
## 🎯 UX Decisions Implemented
Based on user choices:
1. ✅ **Entry Point**: FAB on Chess feed (pending UI implementation)
2. ✅ **Display**: Visual cards in one feed with borders/icons
3. ✅ **Discovery**: Open challenges shown in Chess feed (green border)
4. ✅ **Tap Action**: Navigate directly to full screen (pending nav)
5. ⏳ **Notifications**: In-app badge for counts (pending implementation)
6. ✅ **Filter Scope**: Meaningful events only (completed games, challenges, endings)
7. ⏳ **Storage**: Local cache + relay sync (pending Room/ViewModel)
8. ✅ **Input**: Click-to-move (already implemented)
## 🔧 Quick Start for Development
### Test the Chess Engine:
```kotlin
val engine = ChessEngine()
engine.reset()
val result = engine.makeMove("e2", "e4")
println("Move success: ${result.success}, SAN: ${result.san}")
```
### Test the Interactive Board:
```kotlin
@Composable
fun TestScreen() {
val engine = remember { ChessEngine().apply { reset() } }
InteractiveChessBoard(
engine = engine,
onMoveMade = { san -> println("Move made: $san") }
)
}
```
### View Chess Feed:
1. Open Amethyst
2. Select "Chess" from home feed dropdown
3. See completed games (Kind 64)
4. See challenges with colored borders (Kind 30064)
5. See game endings with results (Kind 30067)
## 📁 File Structure
```
AmethystMultiplatform/
├── quartz/ # Protocol layer (KMP)
│ ├── src/commonMain/kotlin/.../nip64Chess/
│ │ ├── ChessEngine.kt ✅ Engine interface
│ │ ├── ChessPosition.kt ✅ Board state
│ │ ├── ChessMove.kt ✅ Move representation
│ │ ├── ChessGame.kt ✅ Game model
│ │ ├── PGNParser.kt ✅ PGN parsing (31 tests)
│ │ ├── ChessGameEvent.kt ✅ Kind 64
│ │ ├── LiveChessEvents.kt ✅ Data classes
│ │ ├── LiveChessGameEvents.kt ✅ Kind 30064-30067
│ │ └── LiveChessGameState.kt ✅ Game coordinator
│ └── src/jvmAndroid/kotlin/.../nip64Chess/
│ └── ChessEngine.jvmAndroid.kt ✅ kchesslib impl
├── commons/ # Shared UI (Android/Desktop) - KMP
│ └── src/commonMain/kotlin/.../commons/chess/
│ ├── ChessBoard.kt ✅ Static board
│ ├── InteractiveChessBoard.kt ✅ Click-to-move
│ ├── ChessGameViewer.kt ✅ PGN playback
│ ├── MoveNavigator.kt ✅ Move controls
│ ├── PGNMetadata.kt ✅ Game info
│ └── LiveChessGame.kt ✅ Dialog + screen
├── amethyst/ # Android app
│ └── src/main/java/.../amethyst/
│ ├── ui/note/types/
│ │ └── Chess.kt ✅ Event renderers (3 types)
│ ├── ui/note/
│ │ └── NoteCompose.kt ✅ Event dispatching
│ ├── ui/screen/
│ │ ├── TopNavFilterState.kt ✅ Chess filter (3 kinds)
│ │ └── loggedIn/chess/
│ │ ├── ChessViewModel.kt ✅ State & event publishing
│ │ ├── ChessViewModelFactory.kt ✅ ViewModel factory
│ │ ├── ChessGameScreen.kt ✅ Game screen wrapper
│ │ └── dal/ChessFeedFilter.kt ✅ Feed filter
│ └── ui/navigation/routes/
│ └── Route.ChessGame ✅ Navigation route
└── docs/
└── live-chess-implementation-status.md ✅ This file
```
## 🚀 Next Steps
**To complete the chess feature**, implement:
1. ~~**ChessViewModel**~~ ✅ - Game state management & event publishing
2. ~~**Navigation**~~ ✅ - Route to LiveChessGameScreen
3. ~~**Event Subscriptions**~~ ✅ - Listen for opponent moves
4. **FAB** - Add "New Game" button to chess feed
5. **Badge Display** - Show badge count in navigation
6. **Test** - Play a complete game between two test accounts
---
**Status**: Core chess functionality fully implemented. ViewModel and relay subscriptions complete. Ready for FAB/badge polish and end-to-end testing.