|
|
|
@ -19,8 +19,8 @@ public struct BasicDefaultsNoDiag : IRules {
|
|
|
|
|
&& maxNbRows >= minNbRows
|
|
|
|
|
&& maxNbCols >= minNbCols
|
|
|
|
|
&& nbChipsToAlign >= 2
|
|
|
|
|
&& nbChipsToAlign < minNbCols
|
|
|
|
|
&& nbChipsToAlign < minNbRows
|
|
|
|
|
&& nbChipsToAlign <= minNbCols
|
|
|
|
|
&& nbChipsToAlign <= minNbRows
|
|
|
|
|
) else { return nil }
|
|
|
|
|
|
|
|
|
|
self.minNbRows = minNbRows
|
|
|
|
@ -46,28 +46,53 @@ public struct BasicDefaultsNoDiag : IRules {
|
|
|
|
|
|
|
|
|
|
var victoryTiles : [(Int, Int)] = Array(repeating: (0, 0), count: nbChipsToAlign)
|
|
|
|
|
|
|
|
|
|
// assuming that the board is square, we could add a check for that in IRules if we want to leave it open for extension
|
|
|
|
|
let nbCols = grid[0].count
|
|
|
|
|
// assuming that the board is square -- we could add a check for that in IRules if we wanted to leave that open for extension
|
|
|
|
|
let nbRows = grid.count
|
|
|
|
|
let nbCols = grid[0].count
|
|
|
|
|
|
|
|
|
|
for i in 0..<nbRows {
|
|
|
|
|
for j in 0..<nbCols {
|
|
|
|
|
// check if there is room to the right
|
|
|
|
|
if nbCols - j >= nbChipsToAlign && grid[i][j] != nil && grid[i][j] == playerId {
|
|
|
|
|
if (nbCols - j) >= nbChipsToAlign && grid[i][j] != nil && grid[i][j] == playerId {
|
|
|
|
|
|
|
|
|
|
// check for victory
|
|
|
|
|
if checkAligned(byPlayer: playerId, onGrid: grid, fromRow: i, andCol: j, going: directions.right) == nbChipsToAlign {
|
|
|
|
|
let amountAligned = checkAligned(byPlayer: playerId,
|
|
|
|
|
onGrid: grid,
|
|
|
|
|
fromRow: i,
|
|
|
|
|
upToRow: (nbRows - 1),
|
|
|
|
|
andCol: j,
|
|
|
|
|
upToCol: (nbCols - 1),
|
|
|
|
|
going: directions.right)
|
|
|
|
|
|
|
|
|
|
//print("player \(String(describing: Board.descriptionMapper[playerId])) aligned \(amountAligned) horizontally:")
|
|
|
|
|
if amountAligned >= nbChipsToAlign {
|
|
|
|
|
|
|
|
|
|
for x in 0..<nbChipsToAlign {
|
|
|
|
|
|
|
|
|
|
// row i, origin is (i, j), goes to the right
|
|
|
|
|
victoryTiles[x] = (i, j + x)
|
|
|
|
|
}
|
|
|
|
|
return (isOver: true, hasWinner: true, victoryTiles)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check if there is room lower down
|
|
|
|
|
if nbRows - i >= nbChipsToAlign && grid[i][j] != nil && grid[i][j] == playerId {
|
|
|
|
|
if (nbRows - i) >= nbChipsToAlign && grid[i][j] != nil && grid[i][j] == playerId {
|
|
|
|
|
|
|
|
|
|
// check for victory
|
|
|
|
|
if checkAligned(byPlayer: playerId, onGrid: grid, fromRow: i, andCol: j, going: directions.down) == nbChipsToAlign {
|
|
|
|
|
let amountAligned = checkAligned(byPlayer: playerId,
|
|
|
|
|
onGrid: grid,
|
|
|
|
|
fromRow: i,
|
|
|
|
|
upToRow: (nbRows - 1),
|
|
|
|
|
andCol: j,
|
|
|
|
|
upToCol: (nbCols - 1),
|
|
|
|
|
going: directions.down)
|
|
|
|
|
|
|
|
|
|
//print("player \(String(describing: Board.descriptionMapper[playerId])) aligned \(amountAligned) vertically:")
|
|
|
|
|
if amountAligned >= nbChipsToAlign {
|
|
|
|
|
|
|
|
|
|
for x in 0..<nbChipsToAlign {
|
|
|
|
|
|
|
|
|
|
// column j, origin is (i, j), goes down
|
|
|
|
|
victoryTiles[x] = (i + x, j)
|
|
|
|
|
}
|
|
|
|
@ -76,29 +101,38 @@ public struct BasicDefaultsNoDiag : IRules {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
winner exists?
|
|
|
|
|
return (true, true, tiles)
|
|
|
|
|
else is full ?
|
|
|
|
|
return (true, false, nil)
|
|
|
|
|
else
|
|
|
|
|
return (false, false, nil)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
return (isFull, hasWinner: false, nil);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private func checkAligned(byPlayer playerId: Int,
|
|
|
|
|
onGrid grid: [[Int?]],
|
|
|
|
|
fromRow i: Int,
|
|
|
|
|
upToRow iMax: Int,
|
|
|
|
|
andCol j: Int,
|
|
|
|
|
upToCol jMax: Int,
|
|
|
|
|
going direction: directions) -> Int {
|
|
|
|
|
if let tile = grid[i][j] {
|
|
|
|
|
if tile == playerId {
|
|
|
|
|
if direction == directions.right {
|
|
|
|
|
return 1 + checkAligned(byPlayer: playerId, onGrid: grid, fromRow: i, andCol: j + 1, going: direction)
|
|
|
|
|
if j == jMax { return 1 }
|
|
|
|
|
return 1 + checkAligned(byPlayer: playerId,
|
|
|
|
|
onGrid: grid,
|
|
|
|
|
fromRow: i,
|
|
|
|
|
upToRow: iMax,
|
|
|
|
|
andCol: j + 1,
|
|
|
|
|
upToCol: jMax,
|
|
|
|
|
going: direction)
|
|
|
|
|
|
|
|
|
|
} else if direction == directions.down {
|
|
|
|
|
return 1 + checkAligned(byPlayer: playerId, onGrid: grid, fromRow: i + 1, andCol: j, going: direction)
|
|
|
|
|
if i == iMax { return 1 }
|
|
|
|
|
return 1 + checkAligned(byPlayer: playerId,
|
|
|
|
|
onGrid: grid,
|
|
|
|
|
fromRow: i + 1,
|
|
|
|
|
upToRow: iMax,
|
|
|
|
|
andCol: j,
|
|
|
|
|
upToCol: jMax,
|
|
|
|
|
going: direction)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|