GameSpace.groovy
package net.ebdon.trk21;
import groovy.transform.TypeChecked;
/**
* @file
* @author Terry Ebdon
* @date January 2019
* @copyright Terry Ebdon, 2019
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@groovy.util.logging.Log4j2
abstract class GameSpace {
static final int minCoord = 1;
static final int maxCoord = 8;
static final int boardSize = (minCoord..maxCoord).size() ** 2;
static final topLeftCoords = [minCoord,minCoord];
static final bottomRightCoords = [maxCoord,maxCoord];
LinkedHashMap board = [:];
static final float maxSectorDistance =
distanceBetween( topLeftCoords, bottomRightCoords ); /// Sector diagonal
def size() {
assert validBoardSize
boardSize
}
final def getRandomCoords() {
def rnd = new Random()
[
rnd.nextInt(maxCoord) + 1,
rnd.nextInt(maxCoord) + 1
]
}
@TypeChecked
private boolean isValidBoardSize() {
board.size() == boardSize
}
@TypeChecked
boolean isValidKey( final int row, final int col ) {
board.keySet().contains( [row, col] )
}
boolean isValid() {
def badQuadrant = board.keySet().find {
!insideGalaxy( it[0..1] )
} // sparse = false
// assert null == badQuadrant
log.debug "badQuadrant: $badQuadrant, $this"
String diag = ""
minCoord.upto(maxCoord) {
diag += "[$it, $it]=${board[it,it]}, "
}
log.debug diag
badQuadrant == null && board.size() == boardSize
}
String toString() {
"board size: ${board.size()}"
}
// final def putAt( key, int value ) {
// board[key] = Thing.find { it.ordinal() == value }
// }
// final def putAt( key, Thing value ) {
// board[key] = value
// }
final def clear() {
minCoord.upto(maxCoord) { r1 ->
minCoord.upto(maxCoord) { r2 ->
clearSquare r1, r2
}
}
}
abstract void clearSquare( final row, final col ) ;
abstract int getCellPadding() ;
abstract String symbol( final key ) ;
def dump() {
// log.debug "Dumping board:\n$board"
// println "Dumping board:\n$board"
minCoord.upto(maxCoord) { i ->
def boardRow = ''
minCoord.upto(maxCoord) { j ->
// println "i,j: $i,$j"
boardRow += "${symbol([i,j]).padLeft(cellPadding,'0')} "
}
log.info boardRow
}
}
static boolean insideGalaxy( final coords ) {
insideGalaxy( coords.first(), coords.last() )
}
static boolean insideGalaxy( final x, final y ) {
contains( x, y )
}
static boolean contains( final x, final y ) {
(minCoord..maxCoord).containsAll( x, y )
}
static def constrainCoords( coords ) {
coords.collect { constrainCoord it }
}
static int constrainCoord( coord ) {
coord = [coord,minCoord].max() // Line 1930
coord = [coord,maxCoord].min() // Line 1940
}
static def logFmtCoords( final x, final y ) {
"${[x,y]} == $y - $x"
}
/// Distance between two sectors, calculated via Pythagorous
static float distanceBetween(
final coordsFrom,
final coordsTo ) {
assert coordsFrom && coordsTo
assert coordsFrom != coordsTo
assert sectorIsInsideQuadrant( coordsFrom )
assert sectorIsInsideQuadrant( coordsTo )
// println "Calculating distance between $coordsFrom and $coordsTo"
final distance = Math.sqrt(
( coordsFrom.first() - coordsTo.first() ) ** 2 +
( coordsFrom.last() - coordsTo.last() ) ** 2 )
// assert distance <= maxSectorDistance
// println "Distance is $distance"
distance
}
static boolean sectorIsInsideQuadrant( final coords ) {
insideGalaxy( coords )
}
}