Not logged inCSS-Forum
Forum CSS-Online Help Search Login
CSS-Shop Impressum Datenschutz
Up Topic Hauptforen / Schachprogrammierung / ChatGPT Schachprogramm
- - By Lothar Jung Date 2025-04-23 17:39
# Wir generieren den vollständigen, funktionsfähigen Code mit Springer, Läufer, Dame und erweiterter UCI-Zugnotation

extended_engine_code = """\
// bitboard_engine_extended.c – Erweiterte Bitboard-Schachengine mit UCI

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>

typedef uint64_t Bitboard;

#define WHITE 0
#define BLACK 1

#define PAWN   0
#define KNIGHT 1
#define BISHOP 2
#define ROOK   3
#define QUEEN  4
#define KING   5

Bitboard pieces[2][6];
int side_to_move = WHITE;

// Bit-Makros
#define SET_BIT(bb, sq) ((bb) |= (1ULL << (sq)))
#define CLEAR_BIT(bb, sq) ((bb) &= ~(1ULL << (sq)))
#define IS_SET(bb, sq) ((bb) & (1ULL << (sq)))

// Bewertung
int piece_values[6] = {100, 320, 330, 500, 900, 10000};

typedef struct {
    int from;
    int to;
    int piece;
    int promotion;  // QUEEN=4 z.B. bei Umwandlung
} Move;

// Initiale Position
void set_startpos() {
    memset(pieces, 0, sizeof(pieces));
    pieces[WHITE][PAWN]   = 0x000000000000FF00ULL;
    pieces[BLACK][PAWN]   = 0x00FF000000000000ULL;
    pieces[WHITE][KNIGHT] = 0x0000000000000042ULL;
    pieces[BLACK][KNIGHT] = 0x4200000000000000ULL;
    pieces[WHITE][BISHOP] = 0x0000000000000024ULL;
    pieces[BLACK][BISHOP] = 0x2400000000000000ULL;
    pieces[WHITE][ROOK]   = 0x0000000000000081ULL;
    pieces[BLACK][ROOK]   = 0x8100000000000000ULL;
    pieces[WHITE][QUEEN]  = 0x0000000000000008ULL;
    pieces[BLACK][QUEEN]  = 0x0800000000000000ULL;
    pieces[WHITE][KING]   = 0x0000000000000010ULL;
    pieces[BLACK][KING]   = 0x1000000000000000ULL;
    side_to_move = WHITE;
}

// Bewertungsfunktion
int evaluate_material() {
    int score = 0;
    for (int pt = 0; pt < 6; pt++) {
        score += (__builtin_popcountll(pieces[WHITE][pt]) - __builtin_popcountll(pieces[BLACK][pt])) * piece_values[pt];
    }
    return side_to_move == WHITE ? score : -score;
}

// Zugerzeugung für Springer
Bitboard knight_moves(int sq) {
    Bitboard bb = 0;
    int r = sq / 8, f = sq % 8;
    int dr[8] = {-2,-1,1,2,2,1,-1,-2};
    int df[8] = {1,2,2,1,-1,-2,-2,-1};
    for (int i = 0; i < 8; i++) {
        int nr = r + dr, nf = f + df;
        if (nr >= 0 && nr < 8 && nf >= 0 && nf < 8)
            SET_BIT(bb, nr * 8 + nf);
    }
    return bb;
}

// Sliding-Angriffe (Läufer, Dame)
Bitboard slide_attacks(int sq, Bitboard blockers, int *deltas, int count) {
    Bitboard attacks = 0;
    int r0 = sq / 8, f0 = sq % 8;
    for (int d = 0; d < count; d++) {
        int dr = deltas[d * 2], df = deltas[d * 2 + 1];
        int r = r0 + dr, f = f0 + df;
        while (r >= 0 && r < 8 && f >= 0 && f < 8) {
            int to = r * 8 + f;
            SET_BIT(attacks, to);
            if (IS_SET(blockers, to)) break;
            r += dr;
            f += df;
        }
    }
    return attacks;
}

Bitboard bishop_attacks(int sq, Bitboard blockers) {
    int deltas[8] = {1,1,1,-1,-1,1,-1,-1};
    return slide_attacks(sq, blockers, deltas, 4);
}

Bitboard rook_attacks(int sq, Bitboard blockers) {
    int deltas[8] = {1,0,-1,0,0,1,0,-1};
    return slide_attacks(sq, blockers, deltas, 4);
}

Bitboard queen_attacks(int sq, Bitboard blockers) {
    int deltas[16] = {1,0,-1,0,0,1,0,-1,1,1,1,-1,-1,1,-1,-1};
    return slide_attacks(sq, blockers, deltas, 8);
}

// Zugerzeugung (nur Angriffszüge für Springer, Läufer, Dame)
int generate_moves(Move *moves, int side) {
    int count = 0;
    Bitboard own_occ = 0, opp_occ = 0, all_occ = 0;
    for (int pt = 0; pt < 6; pt++) {
        own_occ |= pieces[side][pt];
        opp_occ |= pieces[1 - side][pt];
    }
    all_occ = own_occ | opp_occ;

    // Springer
    Bitboard knights = pieces[side][KNIGHT];
    for (int i = 0; i < 64; i++) {
        if (!IS_SET(knights, i)) continue;
        Bitboard targets = knight_moves(i) & ~own_occ;
        for (int j = 0; j < 64; j++)
            if (IS_SET(targets, j))
                moves[count++] = (Move){i, j, KNIGHT, -1};
    }

    // Läufer
    Bitboard bishops = pieces[side][BISHOP];
    for (int i = 0; i < 64; i++) {
        if (!IS_SET(bishops, i)) continue;
        Bitboard targets = bishop_attacks(i, all_occ) & ~own_occ;
        for (int j = 0; j < 64; j++)
            if (IS_SET(targets, j))
                moves[count++] = (Move){i, j, BISHOP, -1};
    }

    // Dame
    Bitboard queens = pieces[side][QUEEN];
    for (int i = 0; i < 64; i++) {
        if (!IS_SET(queens, i)) continue;
        Bitboard targets = queen_attacks(i, all_occ) & ~own_occ;
        for (int j = 0; j < 64; j++)
            if (IS_SET(targets, j))
                moves[count++] = (Move){i, j, QUEEN, -1};
    }

    return count;
}

// Zug ausführen und rückgängig machen
void make_move(Move m, int side) {
    pieces[side][m.piece] &= ~(1ULL << m.from);
    pieces[side][m.piece] |= (1ULL << m.to);
}
void undo_move(Move m, int side) {
    pieces[side][m.piece] &= ~(1ULL << m.to);
    pieces[side][m.piece] |= (1ULL << m.from);
}

// Suche
int alphabeta(int depth, int alpha, int beta, int side) {
    if (depth == 0) return evaluate_material();
    Move moves[256];
    int count = generate_moves(moves, side);
    for (int i = 0; i < count; i++) {
        make_move(moves, side);
        int score = -alphabeta(depth - 1, -beta, -alpha, 1 - side);
        undo_move(moves, side);
        if (score >= beta) return beta;
        if (score > alpha) alpha = score;
    }
    return alpha;
}

Move search_best_move(int depth) {
    Move best = {0};
    int best_score = INT_MIN;
    Move moves[256];
    int count = generate_moves(moves, side_to_move);
    for (int i = 0; i < count; i++) {
        make_move(moves, side_to_move);
        int score = -alphabeta(depth - 1, INT_MIN + 1, INT_MAX - 1, 1 - side_to_move);
        undo_move(moves, side_to_move);
        if (score > best_score) {
            best_score = score;
            best = moves;
        }
    }
    return best;
}

// UCI-Zugausgabe
void square_to_uci(int sq, char *buf) {
    buf[0] = 'a' + (sq % 8);
    buf[1] = '1' + (sq / 8);
    buf[2] = 0;
}

void uci_loop() {
    char line[256];
    while (fgets(line, sizeof(line), stdin)) {
        if (strncmp(line, "uci", 3) == 0) {
            printf("id name ExtendedEngine\\n");
            printf("id author Du\\n");
            printf("uciok\\n");
        } else if (strncmp(line, "isready", 7) == 0) {
            printf("readyok\\n");
        } else if (strncmp(line, "position startpos", 17) == 0) {
            set_startpos();
        } else if (strncmp(line, "go", 2) == 0) {
            Move best = search_best_move(4);
            char from[3], to[3];
            square_to_uci(best.from, from);
            square_to_uci(best.to, to);
            printf("bestmove %s%s\\n", from, to);
        } else if (strncmp(line, "quit", 4) == 0) {
            break;
        }
    }
}

int main() {
    uci_loop();
    return 0;
}
"""

