Files
Shogi/Shogi.UI/Pages/Play/GameBoard/SeatedGameBoard.razor
2024-10-31 19:14:54 -05:00

159 lines
4.3 KiB
Plaintext

@using Shogi.Contracts.Api.Commands
@using Shogi.Contracts.Types;
@using System.Text.RegularExpressions;
@using System.Net;
@inject ShogiApi ShogiApi;
<div style="position: relative;">
<GameBoardPresentation Session="Session"
Perspective="Perspective"
OnClickHand="OnClickHand"
OnClickTile="OnClickTile"
SelectedPosition="@selectedBoardPosition"
SelectedPieceFromHand="@selectedPieceFromHand" />
@if (showPromotePrompt)
{
<!-- Promote prompt -->
<!-- TODO: Add a background div which prevents mouse inputs to the board while this decision is being made. -->
<section class="promote-prompt">
<p>Do you wish to promote?</p>
<div>
<button type="button" @onclick="() => OnClickPromotionChoice(true)">Yes</button>
<button type="button" @onclick="() => OnClickPromotionChoice(false)">No</button>
<button type="button" @onclick="() => showPromotePrompt = false">Cancel</button>
</div>
</section>
}
</div>
@code {
[Parameter, EditorRequired]
public WhichPlayer Perspective { get; set; }
[Parameter, EditorRequired]
public Session Session { get; set; } = default!;
private string? selectedBoardPosition;
private WhichPiece? selectedPieceFromHand;
private bool showPromotePrompt;
private string? moveTo;
protected override void OnParametersSet()
{
base.OnParametersSet();
selectedBoardPosition = null;
selectedPieceFromHand = null;
if (Session == null)
{
throw new ArgumentException($"{nameof(Session)} cannot be null.", nameof(Session));
}
}
bool IsWithinPromoteArea(string position)
{
if (Perspective == WhichPlayer.Player1 && Regex.IsMatch(position, ".[7-9]"))
{
return true;
}
if (Perspective == WhichPlayer.Player2 && Regex.IsMatch(position, ".[1-3]"))
{
return true;
}
return false;
}
async Task OnClickTile(string position)
{
if (showPromotePrompt) return;
var pieceAtPosition = Session.BoardState.Board[position];
if (selectedBoardPosition == position)
{
// Deselect the selected position.
selectedBoardPosition = null;
StateHasChanged();
return;
}
if (selectedBoardPosition == null && pieceAtPosition?.Owner == Perspective)
{
// Select an owned piece.
selectedBoardPosition = position;
// Prevent selecting pieces from the hand and board at the same time.
selectedPieceFromHand = null;
StateHasChanged();
return;
}
if (selectedPieceFromHand is not null)
{
if (pieceAtPosition is null)
{
// Placing a piece from the hand to an empty space.
var success = await ShogiApi.Move(
Session.SessionId,
new MovePieceCommand(selectedPieceFromHand.Value, position));
if (!success)
{
selectedPieceFromHand = null;
}
}
StateHasChanged();
return;
}
if (selectedBoardPosition != null)
{
if (pieceAtPosition == null || pieceAtPosition?.Owner != Perspective)
{
var pieceBeingMoved = Session.BoardState.Board[selectedBoardPosition];
var isPromotedAlready = pieceBeingMoved != null && pieceBeingMoved.IsPromoted;
Console.WriteLine("Is promoted? {0}", isPromotedAlready);
// Moving to an empty space or capturing an opponent's piece.
if (!isPromotedAlready && (IsWithinPromoteArea(position) || IsWithinPromoteArea(selectedBoardPosition)))
{
Console.WriteLine("Prompt!");
moveTo = position;
showPromotePrompt = true;
}
else
{
var success = await ShogiApi.Move(Session.SessionId, new MovePieceCommand(selectedBoardPosition, position, false));
if (!success)
{
selectedBoardPosition = null;
}
}
StateHasChanged();
return;
}
}
}
void OnClickHand(Piece piece)
{
if (showPromotePrompt) return;
// Prevent selecting from both the hand and the board.
selectedBoardPosition = null;
selectedPieceFromHand = piece.WhichPiece == selectedPieceFromHand
// Deselecting the already-selected piece
? selectedPieceFromHand = null
: selectedPieceFromHand = piece.WhichPiece;
StateHasChanged();
}
private async Task OnClickPromotionChoice(bool shouldPromote)
{
if (selectedBoardPosition != null && moveTo != null)
{
await ShogiApi.Move(Session.SessionId, new MovePieceCommand(selectedBoardPosition, moveTo, shouldPromote));
showPromotePrompt = false;
return;
}
throw new InvalidOperationException("Unexpected scenario during OnClickPromotionChoice.");
}
}