├── Binaries
├── Autofac
│ ├── Autofac.dll
│ ├── Autofac.Configuration.dll
│ ├── Autofac.Integration.Web.dll
│ └── Autofac.Integration.Web.Mvc.dll
├── Newtonsoft.Json.dll
├── Rx
│ ├── System.CoreEx.dll
│ ├── System.Reactive.dll
│ ├── System.Interactive.dll
│ ├── System.Observable.dll
│ └── System.Observable.xml
├── nunit.framework.dll
├── Microsoft.Web.Mvc.dll
├── MvcContrib
│ ├── MvcContrib.dll
│ └── MvcContrib.FluentHtml.dll
└── SpecFlow
│ ├── TechTalk.SpecFlow.dll
│ ├── TechTalk.SpecFlow.Parser.dll
│ └── TechTalk.SpecFlow.Generator.dll
├── Dominion.Web
├── Global.asax
├── Content
│ ├── jqueryUI
│ │ └── images
│ │ │ ├── ui-icons_222222_256x240.png
│ │ │ ├── ui-icons_2e83ff_256x240.png
│ │ │ ├── ui-icons_454545_256x240.png
│ │ │ ├── ui-icons_888888_256x240.png
│ │ │ ├── ui-icons_cd0a0a_256x240.png
│ │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png
│ │ │ ├── ui-bg_flat_75_ffffff_40x100.png
│ │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png
│ │ │ ├── ui-bg_glass_65_ffffff_1x400.png
│ │ │ ├── ui-bg_glass_75_dadada_1x400.png
│ │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png
│ │ │ ├── ui-bg_glass_95_fef1ec_1x400.png
│ │ │ └── ui-bg_highlight-soft_75_cccccc_1x100.png
│ └── HTMLPage1.htm
├── ViewModels
│ ├── PlayerActionResultViewModel.cs
│ ├── GameViewModel.cs
│ └── NewGameViewModel.cs
├── ActionFilters
│ └── InjectClientAttribute.cs
├── Views
│ ├── Home
│ │ └── ViewPlayers.aspx
│ └── Shared
│ │ └── site.Master
├── Web.config
├── Bootstrap
│ └── AutofacConfig.cs
├── Web.Debug.config
├── Web.Release.config
└── Properties
│ └── AssemblyInfo.cs
├── Dominion.Rules
├── CardTypes
│ ├── IMoneyCard.cs
│ ├── ICurseCard.cs
│ ├── ITreasureCard.cs
│ ├── IVictoryCard.cs
│ ├── ISCoreCard.cs
│ ├── SameTypeEqualityComparer.cs
│ └── IActionCard.cs
├── DiscardPile.cs
├── ICard.cs
├── TrashPile.cs
├── Activities
│ ├── WaitingForPlayersActivity.cs
│ ├── PlayActionsActivity.cs
│ ├── DoBuysActivity.cs
│ ├── IActivity.cs
│ ├── ExtensionMethods.cs
│ ├── GainACardActivity.cs
│ └── SelectReactionActivity.cs
├── ILongLivedCardEffect.cs
├── LimitedSupplyCardPile.cs
├── DurationEffect.cs
├── PlayArea.cs
├── NullZone.cs
├── EnumerableCardZone.cs
├── CardPile.cs
├── Hand.cs
├── ReactionEffect.cs
├── GameScores.cs
├── UnlimitedSupplyCardPile.cs
├── Card.cs
├── PassiveCardEffectBase.cs
├── MyExtensions.cs
├── CardBank.cs
└── Properties
│ └── AssemblyInfo.cs
├── Dominion.WinForms
├── app.config
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ └── AssemblyInfo.cs
└── Program.cs
├── .gitignore
├── Dominion.Specs
├── Cards
│ ├── Smithy.feature
│ ├── Gardens.feature
│ ├── Woodcutter.feature
│ ├── Festival.feature
│ ├── Laboratory.feature
│ ├── Market.feature
│ ├── WorkersVillage.feature
│ ├── CouncilRoom.feature
│ ├── Feast.feature
│ ├── Harem.feature
│ ├── GreatHall.feature
│ ├── Moneylender.feature
│ ├── Chapel.feature
│ ├── MerchantShip.feature
│ ├── Wharf.feature
│ ├── ShantyTown.feature
│ ├── Familiar.feature
│ ├── Tactician.feature
│ ├── CountingHouse.feature
│ ├── Witch.feature
│ ├── SeaHag.feature
│ ├── KingsCourt.feature
│ ├── Cutpurse.feature
│ ├── Coppersmith.feature
│ ├── Mine.feature
│ ├── Courtyard.feature
│ ├── Moat.feature
│ ├── Workshop.feature
│ ├── Expand.feature
│ ├── Remodel.feature
│ ├── Nobles.feature
│ ├── TreasureMap.feature
│ ├── Cellar.feature
│ ├── University.feature
│ ├── City.feature
│ ├── Chancellor.feature
│ ├── Duke.feature
│ ├── Vineyard.feature
│ ├── Envoy.feature
│ ├── Warehouse.feature
│ ├── Salvager.feature
│ ├── Apprentice.feature
│ ├── Mountebank.feature
│ ├── TradingPost.feature
│ ├── Explorer.feature
│ ├── Baron.feature
│ ├── Adventurer.feature
│ ├── Torturer.feature
│ └── Apothecary.feature
├── TurnMechanics.feature
├── TurnOrder.feature
├── Hosted
│ ├── GameHost.feature
│ └── Reactions.feature
├── GameLog.feature
├── Scoring.feature
├── Bindings
│ ├── Extensions.cs
│ ├── BindingBase.cs
│ └── ScoringBindings.cs
├── GameEnd.feature
└── Properties
│ └── AssemblyInfo.cs
├── Dominion.GameHost
├── IGameActionMessage.cs
├── AI
│ ├── BehaviourBased
│ │ ├── ProbabilityExtensions.cs
│ │ ├── SkipBuyBehaviour.cs
│ │ ├── SkipActionsBehaviour.cs
│ │ ├── CommentOnGameEndBehaviour.cs
│ │ ├── DefaultSelectFromRevealedBehaviour.cs
│ │ ├── BuyPotionBehaviour.cs
│ │ ├── DefaultMakeChoiceBehaviour.cs
│ │ ├── BigMoneyBuyBehaviour.cs
│ │ ├── DefaultSelectFixedNumberOfCardsToPassOrTrashBehaviour.cs
│ │ ├── BigMoneyAI.cs
│ │ ├── DefaultSelectUpToNumberOfCardsToTrashBehaviour.cs
│ │ ├── PlaySimpleActionsBehaviour.cs
│ │ ├── DefaultDiscardOrRedrawCardsBehaviour.cs
│ │ ├── SimpleAI.cs
│ │ ├── DefaultSelectFixedNumberOfCardsForPlayBehaviour.cs
│ │ ├── ProbabilityAI.cs
│ │ ├── SelectFixedNumberOfCardsBehaviourBase.cs
│ │ └── BuySimpleActionsBehaviour.cs
│ ├── Treasure.cs
│ └── VictoryCards.cs
├── BeginGameMessage.cs
├── EndTurnMessage.cs
├── MoveToBuyStepMessage.cs
├── CardBuilderExtensions.cs
├── BuyCardMessage.cs
├── PlayCardMessage.cs
├── ChoiceMessage.cs
├── ChooseAPileMessage.cs
├── SimpleStartingConfiguration.cs
├── ChosenStartingConfiguration.cs
└── Properties
│ └── AssemblyInfo.cs
├── README.markdown
├── Dominion.AIWorkbench
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ └── AssemblyInfo.cs
└── Program.cs
├── Dominion.Cards
├── Treasure
│ ├── Gold.cs
│ ├── Copper.cs
│ ├── Silver.cs
│ ├── Platinum.cs
│ └── Potion.cs
├── Curses
│ └── Curse.cs
├── Actions
│ ├── Village.cs
│ ├── Woodcutter.cs
│ ├── Smithy.cs
│ ├── WorkersVillage.cs
│ ├── Bazaar.cs
│ ├── Laboratory.cs
│ ├── Workshop.cs
│ ├── Festival.cs
│ ├── Courtyard.cs
│ ├── University.cs
│ ├── Market.cs
│ ├── Harem.cs
│ ├── Cellar.cs
│ ├── CouncilRoom.cs
│ ├── Expand.cs
│ ├── ShantyTown.cs
│ ├── Feast.cs
│ ├── City.cs
│ ├── Moat.cs
│ ├── Ironworks.cs
│ ├── MerchantShip.cs
│ ├── Familiar.cs
│ ├── Chapel.cs
│ ├── Wharf.cs
│ ├── Witch.cs
│ ├── Coppersmith.cs
│ ├── Cutpurse.cs
│ ├── SeaHag.cs
│ ├── TreasureMap.cs
│ ├── Transmute.cs
│ ├── Moneylender.cs
│ ├── Tribute.cs
│ ├── GhostShip.cs
│ ├── CountingHouse.cs
│ ├── Militia.cs
│ ├── KingsCourt.cs
│ ├── FishingVillage.cs
│ ├── ThroneRoom.cs
│ ├── Chancellor.cs
│ ├── Spy.cs
│ ├── Warehouse.cs
│ ├── Explorer.cs
│ ├── Rabble.cs
│ ├── Apothecary.cs
│ └── Salvager.cs
├── Victory
│ ├── Duke.cs
│ ├── Vineyard.cs
│ ├── Colony.cs
│ ├── Province.cs
│ ├── Estate.cs
│ ├── Duchy.cs
│ └── Gardens.cs
├── Hybrid
│ └── GreatHall.cs
├── TestCard.cs
└── Properties
│ └── AssemblyInfo.cs
├── Dominion.Tests
├── HelperExtensions.cs
├── CardMovementTests.cs
└── Properties
│ └── AssemblyInfo.cs
├── Dominion.5.1.ReSharper
└── LICENSE.txt
/Binaries/Autofac/Autofac.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Binaries/Autofac/Autofac.dll
--------------------------------------------------------------------------------
/Binaries/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Binaries/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/Binaries/Rx/System.CoreEx.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Binaries/Rx/System.CoreEx.dll
--------------------------------------------------------------------------------
/Binaries/nunit.framework.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Binaries/nunit.framework.dll
--------------------------------------------------------------------------------
/Binaries/Microsoft.Web.Mvc.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Binaries/Microsoft.Web.Mvc.dll
--------------------------------------------------------------------------------
/Binaries/Rx/System.Reactive.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Binaries/Rx/System.Reactive.dll
--------------------------------------------------------------------------------
/Binaries/MvcContrib/MvcContrib.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Binaries/MvcContrib/MvcContrib.dll
--------------------------------------------------------------------------------
/Binaries/Rx/System.Interactive.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Binaries/Rx/System.Interactive.dll
--------------------------------------------------------------------------------
/Binaries/Rx/System.Observable.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Binaries/Rx/System.Observable.dll
--------------------------------------------------------------------------------
/Binaries/SpecFlow/TechTalk.SpecFlow.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Binaries/SpecFlow/TechTalk.SpecFlow.dll
--------------------------------------------------------------------------------
/Dominion.Web/Global.asax:
--------------------------------------------------------------------------------
1 | <%@ Application Codebehind="Global.asax.cs" Inherits="Dominion.Web.MvcApplication" Language="C#" %>
2 |
--------------------------------------------------------------------------------
/Binaries/Autofac/Autofac.Configuration.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Binaries/Autofac/Autofac.Configuration.dll
--------------------------------------------------------------------------------
/Binaries/Autofac/Autofac.Integration.Web.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Binaries/Autofac/Autofac.Integration.Web.dll
--------------------------------------------------------------------------------
/Binaries/MvcContrib/MvcContrib.FluentHtml.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Binaries/MvcContrib/MvcContrib.FluentHtml.dll
--------------------------------------------------------------------------------
/Binaries/SpecFlow/TechTalk.SpecFlow.Parser.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Binaries/SpecFlow/TechTalk.SpecFlow.Parser.dll
--------------------------------------------------------------------------------
/Binaries/Autofac/Autofac.Integration.Web.Mvc.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Binaries/Autofac/Autofac.Integration.Web.Mvc.dll
--------------------------------------------------------------------------------
/Binaries/SpecFlow/TechTalk.SpecFlow.Generator.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Binaries/SpecFlow/TechTalk.SpecFlow.Generator.dll
--------------------------------------------------------------------------------
/Dominion.Rules/CardTypes/IMoneyCard.cs:
--------------------------------------------------------------------------------
1 | namespace Dominion.Rules.CardTypes
2 | {
3 | public interface IMoneyCard : ITreasureCard
4 | {
5 | }
6 | }
--------------------------------------------------------------------------------
/Dominion.Rules/CardTypes/ICurseCard.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Dominion.Rules.CardTypes
4 | {
5 | public interface ICurseCard : IScoreCard
6 | {
7 | }
8 | }
--------------------------------------------------------------------------------
/Dominion.Web/Content/jqueryUI/images/ui-icons_222222_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Dominion.Web/Content/jqueryUI/images/ui-icons_222222_256x240.png
--------------------------------------------------------------------------------
/Dominion.Web/Content/jqueryUI/images/ui-icons_2e83ff_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Dominion.Web/Content/jqueryUI/images/ui-icons_2e83ff_256x240.png
--------------------------------------------------------------------------------
/Dominion.Web/Content/jqueryUI/images/ui-icons_454545_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Dominion.Web/Content/jqueryUI/images/ui-icons_454545_256x240.png
--------------------------------------------------------------------------------
/Dominion.Web/Content/jqueryUI/images/ui-icons_888888_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Dominion.Web/Content/jqueryUI/images/ui-icons_888888_256x240.png
--------------------------------------------------------------------------------
/Dominion.Web/Content/jqueryUI/images/ui-icons_cd0a0a_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Dominion.Web/Content/jqueryUI/images/ui-icons_cd0a0a_256x240.png
--------------------------------------------------------------------------------
/Dominion.Web/Content/jqueryUI/images/ui-bg_flat_0_aaaaaa_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Dominion.Web/Content/jqueryUI/images/ui-bg_flat_0_aaaaaa_40x100.png
--------------------------------------------------------------------------------
/Dominion.WinForms/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Dominion.Web/Content/jqueryUI/images/ui-bg_flat_75_ffffff_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Dominion.Web/Content/jqueryUI/images/ui-bg_flat_75_ffffff_40x100.png
--------------------------------------------------------------------------------
/Dominion.Web/Content/jqueryUI/images/ui-bg_glass_55_fbf9ee_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Dominion.Web/Content/jqueryUI/images/ui-bg_glass_55_fbf9ee_1x400.png
--------------------------------------------------------------------------------
/Dominion.Web/Content/jqueryUI/images/ui-bg_glass_65_ffffff_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Dominion.Web/Content/jqueryUI/images/ui-bg_glass_65_ffffff_1x400.png
--------------------------------------------------------------------------------
/Dominion.Web/Content/jqueryUI/images/ui-bg_glass_75_dadada_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Dominion.Web/Content/jqueryUI/images/ui-bg_glass_75_dadada_1x400.png
--------------------------------------------------------------------------------
/Dominion.Web/Content/jqueryUI/images/ui-bg_glass_75_e6e6e6_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Dominion.Web/Content/jqueryUI/images/ui-bg_glass_75_e6e6e6_1x400.png
--------------------------------------------------------------------------------
/Dominion.Web/Content/jqueryUI/images/ui-bg_glass_95_fef1ec_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Dominion.Web/Content/jqueryUI/images/ui-bg_glass_95_fef1ec_1x400.png
--------------------------------------------------------------------------------
/Dominion.Rules/CardTypes/ITreasureCard.cs:
--------------------------------------------------------------------------------
1 | namespace Dominion.Rules.CardTypes
2 | {
3 | public interface ITreasureCard : ICard
4 | {
5 | CardCost Value { get; }
6 | }
7 | }
--------------------------------------------------------------------------------
/Dominion.Web/Content/jqueryUI/images/ui-bg_highlight-soft_75_cccccc_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulbatum/Dominion/HEAD/Dominion.Web/Content/jqueryUI/images/ui-bg_highlight-soft_75_cccccc_1x100.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | obj
2 | bin
3 | _ReSharper.*
4 | *.csproj.user
5 | *.resharper.user
6 | *.ReSharper.user
7 | *.resharper
8 | *.suo
9 | *.cache
10 | *~
11 | *.swp
12 | Dominion.Web/Content/Images/Cards
13 | *.Publish.xml
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Smithy.feature:
--------------------------------------------------------------------------------
1 | Feature: Smithy
2 |
3 | Scenario: Play Smithy
4 | Given A new game with 3 players
5 | And Player1 has a Smithy in hand instead of a Copper
6 | When Player1 plays a Smithy
7 | Then Player1 should have 7 cards in hand
--------------------------------------------------------------------------------
/Dominion.Web/ViewModels/PlayerActionResultViewModel.cs:
--------------------------------------------------------------------------------
1 | using Dominion.GameHost;
2 |
3 | namespace Dominion.Web.ViewModels
4 | {
5 | public class PlayerActionResultViewModel
6 | {
7 | public GameViewModel GameState { get; set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Gardens.feature:
--------------------------------------------------------------------------------
1 | Feature: Gardens
2 |
3 | Scenario: GardensInDeck
4 | Given A new game with 3 players
5 | And Player1 has a Gardens in hand instead of a Copper
6 | When The game is scored
7 | Then Player1 should have 4 victory points
8 |
--------------------------------------------------------------------------------
/Dominion.GameHost/IGameActionMessage.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules;
2 |
3 | namespace Dominion.GameHost
4 | {
5 | public interface IGameActionMessage
6 | {
7 | void UpdateGameState(Game game);
8 | void Validate(Game game);
9 | }
10 | }
--------------------------------------------------------------------------------
/README.markdown:
--------------------------------------------------------------------------------
1 | # Dominion #
2 |
3 | This is a C# implementation of [Dominion](http://www.riograndegames.com/games.html?id=278), a board/card game.
4 |
5 | Be aware that the web client isn't very usable after cloning the repository because I do not distribute the card images.
6 |
--------------------------------------------------------------------------------
/Dominion.Rules/CardTypes/IVictoryCard.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Dominion.Rules.CardTypes
7 | {
8 | public interface IVictoryCard : IScoreCard
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Woodcutter.feature:
--------------------------------------------------------------------------------
1 | Feature: Woodcutter
2 |
3 | Scenario: Play Woodcutter
4 | Given A new game with 3 players
5 | And Player1 has a Woodcutter in hand instead of a Copper
6 | When Player1 plays a Woodcutter
7 | Then Player1 should have 2 buys
8 | Then Player1 should have 2 to spend
--------------------------------------------------------------------------------
/Dominion.Web/Content/HTMLPage1.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Dominion.AIWorkbench/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Dominion.WinForms/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Dominion.Rules/CardTypes/ISCoreCard.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Dominion.Rules.CardTypes
7 | {
8 | public interface IScoreCard : ICard
9 | {
10 | int Score(EnumerableCardZone allCards);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Dominion.Rules/DiscardPile.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 |
4 | namespace Dominion.Rules
5 | {
6 | public class DiscardPile : EnumerableCardZone
7 | {
8 | public ICard TopCard
9 | {
10 | get { return this.Cards.Last(); }
11 | }
12 |
13 |
14 | }
15 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Treasure/Gold.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules.CardTypes;
2 | using Dominion.Rules;
3 |
4 | namespace Dominion.Cards.Treasure
5 | {
6 | public class Gold : Card, IMoneyCard
7 | {
8 | public Gold()
9 | : base(6)
10 | { }
11 |
12 | public CardCost Value { get { return 3; } }
13 | }
14 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Treasure/Copper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Dominion.Rules;
3 | using Dominion.Rules.CardTypes;
4 |
5 | namespace Dominion.Cards.Treasure
6 | {
7 | public class Copper : Card, IMoneyCard
8 | {
9 | public Copper() : base(0)
10 | {}
11 |
12 | public CardCost Value { get { return 1; } }
13 | }
14 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Treasure/Silver.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules.CardTypes;
2 | using Dominion.Rules;
3 |
4 | namespace Dominion.Cards.Treasure
5 | {
6 | public class Silver : Card, IMoneyCard
7 | {
8 | public Silver()
9 | : base(3)
10 | { }
11 |
12 | public CardCost Value { get { return 2; } }
13 | }
14 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Festival.feature:
--------------------------------------------------------------------------------
1 | Feature: Festival
2 |
3 | Scenario: Play Festival
4 | Given A new game with 3 players
5 | And Player1 has a Festival in hand instead of a Copper
6 | When Player1 plays a Festival
7 | Then Player1 should have 2 to spend
8 | Then Player1 should have 2 buys
9 | Then Player1 should have 2 remaining action
10 |
--------------------------------------------------------------------------------
/Dominion.Cards/Treasure/Platinum.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules;
2 | using Dominion.Rules.CardTypes;
3 |
4 | namespace Dominion.Cards.Treasure
5 | {
6 | public class Platinum : Card, IMoneyCard
7 | {
8 | public Platinum()
9 | : base(9)
10 | { }
11 |
12 | public CardCost Value { get { return 5; } }
13 | }
14 | }
--------------------------------------------------------------------------------
/Dominion.Rules/ICard.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | namespace Dominion.Rules
3 | {
4 | public interface ICard
5 | {
6 | CardCost Cost { get; }
7 | CardZone CurrentZone { get; }
8 | Guid Id { get; }
9 | void MoveTo(CardZone targetZone);
10 | string Name { get; }
11 | string ToString();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Dominion.Rules/TrashPile.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Dominion.Rules
7 | {
8 | public class TrashPile : EnumerableCardZone
9 | {
10 | public ICard TopCard
11 | {
12 | get { return this.Cards.Last(); }
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Dominion.Cards/Curses/Curse.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules;
2 | using Dominion.Rules.CardTypes;
3 |
4 | namespace Dominion.Cards.Curses
5 | {
6 | public class Curse : Card, ICurseCard
7 | {
8 | public Curse() : base(0) { }
9 |
10 | public int Score(EnumerableCardZone allCards)
11 | {
12 | return -1;
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Laboratory.feature:
--------------------------------------------------------------------------------
1 | Feature: Laboratory
2 |
3 | Background:
4 | Given A new game with 3 players
5 | And Player1 has a Laboratory in hand instead of a Copper
6 | When Player1 plays a Laboratory
7 |
8 | Scenario: Gain 2 Cards
9 | Then Player1 should have 6 cards in hand
10 |
11 | Scenario: Gain 1 Action
12 | Then Player1 should have 1 remaining action
13 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Market.feature:
--------------------------------------------------------------------------------
1 | Feature: Market
2 |
3 | Scenario: Play Market
4 | Given A new game with 3 players
5 | And Player1 has a Market in hand instead of a Copper
6 | When Player1 plays a Market
7 | Then Player1 should have 5 cards in hand
8 | Then Player1 should have 1 remaining action
9 | Then Player1 should have 2 buys
10 | Then Player1 should have 1 to spend
11 |
--------------------------------------------------------------------------------
/Dominion.Rules/Activities/WaitingForPlayersActivity.cs:
--------------------------------------------------------------------------------
1 | namespace Dominion.Rules.Activities
2 | {
3 | public class WaitingForPlayersActivity : ActivityBase
4 | {
5 | public WaitingForPlayersActivity(Player waitingPlayer)
6 | : base(null, waitingPlayer, "Waiting for other players...", ActivityType.WaitingForOtherPlayers, null)
7 | {
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/WorkersVillage.feature:
--------------------------------------------------------------------------------
1 | Feature: Workers Village
2 |
3 | Scenario: Workers Village is +1 card +2 actions +1 buy
4 | Given A new game with 3 players
5 | And Player1 has a WorkersVillage in hand instead of a Copper
6 | When Player1 plays a WorkersVillage
7 | Then Player1 should have 5 cards in hand
8 | Then Player1 should have 2 remaining actions
9 | Then Player1 should have 2 buys
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/CouncilRoom.feature:
--------------------------------------------------------------------------------
1 | Feature: Council Room
2 |
3 | Scenario: Play CouncilRoom
4 | Given A new game with 3 players
5 | And Player1 has a CouncilRoom in hand instead of a Copper
6 | When Player1 plays a CouncilRoom
7 | Then Player1 should have 2 buys
8 | And Player1 should have 8 cards in hand
9 | And Player2 should have 6 cards in hand
10 | And Player3 should have 6 cards in hand
--------------------------------------------------------------------------------
/Dominion.Tests/HelperExtensions.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules;
2 |
3 | namespace Dominion.Tests
4 | {
5 | public static class HelperExtensions
6 | {
7 | public static CardZone AddNewCards(this CardZone targetZone, int count) where T : Card, new()
8 | {
9 | count.Times(() => new T().MoveTo(targetZone));
10 | return targetZone;
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Treasure/Potion.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules;
2 | using Dominion.Rules.CardTypes;
3 |
4 | namespace Dominion.Cards.Treasure
5 | {
6 | public class Potion : Card, ITreasureCard
7 | {
8 | public Potion() : base(4)
9 | {
10 | }
11 |
12 | public CardCost Value
13 | {
14 | get { return CardCost.Potion; }
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/Dominion.Rules/Activities/PlayActionsActivity.cs:
--------------------------------------------------------------------------------
1 | namespace Dominion.Rules.Activities
2 | {
3 | public class PlayActionsActivity : ActivityBase
4 | {
5 | public PlayActionsActivity(Player activePlayer, int actions)
6 | : base(null, activePlayer, string.Format("Play actions. You have {0} action(s) remaining.", actions), ActivityType.PlayActions, null)
7 | {
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Village.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules;
2 | using Dominion.Rules.CardTypes;
3 | namespace Dominion.Cards.Actions
4 | {
5 | public class Village : Card, IActionCard
6 | {
7 | public Village() : base(3)
8 | {}
9 |
10 | public void Play(TurnContext context)
11 | {
12 | context.RemainingActions += 2;
13 | context.DrawCards(1);
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/Dominion.Rules/Activities/DoBuysActivity.cs:
--------------------------------------------------------------------------------
1 | namespace Dominion.Rules.Activities
2 | {
3 | public class DoBuysActivity : ActivityBase
4 | {
5 | public DoBuysActivity(Player activePlayer, int buys, CardCost buyValue)
6 | : base(null, activePlayer, string.Format("Select card(s) to buy. You have {0} buy(s) for a total of {1}.", buys, buyValue), ActivityType.DoBuys, null)
7 | {
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/Dominion.Rules/ILongLivedCardEffect.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Rules.CardTypes;
6 |
7 | namespace Dominion.Rules
8 | {
9 | public interface ILongLivedCardEffect
10 | {
11 | ICard SourceCard { get; }
12 | void OnTurnStarting(TurnContext context);
13 | bool IsFinished { get; }
14 | }
15 |
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Woodcutter.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules;
2 | using Dominion.Rules.CardTypes;
3 |
4 | namespace Dominion.Cards.Actions
5 | {
6 | public class Woodcutter : Card, IActionCard
7 | {
8 | public Woodcutter()
9 | : base(3)
10 | { }
11 |
12 | public void Play(TurnContext context)
13 | {
14 | context.AvailableSpend += 2;
15 | context.Buys += 1;
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Victory/Duke.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Dominion.Rules;
4 | using Dominion.Rules.CardTypes;
5 |
6 | namespace Dominion.Cards.Victory
7 | {
8 | public class Duke : Card, IVictoryCard
9 | {
10 | public Duke() : base(5)
11 | {
12 | }
13 |
14 | public int Score(EnumerableCardZone allCards)
15 | {
16 | return allCards.OfType().Count();
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Victory/Vineyard.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using Dominion.Rules;
3 | using Dominion.Rules.CardTypes;
4 |
5 | namespace Dominion.Cards.Victory
6 | {
7 | public class Vineyard : Card, IVictoryCard
8 | {
9 | public Vineyard() : base(CardCost.Parse("0P"))
10 | {}
11 |
12 | public int Score(EnumerableCardZone allCards)
13 | {
14 | return allCards.OfType().Count() / 3;
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Smithy.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Rules;
6 | using Dominion.Rules.CardTypes;
7 |
8 | namespace Dominion.Cards.Actions
9 | {
10 | public class Smithy : Card, IActionCard
11 | {
12 | public Smithy() : base(4) { }
13 |
14 | public void Play(TurnContext context)
15 | {
16 | context.DrawCards(3);
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Feast.feature:
--------------------------------------------------------------------------------
1 | Feature: Feast
2 |
3 | Background:
4 | Given A new game with 3 players
5 | And Player1 has a Feast in hand instead of a Copper
6 | When Player1 plays a Feast
7 |
8 | Scenario: Player must choose a card to gain
9 | Then Player1 must gain a card of cost 5 or less
10 |
11 | Scenario: Player gains card
12 | When Player1 gains a Silver
13 | Then Player1 should have a Silver on top of the discard pile
14 | Then There should be a Feast on top of the trash pile
15 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Harem.feature:
--------------------------------------------------------------------------------
1 | Feature: Harem
2 |
3 | Scenario: Harem is worth 2 victory points
4 | Given A new game with 3 players
5 | And Player1 has a Harem in hand instead of a Copper
6 | When The game is scored
7 | Then Player1 should have 5 victory points
8 |
9 | Scenario: Harem is worth 2 spend
10 | Given A new game with 3 players
11 | And Player1 has a hand of Copper, Copper, Estate, Estate, Harem
12 | When Player1 moves to the buy step
13 | Then Player1 should have 4 to spend
14 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/GreatHall.feature:
--------------------------------------------------------------------------------
1 | Feature: Great Hall
2 |
3 | Background:
4 | Given A new game with 3 players
5 |
6 | Scenario: GreatHallInDeck
7 | And Player1 has a GreatHall in hand instead of a Copper
8 | When The game is scored
9 | Then Player1 should have 4 victory points
10 |
11 | Scenario: PlayGreatHall
12 | And Player1 has a GreatHall in hand instead of a Copper
13 | When Player1 plays a GreatHall
14 | Then Player1 should have 5 cards in hand
15 | Then Player1 should have 1 remaining action
--------------------------------------------------------------------------------
/Dominion.Web/ViewModels/GameViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Web.Mvc;
4 | using Dominion.GameHost;
5 | using Dominion.Rules;
6 |
7 | namespace Dominion.Web.ViewModels
8 | {
9 |
10 |
11 | public static class CardImageHelper
12 | {
13 | public static string ResolveCardImage(this UrlHelper urlHelper, string cardName)
14 | {
15 | return urlHelper.Content(string.Format("~/Content/Images/Cards/{0}.jpg", cardName));
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/WorkersVillage.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules;
2 | using Dominion.Rules.CardTypes;
3 |
4 | namespace Dominion.Cards.Actions
5 | {
6 | public class WorkersVillage : Card, IActionCard
7 | {
8 | public WorkersVillage()
9 | : base(4)
10 | { }
11 |
12 | public void Play(TurnContext context)
13 | {
14 | context.RemainingActions += 2;
15 | context.DrawCards(1);
16 | context.Buys += 1;
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Victory/Colony.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules;
2 | using Dominion.Rules.CardTypes;
3 |
4 | namespace Dominion.Cards.Victory
5 | {
6 | public class Colony : Card, IVictoryCard
7 | {
8 | public Colony()
9 | : base(11)
10 | { }
11 |
12 | public int Value
13 | {
14 | get { return 10; }
15 | }
16 |
17 | public int Score(EnumerableCardZone allCards)
18 | {
19 | return Value;
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Victory/Province.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules.CardTypes;
2 | using Dominion.Rules;
3 |
4 | namespace Dominion.Cards.Victory
5 | {
6 | public class Province : Card, IVictoryCard
7 | {
8 | public Province()
9 | : base(8)
10 | {}
11 |
12 | public int Value
13 | {
14 | get { return 6; }
15 | }
16 |
17 | public int Score(EnumerableCardZone allCards)
18 | {
19 | return Value;
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/Dominion.Rules/Activities/IActivity.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Dominion.Rules.Activities
5 | {
6 | public interface IActivity
7 | {
8 | string Message { get; }
9 | bool IsSatisfied { get; }
10 | Player Player { get; }
11 | ActivityType Type { get; }
12 | Guid Id { get; }
13 | IDictionary Properties { get; }
14 | string Source { get; }
15 | ActivityHint Hint { get; }
16 | }
17 | }
--------------------------------------------------------------------------------
/Dominion.Rules/CardTypes/SameTypeEqualityComparer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Dominion.Rules.CardTypes
5 | {
6 | public class SameTypeEqualityComparer : EqualityComparer
7 | {
8 | public override bool Equals(T x, T y)
9 | {
10 | return GetHashCode(x) == GetHashCode(y);
11 | }
12 |
13 | public override int GetHashCode(T obj)
14 | {
15 | return obj.GetType().GetHashCode();
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Victory/Estate.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules.CardTypes;
2 | using Dominion.Rules;
3 | namespace Dominion.Cards.Victory
4 | {
5 | public class Estate : Card, IVictoryCard
6 | {
7 | public Estate() : base(2)
8 | {
9 | Value = 1;
10 | }
11 |
12 | public int Value
13 | {
14 | get;private set;
15 | }
16 |
17 | public int Score(EnumerableCardZone allCards)
18 | {
19 | return Value;
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Bazaar.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 | using Dominion.Rules;
3 | using Dominion.Rules.CardTypes;
4 |
5 | namespace Dominion.Cards.Actions
6 | {
7 | public class Bazaar : Card, IActionCard
8 | {
9 | public Bazaar() : base(5)
10 | {
11 | }
12 |
13 | public void Play(TurnContext context)
14 | {
15 | context.DrawCards(1);
16 | context.RemainingActions += 2;
17 | context.AvailableSpend += 1;
18 | }
19 |
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Dominion.Rules/LimitedSupplyCardPile.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 |
3 | namespace Dominion.Rules
4 | {
5 | public class LimitedSupplyCardPile : CardPile
6 | {
7 | public override bool IsEmpty
8 | {
9 | get { return this.CardCount == 0; }
10 | }
11 |
12 | public override ICard TopCard
13 | {
14 | get { return Cards.FirstOrDefault(); }
15 | }
16 |
17 | public override bool IsLimited
18 | {
19 | get { return true; }
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Victory/Duchy.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules.CardTypes;
2 | using Dominion.Rules;
3 |
4 | namespace Dominion.Cards.Victory
5 | {
6 | public class Duchy : Card, IVictoryCard
7 | {
8 | public Duchy()
9 | : base(5)
10 | {
11 | Value = 3;
12 | }
13 |
14 | public int Value
15 | {
16 | get;
17 | private set;
18 | }
19 |
20 | public int Score(EnumerableCardZone allCards)
21 | {
22 | return Value;
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/Dominion.Rules/DurationEffect.cs:
--------------------------------------------------------------------------------
1 | namespace Dominion.Rules
2 | {
3 | public abstract class DurationEffect : ILongLivedCardEffect
4 | {
5 | public DurationEffect(ICard sourceCard)
6 | {
7 | SourceCard = sourceCard;
8 | IsFinished = false;
9 | }
10 |
11 | public ICard SourceCard { get; set; }
12 | public bool IsFinished { get; set; }
13 |
14 | public virtual void OnTurnStarting(TurnContext context)
15 | {
16 | IsFinished = true;
17 | }
18 |
19 |
20 | }
21 | }
--------------------------------------------------------------------------------
/Dominion.Rules/PlayArea.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Dominion.Rules.CardTypes;
4 |
5 | namespace Dominion.Rules
6 | {
7 | public class PlayArea : EnumerableCardZone
8 | {
9 | public void SortForScoring()
10 | {
11 | foreach(var card in this.Cards
12 | .OrderByDescending(c => c is IScoreCard ? ((IScoreCard)c).Score(this) : -100)
13 | .ThenBy(c => c.Name))
14 | {
15 | card.MoveTo(this);
16 | }
17 | }
18 |
19 | }
20 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Laboratory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Rules;
6 | using Dominion.Rules.CardTypes;
7 |
8 | namespace Dominion.Cards.Actions
9 | {
10 | public class Laboratory : Card, IActionCard
11 | {
12 | public Laboratory() : base(5)
13 | {
14 | }
15 |
16 | public void Play(TurnContext context)
17 | {
18 | context.RemainingActions += 1;
19 | context.DrawCards(2);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Workshop.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Dominion.Rules;
3 | using Dominion.Rules.Activities;
4 | using Dominion.Rules.CardTypes;
5 |
6 | namespace Dominion.Cards.Actions
7 | {
8 | public class Workshop : Card, IActionCard
9 | {
10 | public Workshop() : base(3)
11 | {
12 | }
13 |
14 | public void Play(TurnContext context)
15 | {
16 | context.AddSingleActivity(
17 | Activities.GainACardCostingUpToX(context.Game.Log, context.ActivePlayer, 4, this), this);
18 | }
19 |
20 | }
21 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Victory/Gardens.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Dominion.Rules.CardTypes;
3 | using Dominion.Rules;
4 |
5 | namespace Dominion.Cards.Victory
6 | {
7 | public class Gardens : Card, IVictoryCard
8 | {
9 |
10 | public Gardens()
11 | : base(4)
12 | {
13 | }
14 |
15 | public int Score(EnumerableCardZone allCards)
16 | {
17 | return (allCards.CardCount / 10);
18 | }
19 |
20 |
21 | public int Value
22 | {
23 | get { return 0; }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Dominion.WinForms/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Windows.Forms;
5 |
6 | namespace Dominion
7 | {
8 | static class Program
9 | {
10 | ///
11 | /// The main entry point for the application.
12 | ///
13 | [STAThread]
14 | static void Main()
15 | {
16 | Application.EnableVisualStyles();
17 | Application.SetCompatibleTextRenderingDefault(false);
18 | Application.Run(new GameForm());
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Moneylender.feature:
--------------------------------------------------------------------------------
1 | Feature: Moneylender
2 |
3 | Scenario: Moneylender with copper in hand
4 | Given A new game with 3 players
5 | And Player1 has a hand of Moneylender, Copper, Estate, Estate, Estate
6 | When Player1 plays a Moneylender
7 | Then Player1 should have 3 to spend
8 | And There should be a Copper on top of the trash pile
9 |
10 | Scenario: Moneylender without copper in hand
11 | Given A new game with 3 players
12 | And Player1 has a hand of Moneylender, Estate, Estate, Estate, Estate
13 | When Player1 plays a Moneylender
14 | Then Player1 should have 0 to spend
15 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Festival.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Rules;
6 | using Dominion.Rules.CardTypes;
7 |
8 | namespace Dominion.Cards.Actions
9 | {
10 | public class Festival : Card, IActionCard
11 | {
12 | public Festival() : base(5)
13 | {
14 | }
15 |
16 | public void Play(TurnContext context)
17 | {
18 | context.RemainingActions += 2;
19 | context.Buys += 1;
20 | context.AvailableSpend += 2;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Chapel.feature:
--------------------------------------------------------------------------------
1 | Feature: Chapel
2 |
3 | Background:
4 | Given A new game with 3 players
5 | And Player1 has a hand of Chapel, Estate, Estate, Copper, Copper
6 | When Player1 plays a Chapel
7 |
8 | Scenario: Player must select a number of cards to trash
9 | Then Player1 may select up to 4 cards from their hand
10 |
11 | Scenario: Player trashes one card
12 | And Player1 selects a Copper to trash
13 | Then There should be a Copper on top of the trash pile
14 |
15 | Scenario: Player trashes nothing
16 | And Player1 selects nothing to trash
17 | Then Player1 should have 4 cards in hand
18 |
--------------------------------------------------------------------------------
/Dominion.Rules/NullZone.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Dominion.Rules
4 | {
5 | public class NullZone : CardZone
6 | {
7 | protected override void AddCard(ICard card)
8 | {
9 | // NO OP
10 | }
11 |
12 | protected override void RemoveCard(ICard card)
13 | {
14 | // NO OP
15 | }
16 |
17 | public override int CardCount
18 | {
19 | get
20 | {
21 | throw new NotSupportedException("A null zone cannot be considered to have a card count");
22 | }
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Courtyard.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules;
2 | using Dominion.Rules.Activities;
3 | using Dominion.Rules.CardTypes;
4 |
5 | namespace Dominion.Cards.Actions
6 | {
7 | public class Courtyard : Card, IActionCard
8 | {
9 | public Courtyard() : base(2)
10 | {
11 | }
12 |
13 | public void Play(TurnContext context)
14 | {
15 | context.DrawCards(3);
16 | if (context.ActivePlayer.Hand.CardCount > 0)
17 | context.AddSingleActivity(Activities.PutCardFromHandOnTopOfDeck(context, this), this);
18 | }
19 |
20 | }
21 | }
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/ProbabilityExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace Dominion.GameHost.AI.BehaviourBased
4 | {
5 | public static class ProbabilityExtensions
6 | {
7 | public static IEnumerable> GetCumulativeTotals(this IEnumerable> input)
8 | {
9 | var temp = 0;
10 | foreach (var item in input)
11 | {
12 | yield return new KeyValuePair(item.Key, item.Value + temp);
13 | temp += item.Value;
14 | }
15 | }
16 |
17 | }
18 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/University.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules;
2 | using Dominion.Rules.Activities;
3 | using Dominion.Rules.CardTypes;
4 |
5 | namespace Dominion.Cards.Actions
6 | {
7 | public class University : Card, IActionCard
8 | {
9 | public University() : base(CardCost.Parse("2P"))
10 | {
11 | }
12 |
13 | public void Play(TurnContext context)
14 | {
15 | context.RemainingActions += 2;
16 | context.AddSingleActivity(
17 | Activities.GainAnActionCardCostingUpToX(context.Game.Log, context.ActivePlayer, 5, this, true), this);
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/SkipBuyBehaviour.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules.Activities;
2 |
3 | namespace Dominion.GameHost.AI.BehaviourBased
4 | {
5 | public class SkipBuyBehaviour : IAIBehaviour
6 | {
7 | public bool CanRespond(ActivityModel activity, GameViewModel state)
8 | {
9 | return activity.ParseType() == ActivityType.DoBuys;
10 | }
11 |
12 | public void Respond(IGameClient client, ActivityModel activity, GameViewModel state)
13 | {
14 | var message = new EndTurnMessage(client.PlayerId);
15 | client.AcceptMessage(message);
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/MerchantShip.feature:
--------------------------------------------------------------------------------
1 | Feature: Merchant Ship
2 |
3 | Scenario: Player plays Merchant Ship and gains +2 coin immediately
4 | Given A new game with 2 players
5 | And Player1 has a MerchantShip in hand instead of a Copper
6 | When Player1 plays a MerchantShip
7 | Then Player1 should have 2 to spend
8 |
9 | Scenario: Player plays Merchant Ship and gains +2 coin on the following turn
10 | Given A new game with 2 players
11 | And Player1 has a MerchantShip in hand instead of a Copper
12 | When Player1 plays a MerchantShip
13 | And Player1 ends their turn
14 | And Player2 ends their turn
15 | Then Player1 should have 2 to spend
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Market.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Rules;
6 | using Dominion.Rules.CardTypes;
7 |
8 | namespace Dominion.Cards.Actions
9 | {
10 | public class Market : Card, IActionCard
11 | {
12 | public Market()
13 | : base(5)
14 | {
15 | }
16 |
17 | public void Play(TurnContext context)
18 | {
19 | context.DrawCards(1);
20 | context.RemainingActions += 1;
21 | context.Buys += 1;
22 | context.AvailableSpend += 1;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Harem.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 | using Dominion.Rules;
3 | using Dominion.Rules.CardTypes;
4 |
5 | namespace Dominion.Cards.Hybrid
6 | {
7 | public class Harem : Card, IMoneyCard, IVictoryCard
8 | {
9 | public Harem() : base(6)
10 | {
11 | ScoringValue = 2;
12 | }
13 |
14 | public CardCost Value { get { return 2; } }
15 |
16 | public int ScoringValue
17 | {
18 | get;
19 | private set;
20 | }
21 |
22 | public int Score(EnumerableCardZone allCards)
23 | {
24 | return ScoringValue;
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Cellar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Rules;
6 | using Dominion.Rules.Activities;
7 | using Dominion.Rules.CardTypes;
8 |
9 | namespace Dominion.Cards.Actions
10 | {
11 | public class Cellar : Card, IActionCard
12 | {
13 | public Cellar()
14 | : base(2)
15 | {
16 | }
17 |
18 | public void Play(TurnContext context)
19 | {
20 | context.RemainingActions += 1;
21 | context.AddSingleActivity(Activities.DiscardCardsToDrawCards(context, this), this);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/SkipActionsBehaviour.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Dominion.Rules.Activities;
3 |
4 | namespace Dominion.GameHost.AI.BehaviourBased
5 | {
6 | public class SkipActionsBehaviour : IAIBehaviour
7 | {
8 | public bool CanRespond(ActivityModel activity, GameViewModel state)
9 | {
10 | return activity.ParseType() == ActivityType.PlayActions;
11 | }
12 |
13 | public void Respond(IGameClient client, ActivityModel activity, GameViewModel state)
14 | {
15 | var message = new MoveToBuyStepMessage(client.PlayerId);
16 | client.AcceptMessage(message);
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/Dominion.GameHost/BeginGameMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Dominion.Rules;
4 | using Dominion.Rules.CardTypes;
5 |
6 | namespace Dominion.GameHost
7 | {
8 | public class BeginGameMessage : IGameActionMessage
9 | {
10 | public void UpdateGameState(Game game)
11 | {
12 | TurnContext tempQualifier = game.CurrentTurn;
13 | if (tempQualifier.ActivePlayer.Hand.OfType().Any() == false || tempQualifier.RemainingActions == 0)
14 | tempQualifier.MoveToBuyStep();
15 | }
16 |
17 | public void Validate(Game game)
18 | {
19 |
20 | }
21 | }
22 |
23 | }
--------------------------------------------------------------------------------
/Dominion.Web/ViewModels/NewGameViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Web;
5 |
6 | namespace Dominion.Web.ViewModels
7 | {
8 | public class NewGameViewModel
9 | {
10 | public int NumberOfPlayers { get; set; }
11 |
12 | ///
13 | /// A comma delimited list of player names, or types of AI players.
14 | ///
15 | public string Names { get; set; }
16 |
17 | public IList CardsToChooseFrom { get; set; }
18 |
19 | public IList ChosenCards { get; set; }
20 |
21 | public bool UseProsperty { get; set; }
22 | }
23 | }
--------------------------------------------------------------------------------
/Dominion.Rules/EnumerableCardZone.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | namespace Dominion.Rules
6 | {
7 | public abstract class EnumerableCardZone : CardZone, IEnumerable
8 | {
9 | public IEnumerator GetEnumerator()
10 | {
11 | return this.Cards.GetEnumerator();
12 | }
13 |
14 | IEnumerator IEnumerable.GetEnumerator()
15 | {
16 | return GetEnumerator();
17 | }
18 |
19 | public override string ToString()
20 | {
21 | return string.Join(", ", this.Select(c => c.Name).ToArray());
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Wharf.feature:
--------------------------------------------------------------------------------
1 | Feature: Wharf
2 |
3 | Scenario: Player plays Wharf and draws 2 cards and gains a buy
4 | Given A new game with 2 players
5 | And Player1 has a Wharf in hand instead of a Copper
6 | When Player1 plays a Wharf
7 | Then Player1 should have 6 cards in hand
8 | And Player1 should have 2 buys
9 |
10 | Scenario: Player plays Wharf and draws 2 cards and gains a buy on the following turn
11 | Given A new game with 2 players
12 | And Player1 has a Wharf in hand instead of a Copper
13 | When Player1 plays a Wharf
14 | And Player1 ends their turn
15 | And Player2 ends their turn
16 | Then Player1 should have 7 cards in hand
17 | And Player1 should have 2 buys
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/CouncilRoom.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Rules;
6 | using Dominion.Rules.CardTypes;
7 |
8 | namespace Dominion.Cards.Actions
9 | {
10 | public class CouncilRoom : Card, IActionCard
11 | {
12 | public CouncilRoom()
13 | : base(5)
14 | {
15 |
16 | }
17 |
18 | public void Play(TurnContext context)
19 | {
20 | context.DrawCards(4);
21 | context.Buys += 1;
22 |
23 | foreach (var opponent in context.Opponents)
24 | opponent.DrawCards(1);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/ShantyTown.feature:
--------------------------------------------------------------------------------
1 | Feature: ShantyTown
2 |
3 | Scenario: Play Shanty Town with no other actions in hand
4 | Given A new game with 2 players
5 | And Player1 has a ShantyTown in hand instead of a Copper
6 | When Player1 plays a ShantyTown
7 | Then Player1 should have 2 remaining action
8 | Then Player1 should have 6 cards in hand
9 |
10 | Scenario: Play Shanty Town with another action in hand
11 | Given A new game with 2 players
12 | And Player1 has a ShantyTown in hand instead of a Copper
13 | And Player1 has a ShantyTown in hand instead of a Copper
14 | When Player1 plays a ShantyTown
15 | Then Player1 should have 2 remaining action
16 | Then Player1 should have 4 cards in hand
17 |
--------------------------------------------------------------------------------
/Dominion.Specs/TurnMechanics.feature:
--------------------------------------------------------------------------------
1 | Feature: Turn Mechanics
2 | In order to have my turn
3 | As a dominion player
4 | I can perform certain actions
5 |
6 | Background:
7 | Given A new game with 3 players
8 |
9 | Scenario: Discard hand at end of turn
10 | When Player1 ends their turn
11 | Then Player1 should have 5 cards in the discard pile
12 |
13 | Scenario: Draw cards after discarding at end of turn
14 | When Player1 ends their turn
15 | Then Player1 should have 5 cards in hand
16 |
17 | Scenario: Use single action
18 | Given Player1 has a Smithy in hand instead of a Copper
19 | When Player1 plays a Smithy
20 | Then Player1 should have 0 actions remaining
21 | And Smithy should be in play
22 |
23 |
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/CommentOnGameEndBehaviour.cs:
--------------------------------------------------------------------------------
1 | namespace Dominion.GameHost.AI.BehaviourBased
2 | {
3 | public class CommentOnGameEndBehaviour : IAIBehaviour
4 | {
5 | private readonly string _comment;
6 |
7 | public CommentOnGameEndBehaviour(string comment)
8 | {
9 | _comment = comment;
10 | }
11 |
12 | public virtual bool CanRespond(ActivityModel activity, GameViewModel state)
13 | {
14 | return state.Status.GameIsComplete;
15 | }
16 |
17 | public virtual void Respond(IGameClient client, ActivityModel activity, GameViewModel state)
18 | {
19 | client.SendChatMessage(_comment);
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Expand.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using Dominion.Rules;
3 | using Dominion.Rules.Activities;
4 | using Dominion.Rules.CardTypes;
5 |
6 | namespace Dominion.Cards.Actions
7 | {
8 | public class Expand : Card, IActionCard
9 | {
10 | public Expand() : base(7)
11 | {
12 | }
13 |
14 | public void Play(TurnContext context)
15 | {
16 | context.AddEffect(this, new ExpandEffect());
17 | }
18 |
19 | public class ExpandEffect : Remodel.RemodelEffect
20 | {
21 | public ExpandEffect()
22 | :base(3, "Select a card to Expand.")
23 | {
24 |
25 | }
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/DefaultSelectFromRevealedBehaviour.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using Dominion.Rules.Activities;
3 |
4 | namespace Dominion.GameHost.AI.BehaviourBased
5 | {
6 | public class DefaultSelectFromRevealedBehaviour : IAIBehaviour
7 | {
8 | public bool CanRespond(ActivityModel activity, GameViewModel state)
9 | {
10 | return activity.ParseType() == ActivityType.SelectFromRevealed;
11 | }
12 |
13 | public void Respond(IGameClient client, ActivityModel activity, GameViewModel state)
14 | {
15 | var selected = state.Revealed.First();
16 | client.AcceptMessage(new SelectCardsMessage(client.PlayerId, new[] { selected.Id }));
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/Dominion.GameHost/EndTurnMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Dominion.Rules;
3 |
4 | namespace Dominion.GameHost
5 | {
6 | public class EndTurnMessage : IGameActionMessage
7 | {
8 | public EndTurnMessage(Guid playerId)
9 | {
10 | PlayerId = playerId;
11 | }
12 |
13 | public Guid PlayerId { get; private set; }
14 |
15 | public void UpdateGameState(Game game)
16 | {
17 | game.EndTurn();
18 | }
19 |
20 | public void Validate(Game game)
21 | {
22 | if (game.ActivePlayer.Id != PlayerId)
23 | throw new InvalidOperationException(string.Format("Player '{0}' is not active.", PlayerId));
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/ShantyTown.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Dominion.Rules;
5 | using Dominion.Rules.Activities;
6 | using Dominion.Rules.CardTypes;
7 |
8 | namespace Dominion.Cards.Actions
9 | {
10 | public class ShantyTown : Card, IActionCard
11 | {
12 | public ShantyTown() : base(3)
13 | {
14 | }
15 |
16 | public void Play(TurnContext context)
17 | {
18 | context.RemainingActions += 2;
19 |
20 | context.Game.Log.LogRevealHand(context.ActivePlayer);
21 |
22 | if (context.ActivePlayer.Hand.OfType().Count() == 0)
23 | context.DrawCards(2);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/Treasure.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Dominion.Cards.Treasure;
3 | using Dominion.Rules;
4 |
5 | namespace Dominion.GameHost.AI
6 | {
7 | public static class Treasure
8 | {
9 | public static IList Basic = GetBasicTreasure();
10 |
11 | private static IList GetBasicTreasure()
12 | {
13 | var list = new List();
14 | list.AddTreasure();
15 | list.AddTreasure();
16 | list.AddTreasure();
17 | return list;
18 | }
19 |
20 | private static void AddTreasure(this IList list) where T : Card
21 | {
22 | list.Add(typeof(T).Name);
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/Dominion.GameHost/MoveToBuyStepMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Dominion.Rules;
3 |
4 | namespace Dominion.GameHost
5 | {
6 | public class MoveToBuyStepMessage : IGameActionMessage
7 | {
8 | public MoveToBuyStepMessage(Guid playerId)
9 | {
10 | PlayerId = playerId;
11 | }
12 |
13 | public Guid PlayerId { get; private set; }
14 |
15 | public void UpdateGameState(Game game)
16 | {
17 | game.CurrentTurn.MoveToBuyStep();
18 | }
19 |
20 | public void Validate(Game game)
21 | {
22 | if (game.ActivePlayer.Id != PlayerId)
23 | throw new InvalidOperationException(string.Format("Player '{0}' is not active.", PlayerId));
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/VictoryCards.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Dominion.Cards.Victory;
3 | using Dominion.Rules;
4 |
5 | namespace Dominion.GameHost.AI
6 | {
7 | public static class VictoryCards
8 | {
9 | public static IList Basic = GetBasicVP();
10 |
11 | private static IList GetBasicVP()
12 | {
13 | var list = new List();
14 | list.AddCard();
15 | list.AddCard();
16 | list.AddCard();
17 | list.AddCard();
18 | return list;
19 | }
20 |
21 | private static void AddCard(this IList list) where T : Card
22 | {
23 | list.Add(typeof(T).Name);
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Familiar.feature:
--------------------------------------------------------------------------------
1 | Feature: Familiar
2 |
3 | Scenario: Buy Familiar
4 | Given A new game with 3 players
5 | And Familiar is available to buy
6 | And Player1 has a hand of Potion, Copper, Copper, Copper, Copper
7 | When Player1 moves to the buy step
8 | And Player1 buys a Familiar
9 | Then Player1 should have a Familiar on top of the discard pile
10 | And Player1 should have 1 to spend
11 |
12 | Scenario: Play Familiar
13 | Given A new game with 3 players
14 | And Player1 has a Familiar in hand instead of a Copper
15 | When Player1 plays a Familiar
16 | Then Player1 should have 5 cards in hand
17 | Then Player1 should have 1 action remaining
18 | Then Player2 should have a Curse on top of the discard pile
19 | Then Player3 should have a Curse on top of the discard pile
20 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Tactician.feature:
--------------------------------------------------------------------------------
1 | Feature: Tactitian
2 |
3 | Scenario: Play Tactician with a deck of 10 cards
4 | Given A new game with 2 players
5 | And Player1 has a Tactician in hand instead of a Copper
6 | When Player1 plays a Tactician
7 | And Player1 ends their turn
8 | And Player2 ends their turn
9 | Then Player1 should have 9 cards in hand
10 | And Player1 should have 2 remaining actions
11 | And Player1 should have 2 buys
12 |
13 | Scenario: Play Tactician with no cards in hand
14 | Given A new game with 2 players
15 | And Player1 has a hand of Tactician
16 | When Player1 plays a Tactician
17 | And Player1 ends their turn
18 | And Player2 ends their turn
19 | Then Player1 should have 5 cards in hand
20 | And Player1 should have 1 remaining action
21 | And Player1 should have 1 buy
--------------------------------------------------------------------------------
/Dominion.Web/ActionFilters/InjectClientAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Web.Mvc;
4 | using Dominion.GameHost;
5 | using Dominion.Web.Controllers;
6 | using Dominion.Web.Bootstrap;
7 | using Autofac;
8 |
9 | namespace Dominion.Web.ActionFilters
10 | {
11 | public class InjectClientAttribute : ActionFilterAttribute
12 | {
13 | public override void OnActionExecuting(ActionExecutingContext filterContext)
14 | {
15 | Guid playerId = Guid.Parse((string) filterContext.RouteData.Values["id"]);
16 | var multiHost = AutofacConfig.Container.Resolve();
17 | var controller = (IHasGameClient)filterContext.Controller;
18 | controller.Client = multiHost.FindClient(playerId);
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/CountingHouse.feature:
--------------------------------------------------------------------------------
1 | Feature: Counting House
2 |
3 |
4 | Scenario: Counting House does nothing when there are no coppers in the discard pile
5 | Given A new game with 1 players
6 | And Player1 has a CountingHouse in hand instead of a Copper
7 | When Player1 plays a CountingHouse
8 | Then Player1 should have 4 cards in hand
9 |
10 | Scenario: Counting House retrieves coppers
11 | Given A new game with 3 players
12 | And Player1 has a hand of CountingHouse, Estate, Estate, Copper, Copper
13 | And Player1 has a Copper in the discard pile
14 | And Player1 has a Copper in the discard pile
15 | When Player1 plays a CountingHouse
16 | Then Player1 should have a hand of Estate, Estate, Copper, Copper, Copper, Copper
17 | And Player1 should have 0 cards in the discard pile
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Dominion.5.1.ReSharper:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Feast.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Dominion.Rules;
3 | using Dominion.Rules.Activities;
4 | using Dominion.Rules.CardTypes;
5 |
6 | namespace Dominion.Cards.Actions
7 | {
8 | public class Feast : Card, IActionCard
9 | {
10 | public Feast() : base(4) { }
11 |
12 | public void Play(TurnContext context)
13 | {
14 | context.Trash(context.ActivePlayer, this);
15 | context.AddEffect(this, new FeastEffect());
16 | }
17 | }
18 |
19 | public class FeastEffect : CardEffectBase
20 | {
21 | public override void Resolve(TurnContext context, ICard source)
22 | {
23 | _activities.Add(Activities.GainACardCostingUpToX(context.Game.Log, context.ActivePlayer, 5, source));
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Witch.feature:
--------------------------------------------------------------------------------
1 | Feature: Witch
2 |
3 | Scenario: Play Witch
4 | Given A new game with 3 players
5 | And Player1 has a Witch in hand instead of a Copper
6 | When Player1 plays a Witch
7 | Then Player1 should have 6 cards in hand
8 | Then Player2 should have a Curse on top of the discard pile
9 | Then Player3 should have a Curse on top of the discard pile
10 |
11 | Scenario: Play Witch with only 1 Curse left
12 | Given A new game with 3 players
13 | Given There is only 1 Curse left
14 | And Player2 has a Witch in hand instead of a Copper
15 | When Player1 ends their turn
16 | When Player2 plays a Witch
17 | Then Player2 should have 6 cards in hand
18 | Then Player3 should have a Curse on top of the discard pile
19 | Then Player1 should not have a Curse on top of the discard pile
20 |
21 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/SeaHag.feature:
--------------------------------------------------------------------------------
1 | Feature: SeaHag
2 |
3 | Scenario: Play sea hag
4 | Given A new game with 3 players
5 | And Player1 has a SeaHag in hand instead of a Copper
6 | When Player1 plays a SeaHag
7 | Then Player1 should have 4 cards in hand
8 | Then Player2 should have a Curse on top of the deck
9 | Then Player2 should have 1 card in the discard pile
10 | Then Player3 should have a Curse on top of the deck
11 | Then Player3 should have 1 card in the discard pile
12 |
13 | Scenario: Sea hag with no cards in deck or discard pile
14 | Given A new game with 2 players
15 | And Player1 has a SeaHag in hand instead of a Copper
16 | And Player2 has an empty deck
17 | When Player1 plays a SeaHag
18 | Then Player2 should have a Curse on top of the deck
19 | Then Player2 should have 0 cards in the discard pile
20 |
--------------------------------------------------------------------------------
/Dominion.Specs/TurnOrder.feature:
--------------------------------------------------------------------------------
1 | Feature: Turn Order
2 | In order to play the game
3 | As a dominion player
4 | I alternate with the other players, taking turns
5 |
6 | Scenario: Player1 goes first
7 | Given A new game with 3 players
8 | Then Player1 is the active player
9 |
10 | Scenario: Player2 goes second
11 | Given A new game with 3 players
12 | When Player1 ends their turn
13 | Then Player2 is the active player
14 |
15 | Scenario: Player3 goes third
16 | Given A new game with 3 players
17 | When Player1 ends their turn
18 | When Player2 ends their turn
19 | Then Player3 is the active player
20 |
21 | Scenario: Player1 goes after Player3
22 | Given A new game with 3 players
23 | When Player1 ends their turn
24 | When Player2 ends their turn
25 | When Player3 ends their turn
26 | Then Player1 is the active player
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/City.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Dominion.Rules;
3 | using Dominion.Rules.CardTypes;
4 |
5 | namespace Dominion.Cards.Actions
6 | {
7 | public class City : Card, IActionCard
8 | {
9 | public City()
10 | : base(5)
11 | {
12 | }
13 |
14 | public void Play(TurnContext context)
15 | {
16 | context.RemainingActions += 2;
17 | context.DrawCards(1);
18 |
19 | var emptyPileCount = context.Game.Bank.EmptyPileCount;
20 |
21 | if(emptyPileCount >= 1)
22 | context.DrawCards(1);
23 |
24 | if(emptyPileCount >= 2)
25 | {
26 | context.AvailableSpend += 1;
27 | context.Buys += 1;
28 | }
29 |
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/Dominion.Web/Views/Home/ViewPlayers.aspx:
--------------------------------------------------------------------------------
1 | <%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage" MasterPageFile="~/Views/Shared/site.Master" %>
2 | <%@ Import Namespace="Dominion.Web.Controllers" %>
3 |
4 |
5 |
6 | Game key: <%= Model.GameKey %>
7 | <% foreach(var item in Model.Slots)
8 | {
9 | using(Html.BeginForm("JoinGame", "Home", new {id = item.Key }))
10 | { %>
11 | <%= item.Value %> <%=Html.SubmitButton("join", "Play") %>
12 | <%}
13 | }
14 | %>
15 |
16 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Moat.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Dominion.Rules;
3 | using Dominion.Rules.CardTypes;
4 |
5 | namespace Dominion.Cards.Actions
6 | {
7 | public class Moat : Card, IActionCard, IReactionCard
8 | {
9 | public Moat() : base(2)
10 | {
11 | }
12 |
13 | public void Play(TurnContext context)
14 | {
15 | context.DrawCards(2);
16 | }
17 |
18 | public void React(AttackEffect attackEffect, Player player, TurnContext currentTurn)
19 | {
20 | attackEffect.Nullify(player);
21 | currentTurn.Game.Log.LogMessage("{0} reveals a moat and nullifies the attack.", player.Name);
22 | }
23 |
24 | public bool ContinueReactingIfOnlyReaction
25 | {
26 | get { return false; }
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/Dominion.Rules/CardPile.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Dominion.Rules
4 | {
5 | public abstract class CardPile : CardZone
6 | {
7 | public Guid Id { get; set; }
8 | public abstract bool IsEmpty { get; }
9 | public abstract ICard TopCard { get; }
10 | public abstract bool IsLimited { get; }
11 |
12 | private string _cachedName;
13 |
14 | public string Name
15 | {
16 | get
17 | {
18 | // The pile could run out, lets remember the name.
19 | if (_cachedName == null)
20 | _cachedName = TopCard.Name;
21 |
22 | return _cachedName;
23 | }
24 | }
25 |
26 | public CardPile()
27 | {
28 | Id = Guid.NewGuid();
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/KingsCourt.feature:
--------------------------------------------------------------------------------
1 | Feature: Kings Court
2 |
3 | Scenario: Player must choose which card to use Kings Court effect on
4 | Given A new game with 3 players
5 | And Player1 has a KingsCourt in hand instead of a Copper
6 | And Player1 has a Market in hand instead of a Copper
7 | When Player1 plays a KingsCourt
8 | Then Player1 must select 1 action card
9 |
10 | Scenario: Player uses Kings Court's effect on a Market
11 | Given A new game with 3 players
12 | And Player1 has a KingsCourt in hand instead of a Copper
13 | And Player1 has a Market in hand instead of a Copper
14 | When Player1 plays a KingsCourt
15 | And Player1 selects a Market to KingsCourt
16 | Then Player1 should have 6 cards in hand
17 | And Player1 should have 3 remaining actions
18 | And Player1 should have 4 buys
19 | And Player1 should have 3 to spend
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Cutpurse.feature:
--------------------------------------------------------------------------------
1 | Feature: Cutpurse
2 |
3 | Scenario: Cutpurse is played and players discard copper
4 | Given A new game with 3 players
5 | And Player1 has a Cutpurse in hand instead of a Copper
6 | When Player1 plays a Cutpurse
7 | Then Player1 should have 2 to spend
8 | And Player2 should have 4 cards in hand
9 | And Player2 should have a Copper on top of the discard pile
10 | And Player3 should have 4 cards in hand
11 | And Player3 should have a Copper on top of the discard pile
12 |
13 | Scenario: Cutpurse is played but opponent has no copper
14 | Given A new game with 2 players
15 | And Player1 has a Cutpurse in hand instead of a Copper
16 | And Player2 has a hand of Estate, Estate, Silver, Silver, Silver
17 | When Player1 plays a Cutpurse
18 | Then All actions should be resolved
19 | And Player2 should have 5 cards in hand
20 |
--------------------------------------------------------------------------------
/Dominion.Cards/Hybrid/GreatHall.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules;
2 | using Dominion.Rules.CardTypes;
3 |
4 | namespace Dominion.Cards.Hybrid
5 | {
6 | public class GreatHall : Card, IActionCard, IVictoryCard
7 | {
8 | public GreatHall() : base(3)
9 | {
10 | Value = 1;
11 | }
12 |
13 | public void Play(TurnContext context)
14 | {
15 | context.DrawCards(1);
16 | context.RemainingActions += 1;
17 | }
18 |
19 | public int Value
20 | {
21 | get;
22 | set;
23 | }
24 |
25 | public int Score(EnumerableCardZone allCards)
26 | {
27 | return Value;
28 | }
29 |
30 | public void PlayFromOtherAction(TurnContext context)
31 | {
32 | Play(context);
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/BuyPotionBehaviour.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using Dominion.Cards.Treasure;
3 |
4 | namespace Dominion.GameHost.AI.BehaviourBased
5 | {
6 | public class BuyPotionBehaviour : BuyBehaviourBase
7 | {
8 | public override bool CanRespond(ActivityModel activity, GameViewModel state)
9 | {
10 | var potionPile = state.Bank.SingleOrDefault(p => p.Is());
11 | return base.CanRespond(activity, state)
12 | && potionPile != null
13 | && potionPile.CanBuy
14 | && state.Status.AvailableSpend.Money == potionPile.Cost;
15 | }
16 |
17 | protected override CardPileViewModel SelectPile(GameViewModel state, IGameClient client)
18 | {
19 | return state.Bank.Single(p => p.Is());
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Coppersmith.feature:
--------------------------------------------------------------------------------
1 | Feature: Coppersmith
2 |
3 | Background:
4 | Given A new game with 3 players
5 | And Player1 has a hand of Coppersmith, Copper, Copper, Copper, ThroneRoom
6 |
7 | Scenario: Copper is improved in value
8 | When Player1 plays a Coppersmith
9 | And Player1 moves to the buy step
10 | Then Player1 should have 6 to spend
11 |
12 | Scenario: Coppersmith is cumulative
13 | When Player1 plays a ThroneRoom
14 | And Player1 selects a Coppersmith to ThroneRoom
15 | And Player1 moves to the buy step
16 | Then Player1 should have 9 to spend
17 |
18 | Scenario: Coppersmith only modifies Copper value
19 | Given A new game with 3 players
20 | And Player1 has a hand of Coppersmith, Copper, Silver, Gold, ThroneRoom
21 | When Player1 plays a Coppersmith
22 | And Player1 moves to the buy step
23 | Then Player1 should have 7 to spend
24 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Mine.feature:
--------------------------------------------------------------------------------
1 | Feature: Mine
2 |
3 | Background:
4 | Given A new game with 3 players
5 | And Player1 has a hand of Mine, Copper, Silver, Estate, Estate
6 | And Player1 has a Copper in the discard pile
7 | When Player1 plays a Mine
8 |
9 | Scenario: Player must only choose a treasure card to mine
10 | Then Player1 must select 1 treasure card to mine
11 |
12 | Scenario: Player must choose a treasure card to gain
13 | And Player1 selects a Silver to mine
14 | Then Player1 must gain a treasure card of cost 6 or less
15 |
16 | Scenario: Player mines Copper into Silver
17 | And Player1 selects a Copper to mine
18 | And Player1 gains a Silver
19 | Then Player1 should have a hand of Silver, Estate, Estate, Silver
20 |
21 | Scenario: Mined card is trashed
22 | And Player1 selects a Copper to mine
23 | Then There should be a Copper on top of the trash pile
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Courtyard.feature:
--------------------------------------------------------------------------------
1 | Feature: Courtyard
2 |
3 | Scenario: Player plays Courtyard, draws 3 and puts one card from hand back on top
4 | Given A new game with 3 players
5 | And Player1 has a hand of Courtyard, Militia, Copper, Copper, Estate
6 | When Player1 plays a Courtyard
7 | Then Player1 should have 7 cards in hand
8 | And Player1 must select 1 card to put on top of the deck
9 | When Player1 selects a Militia to put on top
10 | Then Player1 should have 6 cards in hand
11 | And Player1 should have a Militia on top of the deck
12 |
13 |
14 | Scenario: Courtyard is played with no other cards in hand, no discards and no deck
15 | Given A new game with 3 players
16 | And Player1 has a hand of Courtyard
17 | And Player1 has an empty deck
18 | When Player1 plays a Courtyard
19 | Then Player1 should have 0 cards in hand
20 | And All actions should be resolved
21 |
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/DefaultMakeChoiceBehaviour.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using Dominion.Rules.Activities;
3 |
4 | namespace Dominion.GameHost.AI.BehaviourBased
5 | {
6 | public class DefaultMakeChoiceBehaviour : IAIBehaviour
7 | {
8 | public virtual bool CanRespond(ActivityModel activity, GameViewModel state)
9 | {
10 | return activity.ParseType() == ActivityType.MakeChoice;
11 | }
12 |
13 | public void Respond(IGameClient client, ActivityModel activity, GameViewModel state)
14 | {
15 | var options = activity.ParseOptions();
16 |
17 | Choice choice = options.First();
18 |
19 | if (options.Contains(Choice.Yes))
20 | choice = Choice.Yes;
21 |
22 | client.AcceptMessage(new ChoiceMessage(client.PlayerId, choice.ToString()));
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Ironworks.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules;
2 | using Dominion.Rules.Activities;
3 | using Dominion.Rules.CardTypes;
4 |
5 | namespace Dominion.Cards.Actions
6 | {
7 | public class Ironworks : Card, IActionCard
8 | {
9 | public Ironworks()
10 | : base(4)
11 | { }
12 |
13 | public void Play(TurnContext context)
14 | {
15 | var activity = Activities.GainACardCostingUpToX(context.Game.Log, context.ActivePlayer, 4, this);
16 | activity.AfterCardGained = card =>
17 | {
18 | if (card is IActionCard) context.RemainingActions += 1;
19 | if (card is ITreasureCard) context.AvailableSpend += 1;
20 | if (card is IVictoryCard) context.DrawCards(1);
21 | };
22 |
23 | context.AddSingleActivity(activity, this);
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/MerchantShip.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules;
2 | using Dominion.Rules.CardTypes;
3 |
4 | namespace Dominion.Cards.Actions
5 | {
6 | public class MerchantShip : Card, IDurationCard
7 | {
8 | public MerchantShip() : base(5)
9 | {}
10 |
11 | public void Play(TurnContext context)
12 | {
13 | context.AvailableSpend += 2;
14 | context.AddLongLivedEffect(new MerchantShipEffect(this));
15 | }
16 |
17 | public class MerchantShipEffect : DurationEffect
18 | {
19 | public MerchantShipEffect(ICard sourceCard) : base(sourceCard)
20 | {}
21 |
22 | public override void OnTurnStarting(TurnContext context)
23 | {
24 | base.OnTurnStarting(context);
25 | context.AvailableSpend += 2;
26 | }
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Moat.feature:
--------------------------------------------------------------------------------
1 | Feature: Moat
2 |
3 | Scenario: Moat draws 2 cards
4 | Given A new game with 3 players
5 | And Player1 has a Moat in hand instead of a Copper
6 | When Player1 plays a Moat
7 | Then Player1 should have 6 cards in hand
8 |
9 | Scenario: Moat is a reaction
10 | Given A new game with 3 players
11 | And Player1 has a Militia in hand instead of a Copper
12 | And Player2 has a Moat in hand instead of a Copper
13 | When Player1 plays a Militia
14 | Then Player2 may reveal a reaction
15 |
16 | Scenario: Moat protects from attacks
17 | Given A new game with 3 players
18 | And Player1 has a Militia in hand instead of a Copper
19 | And Player2 has a Moat in hand instead of a Copper
20 | When Player1 plays a Militia
21 | When Player2 reveals Moat
22 | And Player2 is done with reactions
23 | Then Player2 must wait
24 | And Player3 must select 2 cards to discard
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Familiar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Dominion.Cards.Curses;
3 | using Dominion.Rules;
4 | using Dominion.Rules.CardTypes;
5 |
6 | namespace Dominion.Cards.Actions
7 | {
8 | public class Familiar : Card, IActionCard
9 | {
10 | public Familiar() : base(new CardCost(3, 1))
11 | {}
12 |
13 | public void Play(TurnContext context)
14 | {
15 | context.DrawCards(1);
16 | context.RemainingActions += 1;
17 | context.AddEffect(this, new FamiliarAttack());
18 | }
19 |
20 | private class FamiliarAttack : AttackEffect
21 | {
22 | public override void Attack(Player victim, TurnContext context, ICard source)
23 | {
24 | var gainUtil = new GainUtility(context, victim);
25 | gainUtil.Gain();
26 | }
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Workshop.feature:
--------------------------------------------------------------------------------
1 | Feature: Workshop
2 |
3 | Scenario: Player must choose a card to gain
4 | Given A new game with 3 players
5 | And Player1 has a Workshop in hand instead of a Copper
6 | When Player1 plays a Workshop
7 | Then Player1 must gain a card of cost 4 or less
8 |
9 | Scenario: Player gains card
10 | Given A new game with 3 players
11 | And Player1 has a Workshop in hand instead of a Copper
12 | When Player1 plays a Workshop
13 | When Player1 gains a Silver
14 | Then Player1 should have a Silver on top of the discard pile
15 |
16 | @Hosted
17 | Scenario: Valid choices for workshop gain are marked accordingly in view
18 | Given A new hosted game with 3 players
19 | And Player1 has a Workshop in hand instead of a Copper
20 | When The game begins
21 | And Player1 tells the host to play Workshop
22 | Then Player1's view includes a Silver in the bank that can be gained
--------------------------------------------------------------------------------
/Dominion.Rules/Hand.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 |
4 | namespace Dominion.Rules
5 | {
6 | public class Hand : EnumerableCardZone
7 | {
8 |
9 | }
10 |
11 | public class RevealZone : EnumerableCardZone
12 | {
13 | public RevealZone(Player owner)
14 | {
15 | Owner = owner;
16 | }
17 |
18 | // The owner of the cards in the reveal zone
19 | public Player Owner { get; private set; }
20 |
21 | public void LogReveal(IGameLog log)
22 | {
23 | if(this.CardCount > 0)
24 | log.LogMessage("{0} revealed {1}.", Owner.Name, this);
25 | else
26 | {
27 | log.LogMessage("{0} revealed nothing.", Owner.Name);
28 | }
29 | }
30 | }
31 |
32 | public class LongLivedCardZone : EnumerableCardZone
33 | {
34 | }
35 | }
--------------------------------------------------------------------------------
/Dominion.Rules/ReactionEffect.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using Dominion.Rules.Activities;
3 | using Dominion.Rules.CardTypes;
4 |
5 | namespace Dominion.Rules
6 | {
7 | public class ReactionEffect : CardEffectBase
8 | {
9 | private readonly AttackEffect _attackEffect;
10 |
11 | public ReactionEffect(AttackEffect attackEffect)
12 | {
13 | _attackEffect = attackEffect;
14 | }
15 |
16 | public override void Resolve(TurnContext context, ICard source)
17 | {
18 | foreach(var opponent in context.Opponents)
19 | {
20 | var reactions = opponent.Hand.OfType();
21 |
22 | if(reactions.Count() > 0)
23 | _activities.Add(new SelectReactionActivity(context, opponent, _attackEffect));
24 | }
25 | }
26 |
27 |
28 | }
29 | }
--------------------------------------------------------------------------------
/Dominion.Cards/TestCard.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Rules;
6 |
7 | namespace Dominion.Cards
8 | {
9 | public class TestCard : Card
10 | {
11 | public TestCard(CardCost cost)
12 | : base(cost)
13 | {
14 | }
15 | }
16 |
17 | public class TestCardPile : CardPile
18 | {
19 | public TestCardPile(CardCost cost)
20 | {
21 | AddCard(new TestCard(cost));
22 | }
23 |
24 | public override bool IsEmpty
25 | {
26 | get { return !Cards.Any(); }
27 | }
28 |
29 | public override ICard TopCard
30 | {
31 | get { return Cards.First(); }
32 | }
33 |
34 | public override bool IsLimited
35 | {
36 | get { return true; }
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/BigMoneyBuyBehaviour.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 |
4 | namespace Dominion.GameHost.AI.BehaviourBased
5 | {
6 | public class BigMoneyBuyBehaviour : BuyBehaviourBase
7 | {
8 | public override bool CanRespond(ActivityModel activity, GameViewModel state)
9 | {
10 | return base.CanRespond(activity, state) &&
11 | GetValidBuys(state)
12 | .Any(pile => Treasure.Basic.Contains(pile.Name));
13 | }
14 |
15 | protected override CardPileViewModel SelectPile(GameViewModel state, IGameClient client)
16 | {
17 | return GetValidBuys(state)
18 | .Where(pile => Treasure.Basic.Contains(pile.Name))
19 | .OrderByDescending(pile => pile.Cost)
20 | .First();
21 | }
22 |
23 | }
24 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Expand.feature:
--------------------------------------------------------------------------------
1 | Feature: Expand
2 |
3 | Scenario: Player must choose a card to Expand
4 | Given A new game with 3 players
5 | And Player1 has a Expand in hand instead of a Copper
6 | When Player1 plays a Expand
7 | Then Player1 must select 1 card to Expand
8 |
9 | Scenario: Player Expands Copper
10 | Given A new game with 3 players
11 | And Player1 has a Expand in hand instead of a Copper
12 | When Player1 plays a Expand
13 | And Player1 selects a Copper to Expand
14 | Then Player1 must gain a card of cost 3 or less
15 |
16 | Scenario: Player Expands Copper choosing silver
17 | Given A new game with 3 players
18 | And Player1 has a Expand in hand instead of a Copper
19 | When Player1 plays a Expand
20 | And Player1 selects a Copper to Expand
21 | And Player1 gains a Silver
22 | Then There should be a Copper on top of the trash pile
23 | Then Player1 should have a Silver on top of the discard pile
24 |
--------------------------------------------------------------------------------
/Dominion.Rules/Activities/ExtensionMethods.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Dominion.Rules.CardTypes;
5 |
6 | namespace Dominion.Rules.Activities
7 | {
8 | public static class ExtensionMethods
9 | {
10 | public static string ToOrderString(this int number)
11 | {
12 | switch(number)
13 | {
14 | case 1: return "first";
15 | case 2: return "second";
16 | case 3: return "third";
17 | case 4: return "fourth";
18 | case 5: return "fifth";
19 | case 6: return "sixth";
20 | case 7: return "seventh";
21 | case 8: return "eighth";
22 | case 9: return "ninth";
23 | case 10: return "tenth";
24 | default: return number + "th";
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Remodel.feature:
--------------------------------------------------------------------------------
1 | Feature: Remodel
2 |
3 | Scenario: Player must choose a card to remodel
4 | Given A new game with 3 players
5 | And Player1 has a Remodel in hand instead of a Copper
6 | When Player1 plays a Remodel
7 | Then Player1 must select 1 card to remodel
8 |
9 | Scenario: Player remodels copper
10 | Given A new game with 3 players
11 | And Player1 has a Remodel in hand instead of a Copper
12 | When Player1 plays a Remodel
13 | And Player1 selects a Copper to remodel
14 | Then Player1 must gain a card of cost 2 or less
15 |
16 | Scenario: Player remodels copper choosing estate
17 | Given A new game with 3 players
18 | And Player1 has a Remodel in hand instead of a Copper
19 | When Player1 plays a Remodel
20 | And Player1 selects a Copper to remodel
21 | And Player1 gains a Estate
22 | Then There should be a Copper on top of the trash pile
23 | Then Player1 should have a Estate on top of the discard pile
24 |
--------------------------------------------------------------------------------
/Dominion.GameHost/CardBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Dominion.Rules;
3 | using System;
4 | using Dominion.Rules.CardTypes;
5 |
6 | namespace Dominion.GameHost
7 | {
8 | public static class CardBuilderExtensions
9 | {
10 | public static CardPile WithNewCards(this CardPile targetPile, int count) where T : ICard, new()
11 | {
12 | count.Times(() => new T().MoveTo(targetPile));
13 | return targetPile;
14 | }
15 |
16 | public static CardPile WithNewCards(this CardPile targetPile, string cardName, int count)
17 | {
18 | count.Times(() => CardFactory.CreateCard(cardName).MoveTo(targetPile));
19 | return targetPile;
20 | }
21 |
22 | public static IEnumerable NewCards(this int count) where T : Card, new()
23 | {
24 | return count.Items(() => new T());
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Chapel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Rules;
6 | using Dominion.Rules.Activities;
7 | using Dominion.Rules.CardTypes;
8 |
9 | namespace Dominion.Cards.Actions
10 | {
11 | public class Chapel : Card, IActionCard
12 | {
13 | public Chapel()
14 | : base(2)
15 | {
16 | }
17 |
18 | public void Play(TurnContext context)
19 | {
20 | context.AddEffect(this, new ChapelEffect());
21 | }
22 |
23 | private class ChapelEffect : CardEffectBase
24 | {
25 | public override void Resolve(TurnContext context, ICard source)
26 | {
27 | var activity = Activities.SelectUpToXCardsToTrash(context, context.ActivePlayer, 4, source);
28 | _activities.Add(activity);
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Wharf.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules;
2 | using Dominion.Rules.CardTypes;
3 |
4 | namespace Dominion.Cards.Actions
5 | {
6 | public class Wharf : Card, IDurationCard
7 | {
8 | public Wharf()
9 | : base(5)
10 | { }
11 |
12 | public void Play(TurnContext context)
13 | {
14 | context.DrawCards(2);
15 | context.Buys += 1;
16 | context.AddLongLivedEffect(new WharfEffect(this));
17 | }
18 |
19 | public class WharfEffect : DurationEffect
20 | {
21 | public WharfEffect(ICard sourceCard)
22 | : base(sourceCard)
23 | { }
24 |
25 | public override void OnTurnStarting(TurnContext context)
26 | {
27 | base.OnTurnStarting(context);
28 | context.DrawCards(2);
29 | context.Buys += 1;
30 | }
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Nobles.feature:
--------------------------------------------------------------------------------
1 | Feature: Nobles
2 |
3 | Background:
4 | Given A new game with 3 players
5 | And Player1 has a hand of Nobles, Copper, Silver, Estate, Estate
6 | When Player1 plays a Nobles
7 |
8 | Scenario: Player must choose between cards or actions
9 | Then Player1 must choose from DrawCards, GainActions
10 |
11 | Scenario: Player gets 3 Cards for DrawCards
12 | And Player1 chooses to draw 3 cards (DrawCards)
13 | Then Player1 should have 7 cards in hand
14 | And Player1 should have 0 actions remaining
15 |
16 | Scenario: Player gets 2 Actions for GainActions
17 | And Player1 chooses to gain 2 actions (GainActions)
18 | Then Player1 should have 2 actions remaining
19 | And Player1 should have 4 cards in hand
20 |
21 | Scenario: Is Worth 2 Victory Points
22 | Given A new game with 3 players
23 | And Player1 has a Nobles in hand instead of a Copper
24 | When The game is scored
25 | Then Player1 should have 5 victory points
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/TreasureMap.feature:
--------------------------------------------------------------------------------
1 | Feature: Treasure Map
2 |
3 | Scenario: Playing treasure map with another treasure map in hand gets the gold
4 | Given A new game with 3 players
5 | And Player1 has a hand of TreasureMap, TreasureMap, Copper, Copper, Estate
6 | And Player1 has a deck of Estate, Copper, Copper, Copper, Estate
7 | When Player1 plays a TreasureMap
8 | Then The trash pile should be TreasureMap, TreasureMap
9 | And Player1 should have a deck of: Gold, Gold, Gold, Gold, Estate, Copper, Copper, Copper, Estate
10 |
11 | Scenario: Playing treasure map without another one in hand just trashes it
12 | Given A new game with 3 players
13 | And Player1 has a hand of TreasureMap, Copper, Copper, Copper, Estate
14 | And Player1 has a deck of Estate, Copper, Copper, Copper, Estate
15 | When Player1 plays a TreasureMap
16 | Then The trash pile should be TreasureMap
17 | And Player1 should have a deck of: Estate, Copper, Copper, Copper, Estate
18 |
--------------------------------------------------------------------------------
/Dominion.Specs/Hosted/GameHost.feature:
--------------------------------------------------------------------------------
1 | Feature: Game Host
2 | In order to play with other people
3 | As a Dominion player
4 | I want to interact with the game
5 | And know when the game state changes
6 |
7 | Scenario: Game Begins
8 | Given A new hosted game with 3 players
9 | When The game begins
10 | Then All players should recieve 1 game state update
11 |
12 | Scenario: Player interacts with game
13 | Given A new hosted game with 3 players
14 | When The game begins
15 | And Player1 tells the host to buy Copper
16 | Then All players should recieve 2 game state updates
17 |
18 | Scenario: Player plays an action that requires other players to make decisions
19 | Given A new hosted game with 3 players
20 | And Player1 has a Militia in hand instead of a Copper
21 | When The game begins
22 | And Player1 tells the host to play Militia
23 | Then The host should tell Player2 to discard 2 cards
24 | Then The host should tell Player3 to discard 2 cards
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Cellar.feature:
--------------------------------------------------------------------------------
1 | Feature: Cellar
2 |
3 | Background:
4 | Given A new game with 3 players
5 | And Player1 has a hand of Cellar, Estate, Estate, Copper, Copper
6 | When Player1 plays a Cellar
7 |
8 | Scenario: Player must select a number of cards to discard
9 | Then Player1 may select up to 4 cards from their hand
10 |
11 | Scenario: Player discards one card to Cellar
12 | And Player1 selects a Copper to discard
13 | Then Player1 should have a Copper on top of the discard pile
14 | And Player1 should have 1 actions remaining
15 |
16 | Scenario: Player discards two cards to Cellar
17 | And Player1 selects cards [Copper, Estate] to discard
18 | Then Player1 should have a Estate on top of the discard pile
19 | And Player1 should have 1 actions remaining
20 |
21 | Scenario: Player discards nothing to Cellar
22 | And Player1 selects nothing to discard
23 | Then Player1 should have 4 cards in hand
24 | And Player1 should have 1 actions remaining
25 |
--------------------------------------------------------------------------------
/Dominion.GameHost/BuyCardMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Dominion.Rules;
4 |
5 | namespace Dominion.GameHost
6 | {
7 | public class BuyCardMessage : IGameActionMessage
8 | {
9 | public BuyCardMessage(Guid playerId, Guid pileId)
10 | {
11 | PlayerId = playerId;
12 | PileId = pileId;
13 | }
14 |
15 | public Guid PlayerId { get; private set; }
16 | public Guid PileId { get; private set; }
17 |
18 | public void UpdateGameState(Game game)
19 | {
20 | CardPile pile = game.Bank.Piles.Single(p => p.Id == PileId);
21 | game.CurrentTurn.Buy(pile);
22 | }
23 |
24 | public void Validate(Game game)
25 | {
26 | if(game.ActivePlayer.Id != PlayerId)
27 | throw new InvalidOperationException(string.Format("Player '{0}' is not active.", PlayerId));
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Witch.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Text;
4 | using Dominion.Rules;
5 | using Dominion.Rules.CardTypes;
6 | using Dominion.Cards.Curses;
7 |
8 | namespace Dominion.Cards.Actions
9 | {
10 | public class Witch : Card, IActionCard, IAttackCard
11 | {
12 | public Witch()
13 | : base(5)
14 | {
15 |
16 | }
17 |
18 | public void Play(TurnContext context)
19 | {
20 | context.DrawCards(2);
21 | context.AddEffect(this, new WitchAttack());
22 | }
23 |
24 | private class WitchAttack : AttackEffect
25 | {
26 | public override void Attack(Player victim, TurnContext context, ICard source)
27 | {
28 | var gainUtil = new GainUtility(context, victim);
29 | gainUtil.Gain();
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/University.feature:
--------------------------------------------------------------------------------
1 | Feature: University
2 |
3 | Scenario: Player plays University and must select an action card to gain
4 | Given A new game with 3 players
5 | And Player1 has a University in hand instead of a Copper
6 | When Player1 plays a University
7 | Then Player1 may gain an action card of cost 5 or less
8 | And Player1 should have 2 remaining actions
9 |
10 | Scenario: Player plays University and selects an action
11 | Given A new game with 3 players
12 | And Player1 has a University in hand instead of a Copper
13 | When Player1 plays a University
14 | And Player1 gains a Moat
15 | Then All actions should be resolved
16 | Then Player1 should have a Moat on top of the discard pile
17 |
18 | Scenario: Player plays University and chooses not to gain
19 | Given A new game with 3 players
20 | And Player1 has a University in hand instead of a Copper
21 | When Player1 plays a University
22 | And Player1 gains nothing
23 | Then All actions should be resolved
24 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Coppersmith.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Rules;
6 | using Dominion.Rules.CardTypes;
7 | using Dominion.Cards.Treasure;
8 |
9 | namespace Dominion.Cards.Actions
10 | {
11 | public class Coppersmith : Card, IActionCard
12 | {
13 | public Coppersmith()
14 | : base(4)
15 | {
16 | }
17 |
18 | public void Play(TurnContext context)
19 | {
20 | context.AddPassiveCardEffect(new CoppersmithPassiveEffect());
21 | }
22 |
23 | private class CoppersmithPassiveEffect : PassiveCardEffectBase
24 | {
25 | public override CardCost ModifyValue(CardCost currentValue, ITreasureCard card)
26 | {
27 | if (card is Copper)
28 | return currentValue + 1;
29 |
30 | return currentValue;
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/City.feature:
--------------------------------------------------------------------------------
1 | Feature: City
2 |
3 | Scenario: Play City with no empty piles
4 | Given A new game with 3 players
5 | And Player1 has a City in hand instead of a Copper
6 | When Player1 plays a City
7 | Then Player1 should have 2 remaining actions
8 | Then Player1 should have 5 cards in hand
9 |
10 | Scenario: Play City with 1 empty pile
11 | Given A new game with 3 players
12 | Given There are 1 empty piles
13 | And Player1 has a City in hand instead of a Copper
14 | When Player1 plays a City
15 | Then Player1 should have 2 remaining actions
16 | Then Player1 should have 6 cards in hand
17 |
18 | Scenario: Play City with 2 empty piles
19 | Given A new game with 3 players
20 | Given There are 2 empty piles
21 | And Player1 has a City in hand instead of a Copper
22 | When Player1 plays a City
23 | Then Player1 should have 2 remaining actions
24 | Then Player1 should have 6 cards in hand
25 | Then Player1 should have 1 to spend
26 | Then Player1 should have 2 buys
27 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Chancellor.feature:
--------------------------------------------------------------------------------
1 | Feature: Chancellor
2 |
3 | Background:
4 | Given A new game with 3 players
5 | And Player1 has a Chancellor in hand instead of a Copper
6 |
7 | Scenario: Chancellor is +2 money
8 | When Player1 plays a Chancellor
9 | Then Player1 should have 2 to spend
10 |
11 | Scenario: Player may choose whether to use Chancellor's effect
12 | When Player1 plays a Chancellor
13 | Then Player1 must choose whether to use Chancellor's effect (Yes or No)
14 |
15 | Scenario: Player uses Chancellor's effect
16 | When Player1 plays a Chancellor
17 | When Player1 chooses to move their deck to the discard pile (Yes)
18 | Then Player1 should have a deck of 0 cards
19 | And Player1 should have 5 cards in the discard pile
20 |
21 | Scenario: Player does not use Chancellor's effect
22 | When Player1 plays a Chancellor
23 | When Player1 chooses to leave their deck as is (No)
24 | Then Player1 should have a deck of 5 cards
25 | And Player1 should have 0 cards in the discard pile
26 |
27 |
--------------------------------------------------------------------------------
/Dominion.Rules/Activities/GainACardActivity.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Dominion.Rules.Activities
4 | {
5 | public class GainACardActivity : SelectPileActivity
6 | {
7 | private readonly CardZone _destination;
8 |
9 | public Action AfterCardGained { get; set; }
10 |
11 | public GainACardActivity(IGameLog log, Player player, string message, ISelectionSpecification specification, CardZone destination, ICard source)
12 | : base(log, player, message, specification, source)
13 | {
14 | _destination = destination;
15 | Hint = ActivityHint.GainCards;
16 | }
17 |
18 | public override void SelectPile(CardPile pile)
19 | {
20 | base.SelectPile(pile);
21 |
22 | var card = pile.TopCard;
23 | card.MoveTo(_destination);
24 | Log.LogGain(Player, card);
25 |
26 | if (AfterCardGained != null)
27 | AfterCardGained(card);
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Duke.feature:
--------------------------------------------------------------------------------
1 | Feature: Duke
2 |
3 | Scenario: Duke is worth zero points if there are no duchies in the deck
4 | Given A new game with 3 players
5 | And Player1 has a hand of Copper, Copper, Copper, Copper, Copper
6 | And Player1 has a deck of Copper, Copper, Copper, Copper, Duke
7 | When The game is scored
8 | Then Player1 should have 0 victory points
9 |
10 | Scenario: Duke is worth one point if there is one duchy in the deck
11 | Given A new game with 3 players
12 | And Player1 has a hand of Copper, Copper, Copper, Copper, Copper
13 | And Player1 has a deck of Copper, Duchy, Copper, Copper, Duke
14 | When The game is scored
15 | Then Player1 should have 4 victory points
16 |
17 | Scenario: Duke is worth five points if there are five duchies in the deck
18 | Given A new game with 3 players
19 | And Player1 has a hand of Duchy, Duchy, Duchy, Duchy, Duchy
20 | And Player1 has a deck of Duke, Copper, Copper, Copper, Copper
21 | When The game is scored
22 | Then Player1 should have 20 victory points
--------------------------------------------------------------------------------
/Dominion.GameHost/PlayCardMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Dominion.Rules;
4 | using Dominion.Rules.CardTypes;
5 |
6 | namespace Dominion.GameHost
7 | {
8 | public class PlayCardMessage : IGameActionMessage
9 | {
10 | public PlayCardMessage(Guid playerId, Guid cardId)
11 | {
12 | PlayerId = playerId;
13 | CardId = cardId;
14 | }
15 |
16 | public Guid PlayerId { get; private set; }
17 | public Guid CardId { get; private set; }
18 |
19 | public void UpdateGameState(Game game)
20 | {
21 | ICard card = game.CurrentTurn.ActivePlayer.Hand.Single(c => c.Id == CardId);
22 | game.CurrentTurn.Play((IActionCard) card);
23 | }
24 |
25 | public void Validate(Game game)
26 | {
27 | if (game.ActivePlayer.Id != PlayerId)
28 | throw new InvalidOperationException(string.Format("Player '{0}' is not active.", PlayerId));
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Cutpurse.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Dominion.Cards.Treasure;
4 | using Dominion.Rules;
5 | using Dominion.Rules.CardTypes;
6 |
7 | namespace Dominion.Cards.Actions
8 | {
9 | public class Cutpurse : Card, IActionCard, IAttackCard
10 | {
11 | public Cutpurse() : base(4)
12 | {
13 | }
14 |
15 | public void Play(TurnContext context)
16 | {
17 | context.AvailableSpend += 2;
18 | context.AddEffect(this, new CutpurseAttack());
19 | }
20 |
21 | public class CutpurseAttack : AttackEffect
22 | {
23 | public override void Attack(Player victim, TurnContext context, ICard source)
24 | {
25 | var copper = victim.Hand.FirstOrDefault(c => c is Copper);
26 |
27 | if (copper != null)
28 | context.DiscardCard(victim, copper);
29 | else
30 | context.Game.Log.LogRevealHand(victim);
31 | }
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Vineyard.feature:
--------------------------------------------------------------------------------
1 | Feature: Vineyard
2 |
3 | Scenario: Vineyard is worth zero points if there are 2 (or less) actions in the deck
4 | Given A new game with 3 players
5 | And Player1 has a hand of Copper, Copper, Copper, Copper, Copper
6 | And Player1 has a deck of Copper, Copper, Smithy, Smithy, Vineyard
7 | When The game is scored
8 | Then Player1 should have 0 victory points
9 |
10 | Scenario: Vineyard is worth one point if there are 3 actions in the deck
11 | Given A new game with 3 players
12 | And Player1 has a hand of Copper, Copper, Copper, Copper, Copper
13 | And Player1 has a deck of Copper, Smithy, Smithy, Smithy, Vineyard
14 | When The game is scored
15 | Then Player1 should have 1 victory point
16 |
17 | Scenario: Vineyard is worth two points if there are 6 actions in the deck
18 | Given A new game with 3 players
19 | And Player1 has a hand of Copper, Copper, Copper, Smithy, Smithy
20 | And Player1 has a deck of Smithy, Smithy, Smithy, Smithy, Vineyard
21 | When The game is scored
22 | Then Player1 should have 2 victory points
--------------------------------------------------------------------------------
/Dominion.Web/Views/Shared/site.Master:
--------------------------------------------------------------------------------
1 | <%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= Html.Css("Site.css") %>
9 | <%= Html.Css("jqueryUI/jquery-ui-1.8.4.custom.css")%>
10 | <%= Html.Script("jquery-1.4.1.min.js", "jquery-1.4.1.js")%>
11 | <%= Html.Script("jquery-ui-1.8.4.custom.min.js")%>
12 | <%= Html.Script("jquery.tmpl.js")%>
13 | <%= Html.Script("jquery.form.js")%>
14 | <%= Html.Script("jquery.layout-1.3.0.rc29.4.js")%>
15 | <%= Html.Script("jquery.thumbhover.js")%>
16 | <%= Html.Script("jquery.hotkeys-0.7.9.js")%>
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Dominion.Rules/CardTypes/IActionCard.cs:
--------------------------------------------------------------------------------
1 | namespace Dominion.Rules.CardTypes
2 | {
3 | public interface IActionCard : ICard
4 | {
5 | void Play(TurnContext context);
6 | }
7 |
8 | public interface IReactionCard : ICard
9 | {
10 | void React(AttackEffect attackEffect, Player player, TurnContext currentTurn);
11 |
12 | ///
13 | /// Does it make sense for the player's reaction window to stay open if this was the only reaction in their hand?
14 | /// For example, if you only have a moat in your hand, once its revealed, there is no point in keeping the reaction window open. The rules say you can, but there is no point.
15 | /// Secret Chamber on the other hand, might draw you another reaction, so its worth keeping the window open.
16 | ///
17 | bool ContinueReactingIfOnlyReaction { get; }
18 | }
19 |
20 | public interface IAttackCard : ICard
21 | {
22 |
23 | }
24 |
25 | public interface IDurationCard : IActionCard
26 | {
27 |
28 | }
29 | }
--------------------------------------------------------------------------------
/Dominion.Rules/GameScores.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Dominion.Rules.CardTypes;
5 |
6 | namespace Dominion.Rules
7 | {
8 | public class GameScores : Dictionary
9 | {
10 | private readonly Game _game;
11 |
12 | public GameScores(Game game)
13 | {
14 | _game = game;
15 | }
16 |
17 | public void Score(Player player)
18 | {
19 | player.Discards.MoveAll(player.PlayArea);
20 | player.Hand.MoveAll(player.PlayArea);
21 | player.Deck.MoveAll(player.PlayArea);
22 |
23 | player.PlayArea.SortForScoring();
24 |
25 | this[player] = player.PlayArea.OfType().Sum(c => c.Score(player.PlayArea));
26 | }
27 |
28 | public Player Winner
29 | {
30 | get
31 | {
32 | return _game.Players
33 | .Last(player => this[player] == this.Values.Max());
34 | }
35 | }
36 | }
37 |
38 | }
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/DefaultSelectFixedNumberOfCardsToPassOrTrashBehaviour.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Dominion.Cards.Victory;
5 | using Dominion.Rules.Activities;
6 |
7 | namespace Dominion.GameHost.AI.BehaviourBased
8 | {
9 | public class DefaultSelectFixedNumberOfCardsToPassOrTrashBehaviour : SelectFixedNumberOfCardsBehaviourBase
10 | {
11 | public override bool CanRespond(ActivityModel activity, GameViewModel state)
12 | {
13 | return base.CanRespond(activity, state) &&
14 | (activity.ParseHint() == ActivityHint.PassCards || activity.ParseHint() == ActivityHint.TrashCards);
15 | }
16 |
17 | protected override IEnumerable PrioritiseCards(GameViewModel state, ActivityModel activity)
18 | {
19 | return state.Hand
20 | .OrderByDescending(c => c.Is(CardType.Curse))
21 | .ThenByDescending(c => c.Is())
22 | .ThenBy(c => c.Cost);
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/BigMoneyAI.cs:
--------------------------------------------------------------------------------
1 | namespace Dominion.GameHost.AI.BehaviourBased
2 | {
3 | public class BigMoneyAI : BehaviourBasedAI
4 | {
5 | public BigMoneyAI()
6 | {
7 | Behaviours.Add(new CommentOnGameEndBehaviour("The game is over? But I was about to buy a Province!"));
8 |
9 | Behaviours.Add(new DefaultDiscardOrRedrawCardsBehaviour());
10 | Behaviours.Add(new DefaultMakeChoiceBehaviour());
11 | Behaviours.Add(new DefaultSelectFixedNumberOfCardsToPassOrTrashBehaviour());
12 | Behaviours.Add(new DefaultSelectFromRevealedBehaviour());
13 | Behaviours.Add(new DefaultSelectFixedNumberOfCardsForPlayBehaviour());
14 | Behaviours.Add(new DefaultSelectUpToNumberOfCardsToTrashBehaviour());
15 |
16 | Behaviours.Add(new SkipActionsBehaviour());
17 |
18 | Behaviours.Add(new BuyPointsBehaviour(6));
19 | Behaviours.Add(new BigMoneyBuyBehaviour());
20 | Behaviours.Add(new SkipBuyBehaviour());
21 |
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/SeaHag.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Rules;
6 | using Dominion.Rules.Activities;
7 | using Dominion.Rules.CardTypes;
8 | using Dominion.Cards.Curses;
9 |
10 | namespace Dominion.Cards.Actions
11 | {
12 | public class SeaHag : Card, IActionCard, IAttackCard
13 | {
14 | public SeaHag() : base(4) { }
15 |
16 | public void Play(TurnContext context)
17 | {
18 | context.AddEffect(this, new SeaHagAttack());
19 | }
20 |
21 | private class SeaHagAttack : AttackEffect
22 | {
23 | public override void Attack(Player victim, TurnContext context, ICard source)
24 | {
25 | if (victim.Deck.CardCount + victim.Discards.CardCount > 0)
26 | victim.Deck.MoveTop(1, victim.Discards);
27 |
28 | var gainUtil = new GainUtility(context, victim);
29 | gainUtil.Gain(c => victim.Deck.MoveToTop(c));
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/TreasureMap.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Dominion.Cards.Treasure;
4 | using Dominion.Rules;
5 | using Dominion.Rules.CardTypes;
6 |
7 | namespace Dominion.Cards.Actions
8 | {
9 | public class TreasureMap : Card, IActionCard
10 | {
11 | public TreasureMap() : base(4)
12 | {}
13 |
14 | public void Play(TurnContext context)
15 | {
16 | context.Trash(context.ActivePlayer, this);
17 | var otherMap = context.ActivePlayer.Hand.OfType().FirstOrDefault();
18 | if(otherMap != null)
19 | {
20 | context.Trash(context.ActivePlayer, otherMap);
21 | var gainUtil = new GainUtility(context, context.ActivePlayer);
22 | var deck = context.ActivePlayer.Deck;
23 | gainUtil.Gain(deck.MoveToTop);
24 | gainUtil.Gain(deck.MoveToTop);
25 | gainUtil.Gain(deck.MoveToTop);
26 | gainUtil.Gain(deck.MoveToTop);
27 | }
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Dominion.GameHost/ChoiceMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Rules;
6 | using Dominion.Rules.Activities;
7 |
8 | namespace Dominion.GameHost
9 | {
10 | public class ChoiceMessage : IGameActionMessage
11 | {
12 | public ChoiceMessage(Guid playerId, string choice)
13 | {
14 | PlayerId = playerId;
15 | Choice = choice;
16 | }
17 |
18 | public Guid PlayerId { get; private set; }
19 | public string Choice { get; set; }
20 |
21 | public void UpdateGameState(Game game)
22 | {
23 | var player = game.Players.Single(p => p.Id == PlayerId);
24 | var activity = game.GetPendingActivity(player) as ChoiceActivity;
25 |
26 | if (activity == null)
27 | throw new InvalidOperationException("There must be a corresponding activity");
28 |
29 | activity.MakeChoice(Choice);
30 | }
31 |
32 | public void Validate(Game game)
33 | {
34 |
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Dominion.Specs/GameLog.feature:
--------------------------------------------------------------------------------
1 | Feature: Game Log
2 | In order to know what is going on
3 | As a Dominion player
4 | I want to be told when players do things
5 |
6 | Scenario: A player begins their turn
7 | Given A new game with 3 players
8 | Then The game log should report that Player1's turn has begun
9 |
10 | Scenario: A player plays an action
11 | Given A new game with 3 players
12 | And Player1 has a Woodcutter in hand instead of a Copper
13 | When Player1 plays a Woodcutter
14 | Then The game log should report that Player1 played a Woodcutter
15 |
16 | Scenario: A player buys a card
17 | Given A new game with 3 players
18 | When Player1 moves to the buy step
19 | And Player1 buys a Copper
20 | Then The game log should report that Player1 bought a Copper
21 |
22 | Scenario: The game ends
23 | Given A new game with 3 players
24 | But There is only 1 Province left
25 | And Player1 has 5 Gold in hand
26 | When Player1 moves to the buy step
27 | And Player1 buys a Province
28 | And Player1 ends their turn
29 | Then The game log should report the scores
30 | And Player1 should be the winner
31 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Transmute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Dominion.Cards.Treasure;
3 | using Dominion.Cards.Victory;
4 | using Dominion.Rules;
5 | using Dominion.Rules.Activities;
6 | using Dominion.Rules.CardTypes;
7 |
8 | namespace Dominion.Cards.Actions
9 | {
10 | public class Transmute : Card, IActionCard
11 | {
12 | public Transmute() : base(CardCost.Parse("0P"))
13 | {}
14 |
15 | public void Play(TurnContext context)
16 | {
17 | if(context.ActivePlayer.Hand.CardCount > 0)
18 | {
19 | var gainUtility = new GainUtility(context, context.ActivePlayer);
20 |
21 | var activity = Activities.SelectACardToTrash(context, context.ActivePlayer, this, card =>
22 | {
23 | if (card is IActionCard) gainUtility.Gain();
24 | if (card is ITreasureCard) gainUtility.Gain();
25 | if (card is IVictoryCard) gainUtility.Gain();
26 | });
27 |
28 | context.AddSingleActivity(activity, this);
29 | }
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/DefaultSelectUpToNumberOfCardsToTrashBehaviour.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using Dominion.Cards.Curses;
3 | using Dominion.Cards.Treasure;
4 | using Dominion.Cards.Victory;
5 | using Dominion.Rules.Activities;
6 |
7 | namespace Dominion.GameHost.AI.BehaviourBased
8 | {
9 | public class DefaultSelectUpToNumberOfCardsToTrashBehaviour : IAIBehaviour
10 | {
11 | public virtual bool CanRespond(ActivityModel activity, GameViewModel state)
12 | {
13 | return activity.ParseType() == ActivityType.SelectUpToNumberOfCards
14 | && activity.ParseHint() == ActivityHint.TrashCards;
15 | }
16 |
17 | public void Respond(IGameClient client, ActivityModel activity, GameViewModel state)
18 | {
19 | var idsToTrash = state.Hand.Where(c => c.Is() || c.Is() || c.Is())
20 | .Select(c => c.Id)
21 | .Take(activity.ParseNumberOfCardsToSelect())
22 | .ToArray();
23 |
24 | client.AcceptMessage(new SelectCardsMessage(client.PlayerId, idsToTrash));
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/Dominion.Web/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Envoy.feature:
--------------------------------------------------------------------------------
1 | Feature: Envoy
2 |
3 | Scenario: Player plays Envoy, opponent must choose which card they don't draw
4 | Given A new game with 3 players
5 | And Player1 has a Envoy in hand instead of a Copper
6 | And Player1 has a deck of Silver, Copper, Estate, Copper, Copper
7 | When Player1 plays a Envoy
8 | Then Player2 must select a revealed card from: Silver, Copper, Estate, Copper, Copper
9 |
10 | Scenario: Player plays Envoy, draws 4 cards
11 | Given A new game with 3 players
12 | And Player1 has a hand of Envoy, Copper, Estate, Copper, Copper
13 | And Player1 has a deck of Silver, Copper, Estate, Copper, Copper
14 | When Player1 plays a Envoy
15 | When Player2 selects Silver from the revealed cards
16 | Then Player1 should have a hand of Copper, Estate, Copper, Copper, Copper, Estate, Copper, Copper
17 |
18 | Scenario: Player plays Envoy with empty deck and discards
19 | Given A new game with 3 players
20 | And Player1 has a hand of Envoy, Copper, Estate, Copper, Copper
21 | And Player1 has an empty deck
22 | When Player1 plays a Envoy
23 | Then Player1 should have 4 cards in hand
24 | And All actions should be resolved
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Warehouse.feature:
--------------------------------------------------------------------------------
1 | Feature: Warehouse
2 |
3 | Scenario: Player must decide what cards to discard
4 | Given A new game with 3 players
5 | And Player1 has a Warehouse in hand instead of a Copper
6 | When Player1 plays a Warehouse
7 | Then Player1 should have 7 cards in hand
8 | And Player1 should have 1 remaining action
9 | And Player1 must select 3 cards to discard
10 |
11 | Scenario: Player discards 3 cards
12 | Given A new game with 3 players
13 | And Player1 has a Warehouse in hand instead of a Copper
14 | When Player1 plays a Warehouse
15 | And Player1 selects 3 Copper to discard
16 | Then Player1 should have 4 cards in hand
17 | And Player1 should have 1 remaining action
18 | And Player1 should have 3 cards in the discard pile
19 |
20 | Scenario: Play warehouse with a total of two cards in hand, deck and discard pile
21 | Given A new game with 3 players
22 | And Player1 has a hand of Warehouse, Copper
23 | And Player1 has an empty deck
24 | When Player1 plays a Warehouse
25 | Then Player1 should have 0 cards in hand
26 | And Player1 should have 1 remaining action
27 | And Player1 should have 1 card in the discard pile
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Moneylender.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Dominion.Rules;
5 | using Dominion.Rules.Activities;
6 | using Dominion.Rules.CardTypes;
7 | using Dominion.Cards.Treasure;
8 |
9 | namespace Dominion.Cards.Actions
10 | {
11 | public class Moneylender : Card, IActionCard
12 | {
13 | public Moneylender()
14 | : base(4)
15 | { }
16 |
17 | public void Play(TurnContext context)
18 | {
19 | context.AddEffect(this, new MoneylenderEffect());
20 | }
21 |
22 | private class MoneylenderEffect : CardEffectBase
23 | {
24 | public override void Resolve(TurnContext context, ICard source)
25 | {
26 | if (context.ActivePlayer.Hand.OfType().Any())
27 | {
28 | var copperCard = context.ActivePlayer.Hand.OfType().FirstOrDefault();
29 | context.Trash(context.ActivePlayer, copperCard);
30 | context.AvailableSpend += 3;
31 | };
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/PlaySimpleActionsBehaviour.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Dominion.Rules.Activities;
4 |
5 | namespace Dominion.GameHost.AI.BehaviourBased
6 | {
7 | public class PlaySimpleActionsBehaviour : IAIBehaviour
8 | {
9 |
10 | public bool CanRespond(ActivityModel activity, GameViewModel state)
11 | {
12 | return activity.ParseType() == ActivityType.PlayActions &&
13 | state.Hand.Select(c => c.Name).Intersect(AISupportedActions.All).Any();
14 | }
15 |
16 | public void Respond(IGameClient client, ActivityModel activity, GameViewModel state)
17 | {
18 | var action = state.Hand
19 | .Where(c => c.Is(CardType.Action))
20 | .Where(c => AISupportedActions.All.Contains(c.Name))
21 | .OrderByDescending(c => AISupportedActions.PlusActions.Contains(c.Name))
22 | .ThenByDescending(c => c.Cost)
23 | .First();
24 |
25 | var message = new PlayCardMessage(client.PlayerId, action.Id);
26 | client.AcceptMessage(message);
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/Dominion.GameHost/ChooseAPileMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Dominion.Rules;
4 | using Dominion.Rules.Activities;
5 |
6 | namespace Dominion.GameHost
7 | {
8 | public class ChooseAPileMessage : IGameActionMessage
9 | {
10 | public ChooseAPileMessage(Guid playerId, Guid pileId)
11 | {
12 | PlayerId = playerId;
13 | PileId = pileId;
14 | }
15 |
16 | public Guid PlayerId { get; private set; }
17 | public Guid PileId { get; private set; }
18 |
19 | public void UpdateGameState(Game game)
20 | {
21 | var player = game.Players.Single(p => p.Id == PlayerId);
22 | var pile = game.Bank.Piles.SingleOrDefault(p => p.Id == PileId);
23 | var activity = game.GetPendingActivity(player) as ISelectPileActivity;
24 |
25 | if (activity == null)
26 | throw new InvalidOperationException("There must be a corresponding activity");
27 |
28 | activity.SelectPile(pile);
29 | }
30 |
31 | public void Validate(Game game)
32 | {
33 |
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2010 Paul Batum, Glenn Condron, Trent Kerin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/Dominion.Specs/Hosted/Reactions.feature:
--------------------------------------------------------------------------------
1 | Feature: Reactions
2 | In order to play the game to it's fullest potential
3 | As a dominion player
4 | I want to be able to pull neat tricks with reactions
5 |
6 | Scenario: Player uses Secret Chamber, draws a Moat, uses Moat, uses Secret Chamber again putting both reactions back on top of the deck
7 | Given A new hosted game with 3 players
8 | And Player1 has a Militia in hand instead of a Copper
9 | And Player2 has a hand of SecretChamber, Copper, Copper, Copper, Estate
10 | And Player2 has a deck of Moat, Estate, Estate, Copper, Copper
11 | When Player1 tells the host to play Militia
12 | And Player2 tells the host to reveal SecretChamber
13 | And Player2 tells the host to put Copper on top
14 | And Player2 tells the host to put Copper on top
15 | And Player2 tells the host to reveal Moat
16 | And Player2 tells the host to reveal SecretChamber
17 | And Player2 tells the host to put SecretChamber on top
18 | And Player2 tells the host to put Moat on top
19 | Then Player2 should have a hand of Copper, Estate, Estate, Copper, Copper
20 | And Player2 should have a deck of: Moat, SecretChamber, Estate, Copper, Copper
21 |
22 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Tribute.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using Dominion.Rules;
3 | using Dominion.Rules.CardTypes;
4 |
5 | namespace Dominion.Cards.Actions
6 | {
7 | public class Tribute : Card, IActionCard
8 | {
9 | public Tribute()
10 | : base(5)
11 | {
12 |
13 | }
14 |
15 | public void Play(TurnContext context)
16 | {
17 | var leftPlayer = context.Opponents.FirstOrDefault();
18 | if (leftPlayer != null)
19 | {
20 | var revealZone = new RevealZone(leftPlayer);
21 | leftPlayer.Deck.MoveTop(2, revealZone);
22 | revealZone.LogReveal(context.Game.Log);
23 |
24 | foreach (var card in revealZone.WithDistinctTypes())
25 | {
26 | if (card is IActionCard) context.RemainingActions += 2;
27 | if (card is ITreasureCard) context.AvailableSpend += 2;
28 | if (card is IVictoryCard) context.DrawCards(2);
29 | }
30 |
31 | revealZone.MoveAll(leftPlayer.Discards);
32 | }
33 |
34 |
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/DefaultDiscardOrRedrawCardsBehaviour.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Dominion.Rules.Activities;
5 |
6 | namespace Dominion.GameHost.AI.BehaviourBased
7 | {
8 | public class DefaultDiscardOrRedrawCardsBehaviour : SelectFixedNumberOfCardsBehaviourBase
9 | {
10 | public override bool CanRespond(ActivityModel activity, GameViewModel state)
11 | {
12 | return base.CanRespond(activity, state) &&
13 | (activity.ParseHint() == ActivityHint.DiscardCards || activity.ParseHint() == ActivityHint.RedrawCards);
14 | }
15 |
16 | protected override IEnumerable PrioritiseCards(GameViewModel state, ActivityModel activity)
17 | {
18 |
19 | return state.Hand
20 | .Where(c => !activity.HasTypeRestriction() || c.Types.Contains(activity.ParseTypeRestriction()))
21 | .OrderByDescending(c => c.Is(CardType.Treasure) == false)
22 | .ThenByDescending(c => c.Is(CardType.Action) == false)
23 | .ThenBy(c => c.Cost);
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/SimpleAI.cs:
--------------------------------------------------------------------------------
1 | namespace Dominion.GameHost.AI.BehaviourBased
2 | {
3 | public class SimpleAI : BehaviourBasedAI
4 | {
5 | public SimpleAI()
6 | {
7 | Behaviours.Add(new CommentOnGameEndBehaviour("The game is over? But I was about to buy a Province!"));
8 |
9 | Behaviours.Add(new DefaultDiscardOrRedrawCardsBehaviour());
10 | Behaviours.Add(new DefaultMakeChoiceBehaviour());
11 | Behaviours.Add(new DefaultSelectFixedNumberOfCardsToPassOrTrashBehaviour());
12 | Behaviours.Add(new DefaultSelectFromRevealedBehaviour());
13 | Behaviours.Add(new DefaultSelectFixedNumberOfCardsForPlayBehaviour());
14 | Behaviours.Add(new DefaultSelectUpToNumberOfCardsToTrashBehaviour());
15 |
16 | Behaviours.Add(new PlaySimpleActionsBehaviour());
17 | Behaviours.Add(new SkipActionsBehaviour());
18 |
19 | Behaviours.Add(new BuyPointsBehaviour(6));
20 | Behaviours.Add(new BuyAlternatingMoneyAndActionsBehaviour());
21 | Behaviours.Add(new SkipBuyBehaviour());
22 |
23 |
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/GhostShip.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Text;
4 | using Dominion.Rules;
5 | using Dominion.Rules.Activities;
6 | using Dominion.Rules.CardTypes;
7 |
8 | namespace Dominion.Cards.Actions
9 | {
10 | public class GhostShip : Card, IActionCard, IAttackCard
11 | {
12 | public GhostShip()
13 | : base(5)
14 | {
15 | }
16 |
17 | public void Play(TurnContext context)
18 | {
19 | context.ActivePlayer.DrawCards(2);
20 | context.AddEffect(this, new GhostShipAttack());
21 | }
22 |
23 | private class GhostShipAttack : AttackEffect
24 | {
25 | public override void Attack(Player victim, TurnContext context, ICard source)
26 | {
27 | int cardsToPutBack = victim.Hand.CardCount - 3;
28 |
29 | var activities = Activities.PutMultipleCardsFromHandOnTopOfDeck(context.Game.Log, victim, cardsToPutBack, source);
30 | foreach(var activity in activities)
31 | _activities.Add(activity);
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/CountingHouse.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Cards.Treasure;
6 | using Dominion.Rules;
7 | using Dominion.Rules.CardTypes;
8 |
9 | namespace Dominion.Cards.Actions
10 | {
11 | public class CountingHouse : Card, IActionCard
12 | {
13 | public CountingHouse() : base(5)
14 | {
15 | }
16 |
17 | public void Play(TurnContext context)
18 | {
19 | var coppers = context.ActivePlayer.Discards.OfType().ToList();
20 |
21 | if (coppers.Count > 0)
22 | {
23 | context.Game.Log.LogMessage("{0} put {1} Copper from their discard pile into their hand",
24 | context.ActivePlayer.Name, coppers.Count);
25 |
26 | foreach (var copper in coppers)
27 | copper.MoveTo(context.ActivePlayer.Hand);
28 | }
29 | else
30 | {
31 | context.Game.Log.LogMessage("Counting house did nothing - no Copper in discard pile.");
32 | }
33 |
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Dominion.WinForms/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.1
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Dominion.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Militia.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Dominion.Rules;
4 | using Dominion.Rules.Activities;
5 | using Dominion.Rules.CardTypes;
6 |
7 | namespace Dominion.Cards.Actions
8 | {
9 | public class Militia : Card, IActionCard, IAttackCard
10 | {
11 | public Militia() : base(4)
12 | {
13 | }
14 |
15 | public void Play(TurnContext context)
16 | {
17 | context.AvailableSpend += 2;
18 | context.AddEffect(this, new MilitiaAttack());
19 | }
20 |
21 | private class MilitiaAttack : AttackEffect
22 | {
23 | public override void Attack(Player victim, TurnContext context, ICard source)
24 | {
25 | var numberToDiscard = victim.Hand.CardCount - 3;
26 |
27 | if (numberToDiscard > 0)
28 | _activities.Add(Activities.DiscardCards(context, victim, numberToDiscard, source));
29 | else
30 | {
31 | context.Game.Log.LogMessage("{0} did not have to discard any cards.", victim.Name);
32 | }
33 | }
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Salvager.feature:
--------------------------------------------------------------------------------
1 | Feature: Salvager
2 |
3 | Scenario: Salvager trashes a card
4 | Given A new game with 3 players
5 | And Player1 has a Salvager in hand instead of a Copper
6 | When Player1 plays a Salvager
7 | Then Player1 must select 1 card to trash
8 |
9 | Scenario: Salvager trashing estate gives plus 2 spend
10 | Given A new game with 3 players
11 | And Player1 has a hand of Salvager, Estate, Copper, Copper, Copper
12 | When Player1 plays a Salvager
13 | And Player1 selects a Estate to trash
14 | Then Player1 should have 2 to spend
15 | And Player1 should have 2 buys
16 | And There should be a Estate on top of the trash pile
17 |
18 | Scenario: Salvager with no other cards in hand
19 | Given A new game with 3 players
20 | And Player1 has a hand of Salvager
21 | When Player1 plays a Salvager
22 | Then All actions should be resolved
23 | And Player1 should have 2 buys
24 |
25 | Scenario: Salvaging a potion card does not let the player buy a potion card
26 | Given A new game with 3 players
27 | And Player1 has a hand of Salvager, Golem, Estate, Estate, Estate
28 | When Player1 plays a Salvager
29 | And Player1 selects a Golem to trash
30 | Then Player1 should have 4 to spend
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Apprentice.feature:
--------------------------------------------------------------------------------
1 | Feature: Apprentice
2 |
3 | Scenario: Apprentice trashes a card and is +1 action
4 | Given A new game with 3 players
5 | And Player1 has a Apprentice in hand instead of a Copper
6 | When Player1 plays a Apprentice
7 | Then Player1 must select 1 card to trash
8 | And Player1 should have 1 remaining action
9 |
10 | Scenario: Apprentice trashing estate draws 2 cards
11 | Given A new game with 3 players
12 | And Player1 has a hand of Apprentice, Estate, Copper, Copper, Copper
13 | When Player1 plays a Apprentice
14 | And Player1 selects a Estate to trash
15 | Then Player1 should have 5 cards in hand
16 | And There should be a Estate on top of the trash pile
17 |
18 | Scenario: Apprentice with no other cards in hand
19 | Given A new game with 3 players
20 | And Player1 has a hand of Apprentice
21 | When Player1 plays a Apprentice
22 | Then All actions should be resolved
23 |
24 | Scenario: Apprentice trashing Familiar draws 5 cards
25 | Given A new game with 3 players
26 | And Player1 has a hand of Apprentice, Familiar, Estate, Estate, Estate
27 | When Player1 plays a Apprentice
28 | And Player1 selects a Familiar to trash
29 | Then Player1 should have 8 cards in hand
--------------------------------------------------------------------------------
/Dominion.Specs/Scoring.feature:
--------------------------------------------------------------------------------
1 | Feature: Scoring
2 | In order to know how well I did in the game
3 | As a Dominion player
4 | I want the scores to be calculated
5 |
6 | Scenario: Players start with 3 points
7 | Given A new game with 3 players
8 | When The game is scored
9 | Then Player1 should have 3 victory points
10 | And Player2 should have 3 victory points
11 | And Player3 should have 3 victory points
12 |
13 | Scenario: Score cards in all regions
14 | Given A new game with 3 players
15 | And Player1 has a Curse in hand instead of a Copper
16 | And Player1 has a GreatHall in play
17 | And Player1 has a Province in the discard pile
18 | When The game is scored
19 | Then Player1 should have 9 victory points
20 |
21 | Scenario: Show sorted deck in play area once game is scored
22 | Given A new game with 3 players
23 | And Player1 has a Curse in hand instead of a Copper
24 | And Player1 has a GreatHall in play
25 | And Player1 has a Province in the discard pile
26 | When The game is scored
27 | Then Player1's play area should start with this sequence of cards: Province, Estate, Estate, Estate, GreatHall, Curse
28 | Then Player2's play area should start with this sequence of cards: Estate, Estate, Estate
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/DefaultSelectFixedNumberOfCardsForPlayBehaviour.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Rules.Activities;
6 |
7 | namespace Dominion.GameHost.AI.BehaviourBased
8 | {
9 | public class DefaultSelectFixedNumberOfCardsForPlayBehaviour : SelectFixedNumberOfCardsBehaviourBase
10 | {
11 | public bool CanRespond(ActivityModel activity, GameViewModel state)
12 | {
13 | return base.CanRespond(activity, state)
14 | && activity.ParseHint() == ActivityHint.PlayCards
15 | && state.Hand.Select(c => c.Name).Intersect(AISupportedActions.All).Any();
16 | }
17 |
18 | protected override IEnumerable PrioritiseCards(GameViewModel state, ActivityModel activity)
19 | {
20 | var actions = state.Hand
21 | .Where(c => c.Is(CardType.Action))
22 | .Where(c => AISupportedActions.All.Contains(c.Name))
23 | .OrderByDescending(c => c.Cost)
24 | .Take(activity.ParseNumberOfCardsToSelect());
25 |
26 | return actions;
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Dominion.AIWorkbench/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.1
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Dominion.AIWorkbench.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Dominion.Web/Bootstrap/AutofacConfig.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Web.Mvc;
4 | using Autofac;
5 | using Autofac.Integration.Web;
6 | using Autofac.Integration.Web.Mvc;
7 | using System.Reflection;
8 | using Dominion.GameHost;
9 | using Microsoft.Web.Mvc;
10 |
11 | namespace Dominion.Web.Bootstrap
12 | {
13 | public class AutofacConfig
14 | {
15 | private static IContainer _container;
16 |
17 |
18 | public static IContainer Container
19 | {
20 | get { return _container; }
21 | }
22 |
23 | public static void Initialize()
24 | {
25 | var builder = new ContainerBuilder();
26 | builder.RegisterControllers(Assembly.GetExecutingAssembly());
27 |
28 | var host = new MultiGameHost();
29 | builder.RegisterInstance(host)
30 | .As();
31 |
32 | _container = builder.Build();
33 |
34 | var factory =
35 | new MvcDynamicSessionControllerFactory(new AutofacControllerFactory(new ContainerProvider(_container)));
36 | ControllerBuilder.Current.SetControllerFactory(factory);
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/KingsCourt.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using Dominion.Rules;
3 | using Dominion.Rules.Activities;
4 | using Dominion.Rules.CardTypes;
5 |
6 | namespace Dominion.Cards.Actions
7 | {
8 | public class KingsCourt : Card, IActionCard
9 | {
10 | public KingsCourt() : base(7)
11 | {
12 | }
13 |
14 | public void Play(TurnContext context)
15 | {
16 | context.AddEffect(this, new KingsCourtEffect());
17 | }
18 |
19 | private class KingsCourtEffect : CardEffectBase
20 | {
21 | public override void Resolve(TurnContext context, ICard source)
22 | {
23 | if (context.ActivePlayer.Hand.OfType().Any())
24 | {
25 | var activity = Activities.SelectActionToPlayMultipleTimes(context, context.ActivePlayer, context.Game.Log, source, 3);
26 | _activities.Add(activity);
27 | }
28 | else
29 | {
30 | context.Game.Log.LogMessage("{0} did not have any actions to use Kings Court on.", context.ActivePlayer.Name);
31 | }
32 | }
33 | }
34 |
35 |
36 | }
37 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Mountebank.feature:
--------------------------------------------------------------------------------
1 | Feature: Mountebank
2 |
3 | Scenario: Player plays Mountebank when opponents have no curses in hand
4 | Given A new game with 3 players
5 | And Player1 has a Mountebank in hand instead of a Copper
6 | When Player1 plays a Mountebank
7 | Then Player1 should have 2 to spend
8 | Then Player2 should have a discard pile of Copper, Curse
9 | Then Player3 should have a discard pile of Copper, Curse
10 |
11 | Scenario: Player plays Mountebank, opponent must choose whether to discard a curse
12 | Given A new game with 3 players
13 | And Player1 has a Mountebank in hand instead of a Copper
14 | And Player2 has a Curse in hand instead of a Copper
15 | When Player1 plays a Mountebank
16 | Then Player2 must choose whether to discard a Curse (Yes or No)
17 | Then Player3 must wait
18 |
19 | Scenario: Play Mountebank when an opponent is holding a curse
20 | Given A new game with 3 players
21 | And Player1 has a Mountebank in hand instead of a Copper
22 | And Player2 has a Curse in hand instead of a Copper
23 | When Player1 plays a Mountebank
24 | When Player2 chooses to discard a Curse (Yes)
25 | Then Player2 should have a discard pile of Curse
26 | Then Player3 should have a discard pile of Copper, Curse
--------------------------------------------------------------------------------
/Dominion.Rules/UnlimitedSupplyCardPile.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Dominion.Rules
4 | {
5 | public class UnlimitedSupplyCardPile : CardPile
6 | {
7 | private readonly Func _cardCreator;
8 |
9 | public UnlimitedSupplyCardPile(Func cardCreator)
10 | {
11 | _cardCreator = cardCreator;
12 | }
13 |
14 | public override bool IsEmpty
15 | {
16 | get { return false; }
17 | }
18 |
19 | public override int CardCount
20 | {
21 | get
22 | {
23 | throw new NotSupportedException("A null zone cannot be considered to have a card count");
24 | }
25 | }
26 |
27 | public override ICard TopCard
28 | {
29 | get { return _cardCreator(); }
30 | }
31 |
32 | public override bool IsLimited
33 | {
34 | get { return false; }
35 | }
36 |
37 | protected override void AddCard(ICard card)
38 | {
39 | // NO OP
40 | }
41 |
42 | protected override void RemoveCard(ICard card)
43 | {
44 | // NO OP
45 | }
46 |
47 | }
48 | }
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/ProbabilityAI.cs:
--------------------------------------------------------------------------------
1 | namespace Dominion.GameHost.AI.BehaviourBased
2 | {
3 | public class ProbabilityAI : BehaviourBasedAI
4 | {
5 | public ProbabilityAI(ProbabilityDistribution buyDistribution)
6 | {
7 | var buyBehaviour = new ProbabilisticBuyBehaviour(buyDistribution);
8 |
9 | Behaviours.Add(new ProbabilisticBuyBehaviour.LearnFromGameResultBehaviour(buyDistribution));
10 |
11 | Behaviours.Add(new DefaultDiscardOrRedrawCardsBehaviour());
12 | Behaviours.Add(new DefaultMakeChoiceBehaviour());
13 | Behaviours.Add(new DefaultSelectFixedNumberOfCardsToPassOrTrashBehaviour());
14 | Behaviours.Add(new DefaultSelectFromRevealedBehaviour());
15 | Behaviours.Add(new DefaultSelectFixedNumberOfCardsForPlayBehaviour());
16 | Behaviours.Add(new DefaultSelectUpToNumberOfCardsToTrashBehaviour());
17 |
18 | Behaviours.Add(new PlaySimpleActionsBehaviour());
19 | Behaviours.Add(new SkipActionsBehaviour());
20 |
21 | Behaviours.Add(new BuyPointsBehaviour(6));
22 | Behaviours.Add(buyBehaviour);
23 | Behaviours.Add(new SkipBuyBehaviour());
24 |
25 |
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/FishingVillage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Rules;
6 | using Dominion.Rules.CardTypes;
7 |
8 | namespace Dominion.Cards.Actions
9 | {
10 | public class FishingVillage : Card, IDurationCard
11 | {
12 | public FishingVillage()
13 | : base(3)
14 | {
15 | }
16 |
17 | public void Play(TurnContext context)
18 | {
19 | context.RemainingActions += 2;
20 | context.AvailableSpend += 1;
21 |
22 | context.AddLongLivedEffect(new FishingVillageEffect(this));
23 | }
24 |
25 | public class FishingVillageEffect : DurationEffect
26 | {
27 | public FishingVillageEffect(FishingVillage sourceCard) : base(sourceCard)
28 | {}
29 |
30 | public override void OnTurnStarting(TurnContext context)
31 | {
32 | base.OnTurnStarting(context);
33 |
34 | context.RemainingActions += 1;
35 | context.AvailableSpend += 1;
36 | context.Game.Log.LogMessage("FishingVillage adds one action and one spend");
37 | }
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Dominion.Rules/Card.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Dominion.Rules
4 | {
5 | public delegate void CardZoneChanger(CardZone targetZone);
6 |
7 | public abstract class Card : Dominion.Rules.ICard
8 | {
9 | private CardZone _currentZone;
10 | private readonly CardZoneChanger _zoneChanger;
11 |
12 | public Guid Id { get; private set; }
13 |
14 | protected Card(CardCost cost)
15 | {
16 | Id = Guid.NewGuid();
17 | Cost = cost;
18 | _currentZone = new NullZone();
19 | _zoneChanger = zone => _currentZone = zone;
20 | }
21 |
22 | public void MoveTo(CardZone targetZone)
23 | {
24 | _currentZone.MoveCard(this, targetZone, _zoneChanger);
25 | }
26 |
27 | public CardZone CurrentZone
28 | {
29 | get { return _currentZone; }
30 | }
31 |
32 | public CardCost Cost { get; protected set; }
33 |
34 |
35 | public string Name
36 | {
37 | get { return this.GetType().Name; }
38 | }
39 |
40 | public override string ToString()
41 | {
42 | return this.Name;
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Bindings/Extensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.GameHost;
6 | using Dominion.Rules;
7 | using Dominion.Rules.Activities;
8 |
9 | namespace Dominion.Specs.Bindings
10 | {
11 | public static class Extensions
12 | {
13 | public static int GetCountProperty(this IActivity activity)
14 | {
15 | return (int) activity.Properties["NumberOfCardsToSelect"];
16 | }
17 |
18 | public static CardCost GetCostProperty(this IActivity activity)
19 | {
20 | return (CardCost)activity.Properties["Cost"];
21 | }
22 |
23 | public static Type GetTypeRestrictionProperty(this IActivity activity)
24 | {
25 | return (Type)activity.Properties["CardsMustBeOfType"];
26 | }
27 |
28 | public static string GetTypeRestrictionProperty(this ActivityModel activity)
29 | {
30 | return (string) activity.Properties["CardsMustBeOfType"];
31 | }
32 |
33 | public static string GetCardNames(this CardViewModel[] cards)
34 | {
35 | return string.Join(", ", cards.Select(c => c.Name).ToArray());
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/ThroneRoom.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Dominion.Rules;
5 | using Dominion.Rules.Activities;
6 | using Dominion.Rules.CardTypes;
7 |
8 | namespace Dominion.Cards.Actions
9 | {
10 | public class ThroneRoom : Card, IActionCard
11 | {
12 | public ThroneRoom() : base(4)
13 | {
14 | }
15 |
16 | public void Play(TurnContext context)
17 | {
18 | context.AddEffect(this, new ThroneRoomEffect());
19 | }
20 |
21 | private class ThroneRoomEffect : CardEffectBase
22 | {
23 | public override void Resolve(TurnContext context, ICard source)
24 | {
25 | if (context.ActivePlayer.Hand.OfType().Any())
26 | {
27 | var activity = Activities.SelectActionToPlayMultipleTimes(context, context.ActivePlayer, context.Game.Log, source, 2);
28 | _activities.Add(activity);
29 | }
30 | else
31 | {
32 | context.Game.Log.LogMessage("{0} did not have any actions to use Throne Room on.", context.ActivePlayer.Name);
33 | }
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/SelectFixedNumberOfCardsBehaviourBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using Dominion.Rules.Activities;
6 |
7 | namespace Dominion.GameHost.AI.BehaviourBased
8 | {
9 | public abstract class SelectFixedNumberOfCardsBehaviourBase : IAIBehaviour
10 | {
11 | public virtual bool CanRespond(ActivityModel activity, GameViewModel state)
12 | {
13 | return activity.ParseType() == ActivityType.SelectFixedNumberOfCards;
14 | }
15 |
16 | protected abstract IEnumerable PrioritiseCards(GameViewModel state, ActivityModel activity);
17 |
18 | public void Respond(IGameClient client, ActivityModel activity, GameViewModel state)
19 | {
20 | int count = activity.ParseNumberOfCardsToSelect();
21 |
22 | var ids = PrioritiseCards(state, activity)
23 | .Take(count)
24 | .Select(c => c.Id)
25 | .ToArray();
26 |
27 | if(ids.Length != count)
28 | Debugger.Break();
29 |
30 | var message = new SelectCardsMessage(client.PlayerId, ids);
31 | client.AcceptMessage(message);
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Chancellor.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules;
2 | using Dominion.Rules.Activities;
3 | using Dominion.Rules.CardTypes;
4 |
5 | namespace Dominion.Cards.Actions
6 | {
7 | public class Chancellor : Card, IActionCard
8 | {
9 | public Chancellor()
10 | : base(3)
11 | {
12 | }
13 |
14 | public void Play(TurnContext context)
15 | {
16 | context.AvailableSpend += 2;
17 | context.AddEffect(this, new ChancellorEffect());
18 | }
19 |
20 | public class ChancellorEffect : CardEffectBase
21 | {
22 | public override void Resolve(TurnContext context, ICard source)
23 | {
24 | var player = context.ActivePlayer;
25 | var choiceActivity = Activities.ChooseYesOrNo(context.Game.Log, player,
26 | "Do you wish to put your deck into your discard pile?",
27 | source,
28 | () =>
29 | {
30 | context.Game.Log.LogMessage("{0} put his deck in his discard pile", player);
31 | player.Deck.MoveAll(player.Discards);
32 | });
33 |
34 | _activities.Add(choiceActivity);
35 | }
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Spy.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Rules;
2 | using Dominion.Rules.Activities;
3 | using Dominion.Rules.CardTypes;
4 |
5 | namespace Dominion.Cards.Actions
6 | {
7 | public class Spy : Card, IAttackCard, IActionCard
8 | {
9 | public Spy() : base(4)
10 | {
11 | }
12 |
13 | public void Play(TurnContext context)
14 | {
15 | context.DrawCards(1);
16 | context.RemainingActions += 1;
17 | context.AddEffect(this, new SpyAttack());
18 | }
19 |
20 | public class SpyAttack : AttackEffect
21 | {
22 | public override void Resolve(TurnContext context, ICard source)
23 | {
24 | base.Resolve(context, source);
25 |
26 | if(context.ActivePlayer.Deck.TopCard != null)
27 | _activities.Add(Activities.ChooseWhetherToMillTopCard(context, context.ActivePlayer, context.ActivePlayer, source));
28 | }
29 |
30 | public override void Attack(Player victim, TurnContext context, ICard source)
31 | {
32 | if(victim.Deck.TopCard != null)
33 | _activities.Add(Activities.ChooseWhetherToMillTopCard(context, context.ActivePlayer, victim, source));
34 | }
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Bindings/BindingBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using TechTalk.SpecFlow;
5 |
6 | namespace Dominion.Specs.Bindings
7 | {
8 | // Borrowed from Orchard.
9 | // http://orchard.codeplex.com/SourceControl/changeset/view/c0577b633ffa#src%2fOrchard.Specs%2fBindings%2fBindingBase.cs
10 | public class BindingBase
11 | {
12 | protected static T Binding()
13 | {
14 | return (T)ScenarioContext.Current.GetBindingInstance(typeof(T));
15 | }
16 |
17 | protected Table TableData(params T[] rows)
18 | {
19 | return BuildTable(rows);
20 | }
21 |
22 | protected Table TableData(IEnumerable rows)
23 | {
24 | return BuildTable(rows);
25 | }
26 |
27 | private Table BuildTable(IEnumerable rows)
28 | {
29 | var properties = typeof(T).GetProperties();
30 | var table = new Table(properties.Select(x => x.Name).ToArray());
31 | foreach (var row in rows)
32 | {
33 | var row1 = row;
34 | table.AddRow(properties.Select(p => Convert.ToString(p.GetValue(row1, null))).ToArray());
35 | }
36 | return table;
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/TradingPost.feature:
--------------------------------------------------------------------------------
1 | Feature: Trading Post
2 |
3 | Scenario: Player plays trading post and must choose what to trash
4 | Given A new game with 3 players
5 | And Player1 has a hand of TradingPost, Estate, Estate, Copper, Copper
6 | When Player1 plays a TradingPost
7 | Then Player1 must select 2 cards to trash
8 |
9 | Scenario: Player plays trading post and trashes a copper and an estate, gaining a silver
10 | Given A new game with 3 players
11 | And Player1 has a hand of TradingPost, Estate, Estate, Copper, Copper
12 | When Player1 plays a TradingPost
13 | And Player1 selects cards [Estate, Copper] to trash
14 | Then The trash pile should be Estate, Copper
15 | And Player1 should have a hand of Estate, Copper, Silver
16 |
17 | Scenario: Player plays trading post with only one other card in hand - it is trashed and no silver is gained
18 | Given A new game with 3 players
19 | And Player1 has a hand of TradingPost, Estate
20 | When Player1 plays a TradingPost
21 | Then All actions should be resolved
22 | And The trash pile should be Estate
23 | And Player1 should have 0 cards in hand
24 |
25 | Scenario: Player plays trading post with no other cards in hand
26 | Given A new game with 3 players
27 | And Player1 has a hand of TradingPost
28 | When Player1 plays a TradingPost
29 | Then All actions should be resolved
30 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Warehouse.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Rules;
6 | using Dominion.Rules.Activities;
7 | using Dominion.Rules.CardTypes;
8 |
9 | namespace Dominion.Cards.Actions
10 | {
11 | public class Warehouse : Card, IActionCard
12 | {
13 | public Warehouse() : base(3)
14 | {
15 |
16 | }
17 |
18 | public void Play(TurnContext context)
19 | {
20 | context.RemainingActions += 1;
21 | context.DrawCards(3);
22 | context.AddEffect(this, new WarehouseEffect());
23 | }
24 |
25 | private class WarehouseEffect : CardEffectBase
26 | {
27 | public override void Resolve(TurnContext context, ICard source)
28 | {
29 | if(context.ActivePlayer.Hand.CardCount < 4)
30 | {
31 | context.DiscardCards(context.ActivePlayer, context.ActivePlayer.Hand);
32 | }
33 | else
34 | {
35 | var discardActivity = Activities.DiscardCards(context, context.ActivePlayer, 3, source);
36 | _activities.Add(discardActivity);
37 | }
38 |
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Dominion.AIWorkbench/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Windows.Forms;
5 |
6 | namespace Dominion.AIWorkbench
7 | {
8 | static class Program
9 | {
10 | ///
11 | /// The main entry point for the application.
12 | ///
13 | [STAThread]
14 | static void Main()
15 | {
16 | Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
17 | AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
18 | Application.EnableVisualStyles();
19 | Application.SetCompatibleTextRenderingDefault(false);
20 | Application.Run(new MDIParent());
21 | }
22 |
23 | static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
24 | {
25 | MessageBox.Show(e.ExceptionObject.ToString(), "BOOM!", MessageBoxButtons.OK, MessageBoxIcon.Error);
26 |
27 | }
28 |
29 | static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
30 | {
31 | MessageBox.Show(e.Exception.ToString(), "BOOM!", MessageBoxButtons.OK, MessageBoxIcon.Error);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Explorer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Dominion.Cards.Treasure;
4 | using Dominion.Cards.Victory;
5 | using Dominion.Rules;
6 | using Dominion.Rules.Activities;
7 | using Dominion.Rules.CardTypes;
8 |
9 | namespace Dominion.Cards.Actions
10 | {
11 | public class Explorer : Card, IActionCard
12 | {
13 | public Explorer()
14 | : base(5)
15 | {
16 | }
17 |
18 | public void Play(TurnContext context)
19 | {
20 | var gainUtility = new GainUtility(context, context.ActivePlayer);
21 | Action gainSilver = () => gainUtility.Gain(context.ActivePlayer.Hand);
22 | Action gainGold = () => gainUtility.Gain(context.ActivePlayer.Hand);
23 |
24 | if (context.ActivePlayer.Hand.OfType().Any())
25 | {
26 | var activity = Activities.ChooseYesOrNo(
27 | context.Game.Log,
28 | context.ActivePlayer,
29 | "Reveal a Province to gain a Gold?",
30 | this,
31 | gainGold,
32 | gainSilver);
33 | context.AddSingleActivity(activity, this);
34 | }
35 | else
36 | {
37 | gainSilver();
38 | }
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/Dominion.Web/Web.Debug.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
29 |
30 |
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Rabble.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Dominion.Rules;
4 | using Dominion.Rules.Activities;
5 | using Dominion.Rules.CardTypes;
6 |
7 | namespace Dominion.Cards.Actions
8 | {
9 | public class Rabble : Card, IActionCard, IAttackCard
10 | {
11 | public Rabble()
12 | : base(5)
13 | {
14 | }
15 |
16 | public void Play(TurnContext context)
17 | {
18 | context.DrawCards(3);
19 | context.AddEffect(this, new RabbleAttack());
20 | }
21 |
22 | private class RabbleAttack : AttackEffect
23 | {
24 | public override void Attack(Player victim, TurnContext context, ICard source)
25 | {
26 | var revealZone = new RevealZone(victim);
27 | victim.Deck.MoveTop(3, revealZone);
28 |
29 | revealZone.LogReveal(context.Game.Log);
30 | revealZone.MoveWhere(c => c is IActionCard || c is ITreasureCard, victim.Discards);
31 |
32 | if(revealZone.CardCount == 1)
33 | victim.Deck.MoveToTop(revealZone.Single());
34 |
35 | foreach (var activity in Activities.SelectMultipleRevealedCardsToPutOnTopOfDeck(context.Game.Log, victim, revealZone, source))
36 | _activities.Add(activity);
37 | }
38 |
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/Dominion.GameHost/AI/BehaviourBased/BuySimpleActionsBehaviour.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Dominion.Rules.Activities;
4 |
5 | namespace Dominion.GameHost.AI.BehaviourBased
6 | {
7 | public class BuySimpleActionsBehaviour : BuyBehaviourBase
8 | {
9 | private readonly Random _random = new Random();
10 |
11 | public override bool CanRespond(ActivityModel activity, GameViewModel state)
12 | {
13 | return base.CanRespond(activity, state)
14 | && (GetValidBuys(state).Any(pile => AISupportedActions.All.Contains(pile.Name))
15 | || (activity.ParseType() == ActivityType.SelectPile && (bool)activity.Properties["IsOptional"]));
16 | }
17 |
18 | protected override CardPileViewModel SelectPile(GameViewModel state, IGameClient client)
19 | {
20 | var options = GetValidBuys(state)
21 | .Where(pile => AISupportedActions.All.Contains(pile.Name))
22 | .OrderByDescending(pile => pile.Cost)
23 | .ThenBy(pile => _random.Next(100))
24 | .ToList();
25 |
26 | var message = string.Format("I considered {0}.", string.Join(", ", options.Select(x => x.Name).ToArray()));
27 | client.SendChatMessage(message);
28 |
29 | return options.FirstOrDefault();
30 | }
31 |
32 |
33 | }
34 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Explorer.feature:
--------------------------------------------------------------------------------
1 | Feature: Explorer
2 |
3 | Scenario: Player must decide whether to reveal province after playing explorer
4 | Given A new game with 3 players
5 | And Player1 has a hand of Explorer, Province, Copper, Copper, Estate
6 | When Player1 plays an Explorer
7 | Then Player1 must choose whether to reveal a Province (Yes or No)
8 |
9 | Scenario: Player reveals a province and gains a gold
10 | Given A new game with 3 players
11 | And Player1 has a hand of Explorer, Province, Copper, Copper, Estate
12 | When Player1 plays an Explorer
13 | And Player1 chooses to gain a Gold (Yes)
14 | Then Player1 should have a hand of Province, Copper, Copper, Estate, Gold
15 |
16 | Scenario: Player chooses not to reveal a province and gains a silver
17 | Given A new game with 3 players
18 | And Player1 has a hand of Explorer, Province, Copper, Copper, Estate
19 | When Player1 plays an Explorer
20 | And Player1 chooses to gain a Silver (No)
21 | Then Player1 should have a hand of Province, Copper, Copper, Estate, Silver
22 |
23 | Scenario: Player does not have a Province in hand and gains a silver
24 | Given A new game with 3 players
25 | And Player1 has a hand of Explorer, Estate, Copper, Copper, Estate
26 | When Player1 plays an Explorer
27 | Then All actions should be resolved
28 | And Player1 should have a hand of Estate, Copper, Copper, Estate, Silver
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Binaries/Rx/System.Observable.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | System.Observable
5 |
6 |
7 |
8 |
9 | Represents a push-style collection.
10 |
11 |
12 |
13 |
14 | Subscribes an observer to the observable sequence.
15 |
16 |
17 |
18 |
19 | Supports push-style iteration over an observable sequence.
20 |
21 |
22 |
23 |
24 | Notifies the observer of a new value in the sequence.
25 |
26 |
27 |
28 |
29 | Notifies the observer that an exception has occurred.
30 |
31 |
32 |
33 |
34 | Notifies the observer of the end of the sequence.
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Dominion.Specs/GameEnd.feature:
--------------------------------------------------------------------------------
1 | Feature: Game End
2 | In order to avoid playing Dominion forever
3 | As a Dominion player
4 | I want the game to end at some point
5 |
6 | Scenario: Game ends when last province is bought
7 | Given A new game with 3 players
8 | But There is only 1 Province left
9 | And Player1 has 5 Gold in hand
10 | When Player1 moves to the buy step
11 | And Player1 buys a Province
12 | And Player1 ends their turn
13 | Then The game should have ended
14 |
15 | Scenario Outline: Game ends when piles are exhausted
16 | Given A new game with players
17 | And There are empty piles
18 | When Player1 ends their turn
19 | Then The game should have ended
20 |
21 | Examples:
22 | |player count |empty pile count |
23 | |1 |3 |
24 | |2 |3 |
25 | |3 |3 |
26 | |4 |3 |
27 | |5 |4 |
28 | |6 |4 |
29 |
30 | Scenario: Game still ends when more piles are exhausted than necessary
31 | Given A new game with 4 players
32 | And There are 4 empty piles
33 | When Player1 ends their turn
34 | Then The game should have ended
35 |
36 | Scenario: Game isn't over until the last turn ends
37 | Given A new game with 3 players
38 | But There is only 1 Province left
39 | And Player1 has 5 Gold in hand
40 | When Player1 moves to the buy step
41 | And Player1 buys a Province
42 | Then The game should not have ended
43 |
44 |
--------------------------------------------------------------------------------
/Dominion.Web/Web.Release.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
19 |
30 |
31 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Baron.feature:
--------------------------------------------------------------------------------
1 | Feature: Baron
2 |
3 | Scenario: Player plays baron with no estate in hand
4 | Given A new game with 3 players
5 | And Player1 has a hand of Baron, Copper, Copper, Copper, Copper
6 | When Player1 plays a Baron
7 | Then Player1 should have an Estate on top of the discard pile
8 | And Player1 should have 2 buys
9 |
10 | Scenario: Player plays baron with an estate in hand and must choose
11 | Given A new game with 3 players
12 | And Player1 has a hand of Baron, Estate, Copper, Copper, Copper
13 | When Player1 plays a Baron
14 | Then Player1 must choose whether to use Chancellor's effect (Yes or No)
15 |
16 | Scenario: Player plays baron with an estate in hand and chooses to discard it
17 | Given A new game with 3 players
18 | And Player1 has a hand of Baron, Estate, Copper, Copper, Copper
19 | When Player1 plays a Baron
20 | When Player1 chooses to discard the estate (Yes)
21 | Then Player1 should have 4 to spend
22 | Then Player1 should have an Estate on top of the discard pile
23 | And Player1 should have a hand of Copper, Copper, Copper
24 |
25 | Scenario: Player plays baron with an estate in hand and chooses not to discard
26 | Given A new game with 3 players
27 | And Player1 has a hand of Baron, Estate, Copper, Copper, Copper
28 | When Player1 plays a Baron
29 | When Player1 chooses to keep the estate (No)
30 | Then Player1 should have 0 to spend
31 | And Player1 should have an Estate on top of the discard pile
--------------------------------------------------------------------------------
/Dominion.GameHost/SimpleStartingConfiguration.cs:
--------------------------------------------------------------------------------
1 | using Dominion.Cards.Hybrid;
2 | using Dominion.Cards.Victory;
3 | using Dominion.Rules;
4 | using Dominion.Cards.Actions;
5 |
6 | namespace Dominion.GameHost
7 | {
8 | public class SimpleStartingConfiguration : StartingConfiguration
9 | {
10 | public SimpleStartingConfiguration(int numberOfPlayers) : base(numberOfPlayers)
11 | {}
12 |
13 | public override void InitializeBank(Dominion.Rules.CardBank bank)
14 | {
15 | bank.AddCardPile(new LimitedSupplyCardPile().WithNewCards(10));
16 | bank.AddCardPile(new LimitedSupplyCardPile().WithNewCards(10));
17 | bank.AddCardPile(new LimitedSupplyCardPile().WithNewCards(10));
18 | bank.AddCardPile(new LimitedSupplyCardPile().WithNewCards(10));
19 | bank.AddCardPile(new LimitedSupplyCardPile().WithNewCards(10));
20 | bank.AddCardPile(new LimitedSupplyCardPile().WithNewCards(10));
21 | bank.AddCardPile(new LimitedSupplyCardPile().WithNewCards(10));
22 | bank.AddCardPile(new LimitedSupplyCardPile().WithNewCards(10));
23 | bank.AddCardPile(new LimitedSupplyCardPile().WithNewCards(10));
24 | bank.AddCardPile(new LimitedSupplyCardPile().WithNewCards(10));
25 | base.InitializeBank(bank);
26 | }
27 |
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Dominion.Rules/PassiveCardEffectBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Rules.CardTypes;
6 |
7 | namespace Dominion.Rules
8 | {
9 | ///
10 | ///
11 | ///
12 | public interface IPassiveCardEffect
13 | {
14 | ///
15 | ///
16 | ///
17 | /// The current cost of the card, potentially already modified
18 | /// The card whose cost is being modified
19 | ///
20 | int ModifyCost(int currentCost, ICard card);
21 |
22 | ///
23 | ///
24 | ///
25 | /// The current value of the card, potentially already modified
26 | /// The card whose value is being modified
27 | ///
28 | CardCost ModifyValue(CardCost currentValue, ITreasureCard card);
29 | }
30 |
31 | public class PassiveCardEffectBase : IPassiveCardEffect
32 | {
33 | public virtual int ModifyCost(int currentCost, ICard card)
34 | {
35 | return currentCost;
36 | }
37 |
38 | public virtual CardCost ModifyValue(CardCost currentValue, ITreasureCard card)
39 | {
40 | return currentValue;
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Adventurer.feature:
--------------------------------------------------------------------------------
1 | Feature: Adventurer
2 |
3 | Scenario: Play Adventurer but reveal no treasure
4 | Given A new game with 3 players
5 | And Player1 has a hand of Adventurer, Copper, Copper, Copper, Copper
6 | And Player1 has a deck of Estate, Estate, Estate, Estate, Estate
7 | When Player1 plays a Adventurer
8 | Then Player1 should have a hand of Copper, Copper, Copper, Copper
9 | And Player1 should have 0 cards in deck
10 | And Player1 should have a discard pile of Estate, Estate, Estate, Estate, Estate
11 |
12 | Scenario: Play Adventurer but reveal only one treasure
13 | Given A new game with 3 players
14 | And Player1 has a hand of Adventurer, Copper, Copper, Copper, Copper
15 | And Player1 has a deck of Estate, Estate, Estate, Copper, Estate
16 | When Player1 plays a Adventurer
17 | Then Player1 should have a hand of Copper, Copper, Copper, Copper, Copper
18 | And Player1 should have 0 cards in deck
19 | And Player1 should have a discard pile of Estate, Estate, Estate, Estate
20 |
21 | Scenario: Play Adventurer and reveal two treasure
22 | Given A new game with 3 players
23 | And Player1 has a hand of Adventurer, Copper, Copper, Copper, Copper
24 | And Player1 has a deck of Estate, Copper, Estate, Copper, Silver
25 | When Player1 plays a Adventurer
26 | Then Player1 should have a hand of Copper, Copper, Copper, Copper, Copper, Copper
27 | And Player1 should have a deck of: Silver
28 | And Player1 should have a discard pile of Estate, Estate
29 |
--------------------------------------------------------------------------------
/Dominion.Rules/MyExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Dominion.Rules.CardTypes;
5 |
6 | namespace Dominion.Rules
7 | {
8 | public static class MyExtensions
9 | {
10 | public static void Times(this int count, Action action)
11 | {
12 | if (action != null)
13 | {
14 | for (int i = 1; i <= count; i++)
15 | action();
16 | }
17 | }
18 |
19 | public static IEnumerable Items(this int count, Func builder)
20 | {
21 | if (builder == null)
22 | yield break;
23 |
24 | for (int i = 1; i <= count; i++)
25 | yield return builder();
26 | }
27 |
28 | public static IEnumerable Items(this int count, Func builder)
29 | {
30 | if (builder == null)
31 | yield break;
32 |
33 | for (int i = 1; i <= count; i++)
34 | yield return builder(i);
35 | }
36 |
37 | public static IEnumerable WithDistinctTypes(this IEnumerable input)
38 | {
39 | return input.Distinct(new SameTypeEqualityComparer());
40 | }
41 |
42 | public static bool AllSame(this IEnumerable items, Func selector)
43 | {
44 | return items.Select(selector).Distinct().Count() < 2;
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Torturer.feature:
--------------------------------------------------------------------------------
1 | Feature: Torturer
2 |
3 | Scenario: Player plays Torturer and opponents must decide whether to discard cards or gain a curse
4 | Given A new game with 3 players
5 | And Player1 has a Torturer in hand instead of a Copper
6 | When Player1 plays a Torturer
7 | Then Player1 should have 7 cards in hand
8 | And Player2 must choose whether to discard cards (Yes or No)
9 | And Player3 must choose whether to discard cards (Yes or No)
10 |
11 | Scenario: Player plays Torturer and opponent decides to discard cards
12 | Given A new game with 2 players
13 | And Player1 has a Torturer in hand instead of a Copper
14 | When Player1 plays a Torturer
15 | And Player2 chooses to discard cards (Yes)
16 | Then Player2 must select 2 cards to discard
17 |
18 | Scenario: Player plays Torturer and opponent decides to gain a curse
19 | Given A new game with 2 players
20 | And Player1 has a Torturer in hand instead of a Copper
21 | When Player1 plays a Torturer
22 | And Player2 chooses to gain a curse (No)
23 | Then Player2 should have 6 cards in hand
24 | And All actions should be resolved
25 |
26 | Scenario: Player decides to discard to torturer with only 1 card in hand
27 | Given A new game with 2 players
28 | And Player1 has a Torturer in hand instead of a Copper
29 | And Player2 has a hand of Copper
30 | When Player1 plays a Torturer
31 | And Player2 chooses to discard cards (Yes)
32 | Then Player2 should have 0 cards in hand
33 | And All actions should be resolved
34 |
--------------------------------------------------------------------------------
/Dominion.Specs/Bindings/ScoringBindings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Dominion.Rules;
4 | using TechTalk.SpecFlow;
5 |
6 | namespace Dominion.Specs.Bindings
7 | {
8 | [Binding]
9 | public class ScoringBindings : BindingBase
10 | {
11 | private GameScores _scores;
12 | private Game _game;
13 |
14 | [When(@"The game is scored")]
15 | public void WhenTheGameIsScored()
16 | {
17 | var gameBinding = Binding();
18 | _game = gameBinding.Game;
19 | _game.Score();
20 | _scores = _game.Scores;
21 | }
22 |
23 | [Then(@"(.*) should have (\d+) victory point[s]?")]
24 | public void ThenPlayerShouldHaveVictoryPoints(string playerName, int victoryPoints)
25 | {
26 | var player = _game.Players.Single(p => p.Name == playerName);
27 | _scores[player].ShouldEqual(victoryPoints);
28 | }
29 |
30 | [Then(@"(.*)'s play area should start with this sequence of cards: (.*)")]
31 | public void ThenPlayerPlayAreaShouldStartWithThisSequenceOfCards(string playerName, string sequence)
32 | {
33 | var player = _game.Players.Single(p => p.Name == playerName);
34 | string playAreaCardNames = string.Join(",", player.PlayArea.Select(c => c.Name).ToArray());
35 |
36 | playAreaCardNames.ShouldStartWith(sequence.Replace(" ",""));
37 | }
38 |
39 |
40 | }
41 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Apothecary.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using Dominion.Cards.Treasure;
3 | using Dominion.Rules;
4 | using Dominion.Rules.Activities;
5 | using Dominion.Rules.CardTypes;
6 |
7 | namespace Dominion.Cards.Actions
8 | {
9 | public class Apothecary : Card, IActionCard
10 | {
11 | public Apothecary() : base(CardCost.Parse("2P"))
12 | {
13 | }
14 |
15 | public void Play(TurnContext context)
16 | {
17 | context.DrawCards(1);
18 | context.RemainingActions += 1;
19 |
20 | context.AddEffect(this, new ApothecaryEffect());
21 | }
22 |
23 | public class ApothecaryEffect : CardEffectBase
24 | {
25 | public override void Resolve(TurnContext context, ICard source)
26 | {
27 | var revealZone = new RevealZone(context.ActivePlayer);
28 | context.ActivePlayer.Deck.MoveTop(4, revealZone);
29 |
30 | revealZone.LogReveal(context.Game.Log);
31 | revealZone.MoveWhere(c => c is Copper || c is Potion, context.ActivePlayer.Hand);
32 |
33 | if (revealZone.CardCount == 1)
34 | context.ActivePlayer.Deck.MoveToTop(revealZone.Single());
35 |
36 | foreach (var activity in Activities.SelectMultipleRevealedCardsToPutOnTopOfDeck(context.Game.Log, context.ActivePlayer, revealZone, source))
37 | _activities.Add(activity);
38 | }
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/Dominion.Cards/Actions/Salvager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Rules;
6 | using Dominion.Rules.Activities;
7 | using Dominion.Rules.CardTypes;
8 |
9 | namespace Dominion.Cards.Actions
10 | {
11 | public class Salvager : Card, IActionCard
12 | {
13 | public Salvager()
14 | : base(4)
15 | {
16 | }
17 |
18 | public void Play(TurnContext context)
19 | {
20 | context.Buys += 1;
21 | context.AddEffect(this, new SalvagerEffect());
22 | }
23 |
24 | private class SalvagerEffect : CardEffectBase
25 | {
26 | public override void Resolve(TurnContext context, ICard source)
27 | {
28 | if (context.ActivePlayer.Hand.CardCount > 0)
29 | {
30 | var activity = new SelectCardsActivity(context, "Select a card to trash",
31 | SelectionSpecifications.SelectExactlyXCards(1), source);
32 |
33 | activity.AfterCardsSelected = cardList =>
34 | {
35 | var cardToSalvage = cardList.Single();
36 | context.AvailableSpend += cardToSalvage.Cost.Money;
37 | context.Trash(context.ActivePlayer, cardToSalvage);
38 | };
39 | _activities.Add(activity);
40 | }
41 | }
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Dominion.Rules/Activities/SelectReactionActivity.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Dominion.Rules.CardTypes;
5 |
6 | namespace Dominion.Rules.Activities
7 | {
8 | public class SelectReactionActivity : SelectCardsActivity
9 | {
10 | private readonly TurnContext _currentTurn;
11 | private readonly AttackEffect _attackEffect;
12 |
13 | public SelectReactionActivity(TurnContext currentTurn, Player player, AttackEffect attackEffect)
14 | : base(currentTurn.Game.Log, player, "Select a reaction to use, click Done when finished.", SelectionSpecifications.SelectUpToXCards(1), null)
15 | {
16 | _currentTurn = currentTurn;
17 | _attackEffect = attackEffect;
18 | Specification.CardTypeRestriction = typeof (IReactionCard);
19 | }
20 |
21 | public void SelectReaction(IReactionCard reaction)
22 | {
23 | if (reaction == null)
24 | IsSatisfied = true;
25 | else
26 | reaction.React(_attackEffect, this.Player, _currentTurn);
27 | }
28 |
29 | public override void SelectCards(IEnumerable cards)
30 | {
31 | CheckCards(cards);
32 |
33 | var reaction = cards.OfType().SingleOrDefault();
34 | SelectReaction(reaction);
35 | }
36 |
37 |
38 | public void CloseWindow()
39 | {
40 | SelectReaction(null);
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/Dominion.Web/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Dominion.Web")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Microsoft")]
12 | [assembly: AssemblyProduct("Dominion.Web")]
13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("ef516fc7-fc3d-4a8d-8f7f-c90d852702fa")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Revision and Build Numbers
33 | // by using the '*' as shown below:
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/Dominion.GameHost/ChosenStartingConfiguration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Reflection;
6 | using Dominion.Cards.Actions;
7 | using Dominion.Cards.Treasure;
8 | using Dominion.Rules;
9 |
10 | namespace Dominion.GameHost
11 | {
12 | public class ChosenStartingConfiguration : StartingConfiguration
13 | {
14 | private readonly bool _useProsperity;
15 | IList _chosenCards;
16 |
17 | public ChosenStartingConfiguration(int numberOfPlayers, IEnumerable chosenCards, bool useProsperity)
18 | : base(numberOfPlayers)
19 | {
20 | _useProsperity = useProsperity;
21 | if (chosenCards.Count() != 10)
22 | {
23 | string error = string.Format("Passed card collection contains {0} cards. Expected exactly 10.", chosenCards.Count());
24 | throw new ArgumentException(error, "chosenCards");
25 | }
26 |
27 | _chosenCards = chosenCards.ToList();
28 | }
29 |
30 | public override void InitializeBank(CardBank bank)
31 | {
32 | foreach (string card in _chosenCards)
33 | bank.AddCardPile(new LimitedSupplyCardPile().WithNewCards(card, GetStartingCount(card)));
34 |
35 | if (_useProsperity)
36 | AddProsperityCards(bank);
37 |
38 | base.InitializeBank(bank);
39 | }
40 |
41 |
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Dominion.Rules/CardBank.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | namespace Dominion.Rules
6 | {
7 | public class CardBank
8 | {
9 | private IList _piles;
10 | private IList _gameEndPiles;
11 |
12 | public CardBank()
13 | {
14 | _piles = new List();
15 | _gameEndPiles = new List();
16 | }
17 |
18 | public IEnumerable Piles
19 | {
20 | get { return _piles; }
21 | }
22 |
23 | public void AddCardPile(CardPile pile)
24 | {
25 | _piles.Add(pile);
26 | }
27 |
28 | public void AddCardPileWhichEndsTheGameWhenEmpty(CardPile pile)
29 | {
30 | AddCardPile(pile);
31 | _gameEndPiles.Add(pile);
32 | }
33 |
34 | public int EmptyPileCount
35 | {
36 | get
37 | {
38 | return _piles.Count(x => x.IsEmpty);
39 | }
40 | }
41 |
42 | public int EmptyGameEndingPilesCount
43 | {
44 | get { return _gameEndPiles.Count(x => x.IsEmpty); }
45 | }
46 |
47 | public CardPile Pile()
48 | {
49 | return this.Piles.Single(x => x.Name == typeof(T).Name);
50 | }
51 |
52 | public CardPile NonEmptyPile()
53 | {
54 | var pile = this.Pile();
55 | return pile.IsEmpty ? null : pile;
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/Dominion.Specs/Cards/Apothecary.feature:
--------------------------------------------------------------------------------
1 | Feature: Apothecary
2 |
3 | Scenario: Play Apothecary with all potions and coppers on top
4 | Given A new game with 3 players
5 | And Player1 has an Apothecary in hand instead of a Copper
6 | And Player1 has a deck of Estate, Copper, Potion, Copper, Copper
7 | When Player1 plays an Apothecary
8 | Then All actions should be resolved
9 | And Player1 should have 9 cards in hand
10 | And Player1 should have 1 action remaining
11 |
12 | Scenario: Play Apothecary with no potions or coppers on top
13 | Given A new game with 3 players
14 | And Player1 has an Apothecary in hand instead of a Copper
15 | And Player1 has a deck of Copper, Estate, Curse, Silver, Gold
16 | When Player1 plays an Apothecary
17 | Then Player1 must select a revealed card from: Estate, Curse, Silver, Gold
18 | When Player1 selects Estate from the revealed cards
19 | Then Player1 must select a revealed card from: Curse, Silver, Gold
20 | When Player1 selects Silver from the revealed cards
21 | Then Player1 must select a revealed card from: Curse, Gold
22 | When Player1 selects Curse from the revealed cards
23 | Then Player1 should have a deck of: Gold, Curse, Silver, Estate
24 | And All actions should be resolved
25 |
26 | Scenario: Apothecary is played with no other cards in hand, no discards and no deck
27 | Given A new game with 3 players
28 | And Player1 has a hand of Apothecary
29 | And Player1 has an empty deck
30 | When Player1 plays a Apothecary
31 | Then Player1 should have 0 cards in hand
32 | And All actions should be resolved
33 |
34 |
--------------------------------------------------------------------------------
/Dominion.WinForms/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Dominion")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Microsoft")]
12 | [assembly: AssemblyProduct("Dominion")]
13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("97e03baf-f688-4fd8-9f2c-9c3509b27e2e")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Dominion.Tests/CardMovementTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Dominion.Cards.Treasure;
6 | using Dominion.Rules;
7 | using NUnit.Framework;
8 |
9 | namespace Dominion.Tests
10 | {
11 | [TestFixture]
12 | public class CardMovementTests
13 | {
14 | private CardZone _zone1;
15 | private CardZone _zone2;
16 | private Card _card;
17 |
18 | [SetUp]
19 | public void SetUp()
20 | {
21 | _zone1 = new CardZone();
22 | _zone2 = new CardZone();
23 | _card = new Copper();
24 | }
25 |
26 | [Test]
27 | public void Card_should_start_in_null_zone()
28 | {
29 | _card.CurrentZone.ShouldBeOfType();
30 | }
31 |
32 | [Test]
33 | public void Card_should_change_current_zone_when_moved()
34 | {
35 | _card.MoveTo(_zone1);
36 | _card.CurrentZone.ShouldEqual(_zone1);
37 | }
38 |
39 | [Test]
40 | public void Card_should_be_added_to_target_zone_when_moved()
41 | {
42 | _card.MoveTo(_zone1);
43 | _zone1.CardCount.ShouldEqual(1);
44 | }
45 |
46 | [Test]
47 | public void Card_should_be_removed_from_old_zone_when_moved()
48 | {
49 | _card.MoveTo(_zone1);
50 | _card.MoveTo(_zone2);
51 | _zone1.CardCount.ShouldEqual(0);
52 | _zone2.CardCount.ShouldEqual(1);
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Dominion.Cards/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Dominion.Cards")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Microsoft")]
12 | [assembly: AssemblyProduct("Dominion.Cards")]
13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("9f8ab823-49ae-47d4-9128-0984d7997eca")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Dominion.Rules/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Dominion.Rules")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Microsoft")]
12 | [assembly: AssemblyProduct("Dominion.Rules")]
13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("eb828059-6b22-4e34-8e06-ea937fdfe662")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Dominion.Specs/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Dominion.Specs")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Microsoft")]
12 | [assembly: AssemblyProduct("Dominion.Specs")]
13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("6b24e9cf-c860-4691-aaa9-e7dc21c827e1")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Dominion.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Dominion.Tests")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Microsoft")]
12 | [assembly: AssemblyProduct("Dominion.Tests")]
13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("77564d3e-11a3-4858-9f79-ac442a5760b6")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Dominion.GameHost/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Dominion.GameHost")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Microsoft")]
12 | [assembly: AssemblyProduct("Dominion.GameHost")]
13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("2c8a1718-3bcb-4297-aa41-e5d113d6e0e0")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Dominion.AIWorkbench/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Dominion.AIWorkbench")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Microsoft")]
12 | [assembly: AssemblyProduct("Dominion.AIWorkbench")]
13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("9e70f450-028e-4395-8e8f-6a5c838ce8e3")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------