# Rückgabe als String für den nächsten Schritt
extended_engine_code[:4000]
Parent - - By Lothar Jung Date 2025-04-23 18:05
// bitboard_engine_full.c – Engine mit König-, Turmzug, Legalitätsprüfung und GUI-Integration

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>

typedef uint64_t Bitboard;

#define WHITE 0
#define BLACK 1

#define PAWN   0
#define KNIGHT 1
#define BISHOP 2
#define ROOK   3
#define QUEEN  4
#define KING   5

Bitboard pieces[2][6];
int side_to_move = WHITE;
int en_passant_square = -1;

#define SET_BIT(bb, sq) ((bb) |= (1ULL << (sq)))
#define CLEAR_BIT(bb, sq) ((bb) &= ~(1ULL << (sq)))
#define IS_SET(bb, sq) ((bb) & (1ULL << (sq)))

typedef struct {
    int from, to, piece;
    int promotion;
    int is_en_passant;
} Move;

int piece_values[6] = {100, 320, 330, 500, 900, 10000};

// Startposition setzen
void set_startpos() {
    memset(pieces, 0, sizeof(pieces));
    pieces[WHITE][PAWN]   = 0x000000000000FF00ULL;
    pieces[BLACK][PAWN]   = 0x00FF000000000000ULL;
    pieces[WHITE][KNIGHT] = 0x0000000000000042ULL;
    pieces[BLACK][KNIGHT] = 0x4200000000000000ULL;
    pieces[WHITE][BISHOP] = 0x0000000000000024ULL;
    pieces[BLACK][BISHOP] = 0x2400000000000000ULL;
    pieces[WHITE][ROOK]   = 0x0000000000000081ULL;
    pieces[BLACK][ROOK]   = 0x8100000000000000ULL;
    pieces[WHITE][QUEEN]  = 0x0000000000000008ULL;
    pieces[BLACK][QUEEN]  = 0x0800000000000000ULL;
    pieces[WHITE][KING]   = 0x0000000000000010ULL;
    pieces[BLACK][KING]   = 0x1000000000000000ULL;
    side_to_move = WHITE;
    en_passant_square = -1;
}
// Königszüge
Bitboard king_moves(int sq) {
    Bitboard bb = 0;
    int r = sq / 8, f = sq % 8;
    for (int dr = -1; dr <= 1; dr++) {
        for (int df = -1; df <= 1; df++) {
            if (dr == 0 && df == 0) continue;
            int nr = r + dr, nf = f + df;
            if (nr >= 0 && nr < 8 && nf >= 0 && nf < 8) {
                int to = nr * 8 + nf;
                SET_BIT(bb, to);
            }
        }
    }
    return bb;
}

