Skip to content

Commit f387bbc

Browse files
author
Daniel Barclay
committed
ColoredLines: Refining Board: Renamed BoardPlus items to ...boardPlus.
1 parent c6acf17 commit f387bbc

File tree

7 files changed

+100
-100
lines changed

7 files changed

+100
-100
lines changed

src/main/scala/com/us/dsb/explore/algs/coloredlines/manual/game/GameLogicSupport.scala

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,36 +17,36 @@ object GameLogicSupport {
1717

1818
// (was "private[this]" before test calls:)
1919
@tailrec
20-
private[game] def pickRandomEmptyCell(board: BoardPlus)(implicit rng: Random): Option[CellAddress] = {
21-
if (board.isFull)
20+
private[game] def pickRandomEmptyCell(boardPlus: BoardPlus)(implicit rng: Random): Option[CellAddress] = {
21+
if (boardPlus.isFull)
2222
None
2323
else {
2424
val row = rowIndices(rng.nextInt(BoardOrder))
2525
val col = columnIndices(rng.nextInt(BoardOrder))
26-
if (board.getBallStateAt(CellAddress(row, col)).isEmpty)
26+
if (boardPlus.getBallStateAt(CellAddress(row, col)).isEmpty)
2727
Some(CellAddress(row, col))
2828
else
29-
pickRandomEmptyCell(board) // loop: try again
29+
pickRandomEmptyCell(boardPlus) // loop: try again
3030
}
3131
}
3232

3333
/**
3434
* @param board
3535
* expected to be empty //???? maybe refactor something?
3636
*/
37-
private[game] def placeInitialBalls(board: BoardPlus)(implicit rng: Random): MoveResult = {
37+
private[game] def placeInitialBalls(boardPlus: BoardPlus)(implicit rng: Random): MoveResult = {
3838
val postPlacementsResult =
3939
//???? parameterize:
40-
(1 to 5).foldLeft(MoveResult(board, false)) {
40+
(1 to 5).foldLeft(MoveResult(boardPlus, false)) {
4141
case (resultSoFar, _) =>
4242
val address =
43-
pickRandomEmptyCell(resultSoFar.board).getOrElse(scala.sys.error("Unexpectedly full board"))
44-
val postPlacementBoard = resultSoFar.board.withBallAt(address, pickRandomBallKind())
43+
pickRandomEmptyCell(resultSoFar.boardPlus).getOrElse(scala.sys.error("Unexpectedly full board"))
44+
val postPlacementBoard = resultSoFar.boardPlus.withBallAt(address, pickRandomBallKind())
4545
val placementHandlingResult = LineDetector.handleBallArrival(postPlacementBoard, address)
46-
MoveResult(placementHandlingResult.board, placementHandlingResult.anyRemovals)
46+
MoveResult(placementHandlingResult.boardPlus, placementHandlingResult.anyRemovals)
4747
}
4848
//???? parameterize
49-
postPlacementsResult.copy(board = postPlacementsResult.board.withOnDeckBalls(List.fill(3)(pickRandomBallKind())))
49+
postPlacementsResult.copy(boardPlus = postPlacementsResult.boardPlus.withOnDeckBalls(List.fill(3)(pickRandomBallKind())))
5050
}
5151

5252
private[game] sealed trait Action
@@ -59,12 +59,12 @@ object GameLogicSupport {
5959
}
6060
import Action._
6161

62-
def interpretTapLocationToTapAction(board: BoardPlus,
62+
def interpretTapLocationToTapAction(boardPlus: BoardPlus,
6363
address: CellAddress): Action =
64-
tapAndStateToTapAction(onABall = board.hasABallAt(address),
65-
isSelectedAt = board.isSelectedAt(address),
66-
hasABallSelected = board.hasABallSelected,
67-
hasAnyCellSelected = board.hasAnyCellSelected)
64+
tapAndStateToTapAction(onABall = boardPlus.hasABallAt(address),
65+
isSelectedAt = boardPlus.isSelectedAt(address),
66+
hasABallSelected = boardPlus.hasABallSelected,
67+
hasAnyCellSelected = boardPlus.hasAnyCellSelected)
6868

6969
private def tapAndStateToTapAction(onABall: Boolean,
7070
isSelectedAt: Boolean,
@@ -110,46 +110,46 @@ object GameLogicSupport {
110110
action
111111
}
112112

113-
private[this] def placeNextBalls(board: BoardPlus)(implicit rng: Random): MoveResult = {
113+
private[this] def placeNextBalls(boardPlus: BoardPlus)(implicit rng: Random): MoveResult = {
114114
val postPlacementResult =
115115
//???? for 1 to 3, consume on-deck ball from list, and then place (better for internal state view);;
116116
// can replenish incrementally or later; later might show up better in internal state view
117-
board.getOnDeckBalls
118-
.foldLeft(MoveResult(board, false)) {
117+
boardPlus.getOnDeckBalls
118+
.foldLeft(MoveResult(boardPlus, false)) {
119119
case (curMoveResult, onDeckBall) =>
120-
pickRandomEmptyCell(curMoveResult.board) match {
120+
pickRandomEmptyCell(curMoveResult.boardPlus) match {
121121
case None => // board full; break out early (game will become over)
122122
curMoveResult
123123
case Some(address) =>
124-
val postDeueueBoard =
125-
curMoveResult.board.withOnDeckBalls(curMoveResult.board.getOnDeckBalls.tail)
126-
val postPlacementBoard = postDeueueBoard.withBallAt(address, onDeckBall)
124+
val postDeueueBoardPlus =
125+
curMoveResult.boardPlus.withOnDeckBalls(curMoveResult.boardPlus.getOnDeckBalls.tail)
126+
val postPlacementBoard = postDeueueBoardPlus.withBallAt(address, onDeckBall)
127127
LineDetector.handleBallArrival(postPlacementBoard, address)
128128
}
129129
}
130130
//???? parameterize?
131131
//????? check re duplicate on-deck code (look for other "fill(3)"
132-
postPlacementResult.copy(board = postPlacementResult.board.withOnDeckBalls(List.fill(3)(pickRandomBallKind())))
132+
postPlacementResult.copy(boardPlus = postPlacementResult.boardPlus.withOnDeckBalls(List.fill(3)(pickRandomBallKind())))
133133
}
134134

135135
//???? rename? isn't _user_ move result; is ball move/placement/arrival result
136-
case class MoveResult(board: BoardPlus,
136+
case class MoveResult(boardPlus: BoardPlus,
137137
//??? clarify re placing next three balls (re interpreting differently in different contexts
138138
anyRemovals: Boolean)
139139
{
140140
println(s"??? ${this}")
141141
//??? print("")
142142
}
143143

144-
private[game] def doPass(board: BoardPlus)(implicit rng: Random): MoveResult =
145-
placeNextBalls(board)
144+
private[game] def doPass(boardPlus: BoardPlus)(implicit rng: Random): MoveResult =
145+
placeNextBalls(boardPlus)
146146

147147

148148
//???: likely move core algorithm out; possibly move outer code into BoardPlus/BoardState:
149149
/**
150150
* @param toTapCell - must be empty */
151151
// (was "private[this]" before test calls:)
152-
private[game] def pathExists(board: BoardPlus,
152+
private[game] def pathExists(boardPlus: BoardPlus,
153153
fromBallCell: CellAddress,
154154
toTapCell: CellAddress): Boolean = {
155155
//???? CLEAN ALL THIS:
@@ -160,7 +160,7 @@ object GameLogicSupport {
160160
val blockedAt: Array[Array[Boolean]] =
161161
rowIndices.map { row =>
162162
columnIndices.map { column =>
163-
board.hasABallAt(CellAddress(row, column))
163+
boardPlus.hasABallAt(CellAddress(row, column))
164164
}.toArray
165165
}.toArray
166166
val cellsToExpandFrom = mutable.Queue[CellAddress](fromBallCell)
@@ -202,22 +202,22 @@ object GameLogicSupport {
202202
}
203203

204204

205-
private[game] def doTryMoveBall(board: BoardPlus, //???? change to game state to carry and update score?
205+
private[game] def doTryMoveBall(boardPlus: BoardPlus, //???? change to game state to carry and update score?
206206
from: CellAddress,
207207
to: CellAddress
208208
)(implicit rng: Random): MoveResult = {
209-
val canMoveBall = pathExists(board, from, to)
209+
val canMoveBall = pathExists(boardPlus, from, to)
210210
canMoveBall match {
211211
case false => // can't move--ignore (keep selection state)
212-
MoveResult(board, false)
212+
MoveResult(boardPlus, false)
213213
case true =>
214-
val deselectedBoard = board.withNoSelection
215-
val moveBallColor = deselectedBoard.getBallStateAt(from).get //????
216-
val postMoveBoard = deselectedBoard.withNoBallAt(from).withBallAt(to, moveBallColor)
214+
val deselectedBoardPlus = boardPlus.withNoSelection
215+
val moveBallColor = deselectedBoardPlus.getBallStateAt(from).get //????
216+
val postMoveBoard = deselectedBoardPlus.withNoBallAt(from).withBallAt(to, moveBallColor)
217217

218218
val postHandlingResult = LineDetector.handleBallArrival(postMoveBoard, to)
219219
if (! postHandlingResult.anyRemovals )
220-
placeNextBalls(postHandlingResult.board)
220+
placeNextBalls(postHandlingResult.boardPlus)
221221
else
222222
postHandlingResult
223223
}

src/main/scala/com/us/dsb/explore/algs/coloredlines/manual/game/GameState.scala

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ private[manual] object GameState {
2424
val initialPlacementResult = GameLogicSupport.placeInitialBalls(BoardPlus.empty)
2525
//????? probably split GameState level from slightly lower game state
2626
// carrying board plus score (probably modifying MoveResult for that)
27-
GameState(initialPlacementResult.board, None)
27+
GameState(initialPlacementResult.boardPlus, None)
2828
}
2929

3030
private[manual/*game*/] def initial(seed: Long): GameState = makeInitialState(new Random(seed))
@@ -38,7 +38,7 @@ import GameState._
3838
* @constructor
3939
* @param gameResult `None` means no win or draw yet
4040
*/
41-
private[manual] case class GameState(board: BoardPlus,
41+
private[manual] case class GameState(boardPlus: BoardPlus,
4242
gameResult: Option[GameResult]
4343
)(implicit rng: Random) {
4444

@@ -50,36 +50,36 @@ private[manual] case class GameState(board: BoardPlus,
5050
// game history
5151
private[manual] def tryMoveAt(tapAddress: CellAddress): Either[String, GameState] = {
5252
import GameLogicSupport.Action._
53-
val tapAction = GameLogicSupport.interpretTapLocationToTapAction(board, tapAddress)
53+
val tapAction = GameLogicSupport.interpretTapLocationToTapAction(boardPlus, tapAddress)
5454
println("tryMoveAt: tapAction = " + tapAction)
5555
val moveResult: MoveResult =
5656
tapAction match {
5757
case SelectBall |
5858
SelectEmpty =>
59-
MoveResult(board.withCellSelected(tapAddress), false) //???? ?
59+
MoveResult(boardPlus.withCellSelected(tapAddress), false) //???? ?
6060
case Deselect =>
61-
MoveResult(board.withNoSelection, false) //????
61+
MoveResult(boardPlus.withNoSelection, false) //????
6262
case TryMoveBall =>
6363
//???? should TryMoveBall carry coordinates?:
6464
//???? need to split logical moves/plays (e.g., move ball from source
6565
// to target from top-/selection-level ~UI (keep that separate from cursor-to-taps UI))
6666
val fromAddress =
67-
board.getSelectionCoordinates.getOrElse(sys.error("Shouldn't be able to happen"))
68-
GameLogicSupport.doTryMoveBall(board, fromAddress, tapAddress)
67+
boardPlus.getSelectionCoordinates.getOrElse(sys.error("Shouldn't be able to happen"))
68+
GameLogicSupport.doTryMoveBall(boardPlus, fromAddress, tapAddress)
6969
//???? try to move (conditional) .withNoSelection out of doTryMoveBall
7070
// up to here; need additional could-move flag (addedScore None would be ambiguous)
7171

7272
case Pass =>
73-
val passResult = GameLogicSupport.doPass(board)
74-
passResult.copy(board = passResult.board.withNoSelection)
73+
val passResult = GameLogicSupport.doPass(boardPlus)
74+
passResult.copy(boardPlus = passResult.boardPlus.withNoSelection)
7575
}
7676

7777
val nextState =
78-
if (! moveResult.board.isFull) {
79-
GameState(moveResult.board, gameResult).asRight
78+
if (! moveResult.boardPlus.isFull) {
79+
GameState(moveResult.boardPlus, gameResult).asRight
8080
}
8181
else {
82-
GameState(moveResult.board, Some(Done(moveResult.board.getScore))).asRight
82+
GameState(moveResult.boardPlus, Some(Done(moveResult.boardPlus.getScore))).asRight
8383
}
8484
nextState
8585
}

src/main/scala/com/us/dsb/explore/algs/coloredlines/manual/game/lines/LineDetector.scala

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import com.us.dsb.explore.algs.coloredlines.manual.game.board.{BallKind, BoardPl
1111
object LineDetector {
1212

1313
private[lines] case class LineAxis(labelArray: String,
14-
rowDelta : Int, // -1 / 0 / 1 (Make refined type?)
15-
colDelta : Int)
14+
rowDelta: Int, // -1 / 0 / 1 (Make refined type?)
15+
colDelta: Int)
1616

1717
private[this] val lineAxes =
1818
List(
@@ -23,27 +23,27 @@ object LineDetector {
2323
private[this] val relativeDirectionFactors = List(1, -1) // use type of length 2 (refined List?, Tuple2?, some array?)
2424

2525
private[lines] def haveMatchingBallAt(moveBallColor: BallKind,
26-
board : BoardPlus,
27-
rawRowIndex : Int,
28-
rawColIndex : Int): Boolean = {
26+
boardPlus: BoardPlus,
27+
rawRowIndex: Int,
28+
rawColIndex: Int): Boolean = {
2929
val inRange =
3030
1 <= rawRowIndex && rawRowIndex <= BoardOrder &&
3131
1 <= rawColIndex && rawColIndex <= BoardOrder
3232
val haveMatch =
3333
inRange && {
3434
val candidateAddress = CellAddress.fromRaw(rawRowIndex, rawColIndex)
35-
board.getBallStateAt(candidateAddress).fold(false)(ball => ball == moveBallColor)
35+
boardPlus.getBallStateAt(candidateAddress).fold(false)(ball => ball == moveBallColor)
3636
}
3737
haveMatch
3838
}
3939

4040
private[lines] case class RelativeDirectionResult(excursionLength: Int)
4141

42-
private[lines] def computeDirectionResult(moveBallColor : BallKind,
43-
board : BoardPlus,
44-
ballTo : CellAddress,
42+
private[lines] def computeDirectionResult(moveBallColor: BallKind,
43+
boardPlus: BoardPlus,
44+
ballTo: CellAddress,
4545
lineDirectionAxis: LineAxis,
46-
directionFactor : Int): RelativeDirectionResult = {
46+
directionFactor: Int): RelativeDirectionResult = {
4747
val newBallRowIndex = ballTo.row.value.value
4848
val newBallColIndex = ballTo.column.value.value
4949
import lineDirectionAxis.{colDelta, rowDelta}
@@ -54,7 +54,7 @@ object LineDetector {
5454
val candidateColIndex = newBallColIndex + colDelta * directionFactor * candidateExcursionLength
5555
//??? println(s" ??.n.0: candidate address: ($candidateRowIndex / $candidateColIndex)")
5656

57-
val haveMatchingBall = haveMatchingBallAt(moveBallColor, board, candidateRowIndex, candidateColIndex)
57+
val haveMatchingBall = haveMatchingBallAt(moveBallColor, boardPlus, candidateRowIndex, candidateColIndex)
5858
if (haveMatchingBall) {
5959
excursionLength = candidateExcursionLength
6060
}
@@ -63,19 +63,19 @@ object LineDetector {
6363
RelativeDirectionResult(excursionLength)
6464
}
6565

66-
private[lines] case class AxisResult(axis : LineAxis,
66+
private[lines] case class AxisResult(axis: LineAxis,
6767
axisLineAddedLength: Int, // length WITHOUT moved ball
68-
directionDetails : List[RelativeDirectionResult])
68+
directionDetails: List[RelativeDirectionResult])
6969

70-
private[lines] def computeLineAxisResult(moveBallColor : BallKind,
71-
board : BoardPlus,
72-
ballTo : CellAddress,
70+
private[lines] def computeLineAxisResult(moveBallColor: BallKind,
71+
boardPlus: BoardPlus,
72+
ballTo: CellAddress,
7373
lineDirectionAxis: LineAxis): AxisResult = {
7474
//??? println(s"+ computeLineAxisResult( axis = $lineDirectionAxis ).1")
7575
val directionsResults: List[RelativeDirectionResult] =
7676
relativeDirectionFactors.map { directionFactor =>
7777
computeDirectionResult(moveBallColor,
78-
board,
78+
boardPlus,
7979
ballTo,
8080
lineDirectionAxis,
8181
directionFactor)
@@ -87,10 +87,10 @@ object LineDetector {
8787
result
8888
}
8989

90-
private[lines] def removeCompletedLineBalls(ballTo : CellAddress,
91-
preremovalBoard : BoardPlus,
90+
private[lines] def removeCompletedLineBalls(ballTo: CellAddress,
91+
preremovalBoardPlus: BoardPlus,
9292
completedLineAxesResults: List[AxisResult]): BoardPlus = {
93-
val newBallRemovedBoard = preremovalBoard.withNoBallAt(ballTo)
93+
val newBallRemovedBoard = preremovalBoardPlus.withNoBallAt(ballTo)
9494
val linesRemovedBoard =
9595
completedLineAxesResults.foldLeft(newBallRemovedBoard) { case (axisBoard, axisResult) =>
9696
val fromOffset = -axisResult.directionDetails(1).excursionLength
@@ -113,31 +113,31 @@ object LineDetector {
113113
* None if no line(s) completed; score increment otherwise
114114
*/
115115
//???? rename?: harvestAnyLines?
116-
private[game] def handleBallArrival(board : BoardPlus,
117-
ballTo : CellAddress
116+
private[game] def handleBallArrival(boardPlus: BoardPlus,
117+
ballTo: CellAddress
118118
): MoveResult = {
119119
//println(s"+handleBallArrival(... ballTo = $ballTo...).1")
120-
val moveBallColor = board.getBallStateAt(ballTo).get //????
120+
val moveBallColor = boardPlus.getBallStateAt(ballTo).get //????
121121

122122
val allAxesResults: List[AxisResult] =
123123
lineAxes.map { lineAxis =>
124-
computeLineAxisResult(moveBallColor, board, ballTo, lineAxis)
124+
computeLineAxisResult(moveBallColor, boardPlus, ballTo, lineAxis)
125125
}
126126
//??? println("??? allAxesResults:" + allAxesResults.mkString("\n- ", "\n- ", ""))
127127
val completedLineAxesResults = allAxesResults.filter(_.axisLineAddedLength + 1 >= LineOrder)
128128
//println("??? completedLineAxesResults:" + completedLineAxesResults.map("- " + _.toString).mkString("\n", "\n", "\n:end"))
129129
val (boardResult, scoreResult) =
130130
completedLineAxesResults match {
131131
case Nil =>
132-
(board, None) // return None for score (signal to place 3 more IF ball moved by user)
132+
(boardPlus, None) // return None for score (signal to place 3 more IF ball moved by user)
133133
case linesAxes =>
134134
val totalBallsBeingRemoved = 1 + linesAxes.map(_.axisLineAddedLength).sum
135135
println(s" scoreMove(... ballTo = $ballTo...).x totalBallsBeingRemoved = $totalBallsBeingRemoved")
136136
//???? move?
137137
// note original game scoring: score = totalBallsBeingRemoved * 4 - 10,
138138
// which seems to be from 2 pts per ball in 5-ball line, but 4 for any extra balls in line
139139
val postLinesRemovalBoard = removeCompletedLineBalls(ballTo,
140-
board,
140+
boardPlus,
141141
completedLineAxesResults)
142142
val ballPlacementScore = 2 * LineOrder + 4 * (totalBallsBeingRemoved - LineOrder)
143143
(postLinesRemovalBoard.withAddedScore(ballPlacementScore), Some(ballPlacementScore))

src/main/scala/com/us/dsb/explore/algs/coloredlines/manual/ui/GameUIState.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ private[this] case class GameUIState(gameState: GameState,
5050
columnIndices.map { column =>
5151
val scanAddress = CellAddress(row, column)
5252
val cellStateStr =
53-
gameState.board.getCellBallStateChar(gameState.board.getBallStateAt(scanAddress),
54-
gameState.board.isSelectedAt(scanAddress))
53+
gameState.boardPlus.getCellBallStateChar(gameState.boardPlus.getBallStateAt(scanAddress),
54+
gameState.boardPlus.isSelectedAt(scanAddress))
5555
if (scanAddress == cursorAddress ) {
5656
"*" + cellStateStr + "*"
5757
}
@@ -65,7 +65,7 @@ private[this] case class GameUIState(gameState: GameState,
6565

6666
private[ui] def toDisplayString: String = {
6767
renderTableMultilineWithSelection + "\n" +
68-
s"Score: ${gameState.board.getScore} " +
68+
s"Score: ${gameState.boardPlus.getScore} " +
6969
s"Marking cursor: <row ${cursorAddress.row} / column ${cursorAddress.column}>"
7070
}
7171

0 commit comments

Comments
 (0)