feat: core sepration, observer added
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
plugins {
|
||||
id("scala")
|
||||
id("org.scoverage") version "8.1"
|
||||
application
|
||||
}
|
||||
|
||||
group = "de.nowchess"
|
||||
version = "1.0-SNAPSHOT"
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val versions = rootProject.extra["VERSIONS"] as Map<String, String>
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
scala {
|
||||
scalaVersion = versions["SCALA3"]!!
|
||||
}
|
||||
|
||||
scoverage {
|
||||
scoverageVersion.set(versions["SCOVERAGE"]!!)
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass.set("de.nowchess.ui.Main")
|
||||
}
|
||||
|
||||
tasks.withType<ScalaCompile> {
|
||||
scalaCompileOptions.additionalParameters = listOf("-encoding", "UTF-8")
|
||||
}
|
||||
|
||||
tasks.named<JavaExec>("run") {
|
||||
jvmArgs("-Dfile.encoding=UTF-8", "-Dstdout.encoding=UTF-8", "-Dstderr.encoding=UTF-8")
|
||||
standardInput = System.`in`
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation("org.scala-lang:scala3-compiler_3") {
|
||||
version {
|
||||
strictly(versions["SCALA3"]!!)
|
||||
}
|
||||
}
|
||||
implementation("org.scala-lang:scala3-library_3") {
|
||||
version {
|
||||
strictly(versions["SCALA3"]!!)
|
||||
}
|
||||
}
|
||||
|
||||
implementation(project(":modules:core"))
|
||||
implementation(project(":modules:api"))
|
||||
|
||||
testImplementation(platform("org.junit:junit-bom:5.13.4"))
|
||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||
testImplementation("org.scalatest:scalatest_3:${versions["SCALATEST"]!!}")
|
||||
testImplementation("co.helmethair:scalatest-junit-runner:${versions["SCALATEST_JUNIT"]!!}")
|
||||
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
useJUnitPlatform {
|
||||
includeEngines("scalatest")
|
||||
testLogging {
|
||||
events("passed", "skipped", "failed")
|
||||
}
|
||||
}
|
||||
finalizedBy(tasks.reportScoverage)
|
||||
}
|
||||
tasks.reportScoverage {
|
||||
dependsOn(tasks.test)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.nowchess.ui
|
||||
|
||||
import de.nowchess.chess.engine.GameEngine
|
||||
import de.nowchess.ui.terminal.TerminalUI
|
||||
|
||||
/** Application entry point - starts the Terminal UI for the chess game. */
|
||||
object Main:
|
||||
def main(args: Array[String]): Unit =
|
||||
// Create the core game engine (single source of truth)
|
||||
val engine = new GameEngine()
|
||||
|
||||
// Create and start the terminal UI
|
||||
val tui = new TerminalUI(engine)
|
||||
tui.start()
|
||||
|
||||
end Main
|
||||
@@ -0,0 +1,72 @@
|
||||
package de.nowchess.ui.terminal
|
||||
|
||||
import scala.io.StdIn
|
||||
import de.nowchess.chess.engine.GameEngine
|
||||
import de.nowchess.chess.observer.{Observer, GameEvent, *}
|
||||
import de.nowchess.chess.view.Renderer
|
||||
|
||||
/** Terminal UI that implements Observer pattern.
|
||||
* Subscribes to GameEngine and receives state change events.
|
||||
* Handles all I/O and user interaction in the terminal.
|
||||
*/
|
||||
class TerminalUI(engine: GameEngine) extends Observer:
|
||||
private var running = true
|
||||
|
||||
/** Called by GameEngine whenever a game event occurs. */
|
||||
override def onGameEvent(event: GameEvent): Unit =
|
||||
event match
|
||||
case e: MoveExecutedEvent =>
|
||||
println()
|
||||
print(Renderer.render(e.board))
|
||||
e.capturedPiece.foreach: cap =>
|
||||
println(s"Captured: $cap on ${e.toSquare}")
|
||||
println(s"${e.turn.label}'s turn. Enter move (or 'quit'/'q' to exit):")
|
||||
|
||||
case e: CheckDetectedEvent =>
|
||||
println(s"${e.turn.label} is in check!")
|
||||
|
||||
case e: CheckmateEvent =>
|
||||
println(s"Checkmate! ${e.winner.label} wins.")
|
||||
println()
|
||||
print(Renderer.render(e.board))
|
||||
|
||||
case e: StalemateEvent =>
|
||||
println("Stalemate! The game is a draw.")
|
||||
println()
|
||||
print(Renderer.render(e.board))
|
||||
|
||||
case e: InvalidMoveEvent =>
|
||||
println(s"Invalid move: ${e.reason}")
|
||||
|
||||
case e: BoardResetEvent =>
|
||||
println("Board has been reset to initial position.")
|
||||
println()
|
||||
print(Renderer.render(e.board))
|
||||
println(s"${e.turn.label}'s turn. Enter move (or 'quit'/'q' to exit):")
|
||||
|
||||
/** Start the terminal UI game loop. */
|
||||
def start(): Unit =
|
||||
// Register as observer
|
||||
engine.subscribe(this)
|
||||
|
||||
// Show initial board
|
||||
println()
|
||||
print(Renderer.render(engine.board))
|
||||
println(s"${engine.turn.label}'s turn. Enter move (or 'quit'/'q' to exit):")
|
||||
|
||||
// Game loop
|
||||
while running do
|
||||
val input = Option(StdIn.readLine()).getOrElse("quit").trim
|
||||
input.toLowerCase match
|
||||
case "quit" | "q" =>
|
||||
running = false
|
||||
println("Game over. Goodbye!")
|
||||
case "" =>
|
||||
println("Please enter a valid move.")
|
||||
case _ =>
|
||||
engine.processUserInput(input)
|
||||
|
||||
// Unsubscribe when done
|
||||
engine.unsubscribe(this)
|
||||
|
||||
end TerminalUI
|
||||
Reference in New Issue
Block a user