181 lines
5.2 KiB
Plaintext
181 lines
5.2 KiB
Plaintext
@using Shogi.Contracts.Api
|
|
@using Shogi.Contracts.Types;
|
|
@using System.Text.RegularExpressions;
|
|
@inject IShogiApi ShogiApi
|
|
@inject AccountState Account;
|
|
@inject PromotePrompt PromotePrompt;
|
|
|
|
<article class="game-board">
|
|
<!-- Game board -->
|
|
<section class="board" data-perspective="@Perspective">
|
|
@for (var rank = 1; rank < 10; rank++)
|
|
{
|
|
foreach (var file in Files)
|
|
{
|
|
var position = $"{file}{rank}";
|
|
var piece = session?.BoardState.Board[position];
|
|
<div class="tile"
|
|
data-position="@(position)"
|
|
data-selected="@(piece != null && selectedPosition == position)"
|
|
style="grid-area: @(position)"
|
|
@onclick="() => OnClickTile(piece, position)">
|
|
<GamePiece Piece="piece" Perspective="Perspective" />
|
|
</div>
|
|
}
|
|
}
|
|
<div class="ruler vertical" style="grid-area: rank">
|
|
<span>9</span>
|
|
<span>8</span>
|
|
<span>7</span>
|
|
<span>6</span>
|
|
<span>5</span>
|
|
<span>4</span>
|
|
<span>3</span>
|
|
<span>2</span>
|
|
<span>1</span>
|
|
</div>
|
|
<div class="ruler" style="grid-area: file">
|
|
<span>A</span>
|
|
<span>B</span>
|
|
<span>C</span>
|
|
<span>D</span>
|
|
<span>E</span>
|
|
<span>F</span>
|
|
<span>G</span>
|
|
<span>H</span>
|
|
<span>I</span>
|
|
</div>
|
|
<!-- Promote prompt -->
|
|
<div class="promote-prompt">
|
|
<p>Do you wish to promote?</p>
|
|
<div>
|
|
<button type="button">Yes</button>
|
|
<button type="button">No</button>
|
|
<button type="button">Cancel</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<!-- Side board -->
|
|
@if (session != null)
|
|
{
|
|
<aside class="side-board">
|
|
<div class="hand">
|
|
@foreach (var piece in OpponentHand)
|
|
{
|
|
<div class="tile">
|
|
<GamePiece Piece="piece" Perspective="Perspective" />
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
<div class="spacer" />
|
|
|
|
<div class="hand">
|
|
@foreach (var piece in UserHand)
|
|
{
|
|
<div class="title" @onclick="() => OnClickHand(piece)">
|
|
<GamePiece Piece="piece" Perspective="Perspective" />
|
|
</div>
|
|
}
|
|
</div>
|
|
</aside>
|
|
}
|
|
</article>
|
|
|
|
@code {
|
|
static readonly string[] Files = new[] { "A", "B", "C", "D", "E", "F", "G", "H", "I" };
|
|
|
|
[Parameter]
|
|
public string? SessionName { get; set; }
|
|
|
|
WhichPlayer Perspective => Account.User?.Id == session?.Player1
|
|
? WhichPlayer.Player1
|
|
: WhichPlayer.Player2;
|
|
Session? session;
|
|
IReadOnlyCollection<Piece> OpponentHand
|
|
{
|
|
get
|
|
{
|
|
if (this.session == null) return Array.Empty<Piece>();
|
|
|
|
return Perspective == WhichPlayer.Player1
|
|
? this.session.BoardState.Player1Hand
|
|
: this.session.BoardState.Player2Hand;
|
|
}
|
|
}
|
|
IReadOnlyCollection<Piece> UserHand
|
|
{
|
|
get
|
|
{
|
|
if (this.session == null) return Array.Empty<Piece>();
|
|
|
|
return Perspective == WhichPlayer.Player1
|
|
? this.session.BoardState.Player1Hand
|
|
: this.session.BoardState.Player2Hand;
|
|
}
|
|
}
|
|
|
|
string? selectedPosition;
|
|
WhichPiece? selectedPiece;
|
|
|
|
protected override async Task OnParametersSetAsync()
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(SessionName))
|
|
{
|
|
this.session = await ShogiApi.GetSession(SessionName);
|
|
}
|
|
}
|
|
|
|
bool ShouldPromptForPromotion(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 void OnClickTile(Piece? piece, string position)
|
|
{
|
|
if (SessionName == null) return;
|
|
|
|
if (selectedPosition == null)
|
|
{
|
|
selectedPosition = position;
|
|
return;
|
|
}
|
|
else if (selectedPosition == position)
|
|
{
|
|
selectedPosition = null;
|
|
return;
|
|
}
|
|
else if (piece != null)
|
|
{
|
|
if (ShouldPromptForPromotion(position) || ShouldPromptForPromotion(selectedPosition))
|
|
{
|
|
PromotePrompt.Show(SessionName, new MovePieceCommand
|
|
{
|
|
From = selectedPosition,
|
|
To = position
|
|
});
|
|
}
|
|
else
|
|
{
|
|
await ShogiApi.PostMove(SessionName, new MovePieceCommand
|
|
{
|
|
From = selectedPosition,
|
|
IsPromotion = false,
|
|
To = position
|
|
});
|
|
}
|
|
}
|
|
}
|
|
void OnClickHand(Piece piece)
|
|
{
|
|
selectedPiece = piece.WhichPiece;
|
|
}
|
|
}
|