feat: Introduce Participant trait and update GameEngine to support bot participants

This commit is contained in:
2026-04-13 22:11:54 +02:00
parent c88159ecec
commit d6758ed8ec
25 changed files with 2526369 additions and 1672 deletions
+29 -8
View File
@@ -2,7 +2,7 @@
> **Stack:** raw-http | none | unknown | scala
> 0 routes | 0 models | 0 components | 57 lib files | 1 env vars | 1 middleware
> 0 routes | 0 models | 0 components | 62 lib files | 1 env vars | 1 middleware
> **Token savings:** this file is ~0 tokens. Without it, AI exploration would cost ~0 tokens. **Saves ~0 tokens per conversation.**
---
@@ -61,14 +61,22 @@
- function error
- function totalPages
- `modules/bot/python/nnue.py`
- function get_data_dir: ()
- function get_tactical_data_dir: ()
- function get_weights_dir: ()
- function get_data_dir: ()
- function list_checkpoints: ()
- function migrate_legacy_data: ()
- function show_header: ()
- function show_checkpoints_table: ()
- _...6 more_
- `modules/bot/python/src/export.py` — function export_weights_to_binary: (weights_file, output_file)
- _...10 more_
- `modules/bot/python/src/dataset.py`
- function get_datasets_dir: () -> Path
- function next_dataset_version: () -> int
- function list_datasets: () -> List[Tuple[int, Dict]]
- function load_dataset_metadata: (version) -> Optional[Dict]
- function save_dataset_metadata: (version, metadata) -> None
- function create_dataset: (version, labeled_jsonl_path, sources, stockfish_depth) -> Path
- _...4 more_
- `modules/bot/python/src/export.py` — function export_to_nbai: (weights_file, output_file, trained_by, train_loss)
- `modules/bot/python/src/generate.py` — function play_random_game_and_collect_positions: (output_file, total_positions, samples_per_game, min_move, max_move, num_workers)
- `modules/bot/python/src/label.py` — function normalize_evaluation: (cp_value, method, scale), function label_positions_with_stockfish: (positions_file, output_file, stockfish_path, batch_size, depth, verbose, normalize, num_workers)
- `modules/bot/python/src/tactical_positions_extractor.py`
@@ -76,6 +84,7 @@
- function extract_puzzle_positions: (puzzle_csv, max_puzzles) -> Set[str]
- function load_positions_from_file: (file_path) -> Set[str]
- function merge_positions: (tactical, other, output_file)
- function extract_tactical_only: (puzzle_csv, output_file, max_puzzles) -> int
- function interactive_merge_positions: (puzzle_csv, output_file, max_puzzles)
- `modules/bot/python/src/train.py`
- function fen_to_features: (fen)
@@ -112,9 +121,21 @@
- function initAccumulator
- function pushAccumulator
- function copyAccumulator
- function evaluateAtPly
- function evaluate
- _...1 more_
- function recomputeAccumulator
- function validateAccumulator
- _...4 more_
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiLoader.scala`
- class NbaiLoader
- function load
- function loadDefault
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala` — class NbaiMigrator, function migrateFromBin
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala`
- function toJson
- class NbaiMetadata
- function fromJson
- function str
- function num
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiWriter.scala` — class NbaiWriter, function write
- `modules/bot/src/main/scala/de/nowchess/bot/logic/AlphaBetaSearch.scala`
- function bestMove
- function bestMoveWithTime
+28 -7
View File
@@ -52,14 +52,22 @@
- function error
- function totalPages
- `modules/bot/python/nnue.py`
- function get_data_dir: ()
- function get_tactical_data_dir: ()
- function get_weights_dir: ()
- function get_data_dir: ()
- function list_checkpoints: ()
- function migrate_legacy_data: ()
- function show_header: ()
- function show_checkpoints_table: ()
- _...6 more_
- `modules/bot/python/src/export.py` — function export_weights_to_binary: (weights_file, output_file)
- _...10 more_
- `modules/bot/python/src/dataset.py`
- function get_datasets_dir: () -> Path
- function next_dataset_version: () -> int
- function list_datasets: () -> List[Tuple[int, Dict]]
- function load_dataset_metadata: (version) -> Optional[Dict]
- function save_dataset_metadata: (version, metadata) -> None
- function create_dataset: (version, labeled_jsonl_path, sources, stockfish_depth) -> Path
- _...4 more_
- `modules/bot/python/src/export.py` — function export_to_nbai: (weights_file, output_file, trained_by, train_loss)
- `modules/bot/python/src/generate.py` — function play_random_game_and_collect_positions: (output_file, total_positions, samples_per_game, min_move, max_move, num_workers)
- `modules/bot/python/src/label.py` — function normalize_evaluation: (cp_value, method, scale), function label_positions_with_stockfish: (positions_file, output_file, stockfish_path, batch_size, depth, verbose, normalize, num_workers)
- `modules/bot/python/src/tactical_positions_extractor.py`
@@ -67,6 +75,7 @@
- function extract_puzzle_positions: (puzzle_csv, max_puzzles) -> Set[str]
- function load_positions_from_file: (file_path) -> Set[str]
- function merge_positions: (tactical, other, output_file)
- function extract_tactical_only: (puzzle_csv, output_file, max_puzzles) -> int
- function interactive_merge_positions: (puzzle_csv, output_file, max_puzzles)
- `modules/bot/python/src/train.py`
- function fen_to_features: (fen)
@@ -103,9 +112,21 @@
- function initAccumulator
- function pushAccumulator
- function copyAccumulator
- function evaluateAtPly
- function evaluate
- _...1 more_
- function recomputeAccumulator
- function validateAccumulator
- _...4 more_
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiLoader.scala`
- class NbaiLoader
- function load
- function loadDefault
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala` — class NbaiMigrator, function migrateFromBin
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala`
- function toJson
- class NbaiMetadata
- function fromJson
- function str
- function num
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiWriter.scala` — class NbaiWriter, function write
- `modules/bot/src/main/scala/de/nowchess/bot/logic/AlphaBetaSearch.scala`
- function bestMove
- function bestMoveWithTime
+335 -221
View File
@@ -1,11 +1,11 @@
# Graph Report - . (2026-04-13)
## Corpus Check
- 126 files · ~38,514,178 words
- 132 files · ~24,046,508 words
- Verdict: corpus is large enough that graph structure adds value.
## Summary
- 821 nodes · 1008 edges · 128 communities detected
- 899 nodes · 1116 edges · 146 communities detected
- Extraction: 100% EXTRACTED · 0% INFERRED · 0% AMBIGUOUS
- Token cost: 0 input · 0 output
@@ -138,11 +138,29 @@
- [[_COMMUNITY_Community 125|Community 125]]
- [[_COMMUNITY_Community 126|Community 126]]
- [[_COMMUNITY_Community 127|Community 127]]
- [[_COMMUNITY_Community 128|Community 128]]
- [[_COMMUNITY_Community 129|Community 129]]
- [[_COMMUNITY_Community 130|Community 130]]
- [[_COMMUNITY_Community 131|Community 131]]
- [[_COMMUNITY_Community 132|Community 132]]
- [[_COMMUNITY_Community 133|Community 133]]
- [[_COMMUNITY_Community 134|Community 134]]
- [[_COMMUNITY_Community 135|Community 135]]
- [[_COMMUNITY_Community 136|Community 136]]
- [[_COMMUNITY_Community 137|Community 137]]
- [[_COMMUNITY_Community 138|Community 138]]
- [[_COMMUNITY_Community 139|Community 139]]
- [[_COMMUNITY_Community 140|Community 140]]
- [[_COMMUNITY_Community 141|Community 141]]
- [[_COMMUNITY_Community 142|Community 142]]
- [[_COMMUNITY_Community 143|Community 143]]
- [[_COMMUNITY_Community 144|Community 144]]
- [[_COMMUNITY_Community 145|Community 145]]
## God Nodes (most connected - your core abstractions)
1. `GameEngine` - 35 edges
2. `DefaultRules` - 35 edges
3. `NNUE` - 22 edges
1. `DefaultRules` - 35 edges
2. `GameEngine` - 34 edges
3. `NNUE` - 23 edges
4. `EvaluationClassic` - 21 edges
5. `MoveOrdering` - 21 edges
6. `ChessBoardView` - 19 edges
@@ -157,31 +175,31 @@
## Communities
### Community 0 - "Community 0"
Cohesion: 0.09
Nodes (2): GameEngine, PendingPromotion
### Community 1 - "Community 1"
Cohesion: 0.11
Nodes (2): CastlingMove, DefaultRules
### Community 1 - "Community 1"
Cohesion: 0.1
Nodes (2): GameEngine, PendingPromotion
### Community 2 - "Community 2"
Cohesion: 0.09
Nodes (17): ClassGap, _compact_ranges(), _find_scoverage_xml(), format_agent(), format_json(), format_markdown(), format_module_gaps(), main() (+9 more)
### Community 3 - "Community 3"
Cohesion: 0.13
Nodes (30): burst_train_interactive(), create_dataset_interactive(), datasets_menu(), delete_dataset_interactive(), export_interactive(), extend_dataset_interactive(), get_data_dir(), get_weights_dir() (+22 more)
### Community 4 - "Community 4"
Cohesion: 0.14
Nodes (2): MoveOrdering, OrderingContext
### Community 4 - "Community 4"
### Community 5 - "Community 5"
Cohesion: 0.11
Nodes (21): Dataset, burst_train(), fen_to_features(), find_next_version(), NNUE, NNUEDataset, Find the next version number for model versioning. Looks for nnue_weights_v, Save training metadata alongside the weights file. Args: weights_fi (+13 more)
### Community 5 - "Community 5"
Cohesion: 0.16
Nodes (23): burst_train_interactive(), export_interactive(), extract_tactical_interactive(), get_data_dir(), get_tactical_data_dir(), get_weights_dir(), list_checkpoints(), main() (+15 more)
### Community 6 - "Community 6"
Cohesion: 0.22
Cohesion: 0.23
Nodes (1): NNUE
### Community 7 - "Community 7"
@@ -189,432 +207,432 @@ Cohesion: 0.19
Nodes (1): EvaluationClassic
### Community 8 - "Community 8"
Cohesion: 0.15
Nodes (20): create_dataset(), delete_dataset(), extend_dataset(), get_dataset_labeled_path(), get_datasets_dir(), list_datasets(), load_dataset_metadata(), next_dataset_version() (+12 more)
### Community 9 - "Community 9"
Cohesion: 0.14
Nodes (9): format_module(), load_module(), main(), ModuleResult, parse_suite_xml(), run(), SuiteResult, TestCase (+1 more)
### Community 9 - "Community 9"
### Community 10 - "Community 10"
Cohesion: 0.18
Nodes (1): ChessBoardView
### Community 10 - "Community 10"
### Community 11 - "Community 11"
Cohesion: 0.14
Nodes (1): FenParserFastParse
### Community 11 - "Community 11"
### Community 12 - "Community 12"
Cohesion: 0.12
Nodes (7): InvalidFormat, InvalidMove, MoveCommand, MoveResult, QuitCommand, ResetCommand, Successful
### Community 12 - "Community 12"
### Community 13 - "Community 13"
Cohesion: 0.12
Nodes (12): BoardResetEvent, CheckDetectedEvent, CheckmateEvent, DrawClaimedEvent, FiftyMoveRuleAvailableEvent, InvalidMoveEvent, MoveExecutedEvent, MoveRedoneEvent (+4 more)
### Community 13 - "Community 13"
### Community 14 - "Community 14"
Cohesion: 0.13
Nodes (1): FenParserCombinators
### Community 14 - "Community 14"
### Community 15 - "Community 15"
Cohesion: 0.26
Nodes (2): PgnGame, PgnParser
### Community 15 - "Community 15"
### Community 16 - "Community 16"
Cohesion: 0.15
Nodes (3): candidateMoves(), GameEngineIntegrationTest, legalMoves()
### Community 16 - "Community 16"
### Community 17 - "Community 17"
Cohesion: 0.14
Nodes (3): CommandInvokerBranchTest, ConditionalFailCommand, FailingCommand
### Community 17 - "Community 17"
### Community 18 - "Community 18"
Cohesion: 0.14
Nodes (1): GameEnginePromotionTest
### Community 18 - "Community 18"
### Community 19 - "Community 19"
Cohesion: 0.25
Nodes (1): JsonExporter
### Community 19 - "Community 19"
### Community 20 - "Community 20"
Cohesion: 0.21
Nodes (12): download_and_extract_puzzle_db(), extract_puzzle_positions(), extract_tactical_only(), interactive_merge_positions(), load_positions_from_file(), merge_positions(), Load positions from a text file (one FEN per line)., Merge two position sets and write to file. (+4 more)
### Community 21 - "Community 21"
Cohesion: 0.24
Nodes (1): AlphaBetaSearch
### Community 20 - "Community 20"
### Community 22 - "Community 22"
Cohesion: 0.15
Nodes (2): EngineTestHelpers, MockObserver
### Community 21 - "Community 21"
### Community 23 - "Community 23"
Cohesion: 0.33
Nodes (1): ZobristHash
### Community 22 - "Community 22"
Cohesion: 0.24
Nodes (10): download_and_extract_puzzle_db(), extract_puzzle_positions(), interactive_merge_positions(), load_positions_from_file(), merge_positions(), Load positions from a text file (one FEN per line)., Merge two position sets and write to file., Interactive workflow: extract tactical positions and merge with user selection. (+2 more)
### Community 23 - "Community 23"
### Community 24 - "Community 24"
Cohesion: 0.18
Nodes (1): AlphaBetaSearchTest
### Community 24 - "Community 24"
### Community 25 - "Community 25"
Cohesion: 0.18
Nodes (1): ClassicalBotTest
### Community 25 - "Community 25"
### Community 26 - "Community 26"
Cohesion: 0.33
Nodes (2): BookEntry, PolyglotBook
### Community 26 - "Community 26"
### Community 27 - "Community 27"
Cohesion: 0.22
Nodes (1): CommandInvoker
### Community 27 - "Community 27"
### Community 28 - "Community 28"
Cohesion: 0.36
Nodes (1): FenParser
### Community 28 - "Community 28"
### Community 29 - "Community 29"
Cohesion: 0.31
Nodes (1): JsonParser
### Community 29 - "Community 29"
### Community 30 - "Community 30"
Cohesion: 0.31
Nodes (5): applyMove(), Board, removed(), updated(), withMove()
### Community 30 - "Community 30"
### Community 31 - "Community 31"
Cohesion: 0.22
Nodes (1): GameContext
### Community 31 - "Community 31"
### Community 32 - "Community 32"
Cohesion: 0.25
Nodes (6): ApiError, ApiResponse, Failure, PagedResponse, Pagination, Success
### Community 32 - "Community 32"
### Community 33 - "Community 33"
Cohesion: 0.39
Nodes (1): NbaiLoader
### Community 34 - "Community 34"
Cohesion: 0.22
Nodes (8): JsonCapturedPieces, JsonCastlingRights, JsonGameRecord, JsonGameState, JsonMetadata, JsonMove, JsonMoveType, JsonPiece
### Community 33 - "Community 33"
### Community 35 - "Community 35"
Cohesion: 0.46
Nodes (1): NbaiWriter
### Community 36 - "Community 36"
Cohesion: 0.43
Nodes (1): FenExporter
### Community 34 - "Community 34"
### Community 37 - "Community 37"
Cohesion: 0.29
Nodes (1): CastlingRights
### Community 35 - "Community 35"
### Community 38 - "Community 38"
Cohesion: 0.33
Nodes (6): _evaluate_fen_batch(), label_positions_with_stockfish(), normalize_evaluation(), Normalize centipawn evaluation to a bounded range. Args: cp_value:, Worker function to evaluate a batch of FENs with Stockfish threading. Args:, Read positions and label them with Stockfish evaluations. Args: pos
### Community 36 - "Community 36"
### Community 39 - "Community 39"
Cohesion: 0.29
Nodes (1): EvaluationNNUE
### Community 37 - "Community 37"
### Community 40 - "Community 40"
Cohesion: 0.29
Nodes (4): LayerDescriptor, LayerWeights, NbaiMetadata, NbaiModel
### Community 41 - "Community 41"
Cohesion: 0.53
Nodes (5): export_to_nbai(), _infer_layers(), Derive layer descriptors from state_dict weight shapes. Assumes layers name, _read_sidecar(), _write_floats()
### Community 42 - "Community 42"
Cohesion: 0.53
Nodes (1): NbaiMigrator
### Community 43 - "Community 43"
Cohesion: 0.33
Nodes (2): TranspositionTable, TTEntry
### Community 38 - "Community 38"
### Community 44 - "Community 44"
Cohesion: 0.53
Nodes (1): PolyglotHash
### Community 39 - "Community 39"
### Community 45 - "Community 45"
Cohesion: 0.4
Nodes (2): ChessGUIApp, ChessGUILauncher
### Community 40 - "Community 40"
### Community 46 - "Community 46"
Cohesion: 0.5
Nodes (2): offset(), Square
### Community 41 - "Community 41"
### Community 47 - "Community 47"
Cohesion: 0.4
Nodes (2): PlayerId, PlayerInfo
### Community 42 - "Community 42"
### Community 48 - "Community 48"
Cohesion: 0.4
Nodes (4): play_random_game_and_collect_positions(), Generate games for one worker. Returns: list of FENs generated by t, Generate positions using multiprocessing with multiple workers. Args:, _worker_generate_games()
### Community 43 - "Community 43"
### Community 49 - "Community 49"
Cohesion: 0.4
Nodes (0):
### Community 44 - "Community 44"
### Community 50 - "Community 50"
Cohesion: 0.6
Nodes (1): NNUEBot
### Community 45 - "Community 45"
### Community 51 - "Community 51"
Cohesion: 0.4
Nodes (3): EmptyToken, FenParserSupport, PieceToken
### Community 46 - "Community 46"
### Community 52 - "Community 52"
Cohesion: 0.6
Nodes (1): PgnExporter
### Community 47 - "Community 47"
### Community 53 - "Community 53"
Cohesion: 0.5
Nodes (2): PieceSprites, SquareColors
### Community 48 - "Community 48"
### Community 54 - "Community 54"
Cohesion: 0.6
Nodes (1): TerminalUI
### Community 49 - "Community 49"
### Community 55 - "Community 55"
Cohesion: 0.5
Nodes (1): BotController
### Community 50 - "Community 50"
### Community 56 - "Community 56"
Cohesion: 0.67
Nodes (1): HybridBot
### Community 51 - "Community 51"
### Community 57 - "Community 57"
Cohesion: 0.67
Nodes (1): Parser
### Community 52 - "Community 52"
### Community 58 - "Community 58"
Cohesion: 0.5
Nodes (1): CommandInvokerTest
### Community 53 - "Community 53"
### Community 59 - "Community 59"
Cohesion: 0.5
Nodes (2): EndingMockObserver, GameEngineGameEndingTest
### Community 54 - "Community 54"
### Community 60 - "Community 60"
Cohesion: 0.5
Nodes (2): GameEngineLoadGameTest, MockObserver
### Community 55 - "Community 55"
### Community 61 - "Community 61"
Cohesion: 0.5
Nodes (1): FileSystemGameService
### Community 56 - "Community 56"
### Community 62 - "Community 62"
Cohesion: 0.5
Nodes (1): DefaultRulesStateTransitionsTest
### Community 57 - "Community 57"
### Community 63 - "Community 63"
Cohesion: 0.67
Nodes (1): GUIObserver
### Community 58 - "Community 58"
Cohesion: 0.67
Nodes (0):
### Community 59 - "Community 59"
Cohesion: 0.67
Nodes (2): export_weights_to_binary(), Load PyTorch weights and export as binary file.
### Community 60 - "Community 60"
Cohesion: 0.67
Nodes (1): ClassicalBot
### Community 61 - "Community 61"
Cohesion: 0.67
Nodes (1): MoveCommandTest
### Community 62 - "Community 62"
Cohesion: 0.67
Nodes (1): GameEngineNotationTest
### Community 63 - "Community 63"
Cohesion: 0.67
Nodes (1): GameEngineWithBotTest
### Community 64 - "Community 64"
Cohesion: 0.67
Nodes (1): GameFileServiceSuite
Nodes (0):
### Community 65 - "Community 65"
Cohesion: 0.67
Nodes (1): FenExporterTest
Nodes (1): ClassicalBot
### Community 66 - "Community 66"
Cohesion: 0.67
Nodes (1): PgnExporterTest
Nodes (2): BotParticipant, Human
### Community 67 - "Community 67"
Cohesion: 0.67
Nodes (1): Main
Nodes (1): MoveCommandTest
### Community 68 - "Community 68"
Cohesion: 0.67
Nodes (1): Renderer
Nodes (1): GameEngineNotationTest
### Community 69 - "Community 69"
Cohesion: 1.0
Nodes (1): Piece
Cohesion: 0.67
Nodes (1): GameEngineWithBotTest
### Community 70 - "Community 70"
Cohesion: 1.0
Nodes (0):
Cohesion: 0.67
Nodes (1): GameFileServiceSuite
### Community 71 - "Community 71"
Cohesion: 1.0
Nodes (1): Move
Cohesion: 0.67
Nodes (1): FenExporterTest
### Community 72 - "Community 72"
Cohesion: 1.0
Nodes (1): BoardTest
Cohesion: 0.67
Nodes (1): PgnExporterTest
### Community 73 - "Community 73"
Cohesion: 1.0
Nodes (1): CastlingRightsTest
Cohesion: 0.67
Nodes (1): Main
### Community 74 - "Community 74"
Cohesion: 1.0
Nodes (1): ColorTest
Cohesion: 0.67
Nodes (1): Renderer
### Community 75 - "Community 75"
Cohesion: 1.0
Nodes (1): PieceTest
Nodes (1): Piece
### Community 76 - "Community 76"
Cohesion: 1.0
Nodes (1): PieceTypeTest
Nodes (0):
### Community 77 - "Community 77"
Cohesion: 1.0
Nodes (1): SquareTest
Nodes (1): Move
### Community 78 - "Community 78"
Cohesion: 1.0
Nodes (1): GameContextTest
Nodes (1): BoardTest
### Community 79 - "Community 79"
Cohesion: 1.0
Nodes (1): MoveTest
Nodes (1): CastlingRightsTest
### Community 80 - "Community 80"
Cohesion: 1.0
Nodes (1): PlayerInfoTest
Nodes (1): ColorTest
### Community 81 - "Community 81"
Cohesion: 1.0
Nodes (1): ApiResponseTest
Nodes (1): PieceTest
### Community 82 - "Community 82"
Cohesion: 1.0
Nodes (1): Config
Nodes (1): PieceTypeTest
### Community 83 - "Community 83"
Cohesion: 1.0
Nodes (1): BotControllerTest
Nodes (1): SquareTest
### Community 84 - "Community 84"
Cohesion: 1.0
Nodes (1): BotDifficultyTest
Nodes (1): GameContextTest
### Community 85 - "Community 85"
Cohesion: 1.0
Nodes (1): EvaluationTest
Nodes (1): MoveTest
### Community 86 - "Community 86"
Cohesion: 1.0
Nodes (1): MoveOrderingTest
Nodes (1): PlayerInfoTest
### Community 87 - "Community 87"
Cohesion: 1.0
Nodes (1): PolyglotBookTest
Nodes (1): ApiResponseTest
### Community 88 - "Community 88"
Cohesion: 1.0
Nodes (1): PolyglotHashTest
Nodes (1): Config
### Community 89 - "Community 89"
Cohesion: 1.0
Nodes (1): TranspositionTableTest
Nodes (1): BotControllerTest
### Community 90 - "Community 90"
Cohesion: 1.0
Nodes (1): ZobristHashTest
Nodes (1): BotDifficultyTest
### Community 91 - "Community 91"
Cohesion: 1.0
Nodes (1): CommandTest
Nodes (1): EvaluationTest
### Community 92 - "Community 92"
Cohesion: 1.0
Nodes (1): ParserTest
Nodes (1): MoveOrderingTest
### Community 93 - "Community 93"
Cohesion: 1.0
Nodes (1): GameEngineOutcomesTest
Nodes (1): PolyglotBookTest
### Community 94 - "Community 94"
Cohesion: 1.0
Nodes (1): GameEngineScenarioTest
Nodes (1): PolyglotHashTest
### Community 95 - "Community 95"
Cohesion: 1.0
Nodes (1): GameEngineSpecialMovesTest
Nodes (1): TranspositionTableTest
### Community 96 - "Community 96"
Cohesion: 1.0
Nodes (1): FenParserCombinatorsTest
Nodes (1): ZobristHashTest
### Community 97 - "Community 97"
Cohesion: 1.0
Nodes (1): FenParserFastParseTest
Nodes (1): CommandTest
### Community 98 - "Community 98"
Cohesion: 1.0
Nodes (1): FenParserTest
Nodes (1): ParserTest
### Community 99 - "Community 99"
Cohesion: 1.0
Nodes (1): JsonExporterBranchCoverageSuite
Nodes (1): GameEngineOutcomesTest
### Community 100 - "Community 100"
Cohesion: 1.0
Nodes (1): JsonExporterSuite
Nodes (1): GameEngineScenarioTest
### Community 101 - "Community 101"
Cohesion: 1.0
Nodes (1): JsonModelExtraTestSuite
Nodes (1): GameEngineSpecialMovesTest
### Community 102 - "Community 102"
Cohesion: 1.0
Nodes (1): JsonParserEdgeCasesSuite
Nodes (1): FenParserCombinatorsTest
### Community 103 - "Community 103"
Cohesion: 1.0
Nodes (1): JsonParserErrorHandlingSuite
Nodes (1): FenParserFastParseTest
### Community 104 - "Community 104"
Cohesion: 1.0
Nodes (1): JsonParserMoveTypeSuite
Nodes (1): FenParserTest
### Community 105 - "Community 105"
Cohesion: 1.0
Nodes (1): JsonParserSuite
Nodes (1): JsonExporterBranchCoverageSuite
### Community 106 - "Community 106"
Cohesion: 1.0
Nodes (1): PgnParserTest
Nodes (1): JsonExporterSuite
### Community 107 - "Community 107"
Cohesion: 1.0
Nodes (1): PgnValidatorTest
Nodes (1): JsonModelExtraTestSuite
### Community 108 - "Community 108"
Cohesion: 1.0
Nodes (1): DefaultRulesTest
Nodes (1): JsonParserEdgeCasesSuite
### Community 109 - "Community 109"
Cohesion: 1.0
Nodes (0):
Nodes (1): JsonParserErrorHandlingSuite
### Community 110 - "Community 110"
Cohesion: 1.0
Nodes (1): RendererAndUnicodeTest
Nodes (1): JsonParserMoveTypeSuite
### Community 111 - "Community 111"
Cohesion: 1.0
Nodes (0):
Nodes (1): JsonParserSuite
### Community 112 - "Community 112"
Cohesion: 1.0
Nodes (0):
Nodes (1): PgnParserTest
### Community 113 - "Community 113"
Cohesion: 1.0
Nodes (1): Strip the package prefix from the full method path.
Nodes (1): PgnValidatorTest
### Community 114 - "Community 114"
Cohesion: 1.0
Nodes (1): Lines that are branch points and have at least one uncovered branch statement.
Nodes (1): DefaultRulesTest
### Community 115 - "Community 115"
Cohesion: 1.0
@@ -622,7 +640,7 @@ Nodes (0):
### Community 116 - "Community 116"
Cohesion: 1.0
Nodes (0):
Nodes (1): RendererAndUnicodeTest
### Community 117 - "Community 117"
Cohesion: 1.0
@@ -634,11 +652,11 @@ Nodes (0):
### Community 119 - "Community 119"
Cohesion: 1.0
Nodes (0):
Nodes (1): Strip the package prefix from the full method path.
### Community 120 - "Community 120"
Cohesion: 1.0
Nodes (0):
Nodes (1): Lines that are branch points and have at least one uncovered branch statement.
### Community 121 - "Community 121"
Cohesion: 1.0
@@ -668,142 +686,238 @@ Nodes (0):
Cohesion: 1.0
Nodes (0):
### Community 128 - "Community 128"
Cohesion: 1.0
Nodes (0):
### Community 129 - "Community 129"
Cohesion: 1.0
Nodes (0):
### Community 130 - "Community 130"
Cohesion: 1.0
Nodes (0):
### Community 131 - "Community 131"
Cohesion: 1.0
Nodes (0):
### Community 132 - "Community 132"
Cohesion: 1.0
Nodes (0):
### Community 133 - "Community 133"
Cohesion: 1.0
Nodes (0):
### Community 134 - "Community 134"
Cohesion: 1.0
Nodes (1): Get/create data directory.
### Community 135 - "Community 135"
Cohesion: 1.0
Nodes (1): Get/create data directory.
### Community 136 - "Community 136"
Cohesion: 1.0
Nodes (1): Get/create weights directory.
### Community 137 - "Community 137"
Cohesion: 1.0
Nodes (1): List available checkpoint versions.
### Community 138 - "Community 138"
Cohesion: 1.0
Nodes (1): Display application header.
### Community 139 - "Community 139"
Cohesion: 1.0
Nodes (1): Display available checkpoints in a table.
### Community 140 - "Community 140"
Cohesion: 1.0
Nodes (1): Display and handle main menu.
### Community 141 - "Community 141"
Cohesion: 1.0
Nodes (1): Interactive training menu.
### Community 142 - "Community 142"
Cohesion: 1.0
Nodes (1): Interactive burst training menu.
### Community 143 - "Community 143"
Cohesion: 1.0
Nodes (1): Interactive export menu.
### Community 144 - "Community 144"
Cohesion: 1.0
Nodes (1): Interactive tactical positions extraction and merge menu.
### Community 145 - "Community 145"
Cohesion: 1.0
Nodes (1): Load PyTorch weights and export as binary file.
## Knowledge Gaps
- **116 isolated node(s):** `Strip the package prefix from the full method path.`, `Lines that are branch points and have at least one uncovered branch statement.`, `[1,2,3,5,7,8,9] → '1-3, 5, 7-9`, `Compact agent format — optimised for low token count. Emits only actionable`, `Return the first scoverage.xml found inside *module_dir*, or None.` (+111 more)
- **147 isolated node(s):** `Strip the package prefix from the full method path.`, `Lines that are branch points and have at least one uncovered branch statement.`, `[1,2,3,5,7,8,9] → '1-3, 5, 7-9`, `Compact agent format — optimised for low token count. Emits only actionable`, `Return the first scoverage.xml found inside *module_dir*, or None.` (+142 more)
These have ≤1 connection - possible missing edges or undocumented components.
- **Thin community `Community 69`** (2 nodes): `Piece.scala`, `Piece`
- **Thin community `Community 75`** (2 nodes): `Piece.scala`, `Piece`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 70`** (2 nodes): `PieceType.scala`, `label()`
- **Thin community `Community 76`** (2 nodes): `PieceType.scala`, `label()`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 71`** (2 nodes): `Move.scala`, `Move`
- **Thin community `Community 77`** (2 nodes): `Move.scala`, `Move`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 72`** (2 nodes): `BoardTest`, `BoardTest.scala`
- **Thin community `Community 78`** (2 nodes): `BoardTest`, `BoardTest.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 73`** (2 nodes): `CastlingRightsTest`, `CastlingRightsTest.scala`
- **Thin community `Community 79`** (2 nodes): `CastlingRightsTest`, `CastlingRightsTest.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 74`** (2 nodes): `ColorTest`, `ColorTest.scala`
- **Thin community `Community 80`** (2 nodes): `ColorTest`, `ColorTest.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 75`** (2 nodes): `PieceTest.scala`, `PieceTest`
- **Thin community `Community 81`** (2 nodes): `PieceTest.scala`, `PieceTest`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 76`** (2 nodes): `PieceTypeTest.scala`, `PieceTypeTest`
- **Thin community `Community 82`** (2 nodes): `PieceTypeTest.scala`, `PieceTypeTest`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 77`** (2 nodes): `SquareTest.scala`, `SquareTest`
- **Thin community `Community 83`** (2 nodes): `SquareTest.scala`, `SquareTest`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 78`** (2 nodes): `GameContextTest`, `GameContextTest.scala`
- **Thin community `Community 84`** (2 nodes): `GameContextTest`, `GameContextTest.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 79`** (2 nodes): `MoveTest.scala`, `MoveTest`
- **Thin community `Community 85`** (2 nodes): `MoveTest.scala`, `MoveTest`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 80`** (2 nodes): `PlayerInfoTest.scala`, `PlayerInfoTest`
- **Thin community `Community 86`** (2 nodes): `PlayerInfoTest.scala`, `PlayerInfoTest`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 81`** (2 nodes): `ApiResponseTest`, `ApiResponseTest.scala`
- **Thin community `Community 87`** (2 nodes): `ApiResponseTest`, `ApiResponseTest.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 82`** (2 nodes): `Config`, `Config.scala`
- **Thin community `Community 88`** (2 nodes): `Config`, `Config.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 83`** (2 nodes): `BotControllerTest`, `BotControllerTest.scala`
- **Thin community `Community 89`** (2 nodes): `BotControllerTest`, `BotControllerTest.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 84`** (2 nodes): `BotDifficultyTest`, `BotDifficultyTest.scala`
- **Thin community `Community 90`** (2 nodes): `BotDifficultyTest`, `BotDifficultyTest.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 85`** (2 nodes): `EvaluationTest`, `EvaluationTest.scala`
- **Thin community `Community 91`** (2 nodes): `EvaluationTest`, `EvaluationTest.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 86`** (2 nodes): `MoveOrderingTest.scala`, `MoveOrderingTest`
- **Thin community `Community 92`** (2 nodes): `MoveOrderingTest.scala`, `MoveOrderingTest`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 87`** (2 nodes): `PolyglotBookTest.scala`, `PolyglotBookTest`
- **Thin community `Community 93`** (2 nodes): `PolyglotBookTest.scala`, `PolyglotBookTest`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 88`** (2 nodes): `PolyglotHashTest.scala`, `PolyglotHashTest`
- **Thin community `Community 94`** (2 nodes): `PolyglotHashTest.scala`, `PolyglotHashTest`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 89`** (2 nodes): `TranspositionTableTest.scala`, `TranspositionTableTest`
- **Thin community `Community 95`** (2 nodes): `TranspositionTableTest.scala`, `TranspositionTableTest`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 90`** (2 nodes): `ZobristHashTest.scala`, `ZobristHashTest`
- **Thin community `Community 96`** (2 nodes): `ZobristHashTest.scala`, `ZobristHashTest`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 91`** (2 nodes): `CommandTest`, `CommandTest.scala`
- **Thin community `Community 97`** (2 nodes): `CommandTest`, `CommandTest.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 92`** (2 nodes): `ParserTest.scala`, `ParserTest`
- **Thin community `Community 98`** (2 nodes): `ParserTest.scala`, `ParserTest`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 93`** (2 nodes): `GameEngineOutcomesTest`, `GameEngineOutcomesTest.scala`
- **Thin community `Community 99`** (2 nodes): `GameEngineOutcomesTest`, `GameEngineOutcomesTest.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 94`** (2 nodes): `GameEngineScenarioTest`, `GameEngineScenarioTest.scala`
- **Thin community `Community 100`** (2 nodes): `GameEngineScenarioTest`, `GameEngineScenarioTest.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 95`** (2 nodes): `GameEngineSpecialMovesTest`, `GameEngineSpecialMovesTest.scala`
- **Thin community `Community 101`** (2 nodes): `GameEngineSpecialMovesTest`, `GameEngineSpecialMovesTest.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 96`** (2 nodes): `FenParserCombinatorsTest`, `FenParserCombinatorsTest.scala`
- **Thin community `Community 102`** (2 nodes): `FenParserCombinatorsTest`, `FenParserCombinatorsTest.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 97`** (2 nodes): `FenParserFastParseTest`, `FenParserFastParseTest.scala`
- **Thin community `Community 103`** (2 nodes): `FenParserFastParseTest`, `FenParserFastParseTest.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 98`** (2 nodes): `FenParserTest`, `FenParserTest.scala`
- **Thin community `Community 104`** (2 nodes): `FenParserTest`, `FenParserTest.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 99`** (2 nodes): `JsonExporterBranchCoverageSuite`, `JsonExporterBranchCoverageSuite.scala`
- **Thin community `Community 105`** (2 nodes): `JsonExporterBranchCoverageSuite`, `JsonExporterBranchCoverageSuite.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 100`** (2 nodes): `JsonExporterSuite`, `JsonExporterSuite.scala`
- **Thin community `Community 106`** (2 nodes): `JsonExporterSuite`, `JsonExporterSuite.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 101`** (2 nodes): `JsonModelExtraTestSuite`, `JsonModelExtraTestSuite.scala`
- **Thin community `Community 107`** (2 nodes): `JsonModelExtraTestSuite`, `JsonModelExtraTestSuite.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 102`** (2 nodes): `JsonParserEdgeCasesSuite`, `JsonParserEdgeCasesSuite.scala`
- **Thin community `Community 108`** (2 nodes): `JsonParserEdgeCasesSuite`, `JsonParserEdgeCasesSuite.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 103`** (2 nodes): `JsonParserErrorHandlingSuite`, `JsonParserErrorHandlingSuite.scala`
- **Thin community `Community 109`** (2 nodes): `JsonParserErrorHandlingSuite`, `JsonParserErrorHandlingSuite.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 104`** (2 nodes): `JsonParserMoveTypeSuite`, `JsonParserMoveTypeSuite.scala`
- **Thin community `Community 110`** (2 nodes): `JsonParserMoveTypeSuite`, `JsonParserMoveTypeSuite.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 105`** (2 nodes): `JsonParserSuite`, `JsonParserSuite.scala`
- **Thin community `Community 111`** (2 nodes): `JsonParserSuite`, `JsonParserSuite.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 106`** (2 nodes): `PgnParserTest.scala`, `PgnParserTest`
- **Thin community `Community 112`** (2 nodes): `PgnParserTest.scala`, `PgnParserTest`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 107`** (2 nodes): `PgnValidatorTest.scala`, `PgnValidatorTest`
- **Thin community `Community 113`** (2 nodes): `PgnValidatorTest.scala`, `PgnValidatorTest`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 108`** (2 nodes): `DefaultRulesTest`, `DefaultRulesTest.scala`
- **Thin community `Community 114`** (2 nodes): `DefaultRulesTest`, `DefaultRulesTest.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 109`** (2 nodes): `PieceUnicode.scala`, `unicode()`
- **Thin community `Community 115`** (2 nodes): `PieceUnicode.scala`, `unicode()`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 110`** (2 nodes): `RendererAndUnicodeTest.scala`, `RendererAndUnicodeTest`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 111`** (1 nodes): `build.gradle.kts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 112`** (1 nodes): `settings.gradle.kts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 113`** (1 nodes): `Strip the package prefix from the full method path.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 114`** (1 nodes): `Lines that are branch points and have at least one uncovered branch statement.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 115`** (1 nodes): `test_counter.py`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 116`** (1 nodes): `build.gradle.kts`
- **Thin community `Community 116`** (2 nodes): `RendererAndUnicodeTest.scala`, `RendererAndUnicodeTest`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 117`** (1 nodes): `build.gradle.kts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 118`** (1 nodes): `start.ps1`
- **Thin community `Community 118`** (1 nodes): `settings.gradle.kts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 119`** (1 nodes): `Bot.scala`
- **Thin community `Community 119`** (1 nodes): `Strip the package prefix from the full method path.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 120`** (1 nodes): `BotDifficulty.scala`
- **Thin community `Community 120`** (1 nodes): `Lines that are branch points and have at least one uncovered branch statement.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 121`** (1 nodes): `build.gradle.kts`
- **Thin community `Community 121`** (1 nodes): `test_counter.py`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 122`** (1 nodes): `build.gradle.kts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 123`** (1 nodes): `GameContextExport.scala`
- **Thin community `Community 123`** (1 nodes): `build.gradle.kts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 124`** (1 nodes): `GameContextImport.scala`
- **Thin community `Community 124`** (1 nodes): `start.ps1`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 125`** (1 nodes): `build.gradle.kts`
- **Thin community `Community 125`** (1 nodes): `Bot.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 126`** (1 nodes): `RuleSet.scala`
- **Thin community `Community 126`** (1 nodes): `BotDifficulty.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 127`** (1 nodes): `build.gradle.kts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 128`** (1 nodes): `build.gradle.kts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 129`** (1 nodes): `GameContextExport.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 130`** (1 nodes): `GameContextImport.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 131`** (1 nodes): `build.gradle.kts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 132`** (1 nodes): `RuleSet.scala`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 133`** (1 nodes): `build.gradle.kts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 134`** (1 nodes): `Get/create data directory.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 135`** (1 nodes): `Get/create data directory.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 136`** (1 nodes): `Get/create weights directory.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 137`** (1 nodes): `List available checkpoint versions.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 138`** (1 nodes): `Display application header.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 139`** (1 nodes): `Display available checkpoints in a table.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 140`** (1 nodes): `Display and handle main menu.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 141`** (1 nodes): `Interactive training menu.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 142`** (1 nodes): `Interactive burst training menu.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 143`** (1 nodes): `Interactive export menu.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 144`** (1 nodes): `Interactive tactical positions extraction and merge menu.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 145`** (1 nodes): `Load PyTorch weights and export as binary file.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
- **What connects `Strip the package prefix from the full method path.`, `Lines that are branch points and have at least one uncovered branch statement.`, `[1,2,3,5,7,8,9] → '1-3, 5, 7-9` to the rest of the system?**
_116 weakly-connected nodes found - possible documentation gaps or missing edges._
_147 weakly-connected nodes found - possible documentation gaps or missing edges._
- **Should `Community 0` be split into smaller, more focused modules?**
_Cohesion score 0.09 - nodes in this community are weakly interconnected._
- **Should `Community 1` be split into smaller, more focused modules?**
_Cohesion score 0.11 - nodes in this community are weakly interconnected._
- **Should `Community 1` be split into smaller, more focused modules?**
_Cohesion score 0.1 - nodes in this community are weakly interconnected._
- **Should `Community 2` be split into smaller, more focused modules?**
_Cohesion score 0.09 - nodes in this community are weakly interconnected._
- **Should `Community 3` be split into smaller, more focused modules?**
_Cohesion score 0.14 - nodes in this community are weakly interconnected._
_Cohesion score 0.13 - nodes in this community are weakly interconnected._
- **Should `Community 4` be split into smaller, more focused modules?**
_Cohesion score 0.11 - nodes in this community are weakly interconnected._
- **Should `Community 8` be split into smaller, more focused modules?**
_Cohesion score 0.14 - nodes in this community are weakly interconnected._
_Cohesion score 0.14 - nodes in this community are weakly interconnected._
- **Should `Community 5` be split into smaller, more focused modules?**
_Cohesion score 0.11 - nodes in this community are weakly interconnected._
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "modules_core_src_test_scala_de_nowchess_chess_engine_gameenginewithbottest_scala", "label": "GameEngineWithBotTest.scala", "file_type": "code", "source_file": "modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala", "source_location": "L1"}, {"id": "gameenginewithbottest_gameenginewithbottest", "label": "GameEngineWithBotTest", "file_type": "code", "source_file": "modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala", "source_location": "L13"}, {"id": "gameenginewithbottest_ongameevent", "label": "onGameEvent()", "file_type": "code", "source_file": "modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala", "source_location": "L29"}], "edges": [{"source": "modules_core_src_test_scala_de_nowchess_chess_engine_gameenginewithbottest_scala", "target": "de", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala", "source_location": "L3", "weight": 1.0}, {"source": "modules_core_src_test_scala_de_nowchess_chess_engine_gameenginewithbottest_scala", "target": "de", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala", "source_location": "L4", "weight": 1.0}, {"source": "modules_core_src_test_scala_de_nowchess_chess_engine_gameenginewithbottest_scala", "target": "de", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala", "source_location": "L5", "weight": 1.0}, {"source": "modules_core_src_test_scala_de_nowchess_chess_engine_gameenginewithbottest_scala", "target": "de", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala", "source_location": "L6", "weight": 1.0}, {"source": "modules_core_src_test_scala_de_nowchess_chess_engine_gameenginewithbottest_scala", "target": "de", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala", "source_location": "L7", "weight": 1.0}, {"source": "modules_core_src_test_scala_de_nowchess_chess_engine_gameenginewithbottest_scala", "target": "de", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala", "source_location": "L8", "weight": 1.0}, {"source": "modules_core_src_test_scala_de_nowchess_chess_engine_gameenginewithbottest_scala", "target": "org", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala", "source_location": "L9", "weight": 1.0}, {"source": "modules_core_src_test_scala_de_nowchess_chess_engine_gameenginewithbottest_scala", "target": "org", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala", "source_location": "L10", "weight": 1.0}, {"source": "modules_core_src_test_scala_de_nowchess_chess_engine_gameenginewithbottest_scala", "target": "java", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala", "source_location": "L11", "weight": 1.0}, {"source": "modules_core_src_test_scala_de_nowchess_chess_engine_gameenginewithbottest_scala", "target": "gameenginewithbottest_gameenginewithbottest", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala", "source_location": "L13", "weight": 1.0}, {"source": "modules_core_src_test_scala_de_nowchess_chess_engine_gameenginewithbottest_scala", "target": "gameenginewithbottest_ongameevent", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala", "source_location": "L29", "weight": 1.0}, {"source": "modules_core_src_test_scala_de_nowchess_chess_engine_gameenginewithbottest_scala", "target": "gameenginewithbottest_ongameevent", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala", "source_location": "L75", "weight": 1.0}, {"source": "modules_core_src_test_scala_de_nowchess_chess_engine_gameenginewithbottest_scala", "target": "gameenginewithbottest_ongameevent", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala", "source_location": "L99", "weight": 1.0}]}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "modules_ui_src_main_scala_de_nowchess_ui_main_scala", "label": "Main.scala", "file_type": "code", "source_file": "modules/ui/src/main/scala/de/nowchess/ui/Main.scala", "source_location": "L1"}, {"id": "main_main", "label": "Main", "file_type": "code", "source_file": "modules/ui/src/main/scala/de/nowchess/ui/Main.scala", "source_location": "L11"}, {"id": "main_main_main", "label": ".main()", "file_type": "code", "source_file": "modules/ui/src/main/scala/de/nowchess/ui/Main.scala", "source_location": "L12"}], "edges": [{"source": "modules_ui_src_main_scala_de_nowchess_ui_main_scala", "target": "de", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/ui/src/main/scala/de/nowchess/ui/Main.scala", "source_location": "L3", "weight": 1.0}, {"source": "modules_ui_src_main_scala_de_nowchess_ui_main_scala", "target": "de", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/ui/src/main/scala/de/nowchess/ui/Main.scala", "source_location": "L4", "weight": 1.0}, {"source": "modules_ui_src_main_scala_de_nowchess_ui_main_scala", "target": "de", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/ui/src/main/scala/de/nowchess/ui/Main.scala", "source_location": "L5", "weight": 1.0}, {"source": "modules_ui_src_main_scala_de_nowchess_ui_main_scala", "target": "de", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/ui/src/main/scala/de/nowchess/ui/Main.scala", "source_location": "L6", "weight": 1.0}, {"source": "modules_ui_src_main_scala_de_nowchess_ui_main_scala", "target": "main_main", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/ui/src/main/scala/de/nowchess/ui/Main.scala", "source_location": "L11", "weight": 1.0}, {"source": "main_main", "target": "main_main_main", "relation": "method", "confidence": "EXTRACTED", "source_file": "modules/ui/src/main/scala/de/nowchess/ui/Main.scala", "source_location": "L12", "weight": 1.0}]}
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "modules_bot_src_main_scala_de_nowchess_bot_bots_nnue_nbaimigrator_scala", "label": "NbaiMigrator.scala", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala", "source_location": "L1"}, {"id": "nbaimigrator_nbaimigrator", "label": "NbaiMigrator", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala", "source_location": "L6"}, {"id": "nbaimigrator_nbaimigrator_migratefrombin", "label": ".migrateFromBin()", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala", "source_location": "L22"}, {"id": "nbaimigrator_nbaimigrator_checkbinheader", "label": ".checkBinHeader()", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala", "source_location": "L32"}, {"id": "nbaimigrator_nbaimigrator_readbinlayerweights", "label": ".readBinLayerWeights()", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala", "source_location": "L38"}, {"id": "nbaimigrator_nbaimigrator_readbintensor", "label": ".readBinTensor()", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala", "source_location": "L41"}], "edges": [{"source": "modules_bot_src_main_scala_de_nowchess_bot_bots_nnue_nbaimigrator_scala", "target": "java", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala", "source_location": "L3", "weight": 1.0}, {"source": "modules_bot_src_main_scala_de_nowchess_bot_bots_nnue_nbaimigrator_scala", "target": "nbaimigrator_nbaimigrator", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala", "source_location": "L6", "weight": 1.0}, {"source": "nbaimigrator_nbaimigrator", "target": "nbaimigrator_nbaimigrator_migratefrombin", "relation": "method", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala", "source_location": "L22", "weight": 1.0}, {"source": "nbaimigrator_nbaimigrator", "target": "nbaimigrator_nbaimigrator_checkbinheader", "relation": "method", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala", "source_location": "L32", "weight": 1.0}, {"source": "nbaimigrator_nbaimigrator", "target": "nbaimigrator_nbaimigrator_readbinlayerweights", "relation": "method", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala", "source_location": "L38", "weight": 1.0}, {"source": "nbaimigrator_nbaimigrator", "target": "nbaimigrator_nbaimigrator_readbintensor", "relation": "method", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala", "source_location": "L41", "weight": 1.0}, {"source": "nbaimigrator_nbaimigrator_migratefrombin", "target": "nbaimigrator_nbaimigrator_checkbinheader", "relation": "calls", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala", "source_location": "L27", "weight": 1.0}, {"source": "nbaimigrator_nbaimigrator_migratefrombin", "target": "nbaimigrator_nbaimigrator_readbinlayerweights", "relation": "calls", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala", "source_location": "L28", "weight": 1.0}, {"source": "nbaimigrator_nbaimigrator_readbinlayerweights", "target": "nbaimigrator_nbaimigrator_readbintensor", "relation": "calls", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala", "source_location": "L39", "weight": 1.0}]}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "modules_bot_src_main_scala_de_nowchess_bot_bots_nnue_nbaimodel_scala", "label": "NbaiModel.scala", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala", "source_location": "L1"}, {"id": "nbaimodel_layerdescriptor", "label": "LayerDescriptor", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala", "source_location": "L4"}, {"id": "nbaimodel_nbaimetadata", "label": "NbaiMetadata", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala", "source_location": "L7"}, {"id": "nbaimodel_nbaimetadata_tojson", "label": ".toJson()", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala", "source_location": "L14"}, {"id": "nbaimodel_nbaimetadata_fromjson", "label": ".fromJson()", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala", "source_location": "L24"}, {"id": "nbaimodel_layerweights", "label": "LayerWeights", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala", "source_location": "L30"}, {"id": "nbaimodel_nbaimodel", "label": "NbaiModel", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala", "source_location": "L33"}], "edges": [{"source": "modules_bot_src_main_scala_de_nowchess_bot_bots_nnue_nbaimodel_scala", "target": "nbaimodel_layerdescriptor", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala", "source_location": "L4", "weight": 1.0}, {"source": "modules_bot_src_main_scala_de_nowchess_bot_bots_nnue_nbaimodel_scala", "target": "nbaimodel_nbaimetadata", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala", "source_location": "L7", "weight": 1.0}, {"source": "nbaimodel_nbaimetadata", "target": "nbaimodel_nbaimetadata_tojson", "relation": "method", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala", "source_location": "L14", "weight": 1.0}, {"source": "modules_bot_src_main_scala_de_nowchess_bot_bots_nnue_nbaimodel_scala", "target": "nbaimodel_nbaimetadata", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala", "source_location": "L23", "weight": 1.0}, {"source": "nbaimodel_nbaimetadata", "target": "nbaimodel_nbaimetadata_fromjson", "relation": "method", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala", "source_location": "L24", "weight": 1.0}, {"source": "modules_bot_src_main_scala_de_nowchess_bot_bots_nnue_nbaimodel_scala", "target": "nbaimodel_layerweights", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala", "source_location": "L30", "weight": 1.0}, {"source": "modules_bot_src_main_scala_de_nowchess_bot_bots_nnue_nbaimodel_scala", "target": "nbaimodel_nbaimodel", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala", "source_location": "L33", "weight": 1.0}, {"source": "nbaimodel_nbaimetadata_fromjson", "target": "nbaimodel_nbaimetadata", "relation": "calls", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala", "source_location": "L27", "weight": 1.0}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "modules_bot_src_main_scala_de_nowchess_bot_bots_nnue_evaluationnnue_scala", "label": "EvaluationNNUE.scala", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala", "source_location": "L1"}, {"id": "evaluationnnue_evaluationnnue", "label": "EvaluationNNUE", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala", "source_location": "L7"}, {"id": "evaluationnnue_evaluationnnue_evaluate", "label": ".evaluate()", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala", "source_location": "L15"}, {"id": "evaluationnnue_evaluationnnue_initaccumulator", "label": ".initAccumulator()", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala", "source_location": "L19"}, {"id": "evaluationnnue_evaluationnnue_copyaccumulator", "label": ".copyAccumulator()", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala", "source_location": "L22"}, {"id": "evaluationnnue_evaluationnnue_pushaccumulator", "label": ".pushAccumulator()", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala", "source_location": "L25"}, {"id": "evaluationnnue_evaluationnnue_evaluateaccumulator", "label": ".evaluateAccumulator()", "file_type": "code", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala", "source_location": "L32"}], "edges": [{"source": "modules_bot_src_main_scala_de_nowchess_bot_bots_nnue_evaluationnnue_scala", "target": "de", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala", "source_location": "L3", "weight": 1.0}, {"source": "modules_bot_src_main_scala_de_nowchess_bot_bots_nnue_evaluationnnue_scala", "target": "de", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala", "source_location": "L4", "weight": 1.0}, {"source": "modules_bot_src_main_scala_de_nowchess_bot_bots_nnue_evaluationnnue_scala", "target": "de", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala", "source_location": "L5", "weight": 1.0}, {"source": "modules_bot_src_main_scala_de_nowchess_bot_bots_nnue_evaluationnnue_scala", "target": "evaluationnnue_evaluationnnue", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala", "source_location": "L7", "weight": 1.0}, {"source": "evaluationnnue_evaluationnnue", "target": "evaluationnnue_evaluationnnue_evaluate", "relation": "method", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala", "source_location": "L15", "weight": 1.0}, {"source": "evaluationnnue_evaluationnnue", "target": "evaluationnnue_evaluationnnue_initaccumulator", "relation": "method", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala", "source_location": "L19", "weight": 1.0}, {"source": "evaluationnnue_evaluationnnue", "target": "evaluationnnue_evaluationnnue_copyaccumulator", "relation": "method", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala", "source_location": "L22", "weight": 1.0}, {"source": "evaluationnnue_evaluationnnue", "target": "evaluationnnue_evaluationnnue_pushaccumulator", "relation": "method", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala", "source_location": "L25", "weight": 1.0}, {"source": "evaluationnnue_evaluationnnue", "target": "evaluationnnue_evaluationnnue_evaluateaccumulator", "relation": "method", "confidence": "EXTRACTED", "source_file": "modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala", "source_location": "L32", "weight": 1.0}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "modules_bot_python_src_export_py", "label": "export.py", "file_type": "code", "source_file": "modules/bot/python/src/export.py", "source_location": "L1"}, {"id": "export_read_sidecar", "label": "_read_sidecar()", "file_type": "code", "source_file": "modules/bot/python/src/export.py", "source_location": "L16"}, {"id": "export_infer_layers", "label": "_infer_layers()", "file_type": "code", "source_file": "modules/bot/python/src/export.py", "source_location": "L24"}, {"id": "export_write_floats", "label": "_write_floats()", "file_type": "code", "source_file": "modules/bot/python/src/export.py", "source_location": "L42"}, {"id": "export_export_to_nbai", "label": "export_to_nbai()", "file_type": "code", "source_file": "modules/bot/python/src/export.py", "source_location": "L48"}, {"id": "export_rationale_25", "label": "Derive layer descriptors from state_dict weight shapes. Assumes layers name", "file_type": "rationale", "source_file": "modules/bot/python/src/export.py", "source_location": "L25"}], "edges": [{"source": "modules_bot_python_src_export_py", "target": "json", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/bot/python/src/export.py", "source_location": "L4", "weight": 1.0}, {"source": "modules_bot_python_src_export_py", "target": "struct", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/bot/python/src/export.py", "source_location": "L5", "weight": 1.0}, {"source": "modules_bot_python_src_export_py", "target": "sys", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/bot/python/src/export.py", "source_location": "L6", "weight": 1.0}, {"source": "modules_bot_python_src_export_py", "target": "datetime", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "modules/bot/python/src/export.py", "source_location": "L7", "weight": 1.0}, {"source": "modules_bot_python_src_export_py", "target": "pathlib", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "modules/bot/python/src/export.py", "source_location": "L8", "weight": 1.0}, {"source": "modules_bot_python_src_export_py", "target": "torch", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/bot/python/src/export.py", "source_location": "L10", "weight": 1.0}, {"source": "modules_bot_python_src_export_py", "target": "export_read_sidecar", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/bot/python/src/export.py", "source_location": "L16", "weight": 1.0}, {"source": "modules_bot_python_src_export_py", "target": "export_infer_layers", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/bot/python/src/export.py", "source_location": "L24", "weight": 1.0}, {"source": "modules_bot_python_src_export_py", "target": "export_write_floats", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/bot/python/src/export.py", "source_location": "L42", "weight": 1.0}, {"source": "modules_bot_python_src_export_py", "target": "export_export_to_nbai", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/bot/python/src/export.py", "source_location": "L48", "weight": 1.0}, {"source": "export_export_to_nbai", "target": "export_read_sidecar", "relation": "calls", "confidence": "EXTRACTED", "source_file": "modules/bot/python/src/export.py", "source_location": "L65", "weight": 1.0}, {"source": "export_export_to_nbai", "target": "export_infer_layers", "relation": "calls", "confidence": "EXTRACTED", "source_file": "modules/bot/python/src/export.py", "source_location": "L78", "weight": 1.0}, {"source": "export_export_to_nbai", "target": "export_write_floats", "relation": "calls", "confidence": "EXTRACTED", "source_file": "modules/bot/python/src/export.py", "source_location": "L113", "weight": 1.0}, {"source": "export_rationale_25", "target": "export_infer_layers", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "modules/bot/python/src/export.py", "source_location": "L25", "weight": 1.0}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "modules_core_src_main_scala_de_nowchess_chess_engine_participant_scala", "label": "Participant.scala", "file_type": "code", "source_file": "modules/core/src/main/scala/de/nowchess/chess/engine/Participant.scala", "source_location": "L1"}, {"id": "participant_human", "label": "Human", "file_type": "code", "source_file": "modules/core/src/main/scala/de/nowchess/chess/engine/Participant.scala", "source_location": "L6"}, {"id": "participant_botparticipant", "label": "BotParticipant", "file_type": "code", "source_file": "modules/core/src/main/scala/de/nowchess/chess/engine/Participant.scala", "source_location": "L7"}], "edges": [{"source": "modules_core_src_main_scala_de_nowchess_chess_engine_participant_scala", "target": "de", "relation": "imports", "confidence": "EXTRACTED", "source_file": "modules/core/src/main/scala/de/nowchess/chess/engine/Participant.scala", "source_location": "L3", "weight": 1.0}, {"source": "modules_core_src_main_scala_de_nowchess_chess_engine_participant_scala", "target": "participant_human", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/core/src/main/scala/de/nowchess/chess/engine/Participant.scala", "source_location": "L6", "weight": 1.0}, {"source": "modules_core_src_main_scala_de_nowchess_chess_engine_participant_scala", "target": "participant_botparticipant", "relation": "contains", "confidence": "EXTRACTED", "source_file": "modules/core/src/main/scala/de/nowchess/chess/engine/Participant.scala", "source_location": "L7", "weight": 1.0}]}
File diff suppressed because one or more lines are too long
+3283 -1363
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,51 @@
{
"version": 1,
"created": "2026-04-13T19:58:38.629943",
"total_positions": 2522562,
"stockfish_depth": 12,
"sources": [
{
"type": "legacy_import",
"path": "data/training_data.jsonl",
"count": 2009355,
"note": "Migrated from data/training_data.jsonl"
},
{
"type": "test_extend",
"count": 4,
"actual_count": 3
},
{
"type": "test_new_positions",
"count": 3,
"actual_count": 3
},
{
"type": "test_mixed",
"count": 5,
"actual_count": 0
},
{
"type": "test_all_dups",
"count": 2,
"actual_count": 0
},
{
"type": "guaranteed_unique",
"count": 10,
"actual_count": 8
},
{
"type": "merged_sources",
"count": 600000,
"sources": [
{
"type": "tactical",
"count": 600000,
"max_puzzles": 600000
}
],
"actual_count": 599993
}
]
}
@@ -9,7 +9,6 @@ import de.nowchess.chess.command.{CommandInvoker, MoveCommand, MoveResult}
import de.nowchess.io.{GameContextExport, GameContextImport}
import de.nowchess.rules.RuleSet
import de.nowchess.rules.sets.DefaultRules
import de.nowchess.bot.Bot
import scala.concurrent.{ExecutionContext, Future}
/** Pure game engine that manages game state and notifies observers of state changes. All rule queries delegate to the
@@ -18,6 +17,7 @@ import scala.concurrent.{ExecutionContext, Future}
class GameEngine(
val initialContext: GameContext = GameContext.initial,
val ruleSet: RuleSet = DefaultRules,
val participants: Map[Color, Participant] = Map(Color.White -> Human, Color.Black -> Human),
) extends Observable:
// Ensure that initialBoard is set correctly for threefold repetition detection
private val contextWithInitialBoard = if initialContext.moves.isEmpty && initialContext.board != initialContext.initialBoard then
@@ -33,30 +33,11 @@ class GameEngine(
@SuppressWarnings(Array("DisableSyntax.var"))
private var pendingPromotion: Option[PendingPromotion] = None
/** Optional opponent bot and the color it plays. */
@SuppressWarnings(Array("DisableSyntax.var"))
private var opponentBot: Option[Bot] = None
@SuppressWarnings(Array("DisableSyntax.var"))
private var opponentColor: Option[Color] = None
private implicit val ec: ExecutionContext = ExecutionContext.global
/** True if a pawn promotion move is pending and needs a piece choice. */
def isPendingPromotion: Boolean = synchronized(pendingPromotion.isDefined)
/** Set an opponent bot to play against. The bot will play as the given color and auto-play moves after the opponent
* moves.
*/
def setOpponentBot(bot: Bot, color: Color): Unit = synchronized {
opponentBot = Some(bot)
opponentColor = Some(color)
}
/** Clear the opponent bot. */
def clearOpponentBot(): Unit = synchronized {
opponentBot = None
opponentColor = None
}
// Synchronized accessors for current state
def board: Board = synchronized(currentContext.board)
def turn: Color = synchronized(currentContext.turn)
@@ -231,6 +212,9 @@ class GameEngine(
notifyObservers(BoardResetEvent(currentContext))
}
/** Kick off play when the side to move is a bot (e.g. bot-vs-bot from initial position). */
def startGame(): Unit = synchronized(requestBotMoveIfNeeded())
// ──── Private helpers ────
private def executeMove(move: Move): Unit =
@@ -332,37 +316,34 @@ class GameEngine(
/** Request a move from the opponent bot if it's their turn. Spawns an async task to avoid blocking the engine.
*/
private def requestBotMoveIfNeeded(): Unit =
(opponentBot, opponentColor) match
case (Some(bot), Some(color)) if currentContext.turn == color =>
Future {
bot.nextMove(currentContext) match
case Some(move) => applyBotMove(move, color)
case None => handleBotNoMove()
}
case _ => () // No bot or not bot's turn
val pendingBotMove = synchronized {
participants.get(currentContext.turn) match
case Some(BotParticipant(bot)) => Some((bot, currentContext))
case _ => None
}
private def applyBotMove(move: Move, color: Color): Unit =
pendingBotMove.foreach { case (bot, contextAtRequest) =>
Future {
bot.nextMove(contextAtRequest) match
case Some(move) => applyBotMove(move)
case None => handleBotNoMove()
}
}
private def applyBotMove(move: Move): Unit =
synchronized {
if currentContext.turn == color then
val from = move.from
val to = move.to
currentContext.board.pieceAt(from) match
case Some(piece) if piece.color == color =>
val legal = ruleSet.legalMoves(currentContext)(from)
legal.find(m => m.to == to && m.moveType == move.moveType) match
case Some(legalMove) =>
val isPromotion = move.moveType match
case MoveType.Promotion(_) => true
case _ => false
if isPromotion then
move.moveType match
case MoveType.Promotion(pp) => completePromotion(pp)
case _ => ()
else executeMove(legalMove)
case None =>
notifyObservers(InvalidMoveEvent(currentContext, s"Bot move ${from}${to} is illegal"))
case _ =>
notifyObservers(InvalidMoveEvent(currentContext, "Bot move has invalid source square"))
val color = currentContext.turn
val from = move.from
val to = move.to
currentContext.board.pieceAt(from) match
case Some(piece) if piece.color == color =>
val legal = ruleSet.legalMoves(currentContext)(from)
legal.find(m => m.to == to && m.moveType == move.moveType) match
case Some(legalMove) => executeMove(legalMove)
case None =>
notifyObservers(InvalidMoveEvent(currentContext, s"Bot move ${from}${to} is illegal"))
case _ =>
notifyObservers(InvalidMoveEvent(currentContext, "Bot move has invalid source square"))
}
private def handleBotNoMove(): Unit =
@@ -0,0 +1,8 @@
package de.nowchess.chess.engine
import de.nowchess.bot.Bot
sealed trait Participant
case object Human extends Participant
final case class BotParticipant(bot: Bot) extends Participant
@@ -9,17 +9,16 @@ import de.nowchess.rules.sets.DefaultRules
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers
import java.util.concurrent.atomic.{AtomicBoolean, AtomicInteger}
import scala.concurrent.duration.*
import scala.concurrent.Await
class GameEngineWithBotTest extends AnyFunSuite with Matchers:
test("GameEngine can play against a ClassicalBot"):
val engine = GameEngine(GameContext.initial, DefaultRules)
val bot = ClassicalBot(BotDifficulty.Easy)
// Set White (human) vs Black (bot)
engine.setOpponentBot(bot, Color.Black)
val engine = GameEngine(
GameContext.initial,
DefaultRules,
Map(Color.White -> Human, Color.Black -> BotParticipant(bot)),
)
// Collect events
val moveCount = new AtomicInteger(0)
@@ -49,8 +48,6 @@ class GameEngineWithBotTest extends AnyFunSuite with Matchers:
// White should have moved, then Black (bot) should have responded
moveCount.get() should be >= 2
engine.clearOpponentBot()
test("BotController can list and retrieve bots"):
val bots = BotController.listBots
bots should contain("easy")
@@ -65,10 +62,12 @@ class GameEngineWithBotTest extends AnyFunSuite with Matchers:
BotController.getBot("unknown") should be(None)
test("GameEngine handles bot with different difficulty"):
val engine = GameEngine(GameContext.initial, DefaultRules)
val hardBot = BotController.getBot("hard").get
engine.setOpponentBot(hardBot, Color.Black)
val engine = GameEngine(
GameContext.initial,
DefaultRules,
Map(Color.White -> Human, Color.Black -> BotParticipant(hardBot)),
)
engine.turn should equal(Color.White)
val movesMade = new AtomicInteger(0)
@@ -87,13 +86,13 @@ class GameEngineWithBotTest extends AnyFunSuite with Matchers:
// At least white moved, possibly black also responded
movesMade.get() should be >= 1
engine.clearOpponentBot()
test("GameEngine plays valid bot moves"):
val engine = GameEngine(GameContext.initial, DefaultRules)
val bot = ClassicalBot(BotDifficulty.Easy)
engine.setOpponentBot(bot, Color.Black)
val engine = GameEngine(
GameContext.initial,
DefaultRules,
Map(Color.White -> Human, Color.Black -> BotParticipant(bot)),
)
val moveCount = new AtomicInteger(0)
val observer = new Observer:
@@ -113,4 +112,3 @@ class GameEngineWithBotTest extends AnyFunSuite with Matchers:
// Game should not be ended (checkmate/stalemate)
engine.context.moves.nonEmpty should be(true)
engine.clearOpponentBot()
@@ -1,10 +1,7 @@
package de.nowchess.ui
import de.nowchess.api.board.Color.{Black, White}
import de.nowchess.bot.util.PolyglotBook
import de.nowchess.bot.BotDifficulty
import de.nowchess.bot.bots.{ClassicalBot, HybridBot, NNUEBot}
import de.nowchess.chess.engine.GameEngine
import de.nowchess.ui.terminal.TerminalUI
import de.nowchess.ui.gui.ChessGUILauncher
@@ -13,12 +10,21 @@ import de.nowchess.ui.gui.ChessGUILauncher
*/
object Main:
def main(args: Array[String]): Unit =
// Create the core game engine (single source of truth)
val engine = new GameEngine()
val book = PolyglotBook("../../modules/bot/codekiddy.bin")
engine.setOpponentBot(HybridBot(BotDifficulty.Easy, book = Some(book)), White);
// Create the core game engine (single source of truth)
val engine = new de.nowchess.chess.engine.GameEngine(
participants = Map(
de.nowchess.api.board.Color.White -> de.nowchess.chess.engine.BotParticipant(
de.nowchess.bot.bots.HybridBot(BotDifficulty.Easy, book = Some(book)),
),
de.nowchess.api.board.Color.Black -> de.nowchess.chess.engine.BotParticipant(
de.nowchess.bot.bots.HybridBot(BotDifficulty.Easy, book = Some(book)),
),
),
)
engine.startGame()
// Launch ScalaFX GUI in separate thread
ChessGUILauncher.launch(engine)