Pass fen #1

Merged
owenrees merged 3 commits from pass-fen into main 2026-06-20 18:34:35 +00:00
2 changed files with 16 additions and 17 deletions
Showing only changes of commit 22c4e0d5fd - Show all commits
+7 -13
View File
@@ -3,19 +3,16 @@ import { Chess } from 'chess.js';
export const ChessBoard = { export const ChessBoard = {
mounted() { mounted() {
// Initialize chess.js for local rule validation
this.chess = new Chess(); this.chess = new Chess();
// Initialize Chessground
this.ground = Chessground(this.el, { this.ground = Chessground(this.el, {
fen: this.chess.fen(), fen: this.chess.fen(),
movable: { movable: {
color: 'white', color: 'white',
free: false, // Don't allow completely arbitrary drops free: false,
dests: this.getValidDests() // Only allow legal chess moves dests: this.getValidDests()
}, },
events: { events: {
// Triggered when a piece is successfully dropped
move: (orig, dest, _metadata) => { move: (orig, dest, _metadata) => {
this.handleMove(orig, dest); this.handleMove(orig, dest);
} }
@@ -34,30 +31,27 @@ export const ChessBoard = {
}, },
handleMove(orig, dest) { handleMove(orig, dest) {
// 1. Try to execute the move in chess.js state
const move = this.chess.move({ from: orig, to: dest, promotion: 'q' }); const move = this.chess.move({ from: orig, to: dest, promotion: 'q' });
if (move) { if (move) {
// 2. Telemetry back up to Phoenix LiveView const san = move.san
this.pushEvent("move_played", { this.pushEvent("move_played", {
from: orig, from: orig,
to: dest, to: dest,
san: san,
fen: this.chess.fen() fen: this.chess.fen()
}); });
// 3. Determine whose turn it is now ('w' or 'b')
const nextTurnColor = this.chess.turn() === 'w' ? 'white' : 'black'; const nextTurnColor = this.chess.turn() === 'w' ? 'white' : 'black';
// 4. Force Chessground to update its internal state for the next player
this.ground.set({ this.ground.set({
turnColor: nextTurnColor, // Switches turn tracking turnColor: nextTurnColor,
movable: { movable: {
color: nextTurnColor, // 👈 THIS IS CRITICAL: Changes who is allowed to drag pieces! color: nextTurnColor,
dests: this.getValidDests() // Re-calculates valid legal squares for Black dests: this.getValidDests()
} }
}); });
} else { } else {
// If chess.js says it's an illegal move, snap the piece back instantly
this.ground.set({ fen: this.chess.fen() }); this.ground.set({ fen: this.chess.fen() });
} }
} }
+8 -3
View File
@@ -3,7 +3,7 @@ defmodule ChesstrainerWeb.ChessTestLive do
@impl true @impl true
def mount(_params, _session, socket) do def mount(_params, _session, socket) do
{:ok, assign(socket, last_move: "None yet", total_moves: 0)} {:ok, assign(socket, last_move: "None yet", total_moves: 0, san: "None yet")}
end end
@impl true @impl true
@@ -16,6 +16,7 @@ defmodule ChesstrainerWeb.ChessTestLive do
<div> <div>
<p class="text-sm text-gray-600 font-semibold">Last Played Move:</p> <p class="text-sm text-gray-600 font-semibold">Last Played Move:</p>
<p class="text-lg font-mono text-blue-600">{@last_move}</p> <p class="text-lg font-mono text-blue-600">{@last_move}</p>
<p class="text-lg font-mono text-blue-600">{@san}</p>
</div> </div>
<div> <div>
<p class="text-sm text-gray-600 font-semibold">Total Moves:</p> <p class="text-sm text-gray-600 font-semibold">Total Moves:</p>
@@ -37,11 +38,15 @@ defmodule ChesstrainerWeb.ChessTestLive do
end end
@impl true @impl true
def handle_event("move_played", %{"from" => from, "to" => to, "fen" => _fen}, socket) do def handle_event(
# Receive the payload sent from the client JS Hook via this.pushEvent "move_played",
%{"from" => from, "to" => to, "fen" => _fen, "san" => san},
socket
) do
{:noreply, {:noreply,
socket socket
|> assign(:last_move, "#{from}#{to}") |> assign(:last_move, "#{from}#{to}")
|> assign(:san, san)
|> assign(:total_moves, socket.assigns.total_moves + 1)} |> assign(:total_moves, socket.assigns.total_moves + 1)}
end end
end end