Skip to content

Commit

Permalink
feat: add events that update the view after each move
Browse files Browse the repository at this point in the history
  • Loading branch information
maxim-derevyanchenko committed Feb 23, 2023
1 parent 197818e commit a4de5b4
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 38 deletions.
16 changes: 0 additions & 16 deletions chess/src/main/scala/io/github/chess/events/EndTurnEvent.scala

This file was deleted.

10 changes: 1 addition & 9 deletions chess/src/main/scala/io/github/chess/events/Event.scala
Expand Up @@ -7,12 +7,4 @@
package io.github.chess.events

/** Represents every event happened in the model. */
trait Event:

private final val EventStartAddress = "events/"

/** Specific address to override to make event address unique. */
protected val specificAddress: String

/** Unique event address to communicate through. */
final def address: String = EventStartAddress + specificAddress
trait Event
62 changes: 62 additions & 0 deletions chess/src/main/scala/io/github/chess/events/PieceMovedEvent.scala
@@ -0,0 +1,62 @@
/*
* MIT License
* Copyright (c) 2023 Cesario Jahrim Gabriele & Derevyanchenko Maxim & Felice Mirko & Kentpayeva Madina
*
* Full license description available at: https://github.com/jahrim/PPS-22-chess/blob/master/LICENSE
*/
package io.github.chess.events

import io.github.chess.events.Event
import io.github.chess.model.moves.Move
import io.github.chess.model.pieces.Piece
import io.github.chess.model.{Position, Team}

/** Represents the event in which a piece was moved on the board. */
trait PieceMovedEvent extends Event:

/**
* The team that should be playing next.
* @return the team that should be playing next
*/
def currentTurn: Team

/**
* The disposition of the board after the move was performed.
* @return Current disposition of the board
*/
def boardDisposition: Map[Position, Piece]

/**
* Last move that was performed on the board.
* @return last move that was performed on the board
*/
def lastMove: Move

/** Object helper for PieceMovedEvent. */
object PieceMovedEvent:

/**
* Creates an instance of the Piece Moved Event.
* @param currentTurn the team that should be playing next
* @param boardDisposition current disposition of the board
* @param lastMove last move that was performed on the board
* @return The event containing all the changes applied due to the move
*/
def apply(
currentTurn: Team,
boardDisposition: Map[Position, Piece],
lastMove: Move
): PieceMovedEvent =
PieceMovedEventImpl(currentTurn, boardDisposition, lastMove)

/**
* Address on which this event will be communicated.
* @return the string representing the address on which this event is published
*/
def address(): String = PieceMovedEvent.getClass.toString

private case class PieceMovedEventImpl(
override val currentTurn: Team,
override val boardDisposition: Map[Position, Piece],
override val lastMove: Move
) extends PieceMovedEvent
Expand Up @@ -6,7 +6,7 @@
*/
package io.github.chess.model

import io.github.chess.events.EndTurnEvent
import io.github.chess.events.PieceMovedEvent
import io.github.chess.model.ChessBoardBuilder.DSL.*
import io.github.chess.model.Team.{BLACK, WHITE}
import io.github.chess.model.moves.Move
Expand Down
29 changes: 24 additions & 5 deletions chess/src/main/scala/io/github/chess/model/ChessGame.scala
Expand Up @@ -8,7 +8,7 @@ package io.github.chess.model

import io.github.chess.util.option.OptionExtension.anyToOptionOfAny
import io.github.chess.ports.ChessPort
import io.github.chess.events.Event
import io.github.chess.events.{Event, PieceMovedEvent}
import io.github.chess.model.Team
import io.github.chess.model.moves.{CastlingMove, Move}
import io.github.chess.model.pieces.Piece
Expand All @@ -35,15 +35,19 @@ class ChessGame(private val vertx: Vertx) extends ChessPort:
override def applyMove(move: Move): Future[Unit] =
Future.succeededFuture(
{
state.chessBoard.movePiece(move.from, move.to)
move match
case castlingMove: CastlingMove =>
this.state.chessBoard.movePiece(castlingMove.from, castlingMove.to)
this.state.chessBoard
.movePiece(castlingMove.rookFromPosition, castlingMove.rookToPosition)
// TODO: add other move types before this clause (i.e. CaptureMove, PromotionMove...)
case m: Move =>
this.state.chessBoard.movePiece(m.from, m.to)
this.state.changeTeam()
case _ =>
state.chessBoard.pieces.get(move.from) match
case Some(piece) => state.history.save(piece, move)
case None =>

state.changeTeam()
publishPieceMovedEvent(move)
}
)

