From 403fdc707cf011ff184534d1d332238e89fde826 Mon Sep 17 00:00:00 2001
From: FelixL <50499590+SlaynAndKorpil@users.noreply.github.com>
Date: Sun, 3 May 2020 20:12:10 +0200
Subject: [PATCH 1/4] Refactoring of Square chaos into simpler Sqr
---
console/src/console/InputInterpreter.scala | 4 +-
framework/src/framework/BoardMap.scala | 133 ++++++----------
framework/src/framework/BoardMeta.scala | 2 +-
.../BoardStatus/GameStatus/GameStatus.scala | 4 +-
framework/src/framework/ChessBoard.scala | 84 +++++-----
framework/src/framework/ChessIO.scala | 2 +-
framework/src/framework/Column.scala | 85 ----------
.../src/framework/IOEvents/IOEvent.scala | 6 +-
framework/src/framework/Input/Input.scala | 4 +-
framework/src/framework/MoveData.scala | 10 +-
framework/src/framework/Positions.scala | 2 +-
framework/src/framework/SaveLoader.scala | 16 +-
framework/src/framework/Sqr.scala | 84 ++++++++++
framework/src/framework/Square.scala | 147 ------------------
.../src/framework/javaInterfacing/JInput.java | 4 +-
.../pathfinding/BooleanPathfinder.scala | 6 +-
.../pathfinding/KingMovementPathfinder.scala | 14 +-
.../MonoDirectionalPathfinder.scala | 4 +-
.../framework/pathfinding/Pathfinder.scala | 12 +-
.../pathfinding/TerminableOnce.scala | 22 +--
.../TripleDirectionalPathfinder.scala | 10 +-
graphics/src/graphics/Board.scala | 4 +-
graphics/src/graphics/BoardEventHandler.scala | 2 +-
graphics/src/graphics/SquareButton.scala | 2 +-
24 files changed, 236 insertions(+), 427 deletions(-)
delete mode 100644 framework/src/framework/Column.scala
create mode 100644 framework/src/framework/Sqr.scala
delete mode 100644 framework/src/framework/Square.scala
diff --git a/console/src/console/InputInterpreter.scala b/console/src/console/InputInterpreter.scala
index ed148c2..82f259f 100644
--- a/console/src/console/InputInterpreter.scala
+++ b/console/src/console/InputInterpreter.scala
@@ -267,8 +267,8 @@ class InputInterpreter extends ChessIO with CommandRegistrator {
* Parses a move command.
*/
def parseMove(move: String): CommandResult = {
- val from = Square(move.head, move(1).asDigit)
- val to = Square(move(2), move(3).asDigit)
+ val from = Sqr(move.head, move(1).asDigit)
+ val to = Sqr(move(2), move(3).asDigit)
val moveInput = MoveParams(from, to)
receiveInput(moveInput)
NoMessage
diff --git a/framework/src/framework/BoardMap.scala b/framework/src/framework/BoardMap.scala
index 8d775a3..e719fc8 100644
--- a/framework/src/framework/BoardMap.scala
+++ b/framework/src/framework/BoardMap.scala
@@ -1,6 +1,11 @@
package framework
-import scala.collection.AbstractMap
+import framework.ChessBoard.columnLetter
+
+import scala.collection.IndexedSeqLike
+import scala.collection.generic.CanBuildFrom
+import scala.collection.mutable.ArrayBuffer
+import scala.xml._
/**
* A chess board. Stores pieces in a 2 dimensional system (columns and rows).
@@ -8,77 +13,21 @@ import scala.collection.AbstractMap
* @author Felix Lehner
* @version
*/
-final case class BoardMap(key1: Char, value1: Column,
- key2: Char, value2: Column,
- key3: Char, value3: Column,
- key4: Char, value4: Column,
- key5: Char, value5: Column,
- key6: Char, value6: Column,
- key7: Char, value7: Column,
- key8: Char, value8: Column)
- extends AbstractMap[Char, Column] with Map[Char, Column] with Serializable {
+final case class BoardMap(ps: Array[Array[Piece]])
+ extends IndexedSeq[IndexedSeq[Piece]] with IndexedSeqLike[IndexedSeq[Piece], BoardMap] {
+
+ override val length = 8
override def size = 8
- override def apply(key: Char): Column =
- if (key == key1) value1
- else if (key == key2) value2
- else if (key == key3) value3
- else if (key == key4) value4
- else if (key == key5) value5
- else if (key == key6) value6
- else if (key == key7) value7
- else if (key == key8) value8
- else throw new NoSuchElementException("key not found: " + key)
-
- override def contains(key: Char): Boolean =
- (key == key1) || (key == key2) || (key == key3) || (key == key4) || (key == key5) || (key == key6) || (key == key7) || (key == key7) || (key == key8)
-
- def get(key: Char): Option[Column] =
- if (key == key1) Some(value1)
- else if (key == key2) Some(value2)
- else if (key == key3) Some(value3)
- else if (key == key4) Some(value4)
- else if (key == key5) Some(value5)
- else if (key == key6) Some(value6)
- else if (key == key7) Some(value7)
- else if (key == key8) Some(value8)
- else None
-
- def iterator = Iterator((key1, value1), (key2, value2), (key3, value3), (key4, value4), (key5, value5), (key6, value6), (key7, value7), (key8, value8))
-
- def +[V1 >: Column](kv: (Char, V1)): Map[Char, V1] = throw new UnsupportedOperationException("size of this map limited to 8")
-
- def updated(key: Char, value: Column): BoardMap =
- if (key == key1) new BoardMap(key1, value, key2, value2, key3, value3, key4, value4, key5, value5, key6, value6, key7, value7, key8, value8)
- else if (key == key2) new BoardMap(key1, value1, key2, value, key3, value3, key4, value4, key5, value5, key6, value6, key7, value7, key8, value8)
- else if (key == key3) new BoardMap(key1, value1, key2, value2, key3, value, key4, value4, key5, value5, key6, value6, key7, value7, key8, value8)
- else if (key == key4) new BoardMap(key1, value1, key2, value2, key3, value3, key4, value, key5, value5, key6, value6, key7, value7, key8, value8)
- else if (key == key5) new BoardMap(key1, value1, key2, value2, key3, value3, key4, value4, key5, value, key6, value6, key7, value7, key8, value8)
- else if (key == key6) new BoardMap(key1, value1, key2, value2, key3, value3, key4, value4, key5, value5, key6, value, key7, value7, key8, value8)
- else if (key == key7) new BoardMap(key1, value1, key2, value2, key3, value3, key4, value4, key5, value5, key6, value6, key7, value, key8, value8)
- else if (key == key8) new BoardMap(key1, value1, key2, value2, key3, value3, key4, value4, key5, value5, key6, value6, key7, value7, key8, value)
- else throw new NoSuchElementException("key not found: " + key)
-
- def -(key: Char): Map[Char, Column] = throw new UnsupportedOperationException("size of this map has to be 8")
-
- override def foreach[U](f: ((Char, Column)) => U): Unit = {
- f((key1, value1))
- f((key2, value2))
- f((key3, value3))
- f((key4, value4))
- f((key5, value5))
- f((key6, value6))
- f((key7, value7))
- f((key8, value8))
- }
+ val pieces: Array[Array[Piece]] = if (ps.length == 8 && ps.forall(_.length == 8)) ps else Array.fill(8)(Array.fill(8)(NoPiece))
/**
* @param sqr coordinates of the wanted piece
* @return the chess square at a specific position on the board, [[scala.None]] if the sqr does not exist
*/
- def getPiece(sqr: Square): Option[Piece] =
- if (sqr.isValid) Some(apply(sqr._1).pieceAt(sqr._2))
+ def getPiece(sqr: Sqr): Option[Piece] =
+ if (sqr.isValid) Some(apply(sqr._1)(sqr._2))
else None
/**
@@ -89,7 +38,7 @@ final case class BoardMap(key1: Char, value1: Column,
* @return the piece at some specified position
*/
@inline
- def apply(sqr: Square): Piece = getPiece(sqr) getOrElse NoPiece
+ def apply(sqr: Sqr): Piece = getPiece(sqr) getOrElse NoPiece
/**
* Updates the board.
@@ -98,9 +47,11 @@ final case class BoardMap(key1: Char, value1: Column,
* @param piece the piece the square shall be updated to
* @return a ChessBoard with updated squares.
*/
- def updated(square: Square, piece: Piece): BoardMap = {
- val updated = this(square._1).updated(square._2, piece)
- this.updated(square._1, updated)
+ def updated(square: Sqr, piece: Piece): BoardMap = {
+ if (square.isValid) {
+ val updated = this(square._1).updated(square._2, piece)
+ this.updated(square._1, updated)
+ } else this
}
/**
@@ -108,7 +59,7 @@ final case class BoardMap(key1: Char, value1: Column,
*
* @param sqr the square to be emptied
*/
- def emptySquare(sqr: Square): BoardMap =
+ def emptySquare(sqr: Sqr): BoardMap =
if (sqr.isValid) updated(sqr, NoPiece)
else this
@@ -121,18 +72,18 @@ final case class BoardMap(key1: Char, value1: Column,
* @param piece the moving piece
* @return the board after the move
*/
- def movePiece(from: Square, to: Square, piece: Piece): BoardMap = {
+ def movePiece(from: Sqr, to: Sqr, piece: Piece): BoardMap = {
var result = this
//testing for en passant and castling
piece match {
case Pawn(_, _) if apply(to).isEmpty && from.column != to.column =>
- result = result.emptySquare(Square(to.column, from.row))
+ result = result.emptySquare(Sqr(to.column, from.row))
case King(color, moved) if !moved && (to.column == 'c' || to.column == 'g') =>
val row = ChessBoard.ClassicalValues.piecesStartLine(color)
val col = if (to.column == 'c') 'd' else 'f'
val emptyCol = if (to.column == 'c') 'a' else 'h'
- result = result.updated(Square(col, row), Rook(color)).emptySquare(Square(emptyCol, row))
+ result = result.updated(Sqr(col, row), Rook(color)).emptySquare(Sqr(emptyCol, row))
case _ =>
}
@@ -140,6 +91,20 @@ final case class BoardMap(key1: Char, value1: Column,
result.updated(to, resPiece).emptySquare(from)
}
+ def toXml: NodeSeq = {
+ for (x <- 1 to 8; col = columnLetter(x)) yield
{squares(col).saveData} copy (label = col.toUpper toString)
+
+ // in Column:
+ /**
+ * Saves this column as xml.
+ */
+ def saveData: IndexedSeq[scala.xml.Elem] = {
+ var result: IndexedSeq[scala.xml.Elem] = IndexedSeq()
+ pieces.indices.foreach(i => if (pieces(i).nonEmpty) result = result :+ pieces(i).toXml.copy(label = "l" + (i + 1)))
+ result
+ }
+ }
+
/**
* Formats the board as a [[String]].
*
@@ -155,19 +120,17 @@ final case class BoardMap(key1: Char, value1: Column,
object BoardMap {
- def apply(from: Map[Char, Column]): BoardMap =
- if (from.size >= 8) {
- val seq = from.toSeq
- BoardMap(seq(0), seq(1), seq(2), seq(3), seq(4), seq(5), seq(6), seq(7))
- }
- else throw new UnsupportedOperationException("size of this map has to be 8")
+ def apply(pieces: Seq[Piece]*): BoardMap = fromSeq(pieces)
+
+ def fromSeq(buf: Seq[Seq[Piece]]): BoardMap = new BoardMap(buf.toArray.map(_.toArray))
- def apply(from: scala.IndexedSeq[(Char, Column)]): BoardMap =
- if (from.size >= 8) BoardMap(from(0), from(1), from(2), from(3), from(4), from(5), from(6), from(7))
- else throw new UnsupportedOperationException("size of this map has to be 8")
+ def newBuilder: scala.collection.mutable.Builder[Seq[Piece], BoardMap] = new ArrayBuffer mapResult fromSeq
- def apply(kv1: (Char, Column), kv2: (Char, Column), kv3: (Char, Column), kv4: (Char, Column), kv5: (Char, Column),
- kv6: (Char, Column), kv7: (Char, Column), kv8: (Char, Column)): BoardMap =
- new BoardMap(kv1._1, kv1._2, kv2._1, kv2._2, kv3._1, kv3._2, kv4._1, kv4._2,
- kv5._1, kv5._2, kv6._1, kv6._2, kv7._1, kv7._2, kv8._1, kv8._2)
+ implicit def canBuildFrom: CanBuildFrom[BoardMap, Seq[Piece], BoardMap] =
+ new CanBuildFrom[BoardMap, Seq[Piece], BoardMap] {
+
+ def apply(): scala.collection.mutable.Builder[Seq[Piece], BoardMap] = newBuilder
+
+ def apply(from: BoardMap): scala.collection.mutable.Builder[Seq[Piece], BoardMap] = newBuilder
+ }
}
diff --git a/framework/src/framework/BoardMeta.scala b/framework/src/framework/BoardMeta.scala
index e82fcec..8a44b81 100644
--- a/framework/src/framework/BoardMeta.scala
+++ b/framework/src/framework/BoardMeta.scala
@@ -69,7 +69,7 @@ trait BoardMeta {
if (promoPiece != NoPiece) {
gameStatus match {
- case PromoReq(sqr: Square) =>
+ case PromoReq(sqr: Sqr) =>
val updatedHistory =
PromotionMove(history.head.startPos, history.head.piece, sqr, history.head.captured, promoPiece) :: this.history.tail
val result = updated(sqr, promoPiece).clone(gameStatus = StandardReq, history = updatedHistory)
diff --git a/framework/src/framework/BoardStatus/GameStatus/GameStatus.scala b/framework/src/framework/BoardStatus/GameStatus/GameStatus.scala
index 048c5a7..c605d39 100644
--- a/framework/src/framework/BoardStatus/GameStatus/GameStatus.scala
+++ b/framework/src/framework/BoardStatus/GameStatus/GameStatus.scala
@@ -32,7 +32,7 @@ object GameStatus {
else if (state == StandardReq.toString) Right(StandardReq)
else if (contains(state, "PromoReq(", ")")) {
val sqr = state.substring(9, last)
- val result = Square(sqr)
+ val result = Sqr(sqr)
result match {
case Some(square) => Right(PromoReq(square))
case _ => failMessage
@@ -60,7 +60,7 @@ case object StandardReq extends Active {
}
/** Waiting for a promotion */
-case class PromoReq(on: Square) extends Active
+case class PromoReq(on: Sqr) extends Active
/** Waiting for an answer to a draw offer. */
case object DrawAcceptanceReq extends Active
diff --git a/framework/src/framework/ChessBoard.scala b/framework/src/framework/ChessBoard.scala
index 5a95167..baeda03 100644
--- a/framework/src/framework/ChessBoard.scala
+++ b/framework/src/framework/ChessBoard.scala
@@ -34,16 +34,16 @@ case class ChessBoard(
import ChessBoard._
/** All pieces (excluding [[framework.NoPiece NoPiece]]s) and their position */
- lazy val allPieces: Array[(Square, AnyPiece)] = {
+ lazy val allPieces: Array[(Sqr, AnyPiece)] = {
val allSquares = for {
x <- 1 to 8
col = columnLetter(x)
row <- 1 to 8
- square = Square(col, row)
+ square = Sqr(col, row)
piece: Piece = apply(square)
if piece.nonEmpty
} yield (square, piece)
- allSquares.toArray.asInstanceOf[Array[(Square, AnyPiece)]]
+ allSquares.toArray.asInstanceOf[Array[(Sqr, AnyPiece)]]
}
/**
@@ -115,12 +115,12 @@ case class ChessBoard(
/**
* Applies a function to all pieces and returns the results.
*/
- def mapPiece[T](func: (Square, AnyPiece) => T): IndexedSeq[T] =
+ def mapPiece[T](func: (Sqr, AnyPiece) => T): IndexedSeq[T] =
for {
col <- 1 to 8
column = columnLetter(col)
row <- 1 to 8
- square = Square(column, row)
+ square = Sqr(column, row)
piece = apply(square)
if piece.nonEmpty
} yield func(square, piece.asInstanceOf[AnyPiece])
@@ -133,14 +133,14 @@ case class ChessBoard(
* @return the piece at some specified position
*/
@inline
- def apply(sqr: Square): Piece = getPiece(sqr) getOrElse NoPiece
+ def apply(sqr: Sqr): Piece = getPiece(sqr) getOrElse NoPiece
/**
* @param sqr coordinates of the wanted piece
* @return the chess square at a specific position on the board, [[scala.None]] if the sqr does not exist
*/
@inline
- def getPiece(sqr: Square): Option[Piece] = squares.getPiece(sqr)
+ def getPiece(sqr: Sqr): Option[Piece] = squares.getPiece(sqr)
/**
* Filters for all pieces that match a predicate.
@@ -207,7 +207,7 @@ case class ChessBoard(
*
* @param sqr the square to be emptied
*/
- def emptySquare(sqr: Square): ChessBoard = clone(squares = squares.emptySquare(sqr))
+ def emptySquare(sqr: Sqr): ChessBoard = clone(squares = squares.emptySquare(sqr))
/**
* Moves a piece after testing for validity of the move which depends on the following aspects:
@@ -225,7 +225,7 @@ case class ChessBoard(
* @param to the end-coordinates
* @return the updated board
*/
- def move(from: Square, to: Square): Option[Output] = if (from.isValid && to.isValid) {
+ def move(from: Sqr, to: Sqr): Option[Output] = if (from.isValid && to.isValid) {
val movingPiece = apply(from)
val endPiece = apply(to)
val startColor = movingPiece.color
@@ -283,7 +283,7 @@ case class ChessBoard(
* @tparam T some return type
* @return either the result of `func` or `onFailure`
*/
- def doOnCheck[T](func: Square => T, onFailure: T, color: AnyColor = turn): IndexedSeq[T] = {
+ def doOnCheck[T](func: Sqr => T, onFailure: T, color: AnyColor = turn): IndexedSeq[T] = {
val sqrs = checkedSquares()
if (sqrs nonEmpty) sqrs map func
else IndexedSeq(onFailure)
@@ -295,11 +295,11 @@ case class ChessBoard(
* @param color kings of this color are tested
* @return a list of all positions with checked kings
*/
- def checkedSquares(color: AnyColor = turn): IndexedSeq[Square] = {
+ def checkedSquares(color: AnyColor = turn): IndexedSeq[Sqr] = {
for {
c <- 1 to 8
row <- 1 to 8
- sqr = Square(columnLetter(c), row)
+ sqr = Sqr(columnLetter(c), row)
piece = apply(sqr)
if piece === King(color) && isAttacked(sqr, withKing = true)
} yield sqr
@@ -315,7 +315,7 @@ case class ChessBoard(
* @param endPiece the captured piece or [[framework.NoPiece NoPiece]] for an empty square
* @return `true` if the move is legal, otherwise `false`
*/
- def isLegalMove(start: Square, end: Square, startPiece: Piece, endPiece: Piece): Boolean = {
+ def isLegalMove(start: Sqr, end: Sqr, startPiece: Piece, endPiece: Piece): Boolean = {
val startCIndex = start.colIndx
val endCIndex = end.colIndx
val columnDif = endCIndex - startCIndex
@@ -332,7 +332,7 @@ case class ChessBoard(
val sPos = history.head.startPos
val ePos = history.head.endPos
piece === Pawn(color.opposite) &&
- sPos == Square(end.column, ClassicalValues.pawnStartLine(color.opposite)) &&
+ sPos == Sqr(end.column, ClassicalValues.pawnStartLine(color.opposite)) &&
ePos == sPos + (0, -2 * direction) &&
lineDif == direction &&
(columnDif == 1 || columnDif == -1) &&
@@ -351,12 +351,12 @@ case class ChessBoard(
//castle
(!startPiece.moved && (end.column == 'c' || end.column == 'g') && {
val rookCol = if (end.column == 'c') 'a' else 'h'
- val rook = apply(Square(rookCol, ClassicalValues.piecesStartLine(color)))
+ val rook = apply(Sqr(rookCol, ClassicalValues.piecesStartLine(color)))
val squaresToTest: List[NumericSquare] =
- AbstractSqrCoordinate.sqr2indxSqr(Square(if (startCIndex < endCIndex) 'g' else 'c', start.row)) to start
+ AbstractSqrCoordinate.sqr2indxSqr(Sqr(if (startCIndex < endCIndex) 'g' else 'c', start.row)) to start
def isSqrAttacked(sqr: AbstractSqrCoordinate[_]): Boolean = sqr match {
- case square: Square => isAttacked(square, turn, withKing = true)
+ case square: Sqr => isAttacked(square, turn, withKing = true)
case square: NumericSquare => isAttacked(square, turn, withKing = true)
}
@@ -373,7 +373,7 @@ case class ChessBoard(
* @see [[framework.ChessBoard#isAttacked isAttacked]]
* @return `true` if the square is attacked, otherwise `false`
*/
- def isAttacked(sqr: Square, withKing: Boolean): Boolean = {
+ def isAttacked(sqr: Sqr, withKing: Boolean): Boolean = {
val attackedCol = apply(sqr).color
attackedCol match {
case col: AnyColor => isAttacked(sqr, col, withKing)
@@ -388,7 +388,7 @@ case class ChessBoard(
* @param attacked the 'defending' color
* @return `true` if the square is attacked, otherwise `false`
*/
- def isAttacked(sqr: Square, attacked: AnyColor, withKing: Boolean): Boolean =
+ def isAttacked(sqr: Sqr, attacked: AnyColor, withKing: Boolean): Boolean =
attackingPieces(sqr, attacked, withKing) > 0
/**
@@ -399,7 +399,7 @@ case class ChessBoard(
* @param withKing whether the king should be counted as possible attacker
* @return `true` if the square is attacked, otherwise `false`
*/
- def attackingPieces(sqr: Square, attacked: AnyColor, withKing: Boolean = true): Int = {
+ def attackingPieces(sqr: Sqr, attacked: AnyColor, withKing: Boolean = true): Int = {
implicit class Intersectable[P <: Piece](val content: Array[P]) {
def ^[OtherP <: Piece](other: Array[OtherP]): Int = (for (i <- content; j <- other) yield if (j === i) 1 else 0) sum
}
@@ -442,7 +442,7 @@ case class ChessBoard(
attackedByKnight + attackedByKing + attackedDiagonally + attackedOrthogonally + attackedByPawn
}
- def attackingSquares(sqr: Square, attacked: AnyColor, withKing: Boolean = true): Array[(Square, AnyPiece)] = {
+ def attackingSquares(sqr: Sqr, attacked: AnyColor, withKing: Boolean = true): Array[(Sqr, AnyPiece)] = {
val opponent = attacked.opposite
allPieces
.filter(_._2.color == opponent) // filter all pieces of the correct color
@@ -454,7 +454,7 @@ case class ChessBoard(
* Tests if there is a piece on a specific square that is pinned (it blocks an attack against the king)
* and thereby cannot be moved.
*/
- def isPinnedPiece(square: Square): Boolean = getPiece(square) match {
+ def isPinnedPiece(square: Sqr): Boolean = getPiece(square) match {
case Some(piece) =>
piece match {
case NoPiece => false
@@ -491,14 +491,14 @@ case class ChessBoard(
movesSinceLastCapture / 2 > 50 && movesSinceLastPawnMove / 2 > 50
/**
- * Tests if a certain [[framework.Square]] is blocked,
+ * Tests if a certain [[framework.Sqr]] is blocked,
* i.e. the piece on the square cannot move.
* When the square is empty, `false` is returned.
*/
- def isBlockedSquare(square: Square): Boolean = {
+ def isBlockedSquare(square: Sqr): Boolean = {
val piece = apply(square)
- def atOffset(off: (Int, Int)): Square = square + off
+ def atOffset(off: (Int, Int)): Sqr = square + off
def offsetPiece(off: (Int, Int)) = getPiece(atOffset(off))
@@ -573,9 +573,9 @@ case class ChessBoard(
.forall(isBlockedSquare)
def kingsBlocked = {
- val kings: Array[(Square, AnyPiece)] = allPieces filter (_._2.isInstanceOf[King]) reverse
+ val kings: Array[(Sqr, AnyPiece)] = allPieces filter (_._2.isInstanceOf[King]) reverse
- def kingIsBlocked(kingOnSq: (Square, AnyPiece)): Boolean = {
+ def kingIsBlocked(kingOnSq: (Sqr, AnyPiece)): Boolean = {
import framework.pathfinding.KingMovementPathfinder
import framework.pathfinding.WaypointResult._
@@ -585,7 +585,7 @@ case class ChessBoard(
val kingColor = king.color
val pathfinder = new KingMovementPathfinder {
- override def decision(pos: Square): WaypointResult.Value = getPiece(pos) match {
+ override def decision(pos: Sqr): WaypointResult.Value = getPiece(pos) match {
case Some(piece) if !isAttacked(pos, kingColor, withKing = false) && kingColor != piece.color =>
piece.color match {
case color: AnyColor if color == kingColor.opposite => Positive
@@ -698,7 +698,7 @@ case class ChessBoard(
*
* @see [[framework.ChessBoard#isEmptyDiagonal isEmptyDiagonal]]
*/
- def isEmptyOrthogonal(from: Square, to: Square): Boolean = {
+ def isEmptyOrthogonal(from: Sqr, to: Sqr): Boolean = {
val orthogonal = from._1 == to._1 || from._2 == to._2
orthogonal && isEmptyConnection(from, to)
}
@@ -709,7 +709,7 @@ case class ChessBoard(
*
* @see [[framework.ChessBoard#isEmptyOrthogonal isEmptyOrthogonal]]
*/
- def isEmptyDiagonal(from: Square, to: Square): Boolean = {
+ def isEmptyDiagonal(from: Sqr, to: Sqr): Boolean = {
val startColIndex = from.colIndx
val endColIndex = to.colIndx
val diagonal = startColIndex - endColIndex == from._2 - to._2 || startColIndex - to._2 == endColIndex - from._2
@@ -723,7 +723,7 @@ case class ChessBoard(
* @param piece the piece the square shall be updated to
* @return a ChessBoard with updated squares.
*/
- def updated(square: Square, piece: Piece): ChessBoard =
+ def updated(square: Sqr, piece: Piece): ChessBoard =
clone(squares = squares.updated(square, piece))
/**
@@ -738,7 +738,7 @@ case class ChessBoard(
* @param endColor color of the piece on the end square
* @return the board after the move
*/
- private def doMove(from: Square, to: Square, piece: Piece, startColor: Color, endColor: Color): ChessBoard = {
+ private def doMove(from: Sqr, to: Sqr, piece: Piece, startColor: Color, endColor: Color): ChessBoard = {
val updatedStatus: GameStatus = piece match {
case Pawn(color, _) if to.row == ClassicalValues.piecesStartLine(color.opposite) =>
PromoReq(to)
@@ -773,7 +773,7 @@ case class ChessBoard(
else index + 1
}
- private def kingIsMate(testedKing: (Square, AnyPiece)): Boolean = {
+ private def kingIsMate(testedKing: (Sqr, AnyPiece)): Boolean = {
lazy val kingColor = turn
val kingSq = testedKing._1
lazy val alliedPieces = allPieces.filter(piece => {
@@ -781,7 +781,7 @@ case class ChessBoard(
})
//tests if any piece can move to a specific position (-> block or capture)
- def piecesCanMoveTo(sqr: Square): Boolean = {
+ def piecesCanMoveTo(sqr: Sqr): Boolean = {
val endPiece = apply(sqr)
alliedPieces exists (sp => !isPinnedPiece(sp._1) && isLegalMove(sp._1, sqr, sp._2, endPiece))
}
@@ -809,10 +809,10 @@ case class ChessBoard(
}
@scala.annotation.tailrec
- private def isEmptyConnection(from: Square, to: Square): Boolean = {
+ private def isEmptyConnection(from: Sqr, to: Sqr): Boolean = {
val startColIndex = from.colIndx
val endColIndex = to.colIndx
- val incremented: Square = NumericSquare((endColIndex - startColIndex).signum, (to._2 - from._2).signum) + from
+ val incremented: Sqr = NumericSquare((endColIndex - startColIndex).signum, (to._2 - from._2).signum) + from
if (incremented == to) true
else if (apply(incremented).isEmpty) isEmptyConnection(incremented, to)
else false
@@ -963,12 +963,6 @@ object ChessBoard {
Left(FileOperationError.FileNotFoundError(path))
}
- /**
- * Saves a board as XML
- */
- def saveSquares(squares: Map[Char, Column]): NodeSeq =
- for (x <- 1 to 8; col = columnLetter(x)) yield {squares(col).saveData} copy (label = col.toUpper toString)
-
/**
* Converts a column index to it's corresponding character.
*/
@@ -1031,9 +1025,9 @@ object ChessBoard {
def pawnDir(color: AnyColor): Int =
if (color == White) 1 else -1
- /** @return the [[framework.Square]] where the king of this color is placed. */
- def kingStartSquare(color: AnyColor): Square =
- Square('e', piecesStartLine(color))
+ /** @return the [[framework.Sqr]] where the king of this color is placed. */
+ def kingStartSquare(color: AnyColor): Sqr =
+ Sqr('e', piecesStartLine(color))
}
}
diff --git a/framework/src/framework/ChessIO.scala b/framework/src/framework/ChessIO.scala
index df012f6..c1a4f18 100644
--- a/framework/src/framework/ChessIO.scala
+++ b/framework/src/framework/ChessIO.scala
@@ -26,7 +26,7 @@ import framework.Input._
*
* test receiveInput DrawOffer
* test receiveInput DrawReject
- * test receiveInput MoveParams(from = Square('d', 2), to = Square('d', 4))
+ * test receiveInput MoveParams(from = Sqr('d', 2), to = Sqr('d', 4))
* }}}
*
* @see [[framework.javaInterfacing.JChessIO the java variant]]
diff --git a/framework/src/framework/Column.scala b/framework/src/framework/Column.scala
deleted file mode 100644
index 046b694..0000000
--- a/framework/src/framework/Column.scala
+++ /dev/null
@@ -1,85 +0,0 @@
-package framework
-
-import scala.collection.IndexedSeqLike
-import scala.collection.generic.CanBuildFrom
-import scala.collection.mutable.ArrayBuffer
-
-/**
- * A column that contains 8 pieces.
- *
- * @see [[framework.ChessBoard]]
- * @version alpha 0.1
- * @author Felix Lehner
- */
-final class Column(ps: Array[Piece]) extends IndexedSeq[Piece] with IndexedSeqLike[Piece, Column] {
- val length = 8
-
- val pieces: Array[Piece] = if (ps.length == 8) ps else Array.fill(8)(NoPiece)
-
- def this(ps: Map[Int, Piece]) =
- this(ps.toArray.foldRight(Array.fill[Piece](8)(NoPiece)) {
- (a: (Int, Piece), b: Array[Piece]) =>
- if (a._1 <= 8 && a._1 >= 1) b.updated(a._1 - 1, a._2)
- else b
- })
-
- /** @return a [[framework.Column]] that is filled with a certain piece */
- def this(piece: Piece) =
- this(Array.fill(8)(piece))
-
- /** @return the piece at a specific position in the array */
- def pieceAt(row: Int): Piece = pieces(row - 1)
-
- def apply(idx: Int): Piece = pieces(idx)
-
- def updated(line: Int, piece: Char, color: AnyColor): Column = updated(line, piece.toUpper match {
- case 'P' => Pawn(color)
- case 'R' => Rook(color)
- case 'N' => Knight(color)
- case 'B' => Bishop(color)
- case 'K' => King(color)
- case 'Q' => Queen(color)
- case _ => NoPiece
- })
-
- /**
- * Replaces a piece at a specific position in [[pieces]].
- *
- * @note the line parameter gets subtracted by 1 so you can access the array
- * with the classical chess notation system.
- * @return an updated column
- */
- def updated(line: Int, piece: Piece): Column =
- new Column(pieces.updated(line - 1, piece))
-
- /**
- * Saves this column as xml.
- */
- def saveData: IndexedSeq[scala.xml.Elem] = {
- var result: IndexedSeq[scala.xml.Elem] = IndexedSeq()
- pieces.indices.foreach(i => if (pieces(i).nonEmpty) result = result :+ pieces(i).toXml.copy(label = "l" + (i + 1)))
- result
- }
-
- /**
- * Creates a [[String]] that can be displayed in the console
- */
- override def toString: String = pieces.mkString("| ", " | ", " |")
-
- override def newBuilder: scala.collection.mutable.Builder[Piece, Column] = Column.newBuilder
-}
-
-object Column {
-
- def apply(pieces: Piece*): Column = fromSeq(pieces)
-
- def fromSeq(buf: Seq[Piece]): Column = new Column(buf.toArray)
-
- def newBuilder: scala.collection.mutable.Builder[Piece, Column] = new ArrayBuffer mapResult fromSeq
-
- implicit def canBuildFrom: CanBuildFrom[Column, Piece, Column] = new CanBuildFrom[Column, Piece, Column] {
- def apply(): scala.collection.mutable.Builder[Piece, Column] = newBuilder
-
- def apply(from: Column): scala.collection.mutable.Builder[Piece, Column] = newBuilder
- }
-}
diff --git a/framework/src/framework/IOEvents/IOEvent.scala b/framework/src/framework/IOEvents/IOEvent.scala
index e224e33..b1e219d 100644
--- a/framework/src/framework/IOEvents/IOEvent.scala
+++ b/framework/src/framework/IOEvents/IOEvent.scala
@@ -1,7 +1,7 @@
package framework.IOEvents
import framework.BoardStatus.GameResult.GameResult
-import framework.Square
+import framework.Sqr
/**
* An event given by [[framework.ChessBoard]] as reaction to specific inputs.
@@ -15,7 +15,7 @@ case object ShowDrawOffer extends IOEvent
case object RemoveDrawOffer extends IOEvent
-final case class ShowPromotion(on: Square) extends IOEvent
+final case class ShowPromotion(on: Sqr) extends IOEvent
case object RemovePromotion extends IOEvent
@@ -25,7 +25,7 @@ case object RemoveTakeback extends IOEvent
final case class ShowEnded(result: GameResult) extends IOEvent
-final case class ShowCheck(on: Square) extends IOEvent
+final case class ShowCheck(on: Sqr) extends IOEvent
/** Placeholder event. */
case object NoEvent extends IOEvent
diff --git a/framework/src/framework/Input/Input.scala b/framework/src/framework/Input/Input.scala
index 0bc90ab..5a9b06a 100644
--- a/framework/src/framework/Input/Input.scala
+++ b/framework/src/framework/Input/Input.scala
@@ -1,6 +1,6 @@
package framework.Input
-import framework.{AnyColor, AnyPiece, Square}
+import framework.{AnyColor, AnyPiece, Sqr}
/**
* Inputs for [[framework.ChessBoard#receive framework.ChessBoard]] or [[framework.ChessIO#receiveInput framework.ChessIO]]
@@ -11,7 +11,7 @@ import framework.{AnyColor, AnyPiece, Square}
sealed abstract class Input[InputType](val value: InputType)
/** A move action. */
-final case class MoveParams(from: Square, to: Square) extends Input(from -> to)
+final case class MoveParams(from: Sqr, to: Sqr) extends Input(from -> to)
/** A promotion to a piece type. */
final case class Promotion(piece: (AnyColor, Boolean) => AnyPiece) extends Input(piece)
diff --git a/framework/src/framework/MoveData.scala b/framework/src/framework/MoveData.scala
index a74cabb..765f58d 100644
--- a/framework/src/framework/MoveData.scala
+++ b/framework/src/framework/MoveData.scala
@@ -6,21 +6,21 @@ package framework
* @author Felix Lehner
* @version alpha 0.2
*/
-sealed class MoveData(val startPos: Square, val piece: Piece, val endPos: Square, val captured: Boolean) {
+sealed class MoveData(val startPos: Sqr, val piece: Piece, val endPos: Sqr, val captured: Boolean) {
def xml: scala.xml.Elem =
}
object MoveData {
- def apply(startPos: Square, piece: Piece, endPos: Square, captured: Boolean): MoveData =
+ def apply(startPos: Sqr, piece: Piece, endPos: Sqr, captured: Boolean): MoveData =
new MoveData(startPos, piece, endPos, captured)
- def unapply(md: MoveData): Option[(Square, Piece, Square, Boolean)] = Some(md.startPos, md.piece, md.endPos, md.captured)
+ def unapply(md: MoveData): Option[(Sqr, Piece, Sqr, Boolean)] = Some(md.startPos, md.piece, md.endPos, md.captured)
}
-case class PromotionMove(override val startPos: Square,
+case class PromotionMove(override val startPos: Sqr,
override val piece: Piece,
- override val endPos: Square,
+ override val endPos: Sqr,
override val captured: Boolean,
promoPiece: Piece) extends MoveData(startPos, piece, endPos, captured) {
override def xml: scala.xml.Elem =
diff --git a/framework/src/framework/Positions.scala b/framework/src/framework/Positions.scala
index bcee766..b928b69 100644
--- a/framework/src/framework/Positions.scala
+++ b/framework/src/framework/Positions.scala
@@ -91,7 +91,7 @@ case class Position(pos: BoardMap) extends AnyVal {
col <- 1 to 8
column = ChessBoard.columnLetter(col)
row <- 1 to 8
- square = Square(column, row)
+ square = Sqr(column, row)
otherPiece = other.pos(square)
piece = this.pos(square)
} yield {
diff --git a/framework/src/framework/SaveLoader.scala b/framework/src/framework/SaveLoader.scala
index 17b18be..7b92f63 100644
--- a/framework/src/framework/SaveLoader.scala
+++ b/framework/src/framework/SaveLoader.scala
@@ -90,9 +90,9 @@ object SaveLoader {
try Right(
moves map (move =>
MoveData(
- Square(extractWithFilter(move, "start").head, extractWithFilter(move, "start").last.asDigit),
+ Sqr(extractWithFilter(move, "start").head, extractWithFilter(move, "start").last.asDigit),
Piece(extractWithFilter(move, "movedPiece").head, Color(extractWithFilter(move, "movedPiece").last), moved = true),
- Square(extractWithFilter(move, "end").head, extractWithFilter(move, "end").last.asDigit),
+ Sqr(extractWithFilter(move, "end").head, extractWithFilter(move, "end").last.asDigit),
extractWithFilter(move, "capture").toBoolean
)) toList
)
@@ -202,9 +202,9 @@ object SaveLoader {
val end = move \@ "end"
val captured = move \@ "capture"
MoveData(
- Square(start.head, start.last.asDigit),
+ Sqr(start.head, start.last.asDigit),
Piece(movedPiece.head, Color(movedPiece.last), moved = true),
- Square(end.head, end.last.asDigit),
+ Sqr(end.head, end.last.asDigit),
captured.toBoolean
)
}) toList
@@ -336,16 +336,16 @@ object SaveLoader {
if (move.attributes.exists(_.key == "promoPiece")) {
val promoPieceId = (move \@ "promoPiece").head
PromotionMove(
- Square(start.head, start.last.asDigit),
+ Sqr(start.head, start.last.asDigit),
Piece(pieceId, color, moved = true),
- Square(end.head, end.last.asDigit),
+ Sqr(end.head, end.last.asDigit),
captured.toBoolean,
Piece(promoPieceId, color, moved = false))
}
else MoveData(
- Square(start.head, start.last.asDigit),
+ Sqr(start.head, start.last.asDigit),
Piece(pieceId, color, moved = true),
- Square(end.head, end.last.asDigit),
+ Sqr(end.head, end.last.asDigit),
captured.toBoolean)
}) toList
)
diff --git a/framework/src/framework/Sqr.scala b/framework/src/framework/Sqr.scala
new file mode 100644
index 0000000..75dcb19
--- /dev/null
+++ b/framework/src/framework/Sqr.scala
@@ -0,0 +1,84 @@
+package framework
+
+import scala.language.implicitConversions
+
+/*
+* TODO
+* Reduce complexity to only one class, 'Sqr' or 'Sqr'
+* and generate interchangeability of numerical and classic
+* coordinates by method overloading.
+* This will make the whole code simpler and the planned
+* changes in BoardMap easier to implement.
+*/
+
+/**
+ * A coordinate of a square.
+ *
+ * @version alpha 0.1
+ * @author Felix Lehner
+ */
+private case class Sqr(column: Int, row: Int) {
+ @inline
+ def _1: Int = column
+
+ @inline
+ def _2: Int = row
+
+ def to(square: Sqr): List[Sqr] = {
+ val inc = (square.column - column).signum -> (square.row - row).signum
+ val incremented: Sqr = this + inc
+ this :: (if (incremented == this) Nil else incremented to square)
+ }
+
+ def until(square: Sqr): List[Sqr] = {
+ val inc = (square.column - column).signum -> (square.row - row).signum
+ val incremented = this + inc
+ this :: (if (incremented == square) Nil else incremented until square)
+ }
+
+ def +(sq: Sqr): Sqr = Sqr(column + sq.column, row + sq.row)
+
+ def -(sq: Sqr): Sqr = Sqr(column - sq.column, row - sq.row)
+
+ def -(sq: (Int, Int)): Sqr = Sqr(column - sq._1, row - sq._2)
+
+ /**
+ * All adjacent squares that are on the board.
+ */
+ def validAdjacents: IndexedSeq[Sqr] = adjacents filter (_.isValid)
+
+ /**
+ * All adjacent squares.
+ *
+ * @see [[framework.Sqr#validAdjacents]] for
+ * adjacent squares that are on the board.
+ */
+ def adjacents: IndexedSeq[Sqr] = IndexedSeq(
+ (-1, -1), (-1, 0), (-1, 1),
+ (0, -1), (0, 1),
+ (1, -1), (1, 0), (1, 1)
+ ) map (this + _)
+
+ def +(sq: (Int, Int)): Sqr = Sqr(column + sq._1, row + sq._2)
+
+ /**
+ * Checks if this square is inside of a 8x8 board.
+ */
+ def isValid: Boolean = column >= 1 && column <= 8 && row >= 1 && row <= 8
+
+ def toTuple: (Int, Int) = (column, row)
+
+ override def toString: String = s"$column$row"
+}
+
+object Sqr {
+ def apply(coordinate: String): Option[Sqr] =
+ if (coordinate.length == 2 && coordinate.head.isLetter && coordinate.last.isDigit) {
+ val col = coordinate.head
+ val row = coordinate.last.asDigit
+ Some(Sqr(col, row))
+ }
+ else None
+
+ def apply(column: Char, row: Int): Sqr = Sqr(ChessBoard.columnIndex(column), row)
+}
diff --git a/framework/src/framework/Square.scala b/framework/src/framework/Square.scala
deleted file mode 100644
index e060471..0000000
--- a/framework/src/framework/Square.scala
+++ /dev/null
@@ -1,147 +0,0 @@
-package framework
-
-import scala.language.implicitConversions
-
-import ChessBoard.{columnLetter, columnIndex}
-
-/**
- * A coordinate of a square.
- * @version alpha 0.1
- * @author Felix Lehner
- */
-sealed abstract class AbstractSqrCoordinate[ColumnType] {
- val column: ColumnType
- val row: Int
-
- type Return >: this.type <: AbstractSqrCoordinate[ColumnType]
-
- @inline
- def _1: ColumnType = column
-
- @inline
- def _2: Int = row
-
- def colIndx: Int
-
- def to(square: AbstractSqrCoordinate[ColumnType]): List[Return] = {
- val inc = (square.colIndx - colIndx).signum -> (square.row - row).signum
- val incremented: Return = this + inc
- val head: Return = this
- val tail: List[Return] =
- if (incremented == this) Nil
- else incremented.to(square).asInstanceOf[List[Return]]
- head :: tail
- }
-
- def until(square: AbstractSqrCoordinate[ColumnType]): List[Return] = {
- val inc = (square.colIndx - colIndx).signum -> (square.row - row).signum
- val incremented = this + inc
- val head: Return = this
- val tail: List[Return] =
- if (incremented == square) Nil
- else incremented.until(square).asInstanceOf[List[Return]]
- head :: tail
- }
-
- def +(sq: AbstractSqrCoordinate[_]): Return
-
- def -(sq: AbstractSqrCoordinate[_]): Return
-
- def +(sq: (Int, Int)): Return
-
- def -(sq: (Int, Int)): Return
-
- def unary_+ : Square = NumericSquare(colIndx, row)
-
- def unary_- : Square = NumericSquare(-colIndx, -row)
-
- /**
- * All adjacent squares.
- *
- * @see [[framework.AbstractSqrCoordinate#validAdjacents]] for
- * adjacent squares that are on the board.
- */
- def adjacents: IndexedSeq[Return] = IndexedSeq(
- (-1, -1), (-1, 0), (-1, 1),
- (0, -1), (0, 1),
- (1, -1), (1, 0), (1, 1)
- ) map (this + _)
-
- /**
- * All adjacent squares that are on the board.
- */
- def validAdjacents: IndexedSeq[Return] = adjacents filter (_.isValid)
-
- def toTuple: (ColumnType, Int) = (column, row)
-
- /**
- * Checks if this square is inside of a 8x8 board.
- */
- def isValid: Boolean = colIndx >= 1 && colIndx <= 8 && row >= 1 && row <= 8
-
- override def toString: String = s"$column$row"
-}
-
-
-final case class Square(column: Char, row: Int) extends AbstractSqrCoordinate[Char] {
- val colIndx: Int = columnIndex(column)
-
- override type Return = Square
-
- override def +(sq: AbstractSqrCoordinate[_]): Return = sq match {
- case Square(col, line) =>
- Square(columnLetter(columnIndex(column)+columnIndex(col)), row + line)
- case NumericSquare(col, line) => Square(columnLetter(columnIndex(column) + col), row + line)
- }
-
- override def -(sq: AbstractSqrCoordinate[_]): Square = this.+(-sq)
-
- override def +(sq: (Int, Int)): Square = Square(columnLetter(columnIndex(column) + sq._1), row + sq._2)
-
- override def -(sq: (Int, Int)): Square = this.+(-sq._1, -sq._2)
-}
-
-object Square {
- def apply(coordinate: String): Option[Square] =
- if (coordinate.length == 2 && coordinate.head.isLetter && coordinate.last.isDigit) {
- val col = coordinate.head
- val row = coordinate.last.asDigit
- Some(Square(col, row))
- }
- else None
-}
-
-
-final case class NumericSquare(column: Int, row: Int) extends AbstractSqrCoordinate[Int] {
- def colIndx: Int = column
-
- override type Return = NumericSquare
-
- override def +(sq: AbstractSqrCoordinate[_]): NumericSquare = sq match {
- case Square(col, line) => NumericSquare(column + columnIndex(col), row + line)
- case NumericSquare(col, line) => NumericSquare(column + col, row + line)
- }
-
- override def -(sq: AbstractSqrCoordinate[_]): NumericSquare = this.+(-sq)
-
- override def +(sq: (Int, Int)): NumericSquare = NumericSquare(column + sq._1, row + sq._2)
-
- override def -(sq: (Int, Int)): NumericSquare = this.+(-sq._1, -sq._2)
-}
-
-object NumericSquare {
- def apply(tup: (Int, Int)) = new NumericSquare(tup._1, tup._2)
-}
-
-
-object AbstractSqrCoordinate {
- /**
- * implicit conversion from [[framework.Square]] to [[framework.NumericSquare]]
- */
- implicit def sqr2indxSqr(sqr: Square): NumericSquare = NumericSquare(sqr.colIndx, sqr.row)
-
- /**
- * implicit conversion from [[framework.NumericSquare]] to [[framework.Square]]
- */
- implicit def indxSqr2sqr(iSqr: NumericSquare): Square = Square(columnLetter(iSqr.column), iSqr.row)
-}
diff --git a/framework/src/framework/javaInterfacing/JInput.java b/framework/src/framework/javaInterfacing/JInput.java
index 04b7328..79c9d53 100644
--- a/framework/src/framework/javaInterfacing/JInput.java
+++ b/framework/src/framework/javaInterfacing/JInput.java
@@ -1,7 +1,7 @@
package framework.javaInterfacing;
import framework.Input.*;
-import framework.Square;
+import framework.Sqr;
/**
* Contains wrapper for inputs for more intuitive use with java.
@@ -9,7 +9,7 @@
* @version alpha 0.1
*/
public class JInput {
- public static MoveParams MoveParams(Square from, Square to) {
+ public static MoveParams MoveParams(Sqr from, Sqr to) {
return new MoveParams(from, to);
}
diff --git a/framework/src/framework/pathfinding/BooleanPathfinder.scala b/framework/src/framework/pathfinding/BooleanPathfinder.scala
index 9a4effc..a83dfe4 100644
--- a/framework/src/framework/pathfinding/BooleanPathfinder.scala
+++ b/framework/src/framework/pathfinding/BooleanPathfinder.scala
@@ -1,9 +1,9 @@
package framework.pathfinding
-import framework.Square
+import framework.Sqr
/** A pathfinder that returns [[scala.Boolean]] results. */
trait BooleanPathfinder extends Pathfinder[Boolean] {
- override def terminate(on: Square): Failure.type = Failure
+ override def terminate(on: Sqr): Failure.type = Failure
- override def success(on: Square): Success[Boolean] = Success(true)
+ override def success(on: Sqr): Success[Boolean] = Success(true)
}
diff --git a/framework/src/framework/pathfinding/KingMovementPathfinder.scala b/framework/src/framework/pathfinding/KingMovementPathfinder.scala
index 2ab8fdc..18dc64b 100644
--- a/framework/src/framework/pathfinding/KingMovementPathfinder.scala
+++ b/framework/src/framework/pathfinding/KingMovementPathfinder.scala
@@ -1,6 +1,6 @@
package framework.pathfinding
-import framework.Square
+import framework.Sqr
/**
* Applies the movement of a king to a pathfinder.
@@ -8,11 +8,11 @@ import framework.Square
* @version alpha 0.2
*/
abstract class KingMovementPathfinder extends Pathfinder[Boolean] {
- override def success(on: Square): Success[Boolean] = Success(true)
+ override def success(on: Sqr): Success[Boolean] = Success(true)
- override def continue(from: Square): Result[Boolean] = apply(from)
+ override def continue(from: Sqr): Result[Boolean] = apply(from)
- override def apply(pos: Square): Result[Boolean] = {
+ override def apply(pos: Sqr): Result[Boolean] = {
val agents = Array(
KingMovement(0, 1), KingMovement(0, -1),
KingMovement(1, 1), KingMovement(1, 0), KingMovement(1, -1),
@@ -30,12 +30,12 @@ abstract class KingMovementPathfinder extends Pathfinder[Boolean] {
}
}
- override def terminate(on: Square): Failure.type = Failure
+ override def terminate(on: Sqr): Failure.type = Failure
- override def decision(pos: Square): WaypointResult.Value
+ override def decision(pos: Sqr): WaypointResult.Value
private case class KingMovement(override val vector: (Int, Int))
extends TripleDirectionalPathfinder[Boolean](vector) with BooleanPathfinder {
- override def decision(pos: Square): WaypointResult.Value = KingMovementPathfinder.this.decision(pos)
+ override def decision(pos: Sqr): WaypointResult.Value = KingMovementPathfinder.this.decision(pos)
}
}
diff --git a/framework/src/framework/pathfinding/MonoDirectionalPathfinder.scala b/framework/src/framework/pathfinding/MonoDirectionalPathfinder.scala
index 30fa29e..468b81c 100644
--- a/framework/src/framework/pathfinding/MonoDirectionalPathfinder.scala
+++ b/framework/src/framework/pathfinding/MonoDirectionalPathfinder.scala
@@ -1,8 +1,8 @@
package framework.pathfinding
-import framework.Square
+import framework.Sqr
abstract class MonoDirectionalPathfinder[@specialized(Boolean) ResultType](override val vector: (Int, Int))
extends VectorPathfinder[ResultType](vector) {
- override def continue(from: Square): Result[ResultType] = this.apply(from + vector)
+ override def continue(from: Sqr): Result[ResultType] = this.apply(from + vector)
}
diff --git a/framework/src/framework/pathfinding/Pathfinder.scala b/framework/src/framework/pathfinding/Pathfinder.scala
index 832fc34..73fabf7 100644
--- a/framework/src/framework/pathfinding/Pathfinder.scala
+++ b/framework/src/framework/pathfinding/Pathfinder.scala
@@ -1,6 +1,6 @@
package framework.pathfinding
-import framework.Square
+import framework.Sqr
import WaypointResult._
/**
@@ -11,21 +11,21 @@ import WaypointResult._
*/
abstract class Pathfinder[@specialized(Boolean) ResultType] {
/** ''Sets'' this pathfinder on a square to start it from there. */
- def apply(pos: Square): Result[ResultType] = decision(pos) match {
+ def apply(pos: Sqr): Result[ResultType] = decision(pos) match {
case Termination => terminate(pos)
case Positive => success(pos)
case Continuation => continue(pos)
}
/** Terminates the pathfinder */
- def terminate(on: Square): Result[ResultType]
+ def terminate(on: Sqr): Result[ResultType]
/** Terminates with a positive result. */
- def success(on: Square): Result[ResultType]
+ def success(on: Sqr): Result[ResultType]
/** This lets the pathfinder continue its way. */
- def continue(from: Square): Result[ResultType]
+ def continue(from: Sqr): Result[ResultType]
/** Decides what the pathfinder should do. */
- def decision(pos: Square): WaypointResult.Value
+ def decision(pos: Sqr): WaypointResult.Value
}
diff --git a/framework/src/framework/pathfinding/TerminableOnce.scala b/framework/src/framework/pathfinding/TerminableOnce.scala
index 325c164..de79a9c 100644
--- a/framework/src/framework/pathfinding/TerminableOnce.scala
+++ b/framework/src/framework/pathfinding/TerminableOnce.scala
@@ -1,5 +1,5 @@
package framework.pathfinding
-import framework.Square
+import framework.Sqr
/**
* Wraps another pathfinder and lets it run in a sandbox-like
@@ -11,14 +11,14 @@ case class TerminableOnce[@specialized(Boolean) ResultType](pathfinder: VectorPa
extends Pathfinder[ResultType] {
val pF = new TripleDirectionalPathfinder[ResultType](pathfinder.vector) {
- override def success(on: Square): Result[ResultType] = pathfinder.success(on)
+ override def success(on: Sqr): Result[ResultType] = pathfinder.success(on)
- override def decision(pos: Square): WaypointResult.Value = pathfinder.decision(pos)
+ override def decision(pos: Sqr): WaypointResult.Value = pathfinder.decision(pos)
- override def terminate(on: Square): Result[ResultType] = TerminableOnce.this.terminate(on)
+ override def terminate(on: Sqr): Result[ResultType] = TerminableOnce.this.terminate(on)
}
- override def terminate(on: Square): Result[ResultType] = {
+ override def terminate(on: Sqr): Result[ResultType] = {
val vectors = Array(
(-1, -1), (-1, 0), (-1, 1),
(0, -1), (0, 1),
@@ -39,16 +39,16 @@ case class TerminableOnce[@specialized(Boolean) ResultType](pathfinder: VectorPa
private case class TerminatedPathfinder(override val vector: (Int, Int))
extends TripleDirectionalPathfinder[ResultType](vector) {
- override def terminate(on: Square): Result[ResultType] = pathfinder.terminate(on)
+ override def terminate(on: Sqr): Result[ResultType] = pathfinder.terminate(on)
- override def success(on: Square): Result[ResultType] = pathfinder.success(on)
+ override def success(on: Sqr): Result[ResultType] = pathfinder.success(on)
- override def decision(pos: Square): WaypointResult.Value = pathfinder.decision(pos)
+ override def decision(pos: Sqr): WaypointResult.Value = pathfinder.decision(pos)
}
- override def success(on: Square): Result[ResultType] = pathfinder.success(on)
+ override def success(on: Sqr): Result[ResultType] = pathfinder.success(on)
- override def continue(from: Square): Result[ResultType] = pF.continue(from)
+ override def continue(from: Sqr): Result[ResultType] = pF.continue(from)
- override def decision(pos: Square): WaypointResult.Value = pathfinder.decision(pos)
+ override def decision(pos: Sqr): WaypointResult.Value = pathfinder.decision(pos)
}
diff --git a/framework/src/framework/pathfinding/TripleDirectionalPathfinder.scala b/framework/src/framework/pathfinding/TripleDirectionalPathfinder.scala
index f4bc46e..22da4e8 100644
--- a/framework/src/framework/pathfinding/TripleDirectionalPathfinder.scala
+++ b/framework/src/framework/pathfinding/TripleDirectionalPathfinder.scala
@@ -1,11 +1,11 @@
package framework.pathfinding
-import framework.Square
+import framework.Sqr
abstract class TripleDirectionalPathfinder[@specialized(Boolean) ResultType](override val vector: (Int, Int))
extends VectorPathfinder[ResultType](vector) {
- override def continue(from: Square): Result[ResultType] = {
+ override def continue(from: Sqr): Result[ResultType] = {
val resMain = this.apply(from + vector)
val sideVectors: Array[(Int, Int)] =
@@ -15,11 +15,11 @@ abstract class TripleDirectionalPathfinder[@specialized(Boolean) ResultType](ove
val resSide = sideVectors map { v =>
new MonoDirectionalPathfinder[ResultType](v) {
- override def terminate(on: Square): Result[ResultType] = TripleDirectionalPathfinder.this.terminate(on)
+ override def terminate(on: Sqr): Result[ResultType] = TripleDirectionalPathfinder.this.terminate(on)
- override def success(on: Square): Result[ResultType] = TripleDirectionalPathfinder.this.terminate(on)
+ override def success(on: Sqr): Result[ResultType] = TripleDirectionalPathfinder.this.terminate(on)
- override def decision(pos: Square): WaypointResult.Value = TripleDirectionalPathfinder.this.decision(pos)
+ override def decision(pos: Sqr): WaypointResult.Value = TripleDirectionalPathfinder.this.decision(pos)
} apply (from + v)
}
diff --git a/graphics/src/graphics/Board.scala b/graphics/src/graphics/Board.scala
index 4de64c1..fa7fefe 100644
--- a/graphics/src/graphics/Board.scala
+++ b/graphics/src/graphics/Board.scala
@@ -3,7 +3,7 @@ package graphics
import framework.BoardStatus.GameResult._
import framework.BoardStatus.ResultReason.DrawResultReason.InsufficientMaterial
import framework.IOEvents._
-import framework.{ChessBoard, ChessIO, Square, AnyColor}
+import framework.{ChessBoard, ChessIO, Sqr, AnyColor}
import framework.FileOperationError._
import framework.Input._
@@ -29,7 +29,7 @@ class Board(val window: CWindow) extends GridPanel(0, 9) with BoardEventHandler
else if (j == 0) new CTextField(row.toString)
else {
val color: BoardColor = if (i % 2 == j % 2) Brown.White else Brown.Black
- val pos = Square(col, row)
+ val pos = Sqr(col, row)
new SquareButton(color, pos, chessBoard(pos))
}
}
diff --git a/graphics/src/graphics/BoardEventHandler.scala b/graphics/src/graphics/BoardEventHandler.scala
index 5f3f75b..34824d4 100644
--- a/graphics/src/graphics/BoardEventHandler.scala
+++ b/graphics/src/graphics/BoardEventHandler.scala
@@ -1,7 +1,7 @@
package graphics
import framework.Input.{MoveParams, Promotion}
-import framework.{AnyColor, AnyPiece, Square}
+import framework.{AnyColor, AnyPiece, Sqr}
/**
* [Description]
diff --git a/graphics/src/graphics/SquareButton.scala b/graphics/src/graphics/SquareButton.scala
index 3282cb6..b2c1cd1 100644
--- a/graphics/src/graphics/SquareButton.scala
+++ b/graphics/src/graphics/SquareButton.scala
@@ -1,7 +1,7 @@
package graphics
import BoardColors._
-import framework.Square
+import framework.Sqr
import scala.swing.event.ActionEvent
import scala.swing.{Graphics2D, Image, Insets, ToggleButton}
From 15b8541453c7b57b474413586b1c5a2ec6ce37d1 Mon Sep 17 00:00:00 2001
From: FelixL <50499590+SlaynAndKorpil@users.noreply.github.com>
Date: Sun, 3 May 2020 21:55:54 +0200
Subject: [PATCH 2/4] pretty much fixed the most stuff [Insert informative
description here]
---
framework/src/framework/BoardMap.scala | 40 ++++---
framework/src/framework/ChessBoard.scala | 129 ++++++-----------------
framework/src/framework/SaveLoader.scala | 77 +++++++-------
framework/src/framework/Sqr.scala | 4 +-
4 files changed, 88 insertions(+), 162 deletions(-)
diff --git a/framework/src/framework/BoardMap.scala b/framework/src/framework/BoardMap.scala
index e719fc8..45c7a67 100644
--- a/framework/src/framework/BoardMap.scala
+++ b/framework/src/framework/BoardMap.scala
@@ -13,21 +13,23 @@ import scala.xml._
* @author Felix Lehner
* @version
*/
-final case class BoardMap(ps: Array[Array[Piece]])
+final case class BoardMap(ps: Array[IndexedSeq[Piece]])
extends IndexedSeq[IndexedSeq[Piece]] with IndexedSeqLike[IndexedSeq[Piece], BoardMap] {
override val length = 8
override def size = 8
- val pieces: Array[Array[Piece]] = if (ps.length == 8 && ps.forall(_.length == 8)) ps else Array.fill(8)(Array.fill(8)(NoPiece))
+ val pieces: Array[IndexedSeq[Piece]] = if (ps.length == 8 && ps.forall(_.length == 8)) ps else Array.fill(8)(Array.fill(8)(NoPiece))
+
+ def apply(idx: Int): IndexedSeq[Piece] = pieces(idx)
/**
* @param sqr coordinates of the wanted piece
* @return the chess square at a specific position on the board, [[scala.None]] if the sqr does not exist
*/
def getPiece(sqr: Sqr): Option[Piece] =
- if (sqr.isValid) Some(apply(sqr._1)(sqr._2))
+ if (sqr.isValid) Some(apply(sqr._1 - 1)(sqr._2 - 1))
else None
/**
@@ -49,8 +51,8 @@ final case class BoardMap(ps: Array[Array[Piece]])
*/
def updated(square: Sqr, piece: Piece): BoardMap = {
if (square.isValid) {
- val updated = this(square._1).updated(square._2, piece)
- this.updated(square._1, updated)
+ val updated = this(square._1 - 1).updated(square._2 - 1, piece)
+ this.updated(square._1 - 1, updated)
} else this
}
@@ -59,9 +61,7 @@ final case class BoardMap(ps: Array[Array[Piece]])
*
* @param sqr the square to be emptied
*/
- def emptySquare(sqr: Sqr): BoardMap =
- if (sqr.isValid) updated(sqr, NoPiece)
- else this
+ def emptySquare(sqr: Sqr): BoardMap = updated(sqr, NoPiece)
/**
* Makes a chess move.
@@ -92,17 +92,13 @@ final case class BoardMap(ps: Array[Array[Piece]])
}
def toXml: NodeSeq = {
- for (x <- 1 to 8; col = columnLetter(x)) yield {squares(col).saveData} copy (label = col.toUpper toString)
-
- // in Column:
- /**
- * Saves this column as xml.
- */
- def saveData: IndexedSeq[scala.xml.Elem] = {
- var result: IndexedSeq[scala.xml.Elem] = IndexedSeq()
- pieces.indices.foreach(i => if (pieces(i).nonEmpty) result = result :+ pieces(i).toXml.copy(label = "l" + (i + 1)))
- result
- }
+ for (x <- 0 to 7; col = columnLetter(x + 1)) yield
+ {
+ var result: IndexedSeq[scala.xml.Elem] = IndexedSeq()
+ pieces(x).indices.foreach(i =>
+ if (pieces(x)(i).nonEmpty) result = result :+ pieces(x)(i).toXml.copy(label = "l" + (i + 1)))
+ result
+ } copy (label = col.toUpper.toString)
}
/**
@@ -113,16 +109,18 @@ final case class BoardMap(ps: Array[Array[Piece]])
*/
override def toString: String = {
val separationLine: String = " +---+---+---+---+---+---+---+---+\n"
- val lines = for (x <- 1 to 8; c = ChessBoard.columnLetter(x)) yield c + " " + apply(c)
+ val lines = for (x <- 0 to 7; c = ChessBoard.columnLetter(x + 1)) yield c + " " + apply(x)
lines mkString(" 1 2 3 4 5 6 7 8\n" + separationLine, "\n" + separationLine, "\n" + separationLine)
}
}
object BoardMap {
+ def fill(piece: Piece): BoardMap = BoardMap.fromSeq(Array.fill(8)(IndexedSeq.fill(8)(piece)))
+
def apply(pieces: Seq[Piece]*): BoardMap = fromSeq(pieces)
- def fromSeq(buf: Seq[Seq[Piece]]): BoardMap = new BoardMap(buf.toArray.map(_.toArray))
+ def fromSeq(buf: Seq[Seq[Piece]]): BoardMap = new BoardMap(buf.toArray.map(_.toIndexedSeq))
def newBuilder: scala.collection.mutable.Builder[Seq[Piece], BoardMap] = new ArrayBuffer mapResult fromSeq
diff --git a/framework/src/framework/ChessBoard.scala b/framework/src/framework/ChessBoard.scala
index baeda03..e0bf5c8 100644
--- a/framework/src/framework/ChessBoard.scala
+++ b/framework/src/framework/ChessBoard.scala
@@ -55,14 +55,6 @@ case class ChessBoard(
/** The move counter */
val turnCounter: Int = history.length / 2
- /**
- * @param column the one-letter identifier of a column of squares on the board
- * @return a column of the board, [[scala.None]] if no column with this identifier exists
- */
- def getColumn(column: Char): Option[Column] =
- if (isValidColumn(column)) Some(squares(column))
- else None
-
/**
* Handles different input types depending on the [[framework.ChessBoard#gameStatus gameStatus]].
*
@@ -144,10 +136,9 @@ case class ChessBoard(
/**
* Filters for all pieces that match a predicate.
- *
*/
- def filterPieces(func: Piece => Boolean): Map[Char, Column] =
- squares map { tup => tup._1 -> tup._2.filter(func) }
+ def filterPieces(func: Piece => Boolean): BoardMap =
+ squares map { tup => tup.filter(func) }
/**
* Generates a new [[framework.ChessBoard ChessBoard]] which shares all attributes with this one
@@ -316,8 +307,8 @@ case class ChessBoard(
* @return `true` if the move is legal, otherwise `false`
*/
def isLegalMove(start: Sqr, end: Sqr, startPiece: Piece, endPiece: Piece): Boolean = {
- val startCIndex = start.colIndx
- val endCIndex = end.colIndx
+ val startCIndex = start.column
+ val endCIndex = end.column
val columnDif = endCIndex - startCIndex
val lineDif = end._2 - start._2
@@ -352,13 +343,10 @@ case class ChessBoard(
(!startPiece.moved && (end.column == 'c' || end.column == 'g') && {
val rookCol = if (end.column == 'c') 'a' else 'h'
val rook = apply(Sqr(rookCol, ClassicalValues.piecesStartLine(color)))
- val squaresToTest: List[NumericSquare] =
- AbstractSqrCoordinate.sqr2indxSqr(Sqr(if (startCIndex < endCIndex) 'g' else 'c', start.row)) to start
+ val squaresToTest: List[Sqr] =
+ Sqr(if (startCIndex < endCIndex) 'g' else 'c', start.row) to start
- def isSqrAttacked(sqr: AbstractSqrCoordinate[_]): Boolean = sqr match {
- case square: Sqr => isAttacked(square, turn, withKing = true)
- case square: NumericSquare => isAttacked(square, turn, withKing = true)
- }
+ def isSqrAttacked(sqr: Sqr): Boolean = isAttacked(sqr, turn, withKing = true)
rook == Rook(color, false) && squaresToTest.forall(sqr => !isSqrAttacked(sqr)) && isEmptyOrthogonal(start, end)
})
@@ -405,12 +393,12 @@ case class ChessBoard(
}
val opponent = attacked.opposite
- val colI = sqr.colIndx
+ val colI = sqr.column
val row = sqr.row
- def partNxtPiece(inc: (Int, Int)): Piece = nextPiece(NumericSquare(colI, sqr.row), NumericSquare(inc))
+ def partNxtPiece(inc: (Int, Int)): Piece = nextPiece(sqr, Sqr(inc))
- def partApply(inc: (Int, Int)) = apply(NumericSquare(colI, row) + inc)
+ def partApply(inc: (Int, Int)) = apply(sqr + inc)
val attackedByKnight: Int =
Array(partApply(1, 2), partApply(2, 1), partApply(2, -1), partApply(1, -2), partApply(-1, 2),
@@ -432,7 +420,7 @@ case class ChessBoard(
val attackedByPawn: Int = {
val dir = ClassicalValues.pawnDir(attacked)
- def pieceAtOffset(colD: Int, rowD: Int): Piece = apply(NumericSquare(colI, row) + (colD, rowD))
+ def pieceAtOffset(colD: Int, rowD: Int): Piece = apply(sqr + (colD, rowD))
val arr = Array(pieceAtOffset(1, dir), pieceAtOffset(-1, dir))
@@ -462,7 +450,7 @@ case class ChessBoard(
case anyPiece: AnyPiece =>
val kings = allPieces filter (_._2 === King(anyPiece.color))
kings exists { king =>
- val negVec = NumericSquare((square.colIndx - king._1.colIndx).signum, (square.row - king._1.row).signum)
+ val negVec = Sqr((square.column - king._1.column).signum, (square.row - king._1.row).signum)
val possiblePinner = nextPiece(square, negVec)
@@ -644,7 +632,7 @@ case class ChessBoard(
val piecesOfColor = // pieces of specified color without kings
allPieces
.map { tup => /*replace square with square color*/
- (if (tup._1.colIndx % 2 == tup._1.row % 2) Black else White, tup._2) }
+ (if (tup._1.column % 2 == tup._1.row % 2) Black else White, tup._2) }
.filter(_._2.color == color)
.filterNot(_._2 === King(color))
@@ -684,7 +672,7 @@ case class ChessBoard(
* @return the first piece on a line
*/
@scala.annotation.tailrec
- final def nextPiece(start: NumericSquare, increment: NumericSquare): Piece = {
+ final def nextPiece(start: Sqr, increment: Sqr): Piece = {
val incremented = start + increment
if (incremented.isValid) apply(incremented) match {
case NoPiece => nextPiece(incremented, increment)
@@ -710,8 +698,8 @@ case class ChessBoard(
* @see [[framework.ChessBoard#isEmptyOrthogonal isEmptyOrthogonal]]
*/
def isEmptyDiagonal(from: Sqr, to: Sqr): Boolean = {
- val startColIndex = from.colIndx
- val endColIndex = to.colIndx
+ val startColIndex = from.column
+ val endColIndex = to.column
val diagonal = startColIndex - endColIndex == from._2 - to._2 || startColIndex - to._2 == endColIndex - from._2
diagonal && isEmptyConnection(from, to)
}
@@ -810,9 +798,9 @@ case class ChessBoard(
@scala.annotation.tailrec
private def isEmptyConnection(from: Sqr, to: Sqr): Boolean = {
- val startColIndex = from.colIndx
- val endColIndex = to.colIndx
- val incremented: Sqr = NumericSquare((endColIndex - startColIndex).signum, (to._2 - from._2).signum) + from
+ val startColIndex = from.column
+ val endColIndex = to.column
+ val incremented: Sqr = Sqr((endColIndex - startColIndex).signum, (to._2 - from._2).signum) + from
if (incremented == to) true
else if (apply(incremented).isEmpty) isEmptyConnection(incremented, to)
else false
@@ -840,57 +828,19 @@ object ChessBoard {
* @return a fully filled [[framework.ChessBoard ChessBoard]]
*/
def fill(piece: Piece)(implicit io: ChessIO): ChessBoard =
- this(Array.fill(8)(Column(piece)), Nil, Positions.empty, White).get
+ this(BoardMap.fill(piece), Nil, Positions.empty, White, StandardReq)
val classicalPosition: BoardMap = BoardMap(
- 'a' -> new Column(Map(
- 1 -> Rook(White),
- 2 -> Pawn(White),
- 7 -> Pawn(Black),
- 8 -> Rook(Black)
- )),
- 'b' -> new Column(Map(
- 1 -> Knight(White),
- 2 -> Pawn(White),
- 7 -> Pawn(Black),
- 8 -> Knight(Black)
- )),
- 'c' -> new Column(Map(
- 1 -> Bishop(White),
- 2 -> Pawn(White),
- 7 -> Pawn(Black),
- 8 -> Bishop(Black)
- )),
- 'd' -> new Column(Map(
- 1 -> Queen(White),
- 2 -> Pawn(White),
- 7 -> Pawn(Black),
- 8 -> Queen(Black)
- )),
- 'e' -> new Column(Map(
- 1 -> King(White),
- 2 -> Pawn(White),
- 7 -> Pawn(Black),
- 8 -> King(Black)
- )),
- 'f' -> new Column(Map(
- 1 -> Bishop(White),
- 2 -> Pawn(White),
- 7 -> Pawn(Black),
- 8 -> Bishop(Black)
- )),
- 'g' -> new Column(Map(
- 1 -> Knight(White),
- 2 -> Pawn(White),
- 7 -> Pawn(Black),
- 8 -> Knight(Black)
- )),
- 'h' -> new Column(Map(
- 1 -> Rook(White),
- 2 -> Pawn(White),
- 7 -> Pawn(Black),
- 8 -> Rook(Black)
- )))
+ Array(Rook(White), Knight(White), Bishop(White), Queen(White), King(White), Bishop(White), Knight(White), Rook(White)),
+ Array.fill(8)(Pawn(White)),
+ Array.fill(8)(NoPiece),
+ Array.fill(8)(NoPiece),
+ Array.fill(8)(NoPiece),
+ Array.fill(8)(NoPiece),
+ Array.fill(8)(NoPiece),
+ Array.fill(8)(NoPiece),
+ Array.fill(8)(Pawn(Black)),
+ Array(Rook(Black), Knight(Black), Bishop(Black), Queen(Black), King(Black), Bishop(Black), Knight(Black), Rook(Black)))
/**
* Defines the classical chess standard board
@@ -900,25 +850,6 @@ object ChessBoard {
def classicalBoard(implicit io: ChessIO): ChessBoard =
ChessBoard(classicalPosition, Nil, Positions.empty, White, StandardReq)(io, ClassicPosition)
- /**
- * Generator for chessboards.
- */
- def apply(columns: Array[Column], history: List[MoveData], positions: Positions, turn: AnyColor)
- (implicit io: ChessIO): Option[ChessBoard] =
- if (columns.length >= 8) {
- val board = BoardMap(
- 'a' -> columns(0),
- 'b' -> columns(1),
- 'c' -> columns(2),
- 'd' -> columns(3),
- 'e' -> columns(4),
- 'f' -> columns(5),
- 'g' -> columns(6),
- 'h' -> columns(7)
- )
- Some(new ChessBoard(board, history, positions, turn, StandardReq)(io, ArbitraryPosition(board)))
- } else None
-
/**
* Saves a [[framework.ChessBoard]] to a file using the xml format.
*
diff --git a/framework/src/framework/SaveLoader.scala b/framework/src/framework/SaveLoader.scala
index 7b92f63..1a22f5d 100644
--- a/framework/src/framework/SaveLoader.scala
+++ b/framework/src/framework/SaveLoader.scala
@@ -4,6 +4,7 @@ import FileOperationError._
import BoardStatus.GameStatus._
import ChessBoard.columnLetter
+import scala.language.postfixOps
import scala.xml._
/**
@@ -54,12 +55,12 @@ object SaveLoader {
(xml \ nodeName).text.filter(c => c != ' ' && c != '\n')
trait Loader {
- def loadSquaresFromXML(xml: Node): Either[FileOperationError, Map[Char, Column]]
+ def loadSquaresFromXML(xml: Node): Either[FileOperationError, BoardMap]
/** Loads a board from toXml */
def load(xml: Elem)(implicit io: ChessIO): Either[FileOperationError, ChessBoard]
- def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, Column]
+ def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, IndexedSeq[Piece]]
def loadPieceFromXML(xml: NodeSeq): Either[FileOperationError, Piece]
}
@@ -68,11 +69,11 @@ object SaveLoader {
* Chosen when no other loader is defined for a specific version
*/
object NoLoaderDefined extends Loader {
- override def loadSquaresFromXML(xml: Node): Either[FileOperationError, Map[Char, Column]] = Left(BoardLoadingError(xml.toString))
+ override def loadSquaresFromXML(xml: Node): Either[FileOperationError, BoardMap] = Left(BoardLoadingError(xml.toString))
override def load(xml: Elem)(implicit io: ChessIO): Either[FileOperationError, ChessBoard] = Left(UnknownVersionError)
- override def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, Column] = Left(ColumnLoadingError(xml.toString))
+ override def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, IndexedSeq[Piece]] = Left(ColumnLoadingError(xml.toString))
override def loadPieceFromXML(xml: NodeSeq): Either[FileOperationError, Piece] = Left(PieceLoadingError(xml.toString))
}
@@ -86,15 +87,14 @@ object SaveLoader {
case col: AnyColor =>
val squares = loadSquaresFromXML(boardData.head)
- val history =
+ val history: Either[HistoryLoadingError, List[MoveData]] =
try Right(
- moves map (move =>
- MoveData(
+ (moves map {move => MoveData(
Sqr(extractWithFilter(move, "start").head, extractWithFilter(move, "start").last.asDigit),
Piece(extractWithFilter(move, "movedPiece").head, Color(extractWithFilter(move, "movedPiece").last), moved = true),
Sqr(extractWithFilter(move, "end").head, extractWithFilter(move, "end").last.asDigit),
extractWithFilter(move, "capture").toBoolean
- )) toList
+ )}).toList
)
catch {
case _: Throwable => Left(HistoryLoadingError(moves.toString))
@@ -129,32 +129,31 @@ object SaveLoader {
}
override def loadSquaresFromXML(xml: Node): Either[FileOperationError, BoardMap] = {
- val loadedSquares: IndexedSeq[(Char, Either[FileOperationError, Column])] = for {
+ val loadedSquares: IndexedSeq[Either[FileOperationError, IndexedSeq[Piece]]] = for {
x <- 1 to 8
col = columnLetter(x)
- } yield col -> loadColumnFromXML(xml \ col.toString.toUpperCase)
- val possibleError = loadedSquares find (_._2.isLeft) map (_._2.left)
+ } yield loadColumnFromXML(xml \ col.toString.toUpperCase)
+ val possibleError = loadedSquares find (_.isLeft) map (_.left)
+
possibleError match {
case None =>
- val res = loadedSquares.map { tup =>
- (tup._1, tup._2.right.get)
- }
- Right(BoardMap(res))
+ val res = loadedSquares map { piece => piece.right.get }
+ Right(BoardMap.fromSeq(res))
case Some(error) =>
Left(error.get)
}
}
/**
- * Loads a [[framework.Column]] from toXml data.
+ * Loads a column from toXml data.
*
* @param xml data formatted as toXml
* @return the loaded column
*/
- override def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, Column] = {
+ override def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, IndexedSeq[Piece]] = {
try {
- var pieces: Array[Piece] = Array.empty
- var errors: Array[FileOperationError] = Array.empty
+ var pieces: IndexedSeq[Piece] = IndexedSeq.empty
+ var errors: IndexedSeq[FileOperationError] = IndexedSeq.empty
val loadedData =
for {
i <- 1 to 8
@@ -167,7 +166,7 @@ object SaveLoader {
case Left(error) =>
errors :+= error
}
- if (pieces.length >= 8) Right(new Column(pieces))
+ if (pieces.length >= 8) Right(pieces)
else Left(errors.head)
}
catch {
@@ -248,29 +247,27 @@ object SaveLoader {
}
override def loadSquaresFromXML(xml: Node): Either[FileOperationError, BoardMap] = {
- val loadedSquares: IndexedSeq[(Char, Either[FileOperationError, Column])] = for {
+ val loadedSquares: IndexedSeq[Either[FileOperationError, IndexedSeq[Piece]]] = for {
x <- 1 to 8
col = columnLetter(x)
- } yield col -> loadColumnFromXML(xml \ col.toString.toUpperCase)
- val possibleError = loadedSquares find (_._2.isLeft) map (_._2.left)
+ } yield loadColumnFromXML(xml \ col.toString.toUpperCase)
+ val possibleError = loadedSquares find (_.isLeft) map (_.left)
possibleError match {
case None =>
- val res = loadedSquares.map { tup =>
- (tup._1, tup._2.right.get)
- }
- Right(BoardMap(res))
+ val res = loadedSquares.map { _.right.get }
+ Right(BoardMap.fromSeq(res))
case Some(error) =>
Left(error.get)
}
}
/**
- * Loads a [[framework.Column]] from toXml data.
+ * Loads a column from toXml data.
*
* @param xml data formatted as toXml
* @return the loaded column
*/
- override def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, Column] = {
+ override def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, IndexedSeq[Piece]] = {
try {
var pieces: Array[Piece] = Array.empty
var errors: Array[FileOperationError] = Array.empty
@@ -286,7 +283,7 @@ object SaveLoader {
case Left(error) =>
errors :+= error
}
- if (pieces.length >= 8) Right(new Column(pieces))
+ if (pieces.length >= 8) Right(pieces)
else Left(errors.head)
}
catch {
@@ -369,7 +366,7 @@ object SaveLoader {
if (moveHistory.isEmpty) Positions.empty
else {
val boards: IndexedSeq[BoardMap] = moveHistory.tail.foldRight(Array(startPos.right.get.squares)) {
- (move, positions) => getNextPositionAfterMove(BoardMap(positions.head), move) +: positions
+ (move, positions) => getNextPositionAfterMove(BoardMap.fromSeq(positions.head), move) +: positions
}
Positions(boards map Position)
}
@@ -405,29 +402,27 @@ object SaveLoader {
}
override def loadSquaresFromXML(xml: Node): Either[FileOperationError, BoardMap] = {
- val loadedSquares: IndexedSeq[(Char, Either[FileOperationError, Column])] = for {
+ val loadedSquares: IndexedSeq[Either[FileOperationError, IndexedSeq[Piece]]] = for {
x <- 1 to 8
col = columnLetter(x)
- } yield col -> loadColumnFromXML(xml \ col.toString.toUpperCase)
- val possibleError = loadedSquares find (_._2.isLeft) map (_._2.left)
+ } yield loadColumnFromXML(xml \ col.toString.toUpperCase)
+ val possibleError = loadedSquares find (_.isLeft) map (_.left)
possibleError match {
case None =>
- val res = loadedSquares.map { tup =>
- (tup._1, tup._2.right.get)
- }
- Right(BoardMap(res))
+ val res = loadedSquares.map { _.right.get }
+ Right(BoardMap.fromSeq(res))
case Some(error) =>
Left(error.get)
}
}
/**
- * Loads a [[framework.Column]] from toXml data.
+ * Loads a column from toXml data.
*
* @param xml data formatted as toXml
* @return the loaded column
*/
- override def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, Column] = {
+ override def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, IndexedSeq[Piece]] = {
try {
var pieces: Array[Piece] = Array.empty
var errors: Array[FileOperationError] = Array.empty
@@ -443,7 +438,7 @@ object SaveLoader {
case Left(error) =>
errors :+= error
}
- if (pieces.length >= 8) Right(new Column(pieces))
+ if (pieces.length >= 8) Right(pieces)
else Left(errors.head)
}
catch {
diff --git a/framework/src/framework/Sqr.scala b/framework/src/framework/Sqr.scala
index 75dcb19..f88b622 100644
--- a/framework/src/framework/Sqr.scala
+++ b/framework/src/framework/Sqr.scala
@@ -17,7 +17,7 @@ import scala.language.implicitConversions
* @version alpha 0.1
* @author Felix Lehner
*/
-private case class Sqr(column: Int, row: Int) {
+case class Sqr(column: Int, row: Int) {
@inline
def _1: Int = column
@@ -81,4 +81,6 @@ object Sqr {
else None
def apply(column: Char, row: Int): Sqr = Sqr(ChessBoard.columnIndex(column), row)
+
+ def apply(sqr: (Int, Int)): Sqr = Sqr(sqr._1, sqr._2)
}
From 4643278b38668d1475e8dcbd57bcddab7fee79f4 Mon Sep 17 00:00:00 2001
From: FelixL <50499590+SlaynAndKorpil@users.noreply.github.com>
Date: Tue, 12 May 2020 20:11:41 +0200
Subject: [PATCH 3/4] got it to compile! but it's still broken also simplified
BoardMap to just hold a 2-dimensional Array
---
.idea/runConfigurations/Main.xml | 1 -
framework/src/framework/BoardMap.scala | 65 +++++++++----------
framework/src/framework/ChessBoard.scala | 24 ++++---
framework/src/framework/SaveLoader.scala | 34 +++++-----
framework/src/framework/Sqr.scala | 19 ------
framework/src/framework/StartPosition.scala | 2 +-
graphics/src/graphics/Board.scala | 10 +--
graphics/src/graphics/BoardEventHandler.scala | 4 +-
graphics/src/graphics/SquareButton.scala | 2 +-
9 files changed, 67 insertions(+), 94 deletions(-)
diff --git a/.idea/runConfigurations/Main.xml b/.idea/runConfigurations/Main.xml
index 466c308..caeb46e 100644
--- a/.idea/runConfigurations/Main.xml
+++ b/.idea/runConfigurations/Main.xml
@@ -2,7 +2,6 @@
-
diff --git a/framework/src/framework/BoardMap.scala b/framework/src/framework/BoardMap.scala
index 45c7a67..1a37373 100644
--- a/framework/src/framework/BoardMap.scala
+++ b/framework/src/framework/BoardMap.scala
@@ -2,9 +2,6 @@ package framework
import framework.ChessBoard.columnLetter
-import scala.collection.IndexedSeqLike
-import scala.collection.generic.CanBuildFrom
-import scala.collection.mutable.ArrayBuffer
import scala.xml._
/**
@@ -13,23 +10,13 @@ import scala.xml._
* @author Felix Lehner
* @version
*/
-final case class BoardMap(ps: Array[IndexedSeq[Piece]])
- extends IndexedSeq[IndexedSeq[Piece]] with IndexedSeqLike[IndexedSeq[Piece], BoardMap] {
-
- override val length = 8
-
- override def size = 8
-
- val pieces: Array[IndexedSeq[Piece]] = if (ps.length == 8 && ps.forall(_.length == 8)) ps else Array.fill(8)(Array.fill(8)(NoPiece))
-
- def apply(idx: Int): IndexedSeq[Piece] = pieces(idx)
-
+final case class BoardMap(pieces: Array[Array[Piece]]) {
/**
* @param sqr coordinates of the wanted piece
* @return the chess square at a specific position on the board, [[scala.None]] if the sqr does not exist
*/
def getPiece(sqr: Sqr): Option[Piece] =
- if (sqr.isValid) Some(apply(sqr._1 - 1)(sqr._2 - 1))
+ if (isValid(sqr)) Some(pieces(sqr._1 - 1)(sqr._2 - 1))
else None
/**
@@ -44,20 +31,37 @@ final case class BoardMap(ps: Array[IndexedSeq[Piece]])
/**
* Updates the board.
+ * Returns the unchanged BoardMap object if coordinates are invalid.
*
* @param square the coordinate of the square to updated
* @param piece the piece the square shall be updated to
- * @return a ChessBoard with updated squares.
+ * @return a BoardMap with updated squares.
*/
def updated(square: Sqr, piece: Piece): BoardMap = {
- if (square.isValid) {
- val updated = this(square._1 - 1).updated(square._2 - 1, piece)
- this.updated(square._1 - 1, updated)
+ if (isValid(square)) {
+ val updated = pieces(square._1 - 1).updated(square._2 - 1, piece)
+ BoardMap(pieces.updated(square._1 - 1, updated))
} else this
}
/**
- * Empties a square.
+ * Checks if a pair of coordinates describes a valid position on this BoardMap.
+ *
+ * @param sqr the given [[framework.Sqr]]
+ * @return `true` if sqr is valid, otherwise `false`
+ */
+ def isValid(sqr: Sqr): Boolean = {
+ val outerLen = pieces.length
+
+ // needs to be lazy because pieces(0) might fail so we first need to test for outerLen > 0
+ lazy val innerLen = pieces(0).length
+
+ outerLen > 0 && innerLen > 0 &&
+ 0 < sqr.column && sqr.column <= pieces.length && 0 < sqr.row && sqr.row <= pieces(0).length
+ }
+
+ /**
+ * Empties a square by placing a [[framework.NoPiece]] at this position.
*
* @param sqr the square to be emptied
*/
@@ -101,6 +105,9 @@ final case class BoardMap(ps: Array[IndexedSeq[Piece]])
} copy (label = col.toUpper.toString)
}
+ def filter(predicate: Piece => Boolean): BoardMap =
+ BoardMap(pieces map ( _.filter(predicate) ))
+
/**
* Formats the board as a [[String]].
*
@@ -109,26 +116,14 @@ final case class BoardMap(ps: Array[IndexedSeq[Piece]])
*/
override def toString: String = {
val separationLine: String = " +---+---+---+---+---+---+---+---+\n"
- val lines = for (x <- 0 to 7; c = ChessBoard.columnLetter(x + 1)) yield c + " " + apply(x)
+ val lines = for (x <- 0 to 7; c = ChessBoard.columnLetter(x + 1)) yield c + " " + pieces(x)
lines mkString(" 1 2 3 4 5 6 7 8\n" + separationLine, "\n" + separationLine, "\n" + separationLine)
}
}
object BoardMap {
- def fill(piece: Piece): BoardMap = BoardMap.fromSeq(Array.fill(8)(IndexedSeq.fill(8)(piece)))
-
- def apply(pieces: Seq[Piece]*): BoardMap = fromSeq(pieces)
-
- def fromSeq(buf: Seq[Seq[Piece]]): BoardMap = new BoardMap(buf.toArray.map(_.toIndexedSeq))
+ def fill(piece: Piece): BoardMap = BoardMap(Array.fill(8)(Array.fill(8)(piece)))
- def newBuilder: scala.collection.mutable.Builder[Seq[Piece], BoardMap] = new ArrayBuffer mapResult fromSeq
-
- implicit def canBuildFrom: CanBuildFrom[BoardMap, Seq[Piece], BoardMap] =
- new CanBuildFrom[BoardMap, Seq[Piece], BoardMap] {
-
- def apply(): scala.collection.mutable.Builder[Seq[Piece], BoardMap] = newBuilder
-
- def apply(from: BoardMap): scala.collection.mutable.Builder[Seq[Piece], BoardMap] = newBuilder
- }
+ def empty(): BoardMap = fill(NoPiece)
}
diff --git a/framework/src/framework/ChessBoard.scala b/framework/src/framework/ChessBoard.scala
index e0bf5c8..f51f4ab 100644
--- a/framework/src/framework/ChessBoard.scala
+++ b/framework/src/framework/ChessBoard.scala
@@ -1,13 +1,12 @@
package framework
-import framework.BoardStatus.GameStatus.{GameStatus, PromoReq, StandardReq}
-import framework.pathfinding.WaypointResult
-import framework.Input._
import framework.BoardStatus.GameResult._
-import framework.BoardStatus.GameStatus._
-import framework.BoardStatus.ResultReason.WinResultReason._
+import framework.BoardStatus.GameStatus.{GameStatus, PromoReq, StandardReq, _}
import framework.BoardStatus.ResultReason.DrawResultReason._
+import framework.BoardStatus.ResultReason.WinResultReason._
import framework.IOEvents._
+import framework.Input._
+import framework.pathfinding.WaypointResult
import scala.language.postfixOps
import scala.xml._
@@ -137,8 +136,7 @@ case class ChessBoard(
/**
* Filters for all pieces that match a predicate.
*/
- def filterPieces(func: Piece => Boolean): BoardMap =
- squares map { tup => tup.filter(func) }
+ def filterPieces(func: Piece => Boolean): BoardMap = squares.filter(func)
/**
* Generates a new [[framework.ChessBoard ChessBoard]] which shares all attributes with this one
@@ -216,7 +214,7 @@ case class ChessBoard(
* @param to the end-coordinates
* @return the updated board
*/
- def move(from: Sqr, to: Sqr): Option[Output] = if (from.isValid && to.isValid) {
+ def move(from: Sqr, to: Sqr): Option[Output] = if (squares.isValid(from) && squares.isValid(to)) {
val movingPiece = apply(from)
val endPiece = apply(to)
val startColor = movingPiece.color
@@ -511,7 +509,7 @@ case class ChessBoard(
}
!capturing && !moving && !enPassant
case King(color, _) =>
- val adjacents = square.adjacents.filter(_.isValid)
+ val adjacents = square.adjacents.filter(squares.isValid)
!adjacents.exists(sq => !isAttacked(sq, color, withKing = true) && apply(sq).color != color)
case other if other.isInstanceOf[AnyPiece] =>
val offsets = other match {
@@ -674,7 +672,7 @@ case class ChessBoard(
@scala.annotation.tailrec
final def nextPiece(start: Sqr, increment: Sqr): Piece = {
val incremented = start + increment
- if (incremented.isValid) apply(incremented) match {
+ if (squares.isValid(incremented)) apply(incremented) match {
case NoPiece => nextPiece(incremented, increment)
case piece => piece
}
@@ -774,7 +772,7 @@ case class ChessBoard(
alliedPieces exists (sp => !isPinnedPiece(sp._1) && isLegalMove(sp._1, sqr, sp._2, endPiece))
}
- def adjacents = kingSq.validAdjacents
+ def adjacents = kingSq.adjacents.filter(squares.isValid)
def kingCanMove = adjacents exists (a => {
val adjacentPiece = apply(a)
@@ -830,7 +828,7 @@ object ChessBoard {
def fill(piece: Piece)(implicit io: ChessIO): ChessBoard =
this(BoardMap.fill(piece), Nil, Positions.empty, White, StandardReq)
- val classicalPosition: BoardMap = BoardMap(
+ val classicalPosition: BoardMap = BoardMap(Array(
Array(Rook(White), Knight(White), Bishop(White), Queen(White), King(White), Bishop(White), Knight(White), Rook(White)),
Array.fill(8)(Pawn(White)),
Array.fill(8)(NoPiece),
@@ -840,7 +838,7 @@ object ChessBoard {
Array.fill(8)(NoPiece),
Array.fill(8)(NoPiece),
Array.fill(8)(Pawn(Black)),
- Array(Rook(Black), Knight(Black), Bishop(Black), Queen(Black), King(Black), Bishop(Black), Knight(Black), Rook(Black)))
+ Array(Rook(Black), Knight(Black), Bishop(Black), Queen(Black), King(Black), Bishop(Black), Knight(Black), Rook(Black))))
/**
* Defines the classical chess standard board
diff --git a/framework/src/framework/SaveLoader.scala b/framework/src/framework/SaveLoader.scala
index 1a22f5d..fb8ab6d 100644
--- a/framework/src/framework/SaveLoader.scala
+++ b/framework/src/framework/SaveLoader.scala
@@ -60,7 +60,7 @@ object SaveLoader {
/** Loads a board from toXml */
def load(xml: Elem)(implicit io: ChessIO): Either[FileOperationError, ChessBoard]
- def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, IndexedSeq[Piece]]
+ def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, Array[Piece]]
def loadPieceFromXML(xml: NodeSeq): Either[FileOperationError, Piece]
}
@@ -73,7 +73,7 @@ object SaveLoader {
override def load(xml: Elem)(implicit io: ChessIO): Either[FileOperationError, ChessBoard] = Left(UnknownVersionError)
- override def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, IndexedSeq[Piece]] = Left(ColumnLoadingError(xml.toString))
+ override def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, Array[Piece]] = Left(ColumnLoadingError(xml.toString))
override def loadPieceFromXML(xml: NodeSeq): Either[FileOperationError, Piece] = Left(PieceLoadingError(xml.toString))
}
@@ -129,16 +129,16 @@ object SaveLoader {
}
override def loadSquaresFromXML(xml: Node): Either[FileOperationError, BoardMap] = {
- val loadedSquares: IndexedSeq[Either[FileOperationError, IndexedSeq[Piece]]] = for {
+ val loadedSquares: Array[Either[FileOperationError, Array[Piece]]] = (for {
x <- 1 to 8
col = columnLetter(x)
- } yield loadColumnFromXML(xml \ col.toString.toUpperCase)
+ } yield loadColumnFromXML(xml \ col.toString.toUpperCase)).toArray
val possibleError = loadedSquares find (_.isLeft) map (_.left)
possibleError match {
case None =>
val res = loadedSquares map { piece => piece.right.get }
- Right(BoardMap.fromSeq(res))
+ Right(BoardMap(res))
case Some(error) =>
Left(error.get)
}
@@ -150,10 +150,10 @@ object SaveLoader {
* @param xml data formatted as toXml
* @return the loaded column
*/
- override def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, IndexedSeq[Piece]] = {
+ override def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, Array[Piece]] = {
try {
- var pieces: IndexedSeq[Piece] = IndexedSeq.empty
- var errors: IndexedSeq[FileOperationError] = IndexedSeq.empty
+ var pieces: Array[Piece] = Array.empty
+ var errors: Array[FileOperationError] = Array.empty
val loadedData =
for {
i <- 1 to 8
@@ -247,15 +247,15 @@ object SaveLoader {
}
override def loadSquaresFromXML(xml: Node): Either[FileOperationError, BoardMap] = {
- val loadedSquares: IndexedSeq[Either[FileOperationError, IndexedSeq[Piece]]] = for {
+ val loadedSquares: Array[Either[FileOperationError, Array[Piece]]] = (for {
x <- 1 to 8
col = columnLetter(x)
- } yield loadColumnFromXML(xml \ col.toString.toUpperCase)
+ } yield loadColumnFromXML(xml \ col.toString.toUpperCase)).toArray
val possibleError = loadedSquares find (_.isLeft) map (_.left)
possibleError match {
case None =>
val res = loadedSquares.map { _.right.get }
- Right(BoardMap.fromSeq(res))
+ Right(BoardMap(res))
case Some(error) =>
Left(error.get)
}
@@ -267,7 +267,7 @@ object SaveLoader {
* @param xml data formatted as toXml
* @return the loaded column
*/
- override def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, IndexedSeq[Piece]] = {
+ override def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, Array[Piece]] = {
try {
var pieces: Array[Piece] = Array.empty
var errors: Array[FileOperationError] = Array.empty
@@ -366,7 +366,7 @@ object SaveLoader {
if (moveHistory.isEmpty) Positions.empty
else {
val boards: IndexedSeq[BoardMap] = moveHistory.tail.foldRight(Array(startPos.right.get.squares)) {
- (move, positions) => getNextPositionAfterMove(BoardMap.fromSeq(positions.head), move) +: positions
+ (move, positions) => getNextPositionAfterMove(positions.head, move) +: positions
}
Positions(boards map Position)
}
@@ -402,15 +402,15 @@ object SaveLoader {
}
override def loadSquaresFromXML(xml: Node): Either[FileOperationError, BoardMap] = {
- val loadedSquares: IndexedSeq[Either[FileOperationError, IndexedSeq[Piece]]] = for {
+ val loadedSquares: Array[Either[FileOperationError, Array[Piece]]] = (for {
x <- 1 to 8
col = columnLetter(x)
- } yield loadColumnFromXML(xml \ col.toString.toUpperCase)
+ } yield loadColumnFromXML(xml \ col.toString.toUpperCase)).toArray
val possibleError = loadedSquares find (_.isLeft) map (_.left)
possibleError match {
case None =>
val res = loadedSquares.map { _.right.get }
- Right(BoardMap.fromSeq(res))
+ Right(BoardMap(res))
case Some(error) =>
Left(error.get)
}
@@ -422,7 +422,7 @@ object SaveLoader {
* @param xml data formatted as toXml
* @return the loaded column
*/
- override def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, IndexedSeq[Piece]] = {
+ override def loadColumnFromXML(xml: NodeSeq): Either[FileOperationError, Array[Piece]] = {
try {
var pieces: Array[Piece] = Array.empty
var errors: Array[FileOperationError] = Array.empty
diff --git a/framework/src/framework/Sqr.scala b/framework/src/framework/Sqr.scala
index f88b622..e0e8e03 100644
--- a/framework/src/framework/Sqr.scala
+++ b/framework/src/framework/Sqr.scala
@@ -2,15 +2,6 @@ package framework
import scala.language.implicitConversions
-/*
-* TODO
-* Reduce complexity to only one class, 'Sqr' or 'Sqr'
-* and generate interchangeability of numerical and classic
-* coordinates by method overloading.
-* This will make the whole code simpler and the planned
-* changes in BoardMap easier to implement.
-*/
-
/**
* A coordinate of a square.
*
@@ -42,11 +33,6 @@ case class Sqr(column: Int, row: Int) {
def -(sq: (Int, Int)): Sqr = Sqr(column - sq._1, row - sq._2)
- /**
- * All adjacent squares that are on the board.
- */
- def validAdjacents: IndexedSeq[Sqr] = adjacents filter (_.isValid)
-
/**
* All adjacent squares.
*
@@ -61,11 +47,6 @@ case class Sqr(column: Int, row: Int) {
def +(sq: (Int, Int)): Sqr = Sqr(column + sq._1, row + sq._2)
- /**
- * Checks if this square is inside of a 8x8 board.
- */
- def isValid: Boolean = column >= 1 && column <= 8 && row >= 1 && row <= 8
-
def toTuple: (Int, Int) = (column, row)
override def toString: String = s"$column$row"
diff --git a/framework/src/framework/StartPosition.scala b/framework/src/framework/StartPosition.scala
index c8fb3bc..0ad7b6b 100644
--- a/framework/src/framework/StartPosition.scala
+++ b/framework/src/framework/StartPosition.scala
@@ -29,5 +29,5 @@ object ClassicPosition extends StartPosition {
* @param squares the pieces
*/
case class ArbitraryPosition(squares: BoardMap) extends StartPosition {
- def xml: NodeSeq = ChessBoard.saveSquares(squares)
+ def xml: NodeSeq = squares.toXml
}
diff --git a/graphics/src/graphics/Board.scala b/graphics/src/graphics/Board.scala
index fa7fefe..300d1b7 100644
--- a/graphics/src/graphics/Board.scala
+++ b/graphics/src/graphics/Board.scala
@@ -36,16 +36,16 @@ class Board(val window: CWindow) extends GridPanel(0, 9) with BoardEventHandler
contents foreach (comp => listenTo(comp))
}
- def unselect(square: Square): Unit =
+ def unselect(square: Sqr): Unit =
getSquareOnCoordinate(square) match {
case Some(s) => s.unselect()
case _ =>
}
- private def getSquareOnCoordinate(square: Square): Option[SquareButton] =
- if (square.isValid) {
+ private def getSquareOnCoordinate(square: Sqr): Option[SquareButton] =
+ if (board.squares.isValid(square)) {
val row = 9 - square.row
- val col = square.colIndx + 1
+ val col = square.column + 1
val indx = col + 9 * row - 10
contents(indx) match {
case s: SquareButton => Some(s)
@@ -105,7 +105,7 @@ class Board(val window: CWindow) extends GridPanel(0, 9) with BoardEventHandler
displayCheck(pos)
}
- def displayCheck(on: Square): Unit =
+ def displayCheck(on: Sqr): Unit =
getSquareOnCoordinate(on) match {
case Some(square) =>
square.checked = true
diff --git a/graphics/src/graphics/BoardEventHandler.scala b/graphics/src/graphics/BoardEventHandler.scala
index 34824d4..9669a56 100644
--- a/graphics/src/graphics/BoardEventHandler.scala
+++ b/graphics/src/graphics/BoardEventHandler.scala
@@ -12,7 +12,7 @@ import framework.{AnyColor, AnyPiece, Sqr}
trait BoardEventHandler {
self: Board =>
- private var selectedSquare: Square = _
+ private var selectedSquare: Sqr = _
reactions += {
case SquarePressed(square) =>
@@ -41,7 +41,7 @@ trait BoardEventHandler {
def saveBoard(file: String): Unit = framework.ChessBoard.save(board, file)
- private def move(from: Square, to: Square): Unit =
+ private def move(from: Sqr, to: Sqr): Unit =
receiveInput(MoveParams(from, to))
private def promote(piece: (AnyColor, Boolean) => AnyPiece): Unit =
diff --git a/graphics/src/graphics/SquareButton.scala b/graphics/src/graphics/SquareButton.scala
index b2c1cd1..eecb51e 100644
--- a/graphics/src/graphics/SquareButton.scala
+++ b/graphics/src/graphics/SquareButton.scala
@@ -8,7 +8,7 @@ import scala.swing.{Graphics2D, Image, Insets, ToggleButton}
class SquareButton(
override var color: BoardColor,
- val pos: Square,
+ val pos: Sqr,
override var piece: framework.Piece)
extends ToggleButton with PieceButton {
From c19d3387f2838a047a2f3324fe6d064eeb0c207f Mon Sep 17 00:00:00 2001
From: FelixL <50499590+SlaynAndKorpil@users.noreply.github.com>
Date: Tue, 12 May 2020 21:04:10 +0200
Subject: [PATCH 4/4] if it compiles...
---
console/src/console/ConsoleConsole.scala | 2 ++
console/src/console/ConsoleDebugger.scala | 6 ------
console/src/console/ConsoleError.scala | 6 ------
console/src/console/ConsoleOutput.scala | 17 -----------------
framework/src/framework/BoardMap.scala | 14 +++++++-------
framework/src/framework/ChessBoard.scala | 2 --
framework/src/framework/Piece.scala | 1 -
framework/src/framework/Sqr.scala | 2 +-
8 files changed, 10 insertions(+), 40 deletions(-)
delete mode 100644 console/src/console/ConsoleDebugger.scala
delete mode 100644 console/src/console/ConsoleError.scala
delete mode 100644 console/src/console/ConsoleOutput.scala
diff --git a/console/src/console/ConsoleConsole.scala b/console/src/console/ConsoleConsole.scala
index b4705cb..9702db6 100644
--- a/console/src/console/ConsoleConsole.scala
+++ b/console/src/console/ConsoleConsole.scala
@@ -1,5 +1,7 @@
package console
+import framework.{ConsoleDebugger, ConsoleError, ConsoleOutput}
+
sealed trait ConsoleConsole extends ConsoleOutput {
override val name = "console-interface"
}
diff --git a/console/src/console/ConsoleDebugger.scala b/console/src/console/ConsoleDebugger.scala
deleted file mode 100644
index 579e388..0000000
--- a/console/src/console/ConsoleDebugger.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package console
-
-trait ConsoleDebugger extends ConsoleOutput {
- override val typeDescription: String = "DEBUG"
- def debug (message: String): Unit = println(formatMessage(message))
-}
diff --git a/console/src/console/ConsoleError.scala b/console/src/console/ConsoleError.scala
deleted file mode 100644
index b793c6a..0000000
--- a/console/src/console/ConsoleError.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package console
-
-trait ConsoleError extends ConsoleOutput {
- override val typeDescription: String = "ERROR"
- def error (message: String): Unit = System.err.println(formatMessage(message))
-}
diff --git a/console/src/console/ConsoleOutput.scala b/console/src/console/ConsoleOutput.scala
deleted file mode 100644
index 885804a..0000000
--- a/console/src/console/ConsoleOutput.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package console
-
-/**
- * An interface to the console for more uniform and coincide messages
- */
-trait ConsoleOutput {
- /**The type of message*/
- val typeDescription: String
-
- /**Describes the physical origin (i.e. the package)*/
- val name: String
-
- /**
- * Formats [[name]], [[typeDescription]] and the message to a uniform console output.
- */
- def formatMessage (message: String): String = s"$typeDescription $name >> $message"
-}
diff --git a/framework/src/framework/BoardMap.scala b/framework/src/framework/BoardMap.scala
index 1a37373..5f44094 100644
--- a/framework/src/framework/BoardMap.scala
+++ b/framework/src/framework/BoardMap.scala
@@ -16,7 +16,7 @@ final case class BoardMap(pieces: Array[Array[Piece]]) {
* @return the chess square at a specific position on the board, [[scala.None]] if the sqr does not exist
*/
def getPiece(sqr: Sqr): Option[Piece] =
- if (isValid(sqr)) Some(pieces(sqr._1 - 1)(sqr._2 - 1))
+ if (isValid(sqr)) Some(pieces(sqr._2 - 1)(sqr._1 - 1))
else None
/**
@@ -39,8 +39,8 @@ final case class BoardMap(pieces: Array[Array[Piece]]) {
*/
def updated(square: Sqr, piece: Piece): BoardMap = {
if (isValid(square)) {
- val updated = pieces(square._1 - 1).updated(square._2 - 1, piece)
- BoardMap(pieces.updated(square._1 - 1, updated))
+ val updated = pieces(square._2 - 1).updated(square._1 - 1, piece)
+ BoardMap(pieces.updated(square._2 - 1, updated))
} else this
}
@@ -57,7 +57,7 @@ final case class BoardMap(pieces: Array[Array[Piece]]) {
lazy val innerLen = pieces(0).length
outerLen > 0 && innerLen > 0 &&
- 0 < sqr.column && sqr.column <= pieces.length && 0 < sqr.row && sqr.row <= pieces(0).length
+ 0 < sqr.column && sqr.column <= pieces(0).length && 0 < sqr.row && sqr.row <= pieces.length
}
/**
@@ -112,12 +112,12 @@ final case class BoardMap(pieces: Array[Array[Piece]]) {
* Formats the board as a [[String]].
*
* @usecase Used in consoleUI to show the board in console
- * @return a formatted representation of the board
+ * @return a fancy formatted representation of the board
*/
override def toString: String = {
val separationLine: String = " +---+---+---+---+---+---+---+---+\n"
- val lines = for (x <- 0 to 7; c = ChessBoard.columnLetter(x + 1)) yield c + " " + pieces(x)
- lines mkString(" 1 2 3 4 5 6 7 8\n" + separationLine, "\n" + separationLine, "\n" + separationLine)
+ val lines = for (x <- (0 to 7).reverse) yield (x+1) + pieces(x).mkString(" | ", " | ", " |")
+ lines mkString(" a b c d e f g h\n" + separationLine, "\n" + separationLine, "\n" + separationLine)
}
}
diff --git a/framework/src/framework/ChessBoard.scala b/framework/src/framework/ChessBoard.scala
index f51f4ab..72867e0 100644
--- a/framework/src/framework/ChessBoard.scala
+++ b/framework/src/framework/ChessBoard.scala
@@ -835,8 +835,6 @@ object ChessBoard {
Array.fill(8)(NoPiece),
Array.fill(8)(NoPiece),
Array.fill(8)(NoPiece),
- Array.fill(8)(NoPiece),
- Array.fill(8)(NoPiece),
Array.fill(8)(Pawn(Black)),
Array(Rook(Black), Knight(Black), Bishop(Black), Queen(Black), King(Black), Bishop(Black), Knight(Black), Rook(Black))))
diff --git a/framework/src/framework/Piece.scala b/framework/src/framework/Piece.scala
index f89488c..111ab6b 100644
--- a/framework/src/framework/Piece.scala
+++ b/framework/src/framework/Piece.scala
@@ -3,7 +3,6 @@ package framework
/**
* A chess piece.
*
- * @see [[framework.Column framework.Column]] assigns every line a piece.
* @version alpha 0.2
* @author Felix Lehner
*/
diff --git a/framework/src/framework/Sqr.scala b/framework/src/framework/Sqr.scala
index e0e8e03..90db9ea 100644
--- a/framework/src/framework/Sqr.scala
+++ b/framework/src/framework/Sqr.scala
@@ -49,7 +49,7 @@ case class Sqr(column: Int, row: Int) {
def toTuple: (Int, Int) = (column, row)
- override def toString: String = s"$column$row"
+ override def toString: String = s"${ChessBoard.columnLetter(column)}$row"
}
object Sqr {