|
export const patterns = { |
|
five: new RegExp('11111'), |
|
blockfive: new RegExp('211111|111112'), |
|
four: new RegExp('011110'), |
|
blockFour: new RegExp('10111|11011|11101|211110|211101|211011|210111|011112|101112|110112|111012'), |
|
three: new RegExp('011100|011010|010110|001110'), |
|
blockThree: new RegExp('211100|211010|210110|001112|010112|011012'), |
|
two: new RegExp('001100|011000|000110|010100|001010'), |
|
} |
|
export const shapes = { |
|
FIVE: 5, |
|
BLOCK_FIVE: 50, |
|
FOUR: 4, |
|
FOUR_FOUR: 44, |
|
FOUR_THREE: 43, |
|
THREE_THREE: 33, |
|
BLOCK_FOUR: 40, |
|
THREE: 3, |
|
BLOCK_THREE: 30, |
|
TWO_TWO: 22, |
|
TWO: 2, |
|
NONE: 0, |
|
}; |
|
|
|
export const performance = { |
|
five: 0, |
|
blockFive: 0, |
|
four: 0, |
|
blockFour: 0, |
|
three: 0, |
|
blockThree: 0, |
|
two: 0, |
|
none: 0, |
|
total: 0, |
|
} |
|
|
|
|
|
export const getShape = (board, x, y, offsetX, offsetY, role) => { |
|
const opponent = -role; |
|
let emptyCount = 0; |
|
let selfCount = 1; |
|
let opponentCount = 0; |
|
let shape = shapes.NONE; |
|
|
|
|
|
if (board[x + offsetX + 1][y + offsetY + 1] === 0 |
|
&& board[x - offsetX + 1][y - offsetY + 1] === 0 |
|
&& board[x + 2 * offsetX + 1][y + 2 * offsetY + 1] === 0 |
|
&& board[x - 2 * offsetX + 1][y - 2 * offsetY + 1] === 0 |
|
) { |
|
return [shapes.NONE, selfCount, opponentCount, emptyCount]; |
|
} |
|
|
|
|
|
|
|
for (let i = -3; i <= 3; i++) { |
|
if (i === 0) continue; |
|
const [nx, ny] = [x + i * offsetX + 1, y + i * offsetY + 1]; |
|
if (board[nx] === undefined || board[nx][ny] === undefined) continue; |
|
const currentRole = board[nx][ny]; |
|
if (currentRole === 2) { |
|
opponentCount++; |
|
} else if (currentRole === role) { |
|
selfCount++; |
|
} else if (currentRole === 0) { |
|
emptyCount++; |
|
} |
|
} |
|
if (selfCount === 2) { |
|
if (!opponentCount) { |
|
return [shapes.TWO, selfCount, opponentCount, emptyCount]; |
|
} else { |
|
return [shapes.NONE, selfCount, opponentCount, emptyCount]; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
emptyCount = 0; |
|
selfCount = 1; |
|
opponentCount = 0; |
|
let resultString = '1'; |
|
|
|
for (let i = 1; i <= 5; i++) { |
|
const [nx, ny] = [x + i * offsetX + 1, y + i * offsetY + 1]; |
|
const currentRole = board[nx][ny]; |
|
if (currentRole === 2) resultString += '2'; |
|
else if (currentRole === 0) resultString += '0'; |
|
else resultString += currentRole === role ? '1' : '2'; |
|
if (currentRole === 2 || currentRole === opponent) { |
|
opponentCount++; |
|
break; |
|
} |
|
if (currentRole === 0) { |
|
emptyCount++; |
|
} |
|
if (currentRole === role) { |
|
selfCount++; |
|
} |
|
} |
|
for (let i = 1; i <= 5; i++) { |
|
const [nx, ny] = [x - i * offsetX + 1, y - i * offsetY + 1]; |
|
const currentRole = board[nx][ny]; |
|
if (currentRole === 2) resultString = '2' + resultString; |
|
else if (currentRole === 0) resultString = '0' + resultString; |
|
else resultString = (currentRole === role ? '1' : '2') + resultString; |
|
if (currentRole === 2 || currentRole === opponent) { |
|
opponentCount++; |
|
break; |
|
} |
|
if (currentRole === 0) { |
|
emptyCount++; |
|
} |
|
if (currentRole === role) { |
|
selfCount++; |
|
} |
|
} |
|
if (patterns.five.test(resultString)) { |
|
shape = shapes.FIVE; |
|
performance.five++; |
|
performance.total++; |
|
} else if (patterns.four.test(resultString)) { |
|
shape = shapes.FOUR; |
|
performance.four++; |
|
performance.total++; |
|
} else if (patterns.blockFour.test(resultString)) { |
|
shape = shapes.BLOCK_FOUR; |
|
performance.blockFour++; |
|
performance.total++; |
|
} else if (patterns.three.test(resultString)) { |
|
shape = shapes.THREE; |
|
performance.three++; |
|
performance.total++; |
|
} else if (patterns.blockThree.test(resultString)) { |
|
shape = shapes.BLOCK_THREE; |
|
performance.blockThree++; |
|
performance.total++; |
|
} else if (patterns.two.test(resultString)) { |
|
shape = shapes.TWO; |
|
performance.two++; |
|
performance.total++; |
|
} |
|
|
|
if (selfCount <= 1 || resultString.length < 5) return [shape, selfCount, opponentCount, emptyCount]; |
|
|
|
return [shape, selfCount, opponentCount, emptyCount]; |
|
} |
|
|
|
const countShape = (board, x, y, offsetX, offsetY, role) => { |
|
const opponent = -role; |
|
|
|
let innerEmptyCount = 0; |
|
let tempEmptyCount = 0; |
|
let selfCount = 0; |
|
let totalLength = 0; |
|
|
|
let sideEmptyCount = 0; |
|
let noEmptySelfCount = 0, OneEmptySelfCount = 0; |
|
|
|
|
|
for (let i = 1; i <= 5; i++) { |
|
const [nx, ny] = [x + i * offsetX + 1, y + i * offsetY + 1]; |
|
const currentRole = board[nx][ny]; |
|
if (currentRole === 2 || currentRole === opponent) { |
|
break; |
|
} |
|
if (currentRole === role) { |
|
selfCount++; |
|
sideEmptyCount = 0; |
|
if (tempEmptyCount) { |
|
innerEmptyCount += tempEmptyCount; |
|
tempEmptyCount = 0; |
|
} |
|
if (innerEmptyCount === 0) { |
|
noEmptySelfCount++; |
|
OneEmptySelfCount++; |
|
} else if (innerEmptyCount === 1) { |
|
OneEmptySelfCount++; |
|
} |
|
} |
|
totalLength++; |
|
if (currentRole === 0) { |
|
tempEmptyCount++; |
|
sideEmptyCount++; |
|
} |
|
if (sideEmptyCount >= 2) { |
|
break; |
|
} |
|
} |
|
if (!innerEmptyCount) OneEmptySelfCount = 0; |
|
return { selfCount, totalLength, noEmptySelfCount, OneEmptySelfCount, innerEmptyCount, sideEmptyCount }; |
|
} |
|
|
|
|
|
export const getShapeFast = (board, x, y, offsetX, offsetY, role) => { |
|
|
|
if (board[x + offsetX + 1][y + offsetY + 1] === 0 |
|
&& board[x - offsetX + 1][y - offsetY + 1] === 0 |
|
&& board[x + 2 * offsetX + 1][y + 2 * offsetY + 1] === 0 |
|
&& board[x - 2 * offsetX + 1][y - 2 * offsetY + 1] === 0 |
|
) { |
|
return [shapes.NONE, 1]; |
|
} |
|
|
|
let selfCount = 1; |
|
let totalLength = 1; |
|
let shape = shapes.NONE; |
|
|
|
let leftEmpty = 0, rightEmpty = 0; |
|
let noEmptySelfCount = 1, OneEmptySelfCount = 1; |
|
|
|
const left = countShape(board, x, y, -offsetX, -offsetY, role); |
|
const right = countShape(board, x, y, offsetX, offsetY, role); |
|
|
|
selfCount = left.selfCount + right.selfCount + 1; |
|
totalLength = left.totalLength + right.totalLength + 1; |
|
noEmptySelfCount = left.noEmptySelfCount + right.noEmptySelfCount + 1; |
|
OneEmptySelfCount = Math.max(left.OneEmptySelfCount + right.noEmptySelfCount, left.noEmptySelfCount + right.OneEmptySelfCount) + 1; |
|
rightEmpty = right.sideEmptyCount; |
|
leftEmpty = left.sideEmptyCount; |
|
|
|
if (totalLength < 5) return [shape, selfCount]; |
|
|
|
if (noEmptySelfCount >= 5) { |
|
if (rightEmpty > 0 && leftEmpty > 0) { |
|
return [shapes.FIVE, selfCount]; |
|
} else { |
|
return [shapes.BLOCK_FIVE, selfCount]; |
|
} |
|
} |
|
if (noEmptySelfCount === 4) { |
|
|
|
if ((rightEmpty >= 1 || right.OneEmptySelfCount > right.noEmptySelfCount) && (leftEmpty >= 1 || left.OneEmptySelfCount > left.noEmptySelfCount)) { |
|
return [shapes.FOUR, selfCount]; |
|
} else if (!(rightEmpty === 0 && leftEmpty === 0)) { |
|
return [shapes.BLOCK_FOUR, selfCount]; |
|
} |
|
} |
|
if (OneEmptySelfCount === 4) { |
|
return [shapes.BLOCK_FOUR, selfCount]; |
|
} |
|
|
|
if (noEmptySelfCount === 3) { |
|
if ((rightEmpty >= 2 && leftEmpty >= 1) || (rightEmpty >= 1 && leftEmpty >= 2)) { |
|
return [shapes.THREE, selfCount]; |
|
} else { |
|
return [shapes.BLOCK_THREE, selfCount]; |
|
} |
|
} |
|
if (OneEmptySelfCount === 3) { |
|
if ((rightEmpty >= 1 && leftEmpty >= 1)) { |
|
return [shapes.THREE, selfCount]; |
|
} else { |
|
return [shapes.BLOCK_THREE, selfCount]; |
|
} |
|
} |
|
if ((noEmptySelfCount === 2 || OneEmptySelfCount === 2) && totalLength > 5) { |
|
shape = shapes.TWO; |
|
} |
|
|
|
return [shape, selfCount]; |
|
} |
|
|
|
export const isFive = (shape) => { |
|
return shape === shapes.FIVE || shape === shapes.BLOCK_FIVE; |
|
}; |
|
|
|
export const isFour = (shape) => { |
|
return shape === shapes.FOUR || shape === shapes.BLOCK_FOUR; |
|
}; |
|
|
|
export const getAllShapesOfPoint = (shapeCache, x, y, role) => { |
|
const roles = role ? [role] : [1, -1]; |
|
const result = []; |
|
for (const r of roles) { |
|
for (const d of [0, 1, 2, 3]) { |
|
const shape = shapeCache[r][d][x][y]; |
|
if (shape > 0) { |
|
result.push(shape); |
|
} |
|
} |
|
} |
|
return result; |
|
} |