diff --git a/Bots/src/CardTierList.cs b/Bots/src/CardTierList.cs
index 607ae14..614f2ae 100644
--- a/Bots/src/CardTierList.cs
+++ b/Bots/src/CardTierList.cs
@@ -148,7 +148,20 @@ public class CardTierList
new CardTier("Ragpicker", PatronId.TREASURY, TierEnum.C),
new CardTier("Tithe", PatronId.TREASURY, TierEnum.C),
new CardTier("Writ of Coin", PatronId.TREASURY, TierEnum.D),
- new CardTier("Unknown", PatronId.TREASURY, TierEnum.UNKNOWN)
+ new CardTier("Unknown", PatronId.TREASURY, TierEnum.UNKNOWN),
+ // Added Saint Alessia
+ new CardTier("Alessian Rebel", PatronId.SAINT_ALESSIA, TierEnum.C),
+ new CardTier("Ayleid Defector", PatronId.SAINT_ALESSIA, TierEnum.B),
+ new CardTier("Ayleid Quartermaster", PatronId.SAINT_ALESSIA, TierEnum.B),
+ new CardTier("Chainbreaker Captain", PatronId.SAINT_ALESSIA, TierEnum.A),
+ new CardTier("Chainbreaker Sergeant", PatronId.SAINT_ALESSIA, TierEnum.B),
+ new CardTier("Morihuas Sacred Bull", PatronId.SAINT_ALESSIA, TierEnum.S),
+ new CardTier("Morihuas the Archer", PatronId.SAINT_ALESSIA, TierEnum.A),
+ new CardTier("Pelinal Whitestrake", PatronId.SAINT_ALESSIA, TierEnum.S),
+ new CardTier("Priestess of the Eight", PatronId.SAINT_ALESSIA, TierEnum.B),
+ new CardTier("Saints Wrath", PatronId.SAINT_ALESSIA, TierEnum.B),
+ new CardTier("Soldier of the Empire", PatronId.SAINT_ALESSIA, TierEnum.C),
+ new CardTier("Whitestrake Ascendant", PatronId.SAINT_ALESSIA, TierEnum.S),
};
public static TierEnum GetCardTier(string cardName)
diff --git a/Engine/TalesOfTribute.csproj b/Engine/TalesOfTribute.csproj
index 2bab50c..c90abab 100644
--- a/Engine/TalesOfTribute.csproj
+++ b/Engine/TalesOfTribute.csproj
@@ -18,9 +18,10 @@
-
- Always
-
+
+
+ Never
+
diff --git a/Engine/src/Board/BoardManager.cs b/Engine/src/Board/BoardManager.cs
index b795400..ec662c4 100644
--- a/Engine/src/Board/BoardManager.cs
+++ b/Engine/src/Board/BoardManager.cs
@@ -23,7 +23,7 @@ public BoardManager(PatronId[] patrons, ulong seed)
_rng = new SeededRandom(seed);
Patrons = GetPatrons(patrons);
var patronStarterCardsIds = Patrons.SelectMany(patron => patron.GetStarterCards()).ToArray();
- Tavern = new Tavern(GlobalCardDatabase.Instance.GetCardsByPatron(patrons, patronStarterCardsIds), _rng);
+ Tavern = new Tavern(GlobalCardDatabase.Instance.GetCardsByPatron(patrons, patronStarterCardsIds, CardId.WRIT_OF_COIN), _rng);
_playerContext = new PlayerContext(new Player(PlayerEnum.PLAYER1, _rng), new Player(PlayerEnum.PLAYER2, _rng));
CardActionManager = new CardActionManager(_playerContext, Tavern);
}
diff --git a/Engine/src/Board/CardAction/ComplexEffectExecutor.cs b/Engine/src/Board/CardAction/ComplexEffectExecutor.cs
index c64de05..74dbf87 100644
--- a/Engine/src/Board/CardAction/ComplexEffectExecutor.cs
+++ b/Engine/src/Board/CardAction/ComplexEffectExecutor.cs
@@ -226,17 +226,23 @@ public PlayResult Donate(Choice choice, List choices)
}
private void handleSaintAlessiaTriggers(List knockoutedCards)
{
- if (!_enemyPlayer.AgentCards.Any(c => c.CommonId == CardId.MORIHAUS_SACRED_BULL || c.CommonId == CardId.MORIHAUS_THE_ARCHER))
- return;
-
- foreach (var triggerCard in _enemyPlayer.AgentCards.Where(c => c.CommonId == CardId.MORIHAUS_SACRED_BULL || c.CommonId == CardId.MORIHAUS_THE_ARCHER).ToList())
+ void HandleForPlayer(IPlayer player)
{
- if (knockoutedCards.Any(c => c.UniqueId == triggerCard.UniqueId))
- continue;
- _enemyPlayer.CoinsAmount++;
- _parent.AddToCompletedActionsList(new CompletedAction(_enemyPlayer.ID, CompletedActionType.GAIN_COIN, triggerCard, 1));
+ var morihausAgents = player.AgentCards
+ .Where(c => c.CommonId == CardId.MORIHAUS_SACRED_BULL || c.CommonId == CardId.MORIHAUS_THE_ARCHER)
+ .ToList();
+
+ foreach (var triggerCard in morihausAgents)
+ {
+ if (knockoutedCards.Any(c => c.UniqueId == triggerCard.UniqueId))
+ continue;
+
+ player.CoinsAmount++;
+ _parent.AddToCompletedActionsList(new CompletedAction(player.ID, CompletedActionType.GAIN_COIN, triggerCard, 1));
+ }
}
-
- }
+ HandleForPlayer(_currentPlayer);
+ HandleForPlayer(_enemyPlayer);
+ }
}
diff --git a/Engine/src/Board/Cards/UniqueCard.cs b/Engine/src/Board/Cards/UniqueCard.cs
index ba8d73b..76abdc4 100644
--- a/Engine/src/Board/Cards/UniqueCard.cs
+++ b/Engine/src/Board/Cards/UniqueCard.cs
@@ -18,7 +18,7 @@ public UniqueCard(string name, PatronId deck, CardId commonId, int cost, CardTyp
public override string ToString()
{
return string.Format($"Card: {this.Name}, " +
- $"Deck: {this.Deck}, Cost: {this.Cost}, Type: {this.Type}, UniqueId: {UniqueId.Value}");
+ $"Deck: {this.Deck}, Cost: {this.Cost}, Type: {this.Type}, UniqueId: {UniqueId.Value}");
}
public override bool Equals(object? obj)
diff --git a/Engine/src/Board/Cards/UniqueEffect.cs b/Engine/src/Board/Cards/UniqueEffect.cs
index 3bddeb3..29d1ce6 100644
--- a/Engine/src/Board/Cards/UniqueEffect.cs
+++ b/Engine/src/Board/Cards/UniqueEffect.cs
@@ -143,7 +143,7 @@ public UniqueEffect(EffectType type, int amount, int combo, UniqueCard parentCar
ChoiceFollowUp.REFRESH_CARDS,
context,
amount,
- amount
+ 0
), new List());
}
case EffectType.TOSS:
@@ -213,7 +213,7 @@ public UniqueEffect(EffectType type, int amount, int combo, UniqueCard parentCar
ChoiceFollowUp.REFRESH_CARDS,
context,
agentsCount,
- agentsCount
+ 0
), new List());
case EffectType.DONATE:
{
@@ -250,6 +250,7 @@ public override string ToString()
EffectType.CREATE_SUMMERSET_SACKING => $"Create {Amount} Summerset Sacking cards and place it in CD pile",
EffectType.HEAL => $"Heal this agent by {Amount}",
EffectType.DONATE => $"Discard up to {Amount} cards from hand, draw {Amount} cards",
+ EffectType.KNOCKOUT_ALL => $"Knockout all agents",
_ => ""
};
}
diff --git a/Engine/src/utils/CardDatabase.cs b/Engine/src/utils/CardDatabase.cs
index d38546a..0cbf786 100644
--- a/Engine/src/utils/CardDatabase.cs
+++ b/Engine/src/utils/CardDatabase.cs
@@ -19,10 +19,10 @@ public UniqueCard GetCard(CardId cardId)
return card;
}
- public List GetCardsByPatron(PatronId[] patrons, CardId[] starterCardsId)
+ public List GetCardsByPatron(PatronId[] patrons, CardId[] starterCardsId, params CardId[] excludeCards)
{
var allCardsGrouped = from card in _allCards
- where patrons.Contains(card.Deck) && !starterCardsId.Contains(card.CommonId) && card.Type != CardType.CURSE
+ where patrons.Contains(card.Deck) && !starterCardsId.Contains(card.CommonId) && !excludeCards.Contains(card.CommonId) && card.Type != CardType.CURSE
select Enumerable.Range(0, card.Copies).Select(_ => card.CreateUniqueCopy()).ToList();
return allCardsGrouped.SelectMany(c => c).ToList();
diff --git a/Engine/src/utils/GlobalCardDatabase.cs b/Engine/src/utils/GlobalCardDatabase.cs
index 2be969a..e316ebd 100644
--- a/Engine/src/utils/GlobalCardDatabase.cs
+++ b/Engine/src/utils/GlobalCardDatabase.cs
@@ -1,4 +1,6 @@
-namespace ScriptsOfTribute;
+using System.Reflection;
+
+namespace ScriptsOfTribute;
public class GlobalCardDatabase
{
@@ -10,7 +12,17 @@ public static CardDatabase Instance
{
if (_instance != null) return _instance.Value;
- var data = File.ReadAllText("cards.json");
+ var assembly = Assembly.GetExecutingAssembly();
+ const string resourceName = "TalesOfTribute.cards.json";
+ using Stream? stream = assembly.GetManifestResourceStream(resourceName);
+
+ if (stream == null)
+ {
+ throw new InvalidOperationException($"Cant find resource'{resourceName}' in DLL. Available resources: {string.Join(", ", assembly.GetManifestResourceNames())}");
+ }
+
+ using StreamReader reader = new StreamReader(stream);
+ string data = reader.ReadToEnd();
var parser = new Parser(data);
_instance = new ThreadLocal(() => new CardDatabase(parser.CreateAllCards()));
diff --git a/Tests/Board/SaintAlessiaTests.cs b/Tests/Board/SaintAlessiaTests.cs
index 98bf213..2d3b927 100644
--- a/Tests/Board/SaintAlessiaTests.cs
+++ b/Tests/Board/SaintAlessiaTests.cs
@@ -67,7 +67,7 @@ void TestDonateEffect()
br.CurrentPlayer.Hand.Add(priestess);
br.CurrentPlayer.Hand.Add(sote);
br.CurrentPlayer.Hand.Add(armory);
-
+
var chainbreaker = GlobalCardDatabase.Instance.GetCard(CardId.CHAINBREAKER_CAPTAIN);
var morihaus = GlobalCardDatabase.Instance.GetCard(CardId.MORIHAUS_SACRED_BULL);
br.CurrentPlayer.DrawPile.Add(chainbreaker);
@@ -200,4 +200,35 @@ void TestRefreshTopAgents()
Assert.Equal(BoardState.NORMAL, br.CardActionManager.State);
Assert.Contains(chainbreaker_sergeant, br.CurrentPlayer.DrawPile);
}
+
+ [Fact]
+ void TestMorihausTriggersBothPlayers()
+ {
+ var br = new BoardManager([PatronId.TREASURY, PatronId.PELIN, PatronId.RED_EAGLE, PatronId.ANSEI, PatronId.SAINT_ALESSIA], 123);
+
+ var morihaus1 = Agent.FromCard(GlobalCardDatabase.Instance.GetCard(CardId.MORIHAUS_SACRED_BULL));
+ var morihaus2 = Agent.FromCard(GlobalCardDatabase.Instance.GetCard(CardId.MORIHAUS_THE_ARCHER));
+ var soldier1 = Agent.FromCard(GlobalCardDatabase.Instance.GetCard(CardId.SOLDIER_OF_THE_EMPIRE));
+ var soldier2 = Agent.FromCard(GlobalCardDatabase.Instance.GetCard(CardId.SOLDIER_OF_THE_EMPIRE));
+
+ br.CurrentPlayer.Agents.Add(morihaus1);
+ br.CurrentPlayer.Agents.Add(soldier1);
+
+ br.EnemyPlayer.Agents.Add(morihaus2);
+ br.EnemyPlayer.Agents.Add(soldier2);
+
+ var black_sacrament = GlobalCardDatabase.Instance.GetCard(CardId.BLACK_SACRAMENT);
+ br.CurrentPlayer.Hand.Add(black_sacrament);
+
+ br.PlayCard(black_sacrament);
+
+ var knockout = br.CardActionManager.PendingChoice!.PossibleCards
+ .Where(card => card.CommonId == CardId.SOLDIER_OF_THE_EMPIRE && br.EnemyPlayer.Agents.Any(a => a.RepresentingCard.UniqueId == card.UniqueId))
+ .ToList();
+
+ br.CardActionManager.MakeChoice(knockout);
+
+ Assert.Equal(1, br.EnemyPlayer.CoinsAmount);
+ Assert.Equal(1, br.CurrentPlayer.CoinsAmount);
+ }
}
diff --git a/gRPC/Services/AIService.cs b/gRPC/Services/AIService.cs
index 2148f38..6659409 100644
--- a/gRPC/Services/AIService.cs
+++ b/gRPC/Services/AIService.cs
@@ -44,7 +44,7 @@ public PatronId SelectPatron(List availablePatrons, int round)
};
request.AvailablePatrons.AddRange(availablePatrons.Select(patronId => (PatronIdProto)(patronId)).ToList());
-
+
var response = _client.SelectPatron(request);
return (PatronId)(response.PatronId);
}