change cpp for js
This commit is contained in:
parent
4b49500317
commit
eabc7dbaff
18 changed files with 215 additions and 312 deletions
6
Makefile
6
Makefile
|
|
@ -0,0 +1,6 @@
|
||||||
|
all: docker
|
||||||
|
|
||||||
|
docker:
|
||||||
|
docker-compose -f deploy/docker-compose.dev.yml up --build -d
|
||||||
|
@echo "Frontend is running at http://localhost:3000"
|
||||||
|
@echo "Backend is running at http://localhost:4000"
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
#ifndef BOARD_HPP
|
|
||||||
#define BOARD_HPP
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "cell.hpp"
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
class Board {
|
|
||||||
private:
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
std::vector<std::vector<Cell>> grid;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Board(int w, int h) : width(w), height(h), grid(h, std::vector<Cell>(w)) {}
|
|
||||||
int getWidth() const { return width; }
|
|
||||||
int getHeight() const { return height; }
|
|
||||||
Cell& getCell(int x, int y) { return grid[y][x]; }
|
|
||||||
void setPiece(int x, int y, const Piece& piece) {
|
|
||||||
grid[y][x].pieceId = std::make_shared<Piece>(piece);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace engine
|
|
||||||
|
|
||||||
#endif
|
|
||||||
82
engine/core/board.js
Normal file
82
engine/core/board.js
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
import Cell from './cell.js';
|
||||||
|
|
||||||
|
class Board {
|
||||||
|
/**
|
||||||
|
* @param {number} width
|
||||||
|
* @param {number} height
|
||||||
|
*/
|
||||||
|
constructor(width, height) {
|
||||||
|
/** @type {number} */
|
||||||
|
this.width = width;
|
||||||
|
/** @type {number} */
|
||||||
|
this.height = height;
|
||||||
|
/** @type {Cell[][]} */
|
||||||
|
this.grid = Array.from({ length: height }, () => Array.from({ length: width }, () => new Cell()));
|
||||||
|
|
||||||
|
this.setupInitialPieces();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
getWidth() {
|
||||||
|
return this.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
getHeight() {
|
||||||
|
return this.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} x
|
||||||
|
* @param {number} y
|
||||||
|
* @returns {Cell}
|
||||||
|
*/
|
||||||
|
getCell(x, y) {
|
||||||
|
return this.grid[y][x];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} x
|
||||||
|
* @param {number} y
|
||||||
|
* @param {Piece|null} piece
|
||||||
|
*/
|
||||||
|
setPiece(x, y, piece) {
|
||||||
|
this.grid[y][x].piece = piece;
|
||||||
|
}
|
||||||
|
|
||||||
|
setupInitialPieces() {
|
||||||
|
// Pawns
|
||||||
|
for (let x = 0; x < this.width; x++) {
|
||||||
|
this.setPiece(x, 1, new Piece(PieceColor.WHITE, PieceType.PAWN));
|
||||||
|
this.setPiece(x, 6, new Piece(PieceColor.BLACK, PieceType.PAWN));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rooks
|
||||||
|
this.setPiece(0, 0, new Piece(PieceColor.WHITE, PieceType.ROOK));
|
||||||
|
this.setPiece(7, 0, new Piece(PieceColor.WHITE, PieceType.ROOK));
|
||||||
|
this.setPiece(0, 7, new Piece(PieceColor.BLACK, PieceType.ROOK));
|
||||||
|
this.setPiece(7, 7, new Piece(PieceColor.BLACK, PieceType.ROOK));
|
||||||
|
|
||||||
|
// Knights
|
||||||
|
this.setPiece(1, 0, new Piece(PieceColor.WHITE, PieceType.KNIGHT));
|
||||||
|
this.setPiece(6, 0, new Piece(PieceColor.WHITE, PieceType.KNIGHT));
|
||||||
|
this.setPiece(1, 7, new Piece(PieceColor.BLACK, PieceType.KNIGHT));
|
||||||
|
this.setPiece(6, 7, new Piece(PieceColor.BLACK, PieceType.KNIGHT));
|
||||||
|
|
||||||
|
// Bishops
|
||||||
|
this.setPiece(2, 0, new Piece(PieceColor.WHITE, PieceType.BISHOP));
|
||||||
|
this.setPiece(5, 0, new Piece(PieceColor.WHITE, PieceType.BISHOP));
|
||||||
|
this.setPiece(2, 7, new Piece(PieceColor.BLACK, PieceType.BISHOP));
|
||||||
|
this.setPiece(5, 7, new Piece(PieceColor.BLACK, PieceType.BISHOP));
|
||||||
|
|
||||||
|
// Queens and Kings
|
||||||
|
this.setPiece(3, 0, new Piece(PieceColor.WHITE, PieceType.QUEEN));
|
||||||
|
this.setPiece(4, 0, new Piece(PieceColor.WHITE, PieceType.KING));
|
||||||
|
this.setPiece(3, 7, new Piece(PieceColor.BLACK, PieceType.QUEEN));
|
||||||
|
this.setPiece(4, 7, new Piece(PieceColor.BLACK, PieceType.KING));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
#ifndef CELL_HPP
|
|
||||||
#define CELL_HPP
|
|
||||||
|
|
||||||
#include "piece.hpp"
|
|
||||||
#include <optional>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
struct Cell {
|
|
||||||
std::optional<std::shared_ptr<Piece>> piece;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace engine
|
|
||||||
|
|
||||||
#endif
|
|
||||||
9
engine/core/cell.js
Normal file
9
engine/core/cell.js
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
class Cell {
|
||||||
|
/**
|
||||||
|
* @param {Piece|null} piece
|
||||||
|
*/
|
||||||
|
constructor(piece = null) {
|
||||||
|
/** @type {Piece|null} */
|
||||||
|
this.piece = piece;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <variant>
|
|
||||||
#include <vector>
|
|
||||||
#include "move.hpp"
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
struct Event {
|
|
||||||
std::string type; // e.g., "capture", "move", "promotion", "mine_triggered"
|
|
||||||
std::string detail; // JSON or human-readable details
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace engine
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
# include "game_state.hpp"
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
GameState::GameState() : board(8, 8), whiteTeam(nullptr), blackTeam(nullptr), turn(0) {
|
|
||||||
|
|
||||||
// white pieces
|
|
||||||
board.setPiece(0, 0, Piece(PieceColor::WHITE, PieceType::ROOK));
|
|
||||||
board.setPiece(1, 0, Piece(PieceColor::WHITE, PieceType::KNIGHT));
|
|
||||||
board.setPiece(2, 0, Piece(PieceColor::WHITE, PieceType::BISHOP));
|
|
||||||
board.setPiece(3, 0, Piece(PieceColor::WHITE, PieceType::QUEEN));
|
|
||||||
board.setPiece(4, 0, Piece(PieceColor::WHITE, PieceType::KING));
|
|
||||||
board.setPiece(5, 0, Piece(PieceColor::WHITE, PieceType::BISHOP));
|
|
||||||
board.setPiece(6, 0, Piece(PieceColor::WHITE, PieceType::KNIGHT));
|
|
||||||
board.setPiece(7, 0, Piece(PieceColor::WHITE, PieceType::ROOK));
|
|
||||||
|
|
||||||
for (int x = 0; x < 8; ++x) {
|
|
||||||
board.setPiece(x, 1, Piece(PieceColor::WHITE, PieceType::PAWN));
|
|
||||||
}
|
|
||||||
|
|
||||||
// black pieces
|
|
||||||
board.setPiece(0, 7, Piece(PieceColor::BLACK, PieceType::ROOK));
|
|
||||||
board.setPiece(1, 7, Piece(PieceColor::BLACK, PieceType::KNIGHT));
|
|
||||||
board.setPiece(2, 7, Piece(PieceColor::BLACK, PieceType::BISHOP));
|
|
||||||
board.setPiece(3, 7, Piece(PieceColor::BLACK, PieceType::QUEEN));
|
|
||||||
board.setPiece(4, 7, Piece(PieceColor::BLACK, PieceType::KING));
|
|
||||||
board.setPiece(5, 7, Piece(PieceColor::BLACK, PieceType::BISHOP));
|
|
||||||
board.setPiece(6, 7, Piece(PieceColor::BLACK, PieceType::KNIGHT));
|
|
||||||
board.setPiece(7, 7, Piece(PieceColor::BLACK, PieceType::ROOK));
|
|
||||||
|
|
||||||
for (int x = 0; x < 8; ++x) {
|
|
||||||
board.setPiece(x, 6, Piece(PieceColor::BLACK, PieceType::PAWN));
|
|
||||||
}
|
|
||||||
|
|
||||||
whiteTeam = Team{std::make_shared<Piece>(board.getCell(4, 0).piece -> get() -> getColor(), board.getCell(4, 0).piece -> get() -> getType())};
|
|
||||||
blackTeam = Team{std::make_shared<Piece>(board.getCell(4, 7).piece -> get() -> getColor(), board.getCell(4, 7).piece -> get() -> getType())};
|
|
||||||
}
|
|
||||||
GameState::~GameState() = default;
|
|
||||||
|
|
||||||
bool GameState::hasHisKing(PieceColor color) {
|
|
||||||
if (color == PieceColor::WHITE) {
|
|
||||||
return whiteTeam.king != nullptr;
|
|
||||||
} else {
|
|
||||||
return blackTeam.king != nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace engine
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <optional>
|
|
||||||
#include "piece.hpp"
|
|
||||||
#include "move.hpp"
|
|
||||||
#include "board.hpp"
|
|
||||||
#include "team.hpp"
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
class GameState {
|
|
||||||
private:
|
|
||||||
Board board;
|
|
||||||
Team whiteTeam;
|
|
||||||
Team blackTeam;
|
|
||||||
int turn;
|
|
||||||
|
|
||||||
public:
|
|
||||||
GameState();
|
|
||||||
|
|
||||||
Board getBoard() { return board; };
|
|
||||||
Team getWhiteTeam() { return whiteTeam; };
|
|
||||||
Team getBlackTeam() { return blackTeam; };
|
|
||||||
int getTurn() { return turn; };
|
|
||||||
void nextTurn() { turn = 1 - turn; };
|
|
||||||
|
|
||||||
bool hasHisKing(PieceColor color);
|
|
||||||
bool isInCheck(PieceColor color);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace engine
|
|
||||||
56
engine/core/game_state.js
Normal file
56
engine/core/game_state.js
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
class GameState {
|
||||||
|
constructor() {
|
||||||
|
/** @type {Board} */
|
||||||
|
this.board = new Board();
|
||||||
|
/** @type {Team} */
|
||||||
|
this.whiteTeam = new Team("white");
|
||||||
|
/** @type {Team} */
|
||||||
|
this.blackTeam = new Team("black");
|
||||||
|
/** @type {number} */
|
||||||
|
this.turn = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Board}
|
||||||
|
*/
|
||||||
|
getBoard() {
|
||||||
|
return this.board;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Team}
|
||||||
|
*/
|
||||||
|
getWhiteTeam() {
|
||||||
|
return this.whiteTeam;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Team}
|
||||||
|
*/
|
||||||
|
getBlackTeam() {
|
||||||
|
return this.blackTeam;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
getTurn() {
|
||||||
|
return this.turn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
nextTurn() {
|
||||||
|
this.turn = 1 - this.turn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {PieceColor} color
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
hasHisKing(color) {
|
||||||
|
const team = color === PieceColor.WHITE ? this.whiteTeam : this.blackTeam;
|
||||||
|
return team.hasKing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
#include "piece.hpp"
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
struct Coord { int x; int y; };
|
|
||||||
|
|
||||||
enum class MoveActionKind {
|
|
||||||
Move,
|
|
||||||
Capture,
|
|
||||||
Create,
|
|
||||||
Remove,
|
|
||||||
SetFlag
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MoveAction {
|
|
||||||
MoveActionKind kind;
|
|
||||||
Coord from;
|
|
||||||
Coord to;
|
|
||||||
std::optional<int> extra;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class MoveType {
|
|
||||||
Normal,
|
|
||||||
Capture,
|
|
||||||
Castling,
|
|
||||||
Promotion,
|
|
||||||
Multi,
|
|
||||||
CardEffect
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Move {
|
|
||||||
std::vector<MoveAction> actions;
|
|
||||||
MoveType type = MoveType::Normal;
|
|
||||||
int playerId = -1;
|
|
||||||
std::string tag;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace engine
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "game_state.hpp"
|
|
||||||
#include "move_result.hpp"
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
class MoveApplier {
|
|
||||||
public:
|
|
||||||
MoveApplier();
|
|
||||||
|
|
||||||
MoveResult applyMove(GameState& state, const Move& move);
|
|
||||||
MoveResult simulateApply(const GameState& state, const Move& move, GameState& outState) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace engine
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "move.hpp"
|
|
||||||
#include "game_state.hpp"
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
class MoveGenerator {
|
|
||||||
public:
|
|
||||||
MoveGenerator();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace engine
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include "move.hpp"
|
|
||||||
#include "events.hpp"
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
enum class MoveStatus {
|
|
||||||
Ok,
|
|
||||||
Illegal,
|
|
||||||
BlockedByCard,
|
|
||||||
OutOfBounds,
|
|
||||||
RequiresConfirmation
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MoveResult {
|
|
||||||
MoveStatus status = MoveStatus::Ok;
|
|
||||||
std::vector<Event> events;
|
|
||||||
std::string reason;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace engine
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
#ifndef PIECE_HPP
|
|
||||||
#define PIECE_HPP
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
enum class PieceColor {
|
|
||||||
WHITE,
|
|
||||||
BLACK
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class PieceType {
|
|
||||||
PAWN,
|
|
||||||
KNIGHT,
|
|
||||||
BISHOP,
|
|
||||||
ROOK,
|
|
||||||
QUEEN,
|
|
||||||
KING
|
|
||||||
};
|
|
||||||
|
|
||||||
class Piece {
|
|
||||||
private:
|
|
||||||
PieceColor color;
|
|
||||||
PieceType type;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Piece(PieceColor c, PieceType t) : color(c), type(t) {}
|
|
||||||
|
|
||||||
PieceColor getColor() const { return color; }
|
|
||||||
PieceType getType() const { return type; }
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace engine
|
|
||||||
|
|
||||||
#endif
|
|
||||||
40
engine/core/piece.js
Normal file
40
engine/core/piece.js
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
const PieceColor = {
|
||||||
|
WHITE: 'WHITE',
|
||||||
|
BLACK: 'BLACK'
|
||||||
|
};
|
||||||
|
|
||||||
|
const PieceType = {
|
||||||
|
PAWN: 'PAWN',
|
||||||
|
KNIGHT: 'KNIGHT',
|
||||||
|
BISHOP: 'BISHOP',
|
||||||
|
ROOK: 'ROOK',
|
||||||
|
QUEEN: 'QUEEN',
|
||||||
|
KING: 'KING'
|
||||||
|
};
|
||||||
|
|
||||||
|
class Piece {
|
||||||
|
/**
|
||||||
|
* @param {PieceColor} color
|
||||||
|
* @param {PieceType} type
|
||||||
|
*/
|
||||||
|
constructor(color, type) {
|
||||||
|
/** @type {PieceColor} */
|
||||||
|
this.color = color;
|
||||||
|
/** @type {PieceType} */
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {PieceColor}
|
||||||
|
*/
|
||||||
|
getColor() {
|
||||||
|
return this.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {PieceType}
|
||||||
|
*/
|
||||||
|
getType() {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
#ifndef TEAM_HPP
|
|
||||||
#define TEAM_HPP
|
|
||||||
|
|
||||||
#include "piece.hpp"
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace engine {
|
|
||||||
|
|
||||||
struct Team {
|
|
||||||
Team(std::shared_ptr<Piece> king) : king(king) {}
|
|
||||||
|
|
||||||
enum Type { WHITE, BLACK };
|
|
||||||
std::shared_ptr<Piece> king;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace engine
|
|
||||||
|
|
||||||
#endif
|
|
||||||
22
engine/core/team.js
Normal file
22
engine/core/team.js
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
import Piece from './piece.js';
|
||||||
|
import PieceColor from './piece.js';
|
||||||
|
|
||||||
|
class Team {
|
||||||
|
/**
|
||||||
|
* @param {PieceColor} color
|
||||||
|
* @param {Piece} king
|
||||||
|
*/
|
||||||
|
constructor(color, king) {
|
||||||
|
/** @type {PieceColor} */
|
||||||
|
this.color = color;
|
||||||
|
/** @type {Piece} */
|
||||||
|
this.king = king;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
hasKing() {
|
||||||
|
return this.king !== null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../core/game_state.hpp"
|
|
||||||
#include "../core/move.hpp"
|
|
||||||
#include "../core/move_result.hpp"
|
|
||||||
#include "../core/move_generator.hpp"
|
|
||||||
|
|
||||||
namespace engine::plugins {
|
|
||||||
|
|
||||||
class EffectPlugin {
|
|
||||||
public:
|
|
||||||
virtual ~EffectPlugin() = default;
|
|
||||||
|
|
||||||
// modify the move generation step (can register extra moves)
|
|
||||||
virtual void modifyMoveGeneration(const engine::GameState& state, engine::MoveGenerator& generator) {}
|
|
||||||
|
|
||||||
// hook before applying a move (can mutate the move or block it)
|
|
||||||
virtual void onBeforeApply(engine::GameState& state, engine::Move& move, engine::MoveResult& out) {}
|
|
||||||
|
|
||||||
// hook after move applied
|
|
||||||
virtual void onAfterApply(engine::GameState& state, const engine::Move& move, engine::MoveResult& out) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace engine::plugins
|
|
||||||
Loading…
Reference in a new issue