게시판장기로 이해하는 규칙 엔진과 평가 함수 탐색예제 소스

예제 소스

장기로 이해하는 규칙 엔진과 평가 함수 탐색 · 파일 59개

Types.h

#pragma once

#include <cstdint>
#include <string>

enum class Side : uint8_t { Cho, Han };

inline Side opposite(Side side) {
    return side == Side::Cho ? Side::Han : Side::Cho;
}

enum class PieceType : uint8_t {
    None = 0,
    King,
    Advisor,
    Chariot,
    Cannon,
    Horse,
    Elephant,
    Pawn
};

enum class Formation : uint8_t {
    InnerElephant,  // 마상상마 (내상)
    OuterElephant,  // 상마마상 (외상)
    LeftElephant,   // 상마상마
    RightElephant   // 마상마상
};

enum class GameResult : uint8_t {
    Playing,
    ChoWin,
    HanWin,
    Draw
};

struct Pos {
    int file = 0;  // 0..8  (화면 왼쪽 → 오른쪽)
    int rank = 0;  // 0..9  (0 = 한 궁성 쪽, 9 = 초 궁성 쪽)

    constexpr bool operator==(Pos o) const { return file == o.file && rank == o.rank; }
    constexpr bool operator!=(Pos o) const { return !(*this == o); }
};

struct Piece {
    PieceType type = PieceType::None;
    Side side = Side::Cho;

    constexpr bool empty() const { return type == PieceType::None; }
    constexpr explicit operator bool() const { return !empty(); }
};

struct Move {
    Pos from{};
    Pos to{};
    Piece moving{};
    Piece captured{};
    bool pass = false;

    static Move makePass() {
        Move m;
        m.pass = true;
        return m;
    }
};

inline bool inBoard(Pos p) {
    return p.file >= 0 && p.file < 9 && p.rank >= 0 && p.rank < 10;
}

inline bool inPalace(Pos p, Side side) {
    if (p.file < 3 || p.file > 5) {
        return false;
    }
    if (side == Side::Han) {
        return p.rank >= 0 && p.rank <= 2;
    }
    return p.rank >= 7 && p.rank <= 9;
}

inline bool inAnyPalace(Pos p) {
    return inPalace(p, Side::Han) || inPalace(p, Side::Cho);
}

inline int pawnForward(Side side) {
    return side == Side::Cho ? -1 : 1;
}

inline const char* pieceGlyph(Piece piece) {
    if (piece.empty()) {
        return "";
    }
    if (piece.side == Side::Han) {
        switch (piece.type) {
        case PieceType::King: return "漢";
        case PieceType::Advisor: return "士";
        case PieceType::Chariot: return "車";
        case PieceType::Cannon: return "包";
        case PieceType::Horse: return "馬";
        case PieceType::Elephant: return "象";
        case PieceType::Pawn: return "兵";
        default: return "";
        }
    }
    switch (piece.type) {
    case PieceType::King: return "楚";
    case PieceType::Advisor: return "士";
    case PieceType::Chariot: return "車";
    case PieceType::Cannon: return "包";
    case PieceType::Horse: return "馬";
    case PieceType::Elephant: return "象";
    case PieceType::Pawn: return "卒";
    default: return "";
    }
}

inline const char* pieceNameKo(PieceType type) {
    switch (type) {
    case PieceType::King: return "궁";
    case PieceType::Advisor: return "사";
    case PieceType::Chariot: return "차";
    case PieceType::Cannon: return "포";
    case PieceType::Horse: return "마";
    case PieceType::Elephant: return "상";
    case PieceType::Pawn: return "졸";
    default: return "";
    }
}

inline const char* formationNameKo(Formation f) {
    switch (f) {
    case Formation::InnerElephant: return "마상상마 (내상)";
    case Formation::OuterElephant: return "상마마상 (외상)";
    case Formation::LeftElephant: return "상마상마 (좌상)";
    case Formation::RightElephant: return "마상마상 (우상)";
    }
    return "";
}

inline int materialValue(PieceType type) {
    switch (type) {
    case PieceType::Chariot: return 130;
    case PieceType::Cannon: return 70;
    case PieceType::Horse: return 50;
    case PieceType::Elephant: return 30;
    case PieceType::Advisor: return 30;
    case PieceType::Pawn: return 20;
    case PieceType::King: return 100000;
    default: return 0;
    }
}

inline std::string posLabel(Pos p) {
    static const char* files[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9"};
    static const char* ranks[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
    return std::string(files[p.file]) + ranks[p.rank];
}