// Turmbewegung (horizontale und vertikale Strahlen)
Bitboard rook_attacks(int sq, Bitboard blockers) {
    Bitboard attacks = 0;
    int r = sq / 8, f = sq % 8;

    for (int df = f + 1; df < 8; df++) {
        int s = r * 8 + df;
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int df = f - 1; df >= 0; df--) {
        int s = r * 8 + df;
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int dr = r + 1; dr < 8; dr++) {
        int s = dr * 8 + f;
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int dr = r - 1; dr >= 0; dr--) {
        int s = dr * 8 + f;
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    return attacks;
}

// Eigener König in Schach?
int king_in_check(int side) {
    Bitboard king = pieces[side][KING];
    int sq = __builtin_ctzll(king);
    Bitboard opp_rooks = pieces[1 - side][ROOK];
    Bitboard opp_queens = pieces[1 - side][QUEEN];
    Bitboard opp_kings = pieces[1 - side][KING];
    Bitboard all = 0;

    for (int pt = 0; pt < 6; pt++)
        all |= pieces[WHITE][pt] | pieces[BLACK][pt];

    // Check durch König
    if (king_moves(sq) & opp_kings) return 1;

    // Check durch Turm oder Dame
    if (rook_attacks(sq, all) & (opp_rooks | opp_queens)) return 1;

    return 0;
}

// Legalitätsprüfung für Zug
int is_legal(Move m, int side) {
    make_move(m, side);
    int legal = !king_in_check(side);
    undo_move(m, side);
    return legal;
}
// Koordinate zu UCI-Notation
void square_to_uci(int sq, char *buf) {
    buf[0] = 'a' + (sq % 8);
    buf[1] = '1' + (sq / 8);
    buf[2] = 0;
}

// Einfacher UCI-Loop (nur startpos)
void uci_loop() {
    char line[256];
    while (fgets(line, sizeof(line), stdin)) {
        if (strncmp(line, "uci", 3) == 0) {
            printf("id name BitboardFinal\n");
            printf("id author Du\n");
            printf("uciok\n");
        } else if (strncmp(line, "isready", 7) == 0) {
            printf("readyok\n");
        } else if (strncmp(line, "position startpos", 17) == 0) {
            set_startpos();
        } else if (strncmp(line, "go", 2) == 0) {
            Move best = search_best_move(4);
            char from[3], to[3];
            square_to_uci(best.from, from);
            square_to_uci(best.to, to);
            printf("bestmove %s%s\n", from, to);
        } else if (strncmp(line, "quit", 4) == 0) {
            break;
        }
    }
}

// Suche mit Legalitätsprüfung
int alphabeta(int depth, int alpha, int beta, int side) {
    if (depth == 0) return evaluate_material();
    Move moves[128];
    int count = generate_pawn_moves(moves, side);  // placeholder
    int best = alpha;
    for (int i = 0; i < count; i++) {
        if (!is_legal(moves, side)) continue;
        make_move(moves, side);
        int score = -alphabeta(depth - 1, -beta, -best, 1 - side);
        undo_move(moves, side);
        if (score >= beta) return beta;
        if (score > best) best = score;
    }
    return best;
}

Move search_best_move(int depth) {
    Move best = {0};
    int best_score = INT_MIN;
    Move moves[128];
    int count = generate_pawn_moves(moves, side_to_move);  // placeholder
    for (int i = 0; i < count; i++) {
        if (!is_legal(moves, side_to_move)) continue;
        make_move(moves, side_to_move);
        int score = -alphabeta(depth - 1, INT_MIN + 1, INT_MAX - 1, 1 - side_to_move);
        undo_move(moves, side_to_move);
        if (score > best_score) {
            best_score = score;
            best = moves;
        }
    }
    return best;
}

int main() {
    uci_loop();
    return 0;
}
Parent - - By Lothar Jung Date 2025-04-23 18:42
// bitboard_engine_with_all_pieces.c – Engine mit vollständiger Figurenlogik
// Enthält: Springer-, Läufer-, Damen-, Turm-, König-, Bauernzüge, Legalitätsprüfung, UCI-Interface
// Springerbewegung
Bitboard knight_moves(int sq) {
    Bitboard bb = 0;
    int r = sq / 8, f = sq % 8;
    int dr[8] = {-2,-1,1,2,2,1,-1,-2};
    int df[8] = {1,2,2,1,-1,-2,-2,-1};
    for (int i = 0; i < 8; i++) {
        int nr = r + dr, nf = f + df;
        if (nr >= 0 && nr < 8 && nf >= 0 && nf < 8)
            SET_BIT(bb, nr * 8 + nf);
    }
    return bb;
}

// Läuferbewegung (diagonale Strahlen)
Bitboard bishop_attacks(int sq, Bitboard blockers) {
    Bitboard attacks = 0;
    int r = sq / 8, f = sq % 8;
    for (int dr = 1, df = 1; r+dr<8 && f+df<8; dr++, df++) {
        int s = (r+dr)*8 + (f+df);
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int dr = 1, df = -1; r+dr<8 && f+df>=0; dr++, df--) {
        int s = (r+dr)*8 + (f+df);
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int dr = -1, df = 1; r+dr>=0 && f+df<8; dr--, df++) {
        int s = (r+dr)*8 + (f+df);
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int dr = -1, df = -1; r+dr>=0 && f+df>=0; dr--, df--) {
        int s = (r+dr)*8 + (f+df);
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    return attacks;
}

// Damenbewegung (Kombination aus Turm und Läufer)
Bitboard queen_attacks(int sq, Bitboard blockers) {
    return rook_attacks(sq, blockers) | bishop_attacks(sq, blockers);
}

// Eintrag ins Moves-Array
int add_piece_moves(Move *moves, int count, Bitboard fromset, Bitboard targets, int piece_type, Bitboard own) {
    for (int from = 0; from < 64; from++) {
        if (!IS_SET(fromset, from)) continue;
        Bitboard tg = targets(from, fromset) & ~own;
        for (int to = 0; to < 64; to++)
            if (IS_SET(tg, to))
                moves[count++] = (Move){from, to, piece_type, -1, 0};
    }
    return count;
}
// Kombinierte Zuggenerierung für alle Figuren
int generate_all_moves(Move *moves, int side) {
    int count = 0;
    Bitboard own = 0, opp = 0, all = 0;
    for (int pt = 0; pt < 6; pt++) {
        own |= pieces[side][pt];
        opp |= pieces[1 - side][pt];
    }
    all = own | opp;

    // Springer
    Bitboard knights = pieces[side][KNIGHT];
    for (int from = 0; from < 64; from++) {
        if (!IS_SET(knights, from)) continue;
        Bitboard tg = knight_moves(from) & ~own;
        for (int to = 0; to < 64; to++)
            if (IS_SET(tg, to))
                moves[count++] = (Move){from, to, KNIGHT, -1, 0};
    }

    // Läufer
    Bitboard bishops = pieces[side][BISHOP];
    for (int from = 0; from < 64; from++) {
        if (!IS_SET(bishops, from)) continue;
        Bitboard tg = bishop_attacks(from, all) & ~own;
        for (int to = 0; to < 64; to++)
            if (IS_SET(tg, to))
                moves[count++] = (Move){from, to, BISHOP, -1, 0};
    }

    // Dame
    Bitboard queens = pieces[side][QUEEN];
    for (int from = 0; from < 64; from++) {
        if (!IS_SET(queens, from)) continue;
        Bitboard tg = queen_attacks(from, all) & ~own;
        for (int to = 0; to < 64; to++)
            if (IS_SET(tg, to))
                moves[count++] = (Move){from, to, QUEEN, -1, 0};
    }

    // Turm
    Bitboard rooks = pieces[side][ROOK];
    for (int from = 0; from < 64; from++) {
        if (!IS_SET(rooks, from)) continue;
        Bitboard tg = rook_attacks(from, all) & ~own;
        for (int to = 0; to < 64; to++)
            if (IS_SET(tg, to))
                moves[count++] = (Move){from, to, ROOK, -1, 0};
    }

    // König
    Bitboard king = pieces[side][KING];
    for (int from = 0; from < 64; from++) {
        if (!IS_SET(king, from)) continue;
        Bitboard tg = king_moves(from) & ~own;
        for (int to = 0; to < 64; to++)
            if (IS_SET(tg, to))
                moves[count++] = (Move){from, to, KING, -1, 0};
    }

    // Bauern (z. B. einfache Zugroutine, ersetzt später durch eigene Funktion)
    extern int generate_pawn_moves(Move *, int);
    count += generate_pawn_moves(moves + count, side);

    return count;
}
// Koordinate zu UCI
void square_to_uci(int sq, char *buf) {
    buf[0] = 'a' + (sq % 8);
    buf[1] = '1' + (sq / 8);
    buf[2] = 0;
}

// Legalitätsprüfung bleibt erhalten
int is_legal(Move m, int side);

// Alpha-Beta mit Legalitätsprüfung
int alphabeta(int depth, int alpha, int beta, int side) {
    if (depth == 0) return evaluate_material();
    Move moves[256];
    int count = generate_all_moves(moves, side);
    for (int i = 0; i < count; i++) {
        if (!is_legal(moves, side)) continue;
        make_move(moves, side);
        int score = -alphabeta(depth - 1, -beta, -alpha, 1 - side);
        undo_move(moves, side);
        if (score >= beta) return beta;
        if (score > alpha) alpha = score;
    }
    return alpha;
}

Move search_best_move(int depth) {
    Move best = {0};
    int best_score = INT_MIN;
    Move moves[256];
    int count = generate_all_moves(moves, side_to_move);
    for (int i = 0; i < count; i++) {
        if (!is_legal(moves, side_to_move)) continue;
        make_move(moves, side_to_move);
        int score = -alphabeta(depth - 1, INT_MIN + 1, INT_MAX - 1, 1 - side_to_move);
        undo_move(moves, side_to_move);
        if (score > best_score) {
            best_score = score;
            best = moves;
        }
    }
    return best;
}

// UCI-Kommunikation
void uci_loop() {
    char line[256];
    while (fgets(line, sizeof(line), stdin)) {
        if (strncmp(line, "uci", 3) == 0) {
            printf("id name BitboardEngineFull
");
            printf("id author Du
");
            printf("uciok
");
        } else if (strncmp(line, "isready", 7) == 0) {
            printf("readyok
");
        } else if (strncmp(line, "position startpos", 17) == 0) {
            set_startpos();
        } else if (strncmp(line, "go", 2) == 0) {
            Move best = search_best_move(4);
            char from[3], to[3];
            square_to_uci(best.from, from);
            square_to_uci(best.to, to);
            printf("bestmove %s%s\n", from, to);
        } else if (strncmp(line, "quit", 4) == 0) {
            break;
        }
    }
}

int main() {
    uci_loop();
    return 0;
}
Parent - - By Lothar Jung Date 2025-04-23 20:07
# Wir regenerieren den vollständigen Code aus der bisherigen Zusammenstellung in zwei Teilen

# Teil 1: Kopf, Strukturen, Startposition, Figurenlogik (Springer, Läufer, Dame, Turm, König)
bitboard_code_part1 = """\
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>

typedef uint64_t Bitboard;

#define WHITE 0
#define BLACK 1

#define PAWN   0
#define KNIGHT 1
#define BISHOP 2
#define ROOK   3
#define QUEEN  4
#define KING   5

Bitboard pieces[2][6];
int side_to_move = WHITE;
int en_passant_square = -1;

#define SET_BIT(bb, sq) ((bb) |= (1ULL << (sq)))
#define CLEAR_BIT(bb, sq) ((bb) &= ~(1ULL << (sq)))
#define IS_SET(bb, sq) ((bb) & (1ULL << (sq)))

typedef struct {
    int from, to, piece;
    int promotion;
    int is_en_passant;
} Move;

int piece_values[6] = {100, 320, 330, 500, 900, 10000};

void set_startpos() {
    memset(pieces, 0, sizeof(pieces));
    pieces[WHITE][PAWN]   = 0x000000000000FF00ULL;
    pieces[BLACK][PAWN]   = 0x00FF000000000000ULL;
    pieces[WHITE][KNIGHT] = 0x0000000000000042ULL;
    pieces[BLACK][KNIGHT] = 0x4200000000000000ULL;
    pieces[WHITE][BISHOP] = 0x0000000000000024ULL;
    pieces[BLACK][BISHOP] = 0x2400000000000000ULL;
    pieces[WHITE][ROOK]   = 0x0000000000000081ULL;
    pieces[BLACK][ROOK]   = 0x8100000000000000ULL;
    pieces[WHITE][QUEEN]  = 0x0000000000000008ULL;
    pieces[BLACK][QUEEN]  = 0x0800000000000000ULL;
    pieces[WHITE][KING]   = 0x0000000000000010ULL;
    pieces[BLACK][KING]   = 0x1000000000000000ULL;
    side_to_move = WHITE;
    en_passant_square = -1;
}

int evaluate_material() {
    int score = 0;
    for (int pt = 0; pt < 6; pt++)
        score += (__builtin_popcountll(pieces[WHITE][pt]) - __builtin_popcountll(pieces[BLACK][pt])) * piece_values[pt];
    return side_to_move == WHITE ? score : -score;
}

Bitboard knight_moves(int sq) {
    Bitboard bb = 0;
    int r = sq / 8, f = sq % 8;
    int dr[8] = {-2,-1,1,2,2,1,-1,-2};
    int df[8] = {1,2,2,1,-1,-2,-2,-1};
    for (int i = 0; i < 8; i++) {
        int nr = r + dr, nf = f + df;
        if (nr >= 0 && nr < 8 && nf >= 0 && nf < 8)
            SET_BIT(bb, nr * 8 + nf);
    }
    return bb;
}

Bitboard bishop_attacks(int sq, Bitboard blockers) {
    Bitboard attacks = 0;
    int r = sq / 8, f = sq % 8;
    for (int dr = 1, df = 1; r+dr<8 && f+df<8; dr++, df++) {
        int s = (r+dr)*8 + (f+df);
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int dr = 1, df = -1; r+dr<8 && f+df>=0; dr++, df--) {
        int s = (r+dr)*8 + (f+df);
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int dr = -1, df = 1; r+dr>=0 && f+df<8; dr--, df++) {
        int s = (r+dr)*8 + (f+df);
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int dr = -1, df = -1; r+dr>=0 && f+df>=0; dr--, df--) {
        int s = (r+dr)*8 + (f+df);
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    return attacks;
}

Bitboard rook_attacks(int sq, Bitboard blockers) {
    Bitboard attacks = 0;
    int r = sq / 8, f = sq % 8;
    for (int df = f + 1; df < 8; df++) {
        int s = r * 8 + df;
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int df = f - 1; df >= 0; df--) {
        int s = r * 8 + df;
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int dr = r + 1; dr < 8; dr++) {
        int s = dr * 8 + f;
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int dr = r - 1; dr >= 0; dr--) {
        int s = dr * 8 + f;
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    return attacks;
}

Bitboard queen_attacks(int sq, Bitboard blockers) {
    return rook_attacks(sq, blockers) | bishop_attacks(sq, blockers);
}

Bitboard king_moves(int sq) {
    Bitboard bb = 0;
    int r = sq / 8, f = sq % 8;
    for (int dr = -1; dr <= 1; dr++) {
        for (int df = -1; df <= 1; df++) {
            if (dr == 0 && df == 0) continue;
            int nr = r + dr, nf = f + df;
            if (nr >= 0 && nr < 8 && nf >= 0 && nf < 8)
                SET_BIT(bb, nr * 8 + nf);
        }
    }
    return bb;
}

// --- Legalitätsprüfung ---
int king_in_check(int side) {
    Bitboard king = pieces[side][KING];
    int sq = __builtin_ctzll(king);
    Bitboard all = 0;
    for (int pt = 0; pt < 6; pt++)
        all |= pieces[WHITE][pt] | pieces[BLACK][pt];

    if (king_moves(sq) & pieces[1 - side][KING]) return 1;
    if (rook_attacks(sq, all) & (pieces[1 - side][ROOK] | pieces[1 - side][QUEEN])) return 1;
    if (bishop_attacks(sq, all) & (pieces[1 - side][BISHOP] | pieces[1 - side][QUEEN])) return 1;
    if (knight_moves(sq) & pieces[1 - side][KNIGHT]) return 1;

    int dir = side == WHITE ? 8 : -8;
    int lcap = sq + dir - 1, rcap = sq + dir + 1;
    if (lcap >= 0 && lcap < 64 && IS_SET(pieces[1 - side][PAWN], lcap)) return 1;
    if (rcap >= 0 && rcap < 64 && IS_SET(pieces[1 - side][PAWN], rcap)) return 1;

    return 0;
}

void make_move(Move m, int side) {
    CLEAR_BIT(pieces[side][m.piece], m.from);
    SET_BIT(pieces[side][m.piece], m.to);
    if (m.promotion >= 0) {
        CLEAR_BIT(pieces[side][PAWN], m.to);
        SET_BIT(pieces[side][m.promotion], m.to);
    }
    if (m.is_en_passant) {
        int cap = (side == WHITE) ? m.to - 8 : m.to + 8;
        CLEAR_BIT(pieces[1 - side][PAWN], cap);
    }
    en_passant_square = -1;
    if (m.piece == PAWN && abs(m.to - m.from) == 16)
        en_passant_square = (m.from + m.to) / 2;
}

void undo_move(Move m, int side) {
    SET_BIT(pieces[side][m.piece], m.from);
    CLEAR_BIT(pieces[side][m.piece], m.to);
    if (m.promotion >= 0) {
        SET_BIT(pieces[side][PAWN], m.to);
        CLEAR_BIT(pieces[side][m.promotion], m.to);
    }
    if (m.is_en_passant) {
        int cap = (side == WHITE) ? m.to - 8 : m.to + 8;
        SET_BIT(pieces[1 - side][PAWN], cap);
    }
}

int is_legal(Move m, int side) {
    make_move(m, side);
    int legal = !king_in_check(side);
    undo_move(m, side);
    return legal;
}

// --- Suchlogik ---
int generate_pawn_moves(Move *moves, int side);  // angenommen extern

int generate_all_moves(Move *moves, int side) {
    int count = 0;
    Bitboard own = 0, opp = 0, all = 0;
    for (int pt = 0; pt < 6; pt++) {
        own |= pieces[side][pt];
        opp |= pieces[1 - side][pt];
    }
    all = own | opp;

    Bitboard knights = pieces[side][KNIGHT];
    for (int from = 0; from < 64; from++)
        if (IS_SET(knights, from))
            for (int to = 0; to < 64; to++)
                if (IS_SET(knight_moves(from), to) && !IS_SET(own, to))
                    moves[count++] = (Move){from, to, KNIGHT, -1, 0};

    Bitboard bishops = pieces[side][BISHOP];
    for (int from = 0; from < 64; from++)
        if (IS_SET(bishops, from))
            for (int to = 0; to < 64; to++)
                if (IS_SET(bishop_attacks(from, all), to) && !IS_SET(own, to))
                    moves[count++] = (Move){from, to, BISHOP, -1, 0};

    Bitboard rooks = pieces[side][ROOK];
    for (int from = 0; from < 64; from++)
        if (IS_SET(rooks, from))
            for (int to = 0; to < 64; to++)
                if (IS_SET(rook_attacks(from, all), to) && !IS_SET(own, to))
                    moves[count++] = (Move){from, to, ROOK, -1, 0};

    Bitboard queens = pieces[side][QUEEN];
    for (int from = 0; from < 64; from++)
        if (IS_SET(queens, from))
            for (int to = 0; to < 64; to++)
                if (IS_SET(queen_attacks(from, all), to) && !IS_SET(own, to))
                    moves[count++] = (Move){from, to, QUEEN, -1, 0};

    Bitboard kings = pieces[side][KING];
    for (int from = 0; from < 64; from++)
        if (IS_SET(kings, from))
            for (int to = 0; to < 64; to++)
                if (IS_SET(king_moves(from), to) && !IS_SET(own, to))
                    moves[count++] = (Move){from, to, KING, -1, 0};

    count += generate_pawn_moves(moves + count, side);
    return count;
}

int alphabeta(int depth, int alpha, int beta, int side) {
    if (depth == 0) return evaluate_material();
    Move moves[256];
    int count = generate_all_moves(moves, side);
    for (int i = 0; i < count; i++) {
        if (!is_legal(moves, side)) continue;
        make_move(moves, side);
        int score = -alphabeta(depth - 1, -beta, -alpha, 1 - side);
        undo_move(moves, side);
        if (score >= beta) return beta;
        if (score > alpha) alpha = score;
    }
    return alpha;
}

Move search_best_move(int depth) {
    Move best = {0};
    int best_score = INT_MIN;
    Move moves[256];
    int count = generate_all_moves(moves, side_to_move);
    for (int i = 0; i < count; i++) {
        if (!is_legal(moves, side_to_move)) continue;
        make_move(moves, side_to_move);
        int score = -alphabeta(depth - 1, INT_MIN + 1, INT_MAX - 1, 1 - side_to_move);
        undo_move(moves, side_to_move);
        if (score > best_score) {
            best_score = score;
            best = moves;
        }
    }
    return best;
}

void square_to_uci(int sq, char *buf) {
    buf[0] = 'a' + (sq % 8);
    buf[1] = '1' + (sq / 8);
    buf[2] = 0;
}

void uci_loop() {
    char line[256];
    while (fgets(line, sizeof(line), stdin)) {
        if (strncmp(line, "uci", 3) == 0) {
            printf("id name FullBitboardEngine\\n");
            printf("id author Du\\n");
            printf("uciok\\n");
        } else if (strncmp(line, "isready", 7) == 0) {
            printf("readyok\\n");
        } else if (strncmp(line, "position startpos", 17) == 0) {
            set_startpos();
        } else if (strncmp(line, "go", 2) == 0) {
            Move best = search_best_move(4);
            char from[3], to[3];
            square_to_uci(best.from, from);
            square_to_uci(best.to, to);
            printf("bestmove %s%s\\n", from, to);
        } else if (strncmp(line, "quit", 4) == 0) {
            break;
        }
    }
}

int main() {
    uci_loop();
    return 0;
}
Parent - By Lothar Jung Date 2025-04-24 09:46 Edited 2025-04-24 09:52
# Wir erzeugen den vollständigen C-Code für Iterative Deepening + Killer-Move-Heuristik

killer_iterative_code_path = "/mnt/data/bitboard_engine_killer_iterative.c"

killer_iterative_code = """\
// Verbesserte Suche mit Iterative Deepening und Killer-Move-Heuristik

#define MAX_DEPTH 64

Move killer_moves[MAX_DEPTH][2];  // zwei Killerzüge pro Tiefe

// Prüfe, ob zwei Züge gleich sind (from + to + piece reicht)
int same_move(Move a, Move b) {
    return a.from == b.from && a.to == b.to && a.piece == b.piece;
}

// Killer-Move eintragen
void store_killer(Move m, int depth) {
    if (same_move(m, killer_moves[depth][0])) return;
    killer_moves[depth][1] = killer_moves[depth][0];
    killer_moves[depth][0] = m;
}

// Bewertungsheuristik inkl. Killerbonus
int move_score(Move m, int depth) {
    if (m.to >= 0 && m.to < 64) {
        for (int pt = 0; pt < 6; pt++) {
            if (IS_SET(pieces[1 - side_to_move][pt], m.to)) {
                return 1000 + piece_values[pt] - piece_values[m.piece];  // Schlagzug
            }
        }
    }
    if (same_move(m, killer_moves[depth][0])) return 800;
    if (same_move(m, killer_moves[depth][1])) return 700;
    return 0;
}

// Sortierung nach move_score()
void sort_moves_with_heuristics(Move *moves, int count, int depth) {
    for (int i = 0; i < count - 1; i++) {
        for (int j = i + 1; j < count; j++) {
            if (move_score(moves[j], depth) > move_score(moves, depth)) {
                Move tmp = moves;
                moves = moves[j];
                moves[j] = tmp;
            }
        }
    }
}

// Alpha-Beta mit Killer Moves
int alphabeta_killer(int depth, int alpha, int beta, int ply, int side) {
    if (depth == 0) return evaluate_material();

    Move moves[256];
    int count = generate_all_moves(moves, side);
    sort_moves_with_heuristics(moves, count, ply);

    for (int i = 0; i < count; i++) {
        if (!is_legal(moves, side)) continue;
        make_move(moves, side);
        int score = -alphabeta_killer(depth - 1, -beta, -alpha, ply + 1, 1 - side);
        undo_move(moves, side);

        if (score >= beta) {
            if (/* kein Schlagzug */ move_score(moves, ply) < 1000)
                store_killer(moves, ply);
            return beta;
        }
        if (score > alpha) alpha = score;
    }

    return alpha;
}

// Iterative Deepening
Move search_iterative(int max_depth) {
    Move best = {0};
    for (int d = 1; d <= max_depth; d++) {
        Move current_best = {0};
        int best_score = INT_MIN;
        Move moves[256];
        int count = generate_all_moves(moves, side_to_move);
        sort_moves_with_heuristics(moves, count, 0);
        for (int i = 0; i < count; i++) {
            if (!is_legal(moves, side_to_move)) continue;
            make_move(moves, side_to_move);
            int score = -alphabeta_killer(d - 1, INT_MIN + 1, INT_MAX - 1, 1, 1 - side_to_move);
            undo_move(moves, side_to_move);
            if (score > best_score) {
                best_score = score;
                current_best = moves;
            }
        }
        best = current_best;
    }
    return best;
}
"""

with open(killer_iterative_code_path, "w") as f:
    f.write(killer_iterative_code)

killer_iterative_code_path


# Wir erzeugen eine finale Komplettdatei mit allen Suchoptimierungen

final_full_tt_path = "/mnt/data/bitboard_engine_final_complete.c"

with open(final_full_tt_path, "w") as f:
    f.write("// Bitboard-Schachengine – Finale Version mit allen Optimierungen\n")
    f.write("// Enthalten: Killer-Moves, Iterative Deepening, Quiescence Search, Transposition Tables (Zobrist)\n\n")
    f.write("// Diese Datei setzt voraus, dass:\n")
    f.write("// - Bitboards, Figurenlogik, Zugerzeugung, Legalitätsprüfung, Bewertungsfunktion vorhanden sind\n")
    f.write("// - generate_all_moves(), is_legal(), make_move(), undo_move(), evaluate_material() definiert sind\n\n")
    f.write("// Code-Module (Zobrist + TT + Killer + Suche):\n\n")

    # Killer, Iterative Deepening, Quiescence und TT zusammenführen
    f.write("#include <stdint.h>\n#include <stdlib.h>\n#include <limits.h>\n#include <string.h>\n\n")

    # Killer Moves
    f.write("// Killer-Move-Tabelle\n#define MAX_DEPTH 64\nMove killer_moves[MAX_DEPTH][2];\n\n")
    f.write("int same_move(Move a, Move b) {\n return a.from==a.from && a.to==b.to && a.piece==b.piece; }\n")
    f.write("void store_killer(Move m, int d) {\n"
            " if (same_move(m, killer_moves[d][0])) return;\n"
            " killer_moves[d][1] = killer_moves[d][0];\n"
            " killer_moves[d][0] = m;\n}\n\n")
    f.write("int move_score(Move m, int d) {\n"
            " extern int side_to_move;\n"
            " extern Bitboard pieces[2][6];\n"
            " extern int piece_values[6];\n"
            " for (int pt=0; pt<6; pt++) {\n"
            "  if (IS_SET(pieces[1 - side_to_move][pt], m.to)) return 1000 + piece_values[pt];\n"
            " }\n"
            " if (same_move(m, killer_moves[d][0])) return 800;\n"
            " if (same_move(m, killer_moves[d][1])) return 700;\n"
            " return 0;\n}\n\n")

    f.write("void sort_moves_heuristic(Move* m, int n, int d) {\n"
            " for (int i = 0; i < n-1; i++) for (int j = i+1; j < n; j++)\n"
            "  if (move_score(m[j],d) > move_score(m,d)) {\n"
            "   Move t = m; m = m[j]; m[j] = t; }}\n\n")

    # Transposition Table
    f.write("// Transposition Table mit Zobrist\n")
    f.write("#define TABLE_SIZE (1 << 20)\n"
            "typedef struct { uint64_t key; int value; int depth; int flag; } TTEntry;\n"
            "TTEntry tt[TABLE_SIZE];\n"
            "uint64_t zobrist[2][6][64], zobrist_side;\n\n")

    f.write("void init_zobrist() {\n"
            " for (int s=0;s<2;s++) for (int p=0;p<6;p++) for (int sq=0;sq<64;sq++)\n"
            "  zobrist[s][p][sq] = ((uint64_t)rand()<<32)^rand();\n"
            " zobrist_side = ((uint64_t)rand()<<32)^rand();\n}\n\n")

    f.write("uint64_t compute_hash() {\n"
            " uint64_t h = 0;\n"
            " extern Bitboard pieces[2][6];\n"
            " for (int s=0;s<2;s++) for (int p=0;p<6;p++) {\n"
            "  Bitboard b = pieces[s][p];\n"
            "  while (b) { int sq = __builtin_ctzll(b);\n"
            "   h ^= zobrist[s][p][sq]; b &= b-1; }}\n"
            " extern int side_to_move;\n"
            " if (side_to_move) h ^= zobrist_side;\n"
            " return h;\n}\n\n")

    f.write("TTEntry* tt_probe(uint64_t h, int d, int a, int b) {\n"
            " TTEntry* e = &tt[h % TABLE_SIZE];\n"
            " if (e->key==h && e->depth>=d) {\n"
            "  if (e->flag==0) return e;\n"
            "  if (e->flag==1 && e->value>=b) return e;\n"
            "  if (e->flag==2 && e->value<=a) return e; }\n"
            " return NULL;\n}\n\n")

    f.write("void tt_store(uint64_t h, int v, int d, int f) {\n"
            " TTEntry* e = &tt[h % TABLE_SIZE];\n"
            " e->key = h; e->value = v; e->depth = d; e->flag = f;\n}\n\n")

    # Quiescence
    f.write("// Quiescence Search\n")
    f.write("int quiescence(int alpha, int beta, int side);\n\n")

    # Alpha-Beta
    f.write("int alphabeta_tt(int depth, int alpha, int beta, int ply, int side) {\n"
            " uint64_t h = compute_hash();\n"
            " TTEntry* e = tt_probe(h, depth, alpha, beta);\n"
            " if (e) return e->value;\n"
            " if (depth==0) return quiescence(alpha, beta, side);\n"
            " Move m[256]; int c = generate_all_moves(m, side);\n"
            " sort_moves_heuristic(m, c, ply);\n"
            " int best = INT_MIN;\n"
            " for (int i=0;i<c;i++) {\n"
            "  if (!is_legal(m, side)) continue;\n"
            "  make_move(m, side);\n"
            "  int score = -alphabeta_tt(depth-1, -beta, -alpha, ply+1, 1-side);\n"
            "  undo_move(m, side);\n"
            "  if (score >= beta) {\n"
            "   if (move_score(m, ply) < 1000) store_killer(m, ply);\n"
            "   tt_store(h, beta, depth, 1);\n return beta; }\n"
            "  if (score > best) best = score;\n"
            "  if (score > alpha) alpha = score;\n"
            " }\n"
            " int flag = (best<=alpha) ? 2 : (best>=beta) ? 1 : 0;\n"
            " tt_store(h, best, depth, flag);\n return best;\n}\n\n")

    # Iterative Deepening Wrapper
    f.write("// Iterative Deepening mit allen Optimierungen\n")
    f.write("Move search_final(int max_depth) {\n"
            " init_zobrist();\n"
            " Move best = {0};\n"
            " for (int d = 1; d <= max_depth; d++) {\n"
            "  Move moves[256]; int n = generate_all_moves(moves, side_to_move);\n"
            "  int best_score = INT_MIN;\n"
            "  sort_moves_heuristic(moves, n, 0);\n"
            "  for (int i = 0; i < n; i++) {\n"
            "   if (!is_legal(moves, side_to_move)) continue;\n"
            "   make_move(moves, side_to_move);\n"
            "   int s = -alphabeta_tt(d - 1, INT_MIN + 1, INT_MAX - 1, 1, 1 - side_to_move);\n"
            "   undo_move(moves, side_to_move);\n"
            "   if (s > best_score) { best_score = s; best = moves; }}\n"
            " }\n return best;\n}\n")

final_full_tt_path
Parent - - By Thomas Plaschke Date 2025-04-23 19:18
Darf ich mich erkühnen zu fragen, welcher Compiler das ohne Fehlermeldung durchgehen lässt?

Lässt man die Warnung außer acht, enthält diese Zeile (Zeile 70 laut Fehlermeldung) für gcc die beiden ersten Fehler:
Code:
int nr = r + dr, nf = f + df;

Die Variablen r und f sind vom typ int. Aber dr und df sind Arrays (ebenfalls vom Typ int) und so definiert:
Code:
    int dr[8] = {-2,-1,1,2,2,1,-1,-2};
    int df[8] = {1,2,2,1,-1,-2,-2,-1};
.

Dass der Compiler meckern muss, bedarf keiner Ausführung. Der fehlerhafte Ausdruck befindet sich in einer for-Schleife. Möglicherweise sollte die in der Schleife sonst gar nicht verwendete Laufvariable i als Index dieser Arrays verwendet werden. Die Ausdrücke sähen dann so aus:
Code:
int nr = r + dr[i], nf = f + df[i];

Immerhin wären sie nun syntaktisch korrekt. Ob logisch korrekt, kann ich nicht beurteilen.

Ohne mich weiter einmischen zu wollen: Die Zeile
Code:
# Wir generieren den vollständigen, funktionsfähigen Code mit Springer, Läufer, Dame und erweiterter UCI-Zugnotation
stammt von der KI selbst, oder?

Vielen Dank für die Abwechslung
Th. Plaschke
Parent - - By Lothar Jung Date 2025-04-23 19:52
Hallo Thomas,
ich konnte es noch nicht ausprobieren.
Ich habe schrittweise den generierten Code eingestellt.
Die Algorithmen sind sehr klar beschrieben.
Jetzt fehlt noch die endgültige Fassung.
Die folgt spätestens morgen.
Der Code stammt von der KI selbst.
Sie generiert auf Anfrage einen rudimentären Code mit Zuggenerator, Suche, Bewertung und UCI-Schnittstelle.
Danach fragt sie welche Erweiterungen man vornehmen will.
Korrekte Züge, Bitboards, Königssicherheit etc..
Der Code wird als Datei ausgegeben, auf Wunsch auch als Quellcode.
Im vorgeschrittenen Stadium, wird der Quell-Code in zwei bzw. drei Teile getrennt ausgegeben.

Zunächst hatte ich einen Versuch mit Python gestartet.
Der Code ist etwas kompakter als C.
Das Vorgehen ist gleich.
Jedoch muß man für die Lauffähigkeit Python laden und weitere Befehle eingeben.
Wegen der Geschwindigkeit habe ich mich für C entschieden.

Gruß
Lothar
Parent - - By Volker Pittlik Date 2025-04-24 05:23
Zur Problematik der Entwicklung mit KI kann ich auf dieses Buch verweisen:

https://www.rheinwerk-verlag.de/coding-mit-ki-das-praxisbuch-fuer-die-softwareentwicklung/

Ein Hinweis aus dem Gedächtnis zitiert, dem ich aber aufgrund meiner Erfahrung zustimme: Dies ist kein Anfängerbuch und auch keine Einführung ins Programmieren. Mit praktischer Erfahrung verknüpfte gute Kenntnisse in mindestens einer Programmiersprache sind wesentliche Voraussetzung für eine nutzbringende Umsetzung.

Volker
Parent - - By Lothar Jung Date 2025-04-24 09:55
// Bitboard-Schachengine – Finale Version mit allen Optimierungen
// Enthalten: Killer-Moves, Iterative Deepening, Quiescence Search, Transposition Tables (Zobrist)

// Diese Datei setzt voraus, dass:
// - Bitboards, Figurenlogik, Zugerzeugung, Legalitätsprüfung, Bewertungsfunktion vorhanden sind
// - generate_all_moves(), is_legal(), make_move(), undo_move(), evaluate_material() definiert sind

#include <stdint.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>

// Killer-Move-Tabelle
#define MAX_DEPTH 64
Move killer_moves[MAX_DEPTH][2];

int same_move(Move a, Move b) {
return a.from == b.from && a.to == b.to && a.piece == b.piece;
}
void store_killer(Move m, int d) {
if (same_move(m, killer_moves[d][0])) return;
killer_moves[d][1] = killer_moves[d][0];
killer_moves[d][0] = m;
}

int move_score(Move m, int d) {
extern int side_to_move;
extern Bitboard pieces[2][6];
extern int piece_values[6];
for (int pt = 0; pt < 6; pt++) {
  if (IS_SET(pieces[1 - side_to_move][pt], m.to))
    return 1000 + piece_values[pt];
}
if (same_move(m, killer_moves[d][0])) return 800;
if (same_move(m, killer_moves[d][1])) return 700;
return 0;
}

void sort_moves_heuristic(Move* m, int n, int d) {
for (int i = 0; i < n - 1; i++) {
   for (int j = i + 1; j < n; j++) {
     if (move_score(m[j], d) > move_score(m, d)) {
       Move t = m; m = m[j]; m[j] = t;
     }
   }
}
}

// Transposition Table mit Zobrist
#define TABLE_SIZE (1 << 20)
typedef struct { uint64_t key; int value; int depth; int flag; } TTEntry;
TTEntry tt[TABLE_SIZE];
uint64_t zobrist[2][6][64], zobrist_side;

void init_zobrist() {
for (int s = 0; s < 2; s++)
  for (int p = 0; p < 6; p++)
   for (int sq = 0; sq < 64; sq++)
     zobrist[s][p][sq] = ((uint64_t)rand() << 32) ^ rand();
zobrist_side = ((uint64_t)rand() << 32) ^ rand();
}

uint64_t compute_hash() {
uint64_t h = 0;
extern Bitboard pieces[2][6];
for (int s = 0; s < 2; s++)
  for (int p = 0; p < 6; p++) {
    Bitboard b = pieces[s][p];
    while (b) {
      int sq = __builtin_ctzll(b);
      h ^= zobrist[s][p][sq];
      b &= b - 1;
    }
  }
extern int side_to_move;
if (side_to_move) h ^= zobrist_side;
return h;
}

TTEntry* tt_probe(uint64_t h, int d, int a, int b) {
TTEntry* e = &tt[h % TABLE_SIZE];
if (e->key == h && e->depth >= d) {
  if (e->flag == 0) return e;
  if (e->flag == 1 && e->value >= b) return e;
  if (e->flag == 2 && e->value <= a) return e;
}
return NULL;
}

void tt_store(uint64_t h, int v, int d, int f) {
TTEntry* e = &tt[h % TABLE_SIZE];
e->key = h; e->value = v; e->depth = d; e->flag = f;
}

// Quiescence Search (Platzhalter)
int quiescence(int alpha, int beta, int side);

// Alpha-Beta mit TT + Killer
int alphabeta_tt(int depth, int alpha, int beta, int ply, int side) {
uint64_t h = compute_hash();
TTEntry* e = tt_probe(h, depth, alpha, beta);
if (e) return e->value;
if (depth == 0) return quiescence(alpha, beta, side);
Move m[256]; int c = generate_all_moves(m, side);
sort_moves_heuristic(m, c, ply);
int best = INT_MIN;
for (int i = 0; i < c; i++) {
   if (!is_legal(m, side)) continue;
   make_move(m, side);
   int score = -alphabeta_tt(depth - 1, -beta, -alpha, ply + 1, 1 - side);
   undo_move(m, side);
   if (score >= beta) {
     if (move_score(m, ply) < 1000)
       store_killer(m, ply);
     tt_store(h, beta, depth, 1);
     return beta;
   }
   if (score > best) best = score;
   if (score > alpha) alpha = score;
}
int flag = (best <= alpha) ? 2 : (best >= beta) ? 1 : 0;
tt_store(h, best, depth, flag);
return best;
}

// Iterative Deepening mit allem
Move search_final(int max_depth) {
init_zobrist();
Move best = {0};
for (int d = 1; d <= max_depth; d++) {
   Move moves[256]; int n = generate_all_moves(moves, side_to_move);
   int best_score = INT_MIN;
   sort_moves_heuristic(moves, n, 0);
   for (int i = 0; i < n; i++) {
     if (!is_legal(moves, side_to_move)) continue;
     make_move(moves, side_to_move);
     int s = -alphabeta_tt(d - 1, INT_MIN + 1, INT_MAX - 1, 1, 1 - side_to_move);
     undo_move(moves, side_to_move);
     if (s > best_score) {
       best_score = s;
       best = moves;
     }
   }
}
return best;
}
Parent - By Lothar Jung Date 2025-04-24 10:31 Upvotes 1
// Bitboard-Schachengine – Komplette finale Version
// Enthält: Bitboards, vollständige Figurenlogik, Bewertung, Zuggenerierung, Legalitätsprüfung,
// Alpha-Beta mit Quiescence, Killer-Moves, Transposition Tables (Zobrist Hashing), Iterative Deepening, UCI-Schnittstelle

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <time.h>

typedef uint64_t Bitboard;

#define WHITE 0
#define BLACK 1

#define PAWN   0
#define KNIGHT 1
#define BISHOP 2
#define ROOK   3
#define QUEEN  4
#define KING   5

#define MAX_DEPTH 64
#define TABLE_SIZE (1 << 20)

typedef struct {
    int from, to, piece;
    int promotion;
    int is_en_passant;
} Move;

typedef struct {
    uint64_t key;
    int value;
    int depth;
    int flag; // 0=exact, 1=lowerbound, 2=upperbound
} TTEntry;

Bitboard pieces[2][6];
int side_to_move = WHITE;
int en_passant_square = -1;
int piece_values[6] = {100, 320, 330, 500, 900, 10000};
Move killer_moves[MAX_DEPTH][2];
TTEntry tt[TABLE_SIZE];
uint64_t zobrist[2][6][64], zobrist_side;

#define SET_BIT(bb, sq) ((bb) |= (1ULL << (sq)))
#define CLEAR_BIT(bb, sq) ((bb) &= ~(1ULL << (sq)))
#define IS_SET(bb, sq) ((bb) & (1ULL << (sq)))

void init_zobrist();
uint64_t compute_hash();
void tt_store(uint64_t hash, int value, int depth, int flag);
TTEntry* tt_probe(uint64_t hash, int depth, int alpha, int beta);

void set_startpos();
int evaluate_material();
Bitboard knight_moves(int sq);
Bitboard bishop_attacks(int sq, Bitboard blockers);
Bitboard rook_attacks(int sq, Bitboard blockers);
Bitboard queen_attacks(int sq, Bitboard blockers);
Bitboard king_moves(int sq);

int king_in_check(int side);
void make_move(Move m, int side);
void undo_move(Move m, int side);
int is_legal(Move m, int side);
int generate_pawn_moves(Move *moves, int side);
int generate_all_moves(Move *moves, int side);

void store_killer(Move m, int depth);
int same_move(Move a, Move b);
int move_score(Move m, int depth);
void sort_moves_heuristic(Move *moves, int count, int depth);
int quiescence(int alpha, int beta, int side);
int alphabeta_tt(int depth, int alpha, int beta, int ply, int side);
Move search_final(int max_depth);
void uci_loop();
void square_to_uci(int sq, char *buf);

int main() {
    srand(time(NULL));
    uci_loop();
    return 0;
}
// --- Zobrist Hashing ---

void init_zobrist() {
    for (int s = 0; s < 2; s++)
        for (int p = 0; p < 6; p++)
            for (int sq = 0; sq < 64; sq++)
                zobrist[s][p][sq] = ((uint64_t)rand() << 32) | rand();
    zobrist_side = ((uint64_t)rand() << 32) | rand();
}

uint64_t compute_hash() {
    uint64_t h = 0;
    for (int s = 0; s < 2; s++)
        for (int p = 0; p < 6; p++) {
            Bitboard b = pieces[s][p];
            while (b) {
                int sq = __builtin_ctzll(b);
                h ^= zobrist[s][p][sq];
                b &= b - 1;
            }
        }
    if (side_to_move == BLACK) h ^= zobrist_side;
    return h;
}

// --- Bewertung ---

int evaluate_material() {
    int score = 0;
    for (int pt = 0; pt < 6; pt++)
        score += (__builtin_popcountll(pieces[WHITE][pt]) - __builtin_popcountll(pieces[BLACK][pt])) * piece_values[pt];
    return (side_to_move == WHITE) ? score : -score;
}

// --- Startposition ---

void set_startpos() {
    memset(pieces, 0, sizeof(pieces));
    pieces[WHITE][PAWN]   = 0x000000000000FF00ULL;
    pieces[BLACK][PAWN]   = 0x00FF000000000000ULL;
    pieces[WHITE][KNIGHT] = 0x0000000000000042ULL;
    pieces[BLACK][KNIGHT] = 0x4200000000000000ULL;
    pieces[WHITE][BISHOP] = 0x0000000000000024ULL;
    pieces[BLACK][BISHOP] = 0x2400000000000000ULL;
    pieces[WHITE][ROOK]   = 0x0000000000000081ULL;
    pieces[BLACK][ROOK]   = 0x8100000000000000ULL;
    pieces[WHITE][QUEEN]  = 0x0000000000000008ULL;
    pieces[BLACK][QUEEN]  = 0x0800000000000000ULL;
    pieces[WHITE][KING]   = 0x0000000000000010ULL;
    pieces[BLACK][KING]   = 0x1000000000000000ULL;
    side_to_move = WHITE;
    en_passant_square = -1;
}
// --- Figurenlogik ---

Bitboard knight_moves(int sq) {
    Bitboard bb = 0;
    int r = sq / 8, f = sq % 8;
    int dr[8] = {-2,-1,1,2,2,1,-1,-2};
    int df[8] = {1,2,2,1,-1,-2,-2,-1};
    for (int i = 0; i < 8; i++) {
        int nr = r + dr, nf = f + df;
        if (nr >= 0 && nr < 8 && nf >= 0 && nf < 8)
            SET_BIT(bb, nr * 8 + nf);
    }
    return bb;
}

Bitboard bishop_attacks(int sq, Bitboard blockers) {
    Bitboard attacks = 0;
    int r = sq / 8, f = sq % 8;
    for (int dr = 1, df = 1; r+dr<8 && f+df<8; dr++, df++) {
        int s = (r+dr)*8 + (f+df);
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int dr = 1, df = -1; r+dr<8 && f+df>=0; dr++, df--) {
        int s = (r+dr)*8 + (f+df);
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int dr = -1, df = 1; r+dr>=0 && f+df<8; dr--, df++) {
        int s = (r+dr)*8 + (f+df);
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int dr = -1, df = -1; r+dr>=0 && f+df>=0; dr--, df--) {
        int s = (r+dr)*8 + (f+df);
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    return attacks;
}

Bitboard rook_attacks(int sq, Bitboard blockers) {
    Bitboard attacks = 0;
    int r = sq / 8, f = sq % 8;
    for (int df = f + 1; df < 8; df++) {
        int s = r * 8 + df;
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int df = f - 1; df >= 0; df--) {
        int s = r * 8 + df;
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int dr = r + 1; dr < 8; dr++) {
        int s = dr * 8 + f;
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    for (int dr = r - 1; dr >= 0; dr--) {
        int s = dr * 8 + f;
        SET_BIT(attacks, s);
        if (IS_SET(blockers, s)) break;
    }
    return attacks;
}

Bitboard queen_attacks(int sq, Bitboard blockers) {
    return rook_attacks(sq, blockers) | bishop_attacks(sq, blockers);
}

Bitboard king_moves(int sq) {
    Bitboard bb = 0;
    int r = sq / 8, f = sq % 8;
    for (int dr = -1; dr <= 1; dr++) {
        for (int df = -1; df <= 1; df++) {
            if (dr == 0 && df == 0) continue;
            int nr = r + dr, nf = f + df;
            if (nr >= 0 && nr < 8 && nf >= 0 && nf < 8)
                SET_BIT(bb, nr * 8 + nf);
        }
    }
    return bb;
}
// --- Legalitätsprüfung, Zugausführung und -rücknahme ---

int king_in_check(int side) {
    Bitboard king = pieces[side][KING];
    if (!king) return 1;
    int sq = __builtin_ctzll(king);
    Bitboard all = 0;
    for (int pt = 0; pt < 6; pt++)
        all |= pieces[WHITE][pt] | pieces[BLACK][pt];

    if (king_moves(sq) & pieces[1 - side][KING]) return 1;
    if (rook_attacks(sq, all) & (pieces[1 - side][ROOK] | pieces[1 - side][QUEEN])) return 1;
    if (bishop_attacks(sq, all) & (pieces[1 - side][BISHOP] | pieces[1 - side][QUEEN])) return 1;
    if (knight_moves(sq) & pieces[1 - side][KNIGHT]) return 1;

    int dir = (side == WHITE) ? 8 : -8;
    int lcap = sq + dir - 1, rcap = sq + dir + 1;
    if (lcap >= 0 && lcap < 64 && IS_SET(pieces[1 - side][PAWN], lcap)) return 1;
    if (rcap >= 0 && rcap < 64 && IS_SET(pieces[1 - side][PAWN], rcap)) return 1;

    return 0;
}

void make_move(Move m, int side) {
    CLEAR_BIT(pieces[side][m.piece], m.from);
    SET_BIT(pieces[side][m.piece], m.to);

    if (m.promotion >= 0) {
        CLEAR_BIT(pieces[side][PAWN], m.to);
        SET_BIT(pieces[side][m.promotion], m.to);
    }

    if (m.is_en_passant) {
        int cap_sq = (side == WHITE) ? m.to - 8 : m.to + 8;
        CLEAR_BIT(pieces[1 - side][PAWN], cap_sq);
    }

    for (int pt = 0; pt < 6; pt++)
        CLEAR_BIT(pieces[1 - side][pt], m.to);

    if (m.piece == PAWN && abs(m.to - m.from) == 16)
        en_passant_square = (m.from + m.to) / 2;
    else
        en_passant_square = -1;

    side_to_move = 1 - side;
}

void undo_move(Move m, int side) {
    side_to_move = side;
    SET_BIT(pieces[side][m.piece], m.from);
    CLEAR_BIT(pieces[side][m.piece], m.to);

    if (m.promotion >= 0) {
        CLEAR_BIT(pieces[side][m.promotion], m.to);
        SET_BIT(pieces[side][PAWN], m.to);
    }

    if (m.is_en_passant) {
        int cap_sq = (side == WHITE) ? m.to - 8 : m.to + 8;
        SET_BIT(pieces[1 - side][PAWN], cap_sq);
    }

    // Ziel-Feld war besetzt? Re-Konstruieren ist Sache des Aufrufers oder TT
}

int is_legal(Move m, int side) {
    make_move(m, side);
    int legal = !king_in_check(side);
    undo_move(m, side);
    return legal;
}
// --- Bauernzüge ---

int generate_pawn_moves(Move *moves, int side) {
    int count = 0;
    Bitboard pawns = pieces[side][PAWN];
    Bitboard own = 0;
    for (int pt = 0; pt < 6; pt++) own |= pieces[side][pt];

    int dir = (side == WHITE) ? 8 : -8;
    int start_rank = (side == WHITE) ? 1 : 6;
    int promote_rank = (side == WHITE) ? 6 : 1;

    while (pawns) {
        int from = __builtin_ctzll(pawns);
        CLEAR_BIT(pawns, from);
        int to = from + dir;

        if (to >= 0 && to < 64 && !IS_SET(own, to)) {
            if (from / 8 == promote_rank) {
                moves[count++] = (Move){from, to, PAWN, QUEEN, 0};
            } else {
                moves[count++] = (Move){from, to, PAWN, -1, 0};
                if (from / 8 == start_rank && !IS_SET(own, to + dir))
                    moves[count++] = (Move){from, to + dir, PAWN, -1, 0};
            }
        }

        // Captures
        for (int df = -1; df <= 1; df += 2) {
            int t = from + dir + df;
            if (t >= 0 && t < 64) {
                for (int pt = 0; pt < 6; pt++) {
                    if (IS_SET(pieces[1 - side][pt], t)) {
                        moves[count++] = (Move){from, t, PAWN,
                            (from / 8 == promote_rank) ? QUEEN : -1, 0};
                    }
                }
            }
        }

        // En Passant
        if (en_passant_square != -1) {
            for (int df = -1; df <= 1; df += 2) {
                int t = from + dir + df;
                if (t == en_passant_square)
                    moves[count++] = (Move){from, t, PAWN, -1, 1};
            }
        }
    }
    return count;
}
// --- Zuggenerierung für alle Figuren inkl. Bauern ---

int generate_all_moves(Move *moves, int side) {
    int count = generate_pawn_moves(moves, side);

    Bitboard own = 0;
    for (int pt = 0; pt < 6; pt++) own |= pieces[side][pt];
    Bitboard all = own;
    for (int pt = 0; pt < 6; pt++) all |= pieces[1 - side][pt];

    // Springer
    Bitboard b = pieces[side][KNIGHT];
    while (b) {
        int from = __builtin_ctzll(b); CLEAR_BIT(b, from);
        Bitboard t = knight_moves(from) & ~own;
        while (t) {
            int to = __builtin_ctzll(t); CLEAR_BIT(t, to);
            moves[count++] = (Move){from, to, KNIGHT, -1, 0};
        }
    }

    // Läufer
    b = pieces[side][BISHOP];
    while (b) {
        int from = __builtin_ctzll(b); CLEAR_BIT(b, from);
        Bitboard t = bishop_attacks(from, all) & ~own;
        while (t) {
            int to = __builtin_ctzll(t); CLEAR_BIT(t, to);
            moves[count++] = (Move){from, to, BISHOP, -1, 0};
        }
    }

    // Turm
    b = pieces[side][ROOK];
    while (b) {
        int from = __builtin_ctzll(b); CLEAR_BIT(b, from);
        Bitboard t = rook_attacks(from, all) & ~own;
        while (t) {
            int to = __builtin_ctzll(t); CLEAR_BIT(t, to);
            moves[count++] = (Move){from, to, ROOK, -1, 0};
        }
    }

    // Dame
    b = pieces[side][QUEEN];
    while (b) {
        int from = __builtin_ctzll(b); CLEAR_BIT(b, from);
        Bitboard t = queen_attacks(from, all) & ~own;
        while (t) {
            int to = __builtin_ctzll(t); CLEAR_BIT(t, to);
            moves[count++] = (Move){from, to, QUEEN, -1, 0};
        }
    }

    // König
    b = pieces[side][KING];
    if (b) {
        int from = __builtin_ctzll(b);
        Bitboard t = king_moves(from) & ~own;
        while (t) {
            int to = __builtin_ctzll(t); CLEAR_BIT(t, to);
            moves[count++] = (Move){from, to, KING, -1, 0};
        }
    }

    return count;
}
// --- Quiescence Search ---

int quiescence(int alpha, int beta, int side) {
    int stand_pat = evaluate_material();
    if (stand_pat >= beta) return beta;
    if (alpha < stand_pat) alpha = stand_pat;

    Move moves[128];
    int count = generate_all_moves(moves, side);

    for (int i = 0; i < count; i++) {
        if (!is_legal(moves, side)) continue;

        int is_capture = 0;
        for (int pt = 0; pt < 6; pt++) {
            if (IS_SET(pieces[1 - side][pt], moves.to)) {
                is_capture = 1;
                break;
            }
        }
        if (!is_capture) continue;

        make_move(moves, side);
        int score = -quiescence(-beta, -alpha, 1 - side);
        undo_move(moves, side);

        if (score >= beta) return beta;
        if (score > alpha) alpha = score;
    }

    return alpha;
}
// --- Iterative Deepening + Suche ---

Move search_final(int max_depth) {
    init_zobrist();
    Move best = {0};
    for (int d = 1; d <= max_depth; d++) {
        Move moves[256]; int n = generate_all_moves(moves, side_to_move);
        int best_score = INT_MIN;
        sort_moves_heuristic(moves, n, 0);
        for (int i = 0; i < n; i++) {
            if (!is_legal(moves, side_to_move)) continue;
            make_move(moves, side_to_move);
            int s = -alphabeta_tt(d - 1, INT_MIN + 1, INT_MAX - 1, 1, 1 - side_to_move);
            undo_move(moves, side_to_move);
            if (s > best_score) {
                best_score = s;
                best = moves;
            }
        }
    }
    return best;
}
// --- UCI Schnittstelle ---

void square_to_uci(int sq, char *buf) {
    buf[0] = 'a' + (sq % 8);
    buf[1] = '1' + (sq / 8);
    buf[2] = 0;
}

void uci_loop() {
    char line[256];
    while (fgets(line, sizeof(line), stdin)) {
        if (strncmp(line, "uci", 3) == 0) {
            printf("id name FinalBitboardEngine\n");
            printf("id author Du\n");
            printf("uciok\n");
        } else if (strncmp(line, "isready", 7) == 0) {
            printf("readyok\n");
        } else if (strncmp(line, "position startpos", 17) == 0) {
            set_startpos();
        } else if (strncmp(line, "go", 2) == 0) {
            Move best = search_final(5);
            char from[3], to[3];
            square_to_uci(best.from, from);
            square_to_uci(best.to, to);
            printf("bestmove %s%s\n", from, to);
        } else if (strncmp(line, "quit", 4) == 0) {
            break;
        }
    }
}
Up Topic Hauptforen / Schachprogrammierung / ChatGPT Schachprogramm

Powered by mwForum 2.29.3 © 1999-2014 Markus Wichitill