148 lines
4.2 KiB
C#
148 lines
4.2 KiB
C#
|
|
using OECS;
|
|||
|
|
|
|||
|
|
namespace Blackjack;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Renders the current game state to the console.
|
|||
|
|
/// </summary>
|
|||
|
|
public class RenderSystem : ISystem
|
|||
|
|
{
|
|||
|
|
public void Run(World world)
|
|||
|
|
{
|
|||
|
|
var state = world.ReadSingleton<GameState>();
|
|||
|
|
|
|||
|
|
Console.WriteLine();
|
|||
|
|
Console.WriteLine(" Blackjack");
|
|||
|
|
Console.WriteLine(" ═════════");
|
|||
|
|
Console.WriteLine();
|
|||
|
|
Console.WriteLine($" Chips: {state.Chips} | Round: {state.RoundNumber}");
|
|||
|
|
Console.WriteLine();
|
|||
|
|
|
|||
|
|
// Show dealer's hand.
|
|||
|
|
var dealerTotal = HandUtil.CalculateHand(world, DealerHandTag.Instance);
|
|||
|
|
Console.Write(" Dealer: ");
|
|||
|
|
if (state.Phase == GamePhase.PlayerTurn)
|
|||
|
|
{
|
|||
|
|
// Hide first card (hole card) during player's turn.
|
|||
|
|
Console.Write("?? ");
|
|||
|
|
PrintHand(world, DealerHandTag.Instance, skipFirst: true);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
PrintHand(world, DealerHandTag.Instance);
|
|||
|
|
Console.Write($" ({dealerTotal})");
|
|||
|
|
}
|
|||
|
|
Console.WriteLine();
|
|||
|
|
|
|||
|
|
// Show player's hand.
|
|||
|
|
var playerTotal = HandUtil.CalculateHand(world, PlayerHandTag.Instance);
|
|||
|
|
Console.Write(" Player: ");
|
|||
|
|
PrintHand(world, PlayerHandTag.Instance);
|
|||
|
|
Console.Write($" ({playerTotal})");
|
|||
|
|
Console.WriteLine();
|
|||
|
|
Console.WriteLine();
|
|||
|
|
|
|||
|
|
// Status line.
|
|||
|
|
switch (state.Phase)
|
|||
|
|
{
|
|||
|
|
case GamePhase.Betting:
|
|||
|
|
Console.Write($" Enter bet (1–{state.Chips}): ");
|
|||
|
|
break;
|
|||
|
|
case GamePhase.PlayerTurn:
|
|||
|
|
Console.Write(" [H]it or [S]tand: ");
|
|||
|
|
break;
|
|||
|
|
case GamePhase.RoundOver:
|
|||
|
|
Console.WriteLine($" {ResultText(state.Result)}");
|
|||
|
|
Console.WriteLine();
|
|||
|
|
Console.Write(" Press Enter for next round...");
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static void PrintHand(World world, DealerHand hand, bool skipFirst = false)
|
|||
|
|
{
|
|||
|
|
PrintHandImpl(world, hand, skipFirst);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static void PrintHand(World world, PlayerHand hand)
|
|||
|
|
{
|
|||
|
|
PrintHandImpl(world, hand, skipFirst: false);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static void PrintHandImpl<T>(World world, T handTag, bool skipFirst)
|
|||
|
|
where T : struct
|
|||
|
|
{
|
|||
|
|
Entity handEntity = Entity.Null;
|
|||
|
|
using (var iter = world.Select<T>())
|
|||
|
|
{
|
|||
|
|
while (iter.MoveNext())
|
|||
|
|
{
|
|||
|
|
if (iter.CurrentEntity != World.SingletonEntity)
|
|||
|
|
{
|
|||
|
|
handEntity = iter.CurrentEntity;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (handEntity == Entity.Null)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
var cards = world.GetSources<Holds>(handEntity);
|
|||
|
|
var ordered = cards.OrderByDescending(c =>
|
|||
|
|
{
|
|||
|
|
var card = world.ReadComponent<Card>(c);
|
|||
|
|
return (int)card.Rank;
|
|||
|
|
}).ToList();
|
|||
|
|
|
|||
|
|
bool first = true;
|
|||
|
|
foreach (var cardEntity in ordered)
|
|||
|
|
{
|
|||
|
|
if (skipFirst && first)
|
|||
|
|
{
|
|||
|
|
first = false;
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
first = false;
|
|||
|
|
var card = world.ReadComponent<Card>(cardEntity);
|
|||
|
|
Console.Write(CardToString(card));
|
|||
|
|
Console.Write(" ");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static string CardToString(Card card)
|
|||
|
|
{
|
|||
|
|
var suit = card.Suit switch
|
|||
|
|
{
|
|||
|
|
Suit.Hearts => "♥",
|
|||
|
|
Suit.Diamonds => "♦",
|
|||
|
|
Suit.Clubs => "♣",
|
|||
|
|
Suit.Spades => "♠",
|
|||
|
|
_ => "?"
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
var rank = card.Rank switch
|
|||
|
|
{
|
|||
|
|
Rank.Ace => "A",
|
|||
|
|
Rank.Jack => "J",
|
|||
|
|
Rank.Queen => "Q",
|
|||
|
|
Rank.King => "K",
|
|||
|
|
_ => ((int)card.Rank).ToString()
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return $"{rank}{suit}";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static string ResultText(RoundResult result) => result switch
|
|||
|
|
{
|
|||
|
|
RoundResult.PlayerBust => "You bust! Dealer wins.",
|
|||
|
|
RoundResult.DealerBust => "Dealer busts! You win!",
|
|||
|
|
RoundResult.PlayerWin => "You win!",
|
|||
|
|
RoundResult.DealerWin => "Dealer wins.",
|
|||
|
|
RoundResult.Push => "Push — it's a tie!",
|
|||
|
|
RoundResult.Blackjack => "Blackjack!",
|
|||
|
|
_ => ""
|
|||
|
|
};
|
|||
|
|
}
|