refactor: reorganize project structure and move examples
- Move examples (Blackjack, TicTacToe) to the root directory - Convert example projects from Console applications to Libraries - Add Directory.Build.props for shared build settings - Update solution file and project references to reflect new paths
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
using MessagePack;
|
||||
using OECS;
|
||||
|
||||
namespace Blackjack;
|
||||
|
||||
/// <summary>
|
||||
/// Player hits: draws one card from the deck to the player's hand.
|
||||
/// </summary>
|
||||
[MessagePackObject]
|
||||
public struct HitCommand : ICommand
|
||||
{
|
||||
public void Execute(World world)
|
||||
{
|
||||
ref var state = ref world.GetSingleton<GameState>();
|
||||
|
||||
if (state.Phase != GamePhase.PlayerTurn)
|
||||
return;
|
||||
|
||||
DrawCard<PlayerHand>(world);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the top card from the deck and adds it to the given hand.
|
||||
/// </summary>
|
||||
internal static void DrawCard<THand>(World world)
|
||||
where THand : struct
|
||||
{
|
||||
var singletonEntity = World.SingletonEntity;
|
||||
var deckEntity = FindEntity<Deck>(world, singletonEntity);
|
||||
var handEntity = FindEntity<THand>(world, singletonEntity);
|
||||
|
||||
if (deckEntity == Entity.Null || handEntity == Entity.Null)
|
||||
return;
|
||||
|
||||
// Find a card still in the deck.
|
||||
var cardsInDeck = world.GetSources<InDeck>(deckEntity);
|
||||
if (cardsInDeck.Count == 0)
|
||||
return;
|
||||
|
||||
var cardEntity = cardsInDeck.First();
|
||||
|
||||
// Remove from deck, add to hand.
|
||||
world.RemoveComponent<InDeck>(cardEntity);
|
||||
world.AddComponent(cardEntity, new Holds { Source = cardEntity, Target = handEntity });
|
||||
}
|
||||
|
||||
internal static Entity FindEntity<T>(World world, Entity singletonEntity)
|
||||
where T : struct
|
||||
{
|
||||
using var iter = world.Select<T>();
|
||||
while (iter.MoveNext())
|
||||
{
|
||||
if (iter.CurrentEntity != singletonEntity)
|
||||
return iter.CurrentEntity;
|
||||
}
|
||||
return Entity.Null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using MessagePack;
|
||||
using OECS;
|
||||
|
||||
namespace Blackjack;
|
||||
|
||||
/// <summary>
|
||||
/// Starts a new round after the previous one ended.
|
||||
/// </summary>
|
||||
[MessagePackObject]
|
||||
public struct NewRoundCommand : ICommand
|
||||
{
|
||||
public void Execute(World world)
|
||||
{
|
||||
ref var state = ref world.GetSingleton<GameState>();
|
||||
|
||||
if (state.Phase != GamePhase.RoundOver)
|
||||
return;
|
||||
|
||||
// Clear hands from previous round.
|
||||
var singletonEntity = World.SingletonEntity;
|
||||
var handEntities = new List<Entity>();
|
||||
using (var iter = world.Select<PlayerHand>())
|
||||
{
|
||||
while (iter.MoveNext())
|
||||
{
|
||||
if (iter.CurrentEntity != singletonEntity)
|
||||
handEntities.Add(iter.CurrentEntity);
|
||||
}
|
||||
}
|
||||
using (var iter = world.Select<DealerHand>())
|
||||
{
|
||||
while (iter.MoveNext())
|
||||
{
|
||||
if (iter.CurrentEntity != singletonEntity)
|
||||
handEntities.Add(iter.CurrentEntity);
|
||||
}
|
||||
}
|
||||
foreach (var hand in handEntities)
|
||||
{
|
||||
var cards = world.GetSources<Holds>(hand);
|
||||
var deckEntity = HitCommand.FindEntity<Deck>(world, singletonEntity);
|
||||
foreach (var card in cards)
|
||||
{
|
||||
world.RemoveComponent<Holds>(card);
|
||||
world.AddComponent(card, new InDeck { Source = card, Target = deckEntity });
|
||||
}
|
||||
}
|
||||
|
||||
state.Phase = GamePhase.Betting;
|
||||
state.Result = RoundResult.None;
|
||||
world.MarkModified<GameState>(World.SingletonEntity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using MessagePack;
|
||||
using OECS;
|
||||
|
||||
namespace Blackjack;
|
||||
|
||||
/// <summary>
|
||||
/// Places a bet and advances the game to the dealing phase.
|
||||
/// </summary>
|
||||
[MessagePackObject]
|
||||
public struct PlaceBetCommand : ICommand
|
||||
{
|
||||
[Key(0)] public int Amount;
|
||||
|
||||
public void Execute(World world)
|
||||
{
|
||||
ref var state = ref world.GetSingleton<GameState>();
|
||||
|
||||
if (state.Phase != GamePhase.Betting)
|
||||
return;
|
||||
|
||||
if (Amount < 1 || Amount > state.Chips)
|
||||
return;
|
||||
|
||||
state.CurrentBet = Amount;
|
||||
state.Chips -= Amount;
|
||||
state.Phase = GamePhase.Dealing;
|
||||
world.MarkModified<GameState>(World.SingletonEntity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using MessagePack;
|
||||
using OECS;
|
||||
|
||||
namespace Blackjack;
|
||||
|
||||
/// <summary>
|
||||
/// Player stands: advance to the dealer's turn.
|
||||
/// </summary>
|
||||
[MessagePackObject]
|
||||
public struct StandCommand : ICommand
|
||||
{
|
||||
public void Execute(World world)
|
||||
{
|
||||
ref var state = ref world.GetSingleton<GameState>();
|
||||
|
||||
if (state.Phase != GamePhase.PlayerTurn)
|
||||
return;
|
||||
|
||||
state.Phase = GamePhase.DealerTurn;
|
||||
world.MarkModified<GameState>(World.SingletonEntity);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user