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

예제 소스

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

types.ts

export type Side = "cho" | "han";

export type PieceType =
  | "none"
  | "king"
  | "advisor"
  | "chariot"
  | "cannon"
  | "horse"
  | "elephant"
  | "pawn";

export type Formation = "inner" | "outer" | "left" | "right";

export type GameResult = "playing" | "cho_win" | "han_win" | "draw";

export type GameMode = "human_cho" | "human_han" | "human_vs_human" | "ai_vs_ai";

export type Pos = { file: number; rank: number };

export type Piece = { type: PieceType; side: Side };

export type Move = {
  from: Pos;
  to: Pos;
  moving: Piece;
  captured: Piece;
  pass: boolean;
};

export type GameSettings = {
  choFormation: Formation;
  hanFormation: Formation;
  mode: GameMode;
  /** 컴퓨터 깊이 (AI 대 AI에서는 초 쪽) */
  aiDepth: number;
  /** AI 대 AI에서 한 쪽 깊이 */
  hanAiDepth: number;
  bikjangEnabled: boolean;
};

export const EMPTY: Piece = { type: "none", side: "cho" };

export function opposite(side: Side): Side {
  return side === "cho" ? "han" : "cho";
}

export function posEq(a: Pos, b: Pos): boolean {
  return a.file === b.file && a.rank === b.rank;
}

export function inBoard(p: Pos): boolean {
  return p.file >= 0 && p.file < 9 && p.rank >= 0 && p.rank < 10;
}

export function inPalace(p: Pos, side: Side): boolean {
  if (p.file < 3 || p.file > 5) return false;
  if (side === "han") return p.rank >= 0 && p.rank <= 2;
  return p.rank >= 7 && p.rank <= 9;
}

export function inAnyPalace(p: Pos): boolean {
  return inPalace(p, "han") || inPalace(p, "cho");
}

export function pawnForward(side: Side): number {
  return side === "cho" ? -1 : 1;
}

export function pieceEmpty(p: Piece): boolean {
  return p.type === "none";
}

export function makePass(): Move {
  return {
    from: { file: 0, rank: 0 },
    to: { file: 0, rank: 0 },
    moving: EMPTY,
    captured: EMPTY,
    pass: true,
  };
}

export function pieceGlyph(piece: Piece): string {
  if (pieceEmpty(piece)) return "";
  if (piece.side === "han") {
    switch (piece.type) {
      case "king":
        return "漢";
      case "advisor":
        return "士";
      case "chariot":
        return "車";
      case "cannon":
        return "包";
      case "horse":
        return "馬";
      case "elephant":
        return "象";
      case "pawn":
        return "兵";
      default:
        return "";
    }
  }
  switch (piece.type) {
    case "king":
      return "楚";
    case "advisor":
      return "士";
    case "chariot":
      return "車";
    case "cannon":
      return "包";
    case "horse":
      return "馬";
    case "elephant":
      return "象";
    case "pawn":
      return "卒";
    default:
      return "";
  }
}

export function pieceNameKo(type: PieceType): string {
  switch (type) {
    case "king":
      return "궁";
    case "advisor":
      return "사";
    case "chariot":
      return "차";
    case "cannon":
      return "포";
    case "horse":
      return "마";
    case "elephant":
      return "상";
    case "pawn":
      return "졸";
    default:
      return "";
  }
}

export function formationNameKo(f: Formation): string {
  switch (f) {
    case "inner":
      return "마상상마 (내상)";
    case "outer":
      return "상마마상 (외상)";
    case "left":
      return "상마상마 (좌상)";
    case "right":
      return "마상마상 (우상)";
  }
}

export function materialValue(type: PieceType): number {
  switch (type) {
    case "chariot":
      return 130;
    case "cannon":
      return 70;
    case "horse":
      return 50;
    case "elephant":
      return 30;
    case "advisor":
      return 30;
    case "pawn":
      return 20;
    case "king":
      return 100000;
    default:
      return 0;
  }
}

export function posLabel(p: Pos): string {
  return `${p.file + 1}${p.rank + 1}`;
}

export function sideNameKo(side: Side): string {
  return side === "cho" ? "초 (楚)" : "한 (漢)";
}

export function resultText(result: GameResult): string {
  switch (result) {
    case "cho_win":
      return "초 승리 (외통)";
    case "han_win":
      return "한 승리 (외통)";
    case "draw":
      return "무승부";
    default:
      return "";
  }
}

export const FORMATIONS: Formation[] = ["inner", "outer", "left", "right"];

export const DEFAULT_SETTINGS: GameSettings = {
  choFormation: "inner",
  hanFormation: "inner",
  mode: "human_cho",
  aiDepth: 3,
  hanAiDepth: 3,
  bikjangEnabled: true,
};