feat: Refactor bot participant handling to include player information and update package structure

This commit is contained in:
2026-04-16 21:18:44 +02:00
parent f8d2858d98
commit 8ecfbd6266
10 changed files with 31 additions and 20 deletions
@@ -1,4 +1,4 @@
package de.nowchess.bot
package de.nowchess.api.bot
import de.nowchess.api.game.GameContext
import de.nowchess.api.move.Move
@@ -0,0 +1,9 @@
package de.nowchess.api.game
import de.nowchess.api.bot.Bot
import de.nowchess.api.player.PlayerInfo
sealed trait Participant
final case class Human(playerInfo: PlayerInfo) extends Participant
final case class BotParticipant(bot: Bot) extends Participant
@@ -1,5 +1,6 @@
package de.nowchess.bot
import de.nowchess.api.bot.Bot
import de.nowchess.bot.bots.ClassicalBot
object BotController {
@@ -1,11 +1,12 @@
package de.nowchess.bot.bots
import de.nowchess.api.bot.Bot
import de.nowchess.api.game.GameContext
import de.nowchess.api.move.Move
import de.nowchess.bot.bots.classic.EvaluationClassic
import de.nowchess.bot.logic.AlphaBetaSearch
import de.nowchess.bot.util.PolyglotBook
import de.nowchess.bot.{Bot, BotDifficulty, BotMoveRepetition}
import de.nowchess.bot.{BotDifficulty, BotMoveRepetition}
import de.nowchess.rules.RuleSet
import de.nowchess.rules.sets.DefaultRules
@@ -1,12 +1,13 @@
package de.nowchess.bot.bots
import de.nowchess.api.bot.Bot
import de.nowchess.api.game.GameContext
import de.nowchess.api.move.Move
import de.nowchess.bot.bots.classic.EvaluationClassic
import de.nowchess.bot.bots.nnue.EvaluationNNUE
import de.nowchess.bot.logic.{AlphaBetaSearch, TranspositionTable}
import de.nowchess.bot.util.PolyglotBook
import de.nowchess.bot.{Bot, BotDifficulty, BotMoveRepetition, Config}
import de.nowchess.bot.{BotDifficulty, BotMoveRepetition, Config}
import de.nowchess.rules.RuleSet
import de.nowchess.rules.sets.DefaultRules
@@ -1,11 +1,12 @@
package de.nowchess.bot.bots
import de.nowchess.api.bot.Bot
import de.nowchess.api.game.GameContext
import de.nowchess.api.move.Move
import de.nowchess.bot.bots.nnue.EvaluationNNUE
import de.nowchess.bot.logic.AlphaBetaSearch
import de.nowchess.bot.util.{PolyglotBook, ZobristHash}
import de.nowchess.bot.{Bot, BotDifficulty, BotMoveRepetition}
import de.nowchess.bot.{BotDifficulty, BotMoveRepetition}
import de.nowchess.rules.RuleSet
import de.nowchess.rules.sets.DefaultRules
@@ -2,13 +2,15 @@ package de.nowchess.chess.engine
import de.nowchess.api.board.{Board, Color, Piece, PieceType, Square}
import de.nowchess.api.move.{Move, MoveType, PromotionPiece}
import de.nowchess.api.game.{DrawReason, GameContext, GameResult}
import de.nowchess.api.game.{BotParticipant, DrawReason, GameContext, GameResult, Human, Participant}
import de.nowchess.api.player.{PlayerId, PlayerInfo}
import de.nowchess.chess.controller.Parser
import de.nowchess.chess.observer.*
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 scala.concurrent.{ExecutionContext, Future}
/** Pure game engine that manages game state and notifies observers of state changes. All rule queries delegate to the
@@ -17,7 +19,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),
val participants: Map[Color, Participant] = Map(Color.White -> Human(PlayerInfo(PlayerId("p1"), "Player 1")), Color.Black -> Human(PlayerInfo(PlayerId("p2"), "Player 2"))),
) extends Observable:
// Ensure that initialBoard is set correctly for threefold repetition detection
private val contextWithInitialBoard = if initialContext.moves.isEmpty && initialContext.board != initialContext.initialBoard then
@@ -1,8 +0,0 @@
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
@@ -1,13 +1,15 @@
package de.nowchess.chess.engine
import de.nowchess.api.board.Color
import de.nowchess.api.game.GameContext
import de.nowchess.api.game.{BotParticipant, GameContext, Human}
import de.nowchess.api.player.{PlayerId, PlayerInfo}
import de.nowchess.bot.bots.ClassicalBot
import de.nowchess.bot.{BotController, BotDifficulty}
import de.nowchess.chess.observer.*
import de.nowchess.rules.sets.DefaultRules
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers
import java.util.concurrent.atomic.{AtomicBoolean, AtomicInteger}
class GameEngineWithBotTest extends AnyFunSuite with Matchers:
@@ -17,7 +19,7 @@ class GameEngineWithBotTest extends AnyFunSuite with Matchers:
val engine = GameEngine(
GameContext.initial,
DefaultRules,
Map(Color.White -> Human, Color.Black -> BotParticipant(bot)),
Map(Color.White -> Human(PlayerInfo(PlayerId("p1"), "Player 1")), Color.Black -> BotParticipant(bot)),
)
// Collect events
@@ -66,7 +68,7 @@ class GameEngineWithBotTest extends AnyFunSuite with Matchers:
val engine = GameEngine(
GameContext.initial,
DefaultRules,
Map(Color.White -> Human, Color.Black -> BotParticipant(hardBot)),
Map(Color.White -> Human(PlayerInfo(PlayerId("p1"), "Player 1")), Color.Black -> BotParticipant(hardBot)),
)
engine.turn should equal(Color.White)
@@ -91,7 +93,7 @@ class GameEngineWithBotTest extends AnyFunSuite with Matchers:
val engine = GameEngine(
GameContext.initial,
DefaultRules,
Map(Color.White -> Human, Color.Black -> BotParticipant(bot)),
Map(Color.White -> Human(PlayerInfo(PlayerId("p1"), "Player 1")), Color.Black -> BotParticipant(bot)),
)
val moveCount = new AtomicInteger(0)
@@ -1,5 +1,7 @@
package de.nowchess.ui
import de.nowchess.api.game.{BotParticipant, Human}
import de.nowchess.api.player.{PlayerId, PlayerInfo}
import de.nowchess.bot.util.PolyglotBook
import de.nowchess.bot.BotDifficulty
import de.nowchess.ui.terminal.TerminalUI
@@ -15,10 +17,10 @@ object Main:
// 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.api.board.Color.White -> BotParticipant(
de.nowchess.bot.bots.HybridBot(BotDifficulty.Easy, book = Some(book)),
),
de.nowchess.api.board.Color.Black -> de.nowchess.chess.engine.Human,
de.nowchess.api.board.Color.Black -> Human(PlayerInfo(PlayerId("p1"), "Player 1")),
),
)