aboutsummaryrefslogtreecommitdiff
path: root/Sources/SwiftChessNeo/Tables.swift
blob: afad90d08d51a1308b315e226708373bd87312a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//
//  Tables.swift
//  Sage
//
//  Copyright 2016-2017 Nikolai Vazquez
//  Modified by SuperGeroy
//
//  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.
//

/// Returns the pawn attack table for `color`.
internal func _pawnAttackTable(for color: Color) -> [Bitboard] {
    if color.isWhite {
        return _whitePawnAttackTable
    } else {
        return _blackPawnAttackTable
    }
}

/// A lookup table of all white pawn attack bitboards.
internal let _whitePawnAttackTable = Square.all.map { square in
    return Bitboard(square: square)._pawnAttacks(for: ._white)
}

/// A lookup table of all black pawn attack bitboards.
internal let _blackPawnAttackTable = Square.all.map { square in
    return Bitboard(square: square)._pawnAttacks(for: ._black)
}

/// A lookup table of all king attack bitboards.
internal let _kingAttackTable = Square.all.map { square in
    return Bitboard(square: square)._kingAttacks()
}

/// A lookup table of all knight attack bitboards.
internal let _knightAttackTable = Square.all.map { square in
    return Bitboard(square: square)._knightAttacks()
}

/// Returns the squares between `start` and `end`.
private func _between(_ start: Square, _ end: Square) -> Bitboard {
    let start = UInt64(start.hashValue)
    let end = UInt64(end.hashValue)
    let max = UInt64.max
    let a2a7: UInt64 = 0x0001010101010100
    let b2g7: UInt64 = 0x0040201008040200
    let h1b7: UInt64 = 0x0002040810204080

    let between = (max << start) ^ (max << end)
    let file = (end & 7) &- (start & 7)
    let rank = ((end | 7) &- start) >> 3

    var line = ((file & 7) &- 1) & a2a7
    line += 2 &* (((rank & 7) &- 1) >> 58)
    line += (((rank &- file) & 15) &- 1) & b2g7
    line += (((rank &+ file) & 15) &- 1) & h1b7
    line = line &* (between & (0 &- between))

    return Bitboard(rawValue: line & between)
}

/// Returns the triangle index for `start` and `end`.
internal func _triangleIndex(_ start: Square, _ end: Square) -> Int {
    var a = start.hashValue
    var b = end.hashValue
    var d = a &- b
    d &= d >> 31
    b = b &+ d
    a = a &- d
    b = b &* (b ^ 127)
    return (b >> 1) + a
}

/// A lookup table of squares between two squares.
internal let _betweenTable: [Bitboard] = {
    var table = [Bitboard](repeating: 0, count: 2080)
    for start in Square.all {
        for end in Square.all {
            let index = _triangleIndex(start, end)
            table[index] = _between(start, end)
        }
    }
    return table
}()

/// A lookup table of lines for two squares.
internal let _lineTable: [Bitboard] = {
    var table = [Bitboard](repeating: 0, count: 2080)
    for start in Square.all {
        for end in Square.all {
            let startBB = Bitboard(square: start)
            let endBB = Bitboard(square: end)
            let index = _triangleIndex(start, end)
            let rookAttacks = startBB._rookAttacks()
            let bishopAttacks = startBB._bishopAttacks()
            if rookAttacks[end] {
                table[index] = startBB | endBB | (rookAttacks & endBB._rookAttacks())
            } else if bishopAttacks[end] {
                table[index] = startBB | endBB | (bishopAttacks & endBB._bishopAttacks())
            }
        }
    }
    return table
}()