Expand All @@ -55,3 +59,18 @@ class ChessGame(private val vertx: Vertx) extends ChessPort:
private def playingTeam: Map[Position, Piece] = this.state.currentTurn match
case Team.WHITE => this.state.chessBoard.whitePieces
case Team.BLACK => this.state.chessBoard.blackPieces

private def publishPieceMovedEvent(lastMove: Move): Unit =
vertx
.eventBus()
.publish(
PieceMovedEvent.address(),
createPieceMovedEvent(lastMove)
)

private def createPieceMovedEvent(lastMove: Move): PieceMovedEvent =
PieceMovedEvent(
state.currentTurn,
state.chessBoard.pieces,
lastMove
)
Expand Up @@ -18,6 +18,7 @@ class PawnCaptureMoves extends ChessRule with RuleShorthands:
private val blackPawnCaptureRule: BlackPawnCaptureRule = PawnCaptureMoves.blackCaptureRule

override def findMoves(position: Position, status: ChessGameStatus): Set[Move] =
// TODO return the set of CaptureMoves instead of simple Moves
status.chessBoard.pieces.get(position) match
case Some(piece) =>
(piece.team match
Expand Down
Expand Up @@ -82,8 +82,6 @@ case class ChessBoardController private (
enter(NoneSelected)
case None => this.selectCell(clickedCell)
if clickedCell.position == selectedCell.position then enter(NoneSelected)
// TODO: temporary. Repaint will be called in the subscription to the state changes
repaint()

/**
* Select the specified cell, checking if any piece was selected.
Expand Down
Expand Up @@ -6,14 +6,18 @@
*/
package io.github.chess.viewcontroller.fxcomponents.controllers

import io.github.chess.events.PieceMovedEvent
import io.github.chess.viewcontroller.ChessApplication.given
import io.github.chess.viewcontroller.{ChessApplicationComponent, ChessApplicationContext}
import io.github.chess.viewcontroller.fxcomponents.controllers.ChessBoardController
import io.github.chess.viewcontroller.fxcomponents.controllers.template.FXMLController
import io.github.chess.viewcontroller.fxcomponents.pages.MainMenuPage
import io.vertx.core.eventbus.Message
import javafx.scene.control.{Button, TextField}
import javafx.scene.layout.GridPane
import scalafx.application.Platform
import scalafx.stage.Stage

import java.net.URL
import java.util.ResourceBundle

Expand All @@ -35,12 +39,25 @@ class GamePageController(override protected val stage: Stage)(using
private var timeRemainingText: TextField = _
@FXML @SuppressWarnings(Array("org.wartremover.warts.Null"))
private var lastMoveText: TextField = _
@FXML @SuppressWarnings(Array("org.wartremover.warts.Null"))
private var chessBoardController: ChessBoardController = _

override def initialize(url: URL, resourceBundle: ResourceBundle): Unit =
val chessBoardController = ChessBoardController.fromGridPane(this.chessBoardGridPane)(stage)
chessBoardController = ChessBoardController.fromGridPane(this.chessBoardGridPane)(stage)
this.surrenderButton.onMouseClicked = _ => MainMenuPage(stage)
// TODO get the game status and set the state values in the beginning
context.chessEngineProxy.subscribe[PieceMovedEvent](
PieceMovedEvent.address(),
onPieceMoved
)

private def onPieceMoved(message: Message[PieceMovedEvent]): Unit =
Platform.runLater(() =>
val event: PieceMovedEvent = message.body()
currentTurnText.setText(event.currentTurn.toString)
lastMoveText.setText(s"${event.lastMove.from} -> ${event.lastMove.to}")
chessBoardController.repaint(event.boardDisposition)
)

// TODO: get access to the proxy for the chess engine service (as a given constructor parameter?)
// TODO: subscribe to game state changes, calling the repaint of the chess board controller
// and updating the information texts to the left
// TODO: handle surrender logic
// TODO: get access to the proxy for the chess engine service (as a given constructor parameter?)
// TODO: handle surrender logic

0 comments on commit a4de5b4

Please sign in to comment.