예제 소스
장기로 이해하는 규칙 엔진과 평가 함수 탐색 · 파일 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];
}