This commit is contained in:
2024-10-31 18:40:12 -05:00
parent a507212551
commit 09587b2f4d
6 changed files with 44 additions and 22 deletions

View File

@@ -67,7 +67,10 @@ public class SessionsController(
Player1Hand = session.Board.BoardState.Player1Hand.ToContract(), Player1Hand = session.Board.BoardState.Player1Hand.ToContract(),
Player2Hand = session.Board.BoardState.Player2Hand.ToContract(), Player2Hand = session.Board.BoardState.Player2Hand.ToContract(),
PlayerInCheck = session.Board.BoardState.InCheck?.ToContract(), PlayerInCheck = session.Board.BoardState.InCheck?.ToContract(),
WhoseTurn = session.Board.BoardState.WhoseTurn.ToContract() WhoseTurn = session.Board.BoardState.WhoseTurn.ToContract(),
Victor = session.Board.BoardState.IsCheckmate
? session.Board.BoardState.InCheck == Domain.ValueObjects.WhichPlayer.Player1 ? WhichPlayer.Player2 : WhichPlayer.Player1
: null
}, },
Player1 = application.GetUsername(session.Player1), Player1 = application.GetUsername(session.Player1),
Player2 = application.GetUsername(session.Player2), Player2 = application.GetUsername(session.Player2),

View File

@@ -1,14 +1,14 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Shogi.Contracts.Types namespace Shogi.Contracts.Types;
public class BoardState
{ {
public class BoardState public Dictionary<string, Piece?> Board { get; set; } = new Dictionary<string, Piece?>();
{ public IReadOnlyCollection<Piece> Player1Hand { get; set; } = Array.Empty<Piece>();
public Dictionary<string, Piece?> Board { get; set; } = new Dictionary<string, Piece?>(); public IReadOnlyCollection<Piece> Player2Hand { get; set; } = Array.Empty<Piece>();
public IReadOnlyCollection<Piece> Player1Hand { get; set; } = Array.Empty<Piece>(); public WhichPlayer? PlayerInCheck { get; set; }
public IReadOnlyCollection<Piece> Player2Hand { get; set; } = Array.Empty<Piece>(); public WhichPlayer WhoseTurn { get; set; }
public WhichPlayer? PlayerInCheck { get; set; } public WhichPlayer? Victor { get; set; }
public WhichPlayer WhoseTurn { get; set; }
}
} }

View File

@@ -91,6 +91,11 @@ public sealed class ShogiBoard(BoardState initialState)
public MoveResult Move(WhichPiece pieceInHand, string to) public MoveResult Move(WhichPiece pieceInHand, string to)
{ {
if (BoardState.IsCheckmate)
{
return new MoveResult(false, "The game is over. A winner has been decided.");
}
var index = BoardState.ActivePlayerHand.FindIndex(p => p.WhichPiece == pieceInHand); var index = BoardState.ActivePlayerHand.FindIndex(p => p.WhichPiece == pieceInHand);
if (index == -1) if (index == -1)
{ {
@@ -250,7 +255,8 @@ public sealed class ShogiBoard(BoardState initialState)
list.Add(position); list.Add(position);
position += path.Step; position += path.Step;
} }
} else if (position.IsInsideBoardBoundary()) }
else if (position.IsInsideBoardBoundary())
{ {
list.Add(position); list.Add(position);
} }

View File

@@ -2,14 +2,6 @@
@using System.Text.Json; @using System.Text.Json;
<article class="game-board"> <article class="game-board">
@if (IsSpectating)
{
<aside class="icons">
<div title="You are spectating.">
<span>Camera icon</span>
</div>
</aside>
}
<!-- Game board --> <!-- Game board -->
<section class="board" data-perspective="@Perspective"> <section class="board" data-perspective="@Perspective">
@for (var rank = 1; rank < 10; rank++) @for (var rank = 1; rank < 10; rank++)
@@ -74,13 +66,13 @@
</div> </div>
<div class="place-self-center"> <div class="place-self-center">
<PlayerName Name="@opponentName" IsTurn="!IsMyTurn" InCheck="IsOpponentInCheck" /> <PlayerName Name="@opponentName" IsTurn="!IsMyTurn" InCheck="IsOpponentInCheck" IsVictor="IsOpponentVictor" />
<hr /> <hr />
<PlayerName Name="@userName" IsTurn="IsMyTurn" InCheck="IsPlayerInCheck" /> <PlayerName Name="@userName" IsTurn="IsMyTurn" InCheck="IsPlayerInCheck" IsVictor="IsPlayerVictor" />
</div> </div>
<div class="player-area"> <div class="player-area">
@if (string.IsNullOrEmpty(Session.Player2) && !string.IsNullOrEmpty(Session.Player1)) @if (Perspective == WhichPlayer.Player2 && string.IsNullOrEmpty(Session.Player2))
{ {
<div class="place-self-center"> <div class="place-self-center">
<button @onclick="OnClickJoinGameInternal">Join Game</button> <button @onclick="OnClickJoinGameInternal">Join Game</button>
@@ -172,6 +164,11 @@
private bool IsOpponentInCheck => Session?.BoardState.PlayerInCheck != null && Session.BoardState.PlayerInCheck != Perspective; private bool IsOpponentInCheck => Session?.BoardState.PlayerInCheck != null && Session.BoardState.PlayerInCheck != Perspective;
private bool IsPlayerVictor => Session?.BoardState.Victor == Perspective;
private bool IsOpponentVictor => Session?.BoardState.Victor != null && Session.BoardState.Victor != Perspective;
private Func<Task> OnClickTileInternal(string position) => () => private Func<Task> OnClickTileInternal(string position) => () =>
{ {
if (IsMyTurn) if (IsMyTurn)

View File

@@ -11,6 +11,12 @@
<span>&nbsp;</span> <span>&nbsp;</span>
} }
@if (IsVictor)
{
<span class="victory-marker" title="Victory!">Victor</span>
<span>&nbsp;</span>
}
@if (string.IsNullOrEmpty(Name)) @if (string.IsNullOrEmpty(Name))
{ {
<span>Empty Seat</span> <span>Empty Seat</span>
@@ -25,5 +31,6 @@
@code { @code {
[Parameter][EditorRequired] public bool IsTurn { get; set; } [Parameter][EditorRequired] public bool IsTurn { get; set; }
[Parameter][EditorRequired] public bool InCheck { get; set; } [Parameter][EditorRequired] public bool InCheck { get; set; }
[Parameter][EditorRequired] public bool IsVictor { get; set; }
[Parameter][EditorRequired] public string Name { get; set; } = string.Empty; [Parameter][EditorRequired] public string Name { get; set; } = string.Empty;
} }

View File

@@ -15,3 +15,12 @@
font-weight: bold; font-weight: bold;
font-size: 80%; font-size: 80%;
} }
.victory-marker {
display: inline-block;
padding: 3px 8px;
background-color: darkgreen;
color: beige;
font-weight: bold;
font-size: 80%;
}