diff --git a/src/Waterdeep/Actions.hs b/src/Waterdeep/Actions.hs index af458d2..90e3864 100644 --- a/src/Waterdeep/Actions.hs +++ b/src/Waterdeep/Actions.hs @@ -41,6 +41,7 @@ module Waterdeep.Actions , restockCliffwatchInn , restockBuildersHall , getOpponents + , mandatoryQuestCard ) where import Control.Applicative @@ -176,9 +177,11 @@ completeQuest = do name <- use activePlayerName broadcast $ name ++ " completed the " ++ (quest ^. questTitle) ++ " quest." quest ^. questReward - if null (quest ^. questPlotActions) - then activePlayerState . playerCompletedQuests <>= [quest] - else activePlayerState . playerActivePlotQuests <>= [quest] + if (quest ^. questType == Mandatory) + then gameIntrigueDiscard <>= [mandatoryQuestCard quest] + else if null (quest ^. questPlotActions) + then activePlayerState . playerCompletedQuests <>= [quest] + else activePlayerState . playerActivePlotQuests <>= [quest] chooseAndCompleteQuest :: GameAction -> GameAction chooseAndCompleteQuest bonusAction = do @@ -287,7 +290,8 @@ playIntrigue = do name <- use $ activePlayerName broadcast $ name ++ " played the " ++ (intrigue ^. intrigueTitle) ++ " Intrigue card." intrigue ^. intrigueAction - gameIntrigueDiscard <>= [intrigue] + unless (intrigue ^. intrigueType == MandatoryQuest) $ + gameIntrigueDiscard <>= [intrigue] return () returnAgent :: GameAction @@ -490,3 +494,12 @@ forEachControlledBuilding m = do replicateM_ controlledBuildings m where b `isControlledBy` p = b ^. buildingOwner == p + +mandatoryQuestCard :: Quest -> IntrigueCard +mandatoryQuestCard q = + IntrigueCard + { _intrigueTitle = (q ^. questTitle) + , _intrigueType = MandatoryQuest + , _intrigueAction = assignMandatoryQuest q + , _intrigueQuote = (q ^. questQuote) + } diff --git a/src/Waterdeep/Intrigues.hs b/src/Waterdeep/Intrigues.hs index 4d63153..41ab4e3 100644 --- a/src/Waterdeep/Intrigues.hs +++ b/src/Waterdeep/Intrigues.hs @@ -3,6 +3,7 @@ module Waterdeep.Intrigues ) where import Control.Applicative +import Control.Arrow ((&&&)) import Control.Monad import Data.List import Data.Monoid @@ -21,18 +22,291 @@ import qualified Data.MultiSet as MS defaultIntrigueDeck :: [IntrigueCard] defaultIntrigueDeck = concat $ map (uncurry replicate) $ - [ (2, IntrigueCard { _intrigueTitle = "Graduation Day" + [ (1, mandatoryQuestCard $ + Quest { _questType = Mandatory + , _questTitle = "Repel Drow Invaders" + , _questQuote = "" + , _questCost = do + returnResources 1 [Cleric] + returnResources 2 [Rogue] + , _questReward = scorePoints 2 + , _questPlotActions = [] + }) + , (1, mandatoryQuestCard $ + Quest { _questType = Mandatory + , _questTitle = "Fend Off Bandits" + , _questQuote = "" + , _questCost = do + returnResources 2 [Fighter] + returnResources 2 [Wizard] + , _questReward = scorePoints 2 + , _questPlotActions = [] + }) + , (1, mandatoryQuestCard $ + Quest { _questType = Mandatory + , _questTitle = "Foil the Zhentarim" + , _questQuote = "" + , _questCost = do + returnResources 1 [Fighter] + returnResources 1 [Rogue] + returnResources 1 [Wizard] + , _questReward = scorePoints 2 + , _questPlotActions = [] + }) + , (1, mandatoryQuestCard $ + Quest { _questType = Mandatory + , _questTitle = "Stamp Out Cultists" + , _questQuote = "" + , _questCost = do + returnResources 1 [Cleric] + returnResources 1 [Fighter] + returnResources 1 [Rogue] + , _questReward = scorePoints 2 + , _questPlotActions = [] + }) + , (1, mandatoryQuestCard $ + Quest { _questType = Mandatory + , _questTitle = "Placate Angry Merchants" + , _questQuote = "" + , _questCost = do + returnResources 1 [Cleric] + returnResources 1 [Fighter] + returnResources 1 [Wizard] + , _questReward = scorePoints 4 + , _questPlotActions = [] + }) + , (1, mandatoryQuestCard $ + Quest { _questType = Mandatory + , _questTitle = "Quell Riots" + , _questQuote = "" + , _questCost = do + returnResources 2 [Cleric] + returnResources 1 [Fighter] + , _questReward = scorePoints 4 + , _questPlotActions = [] + }) + , (1, IntrigueCard { _intrigueTitle = "Accelerate Plans" , _intrigueType = Utility , _intrigueAction = do - takeResources 2 [Wizard] - forOneOpponent (takeResources 1 [Wizard]) + returnAgentFromHarbor + assignAgent + assignAgent + , _intrigueQuote = "" + }) + , (2, IntrigueCard { _intrigueTitle = "Arcane Mishap" + , _intrigueType = Attack + , _intrigueAction = forEachOpponent $ do + result <- filterChoices $ returnResources 1 [Wizard] + when (result == Nothing) $ do + forCurrentPlayer $ drawIntrigue + , _intrigueQuote = "" + }) + , (2, IntrigueCard { _intrigueTitle = "Assassination" + , _intrigueType = Attack + , _intrigueAction = forEachOpponent $ do + result <- filterChoices $ returnResources 1 [Rogue] + when (result == Nothing) $ do + forCurrentPlayer $ takeResources 2 [Gold] + , _intrigueQuote = "" + }) + , (2, IntrigueCard { _intrigueTitle = "Ambush" + , _intrigueType = Attack + , _intrigueAction = forEachOpponent $ do + result <- filterChoices $ returnResources 1 [Fighter] + when (result == Nothing) $ do + forCurrentPlayer $ takeResources 1 [Fighter] + , _intrigueQuote = "" + }) + , (3, IntrigueCard { _intrigueTitle = "Bidding War" + , _intrigueType = Utility + , _intrigueAction = distributeQuests + , _intrigueQuote = "" + }) + , (2, IntrigueCard { _intrigueTitle = "Bribe Agent" + , _intrigueType = Attack + , _intrigueAction = do + returnResources 2 [Gold] + useOpponentsSpace + , _intrigueQuote = "" + }) + , (2, IntrigueCard { _intrigueTitle = "Call in a Favor" + , _intrigueType = Utility + , _intrigueAction = do + join . solicitChoice "Choose one:" $ + [ ("4 Gold", takeResources 4 [Gold]) + , ("2 Fighters", takeResources 2 [Fighter]) + , ("2 Rogues", takeResources 2 [Rogue]) + , ("1 Wizard", takeResources 1 [Wizard]) + , ("1 Cleric", takeResources 1 [Cleric]) + ] , _intrigueQuote = "" }) , (2, IntrigueCard { _intrigueTitle = "Call for Adventurers" , _intrigueType = Utility , _intrigueAction = do - takeResources 2 [Cleric, Fighter, Rogue, Wizard] - forOneOpponent (takeResources 1 [Cleric, Fighter, Rogue, Wizard]) + takeResources 2 [Cleric, Fighter, Rogue, Wizard] + forEachOpponent $ takeResources 1 [Cleric, Fighter, Rogue, Wizard] + , _intrigueQuote = "" + }) + , (1, IntrigueCard { _intrigueTitle = "Change of Plans" + , _intrigueType = Utility + , _intrigueAction = do + discardUncompletedQuest + scorePoints 6 + forEachOpponent $ do + join . solicitChoice "Discard uncompleted quest for 3 points?" $ + [ ("Yes", discardUncompletedQuest >> scorePoints 3) + , ("No", return ()) + ] + , _intrigueQuote = "" + }) + , (2, IntrigueCard { _intrigueTitle = "Conscription" + , _intrigueType = Utility + , _intrigueAction = do + takeResources 2 [Fighter] + forOneOpponent $ takeResources 1 [Fighter] + , _intrigueQuote = "" + }) + , (2, IntrigueCard { _intrigueTitle = "Crime Wave" + , _intrigueType = Utility + , _intrigueAction = do + takeResources 2 [Rogue] + forOneOpponent $ takeResources 1 [Rogue] + , _intrigueQuote = "" + }) + , (2, IntrigueCard { _intrigueTitle = "Free Drinks!" + , _intrigueType = Attack + , _intrigueAction = do + r <- solicitChoice "Choose one:" $ map (show &&& id) $ + [Cleric, Fighter, Rogue, Wizard] + forOneOpponent $ returnResources 1 [r] + takeResources 1 [r] + , _intrigueQuote = "" + }) + , (2, IntrigueCard { _intrigueTitle = "Good Faith" + , _intrigueType = Utility + , _intrigueAction = do + takeResources 2 [Cleric] + forOneOpponent $ takeResources 1 [Cleric] + , _intrigueQuote = "" + }) + , (2, IntrigueCard { _intrigueTitle = "Graduation Day" + , _intrigueType = Utility + , _intrigueAction = do + takeResources 2 [Wizard] + forOneOpponent $ takeResources 1 [Wizard] + , _intrigueQuote = "" + }) + , (2, IntrigueCard { _intrigueTitle = "Lack of Faith" + , _intrigueType = Attack + , _intrigueAction = forEachOpponent $ do + result <- filterChoices $ returnResources 1 [Cleric] + when (result == Nothing) $ do + forCurrentPlayer $ scorePoints 2 + , _intrigueQuote = "" + }) + , (1, IntrigueCard { _intrigueTitle = "Real Estate Deal" + , _intrigueType = Utility + , _intrigueAction = do + discardUnoccupiedBuilding + chooseFreeBuilding + , _intrigueQuote = "" + }) + , (2, IntrigueCard { _intrigueTitle = "Recall Agent" + , _intrigueType = Utility + , _intrigueAction = returnAgent + , _intrigueQuote = "" + }) + , (1, IntrigueCard { _intrigueTitle = "Recruit Spies" + , _intrigueType = Utility + , _intrigueAction = do + takeResources 2 [Rogue] + name <- use activePlayerName + forEachOpponent $ do + join . solicitChoice ("Give " ++ name ++ " 1 Rogue for 3 points?") $ + [ ("Yes", do { returnResources 1 [Rogue] + ; forCurrentPlayer $ takeResources 1 [Rogue] + ; scorePoints 3 + }) + , ("No", return ()) + ] + , _intrigueQuote = "" + }) + , (1, IntrigueCard { _intrigueTitle = "Request Assistance" + , _intrigueType = Utility + , _intrigueAction = do + takeResources 2 [Fighter] + name <- use activePlayerName + forEachOpponent $ do + join . solicitChoice ("Give " ++ name ++ " 1 Fighter for 3 points?") $ + [ ("Yes", do { returnResources 1 [Fighter] + ; forCurrentPlayer $ takeResources 1 [Fighter] + ; scorePoints 3 + }) + , ("No", return ()) + ] + , _intrigueQuote = "" + }) + , (1, IntrigueCard { _intrigueTitle = "Research Agreement" + , _intrigueType = Utility + , _intrigueAction = do + takeResources 1 [Wizard] + name <- use activePlayerName + forEachOpponent $ do + join . solicitChoice ("Give " ++ name ++ " 1 Wizard for 5 points?") $ + [ ("Yes", do { returnResources 1 [Wizard] + ; forCurrentPlayer $ takeResources 1 [Wizard] + ; scorePoints 5 + }) + , ("No", return ()) + ] + , _intrigueQuote = "" + }) + , (2, IntrigueCard { _intrigueTitle = "Sample Wares" + , _intrigueType = Utility + , _intrigueAction = assignAgentToBuildersHall + , _intrigueQuote = "" + }) + , (2, IntrigueCard { _intrigueTitle = "Special Assignment" + , _intrigueType = Utility + , _intrigueAction = drawNamedQuestType + , _intrigueQuote = "" + }) + , (2, IntrigueCard { _intrigueTitle = "Spread the Wealth" + , _intrigueType = Utility + , _intrigueAction = do + takeResources 4 [Gold] + forOneOpponent $ takeResources 2 [Gold] + , _intrigueQuote = "" + }) + , (1, IntrigueCard { _intrigueTitle = "Summon the Faithful" + , _intrigueType = Utility + , _intrigueAction = do + takeResources 1 [Cleric] + name <- use activePlayerName + forEachOpponent $ do + join . solicitChoice ("Give " ++ name ++ " 1 Cleric for 5 points?") $ + [ ("Yes", do { returnResources 1 [Cleric] + ; forCurrentPlayer $ takeResources 1 [Cleric] + ; scorePoints 5 + }) + , ("No", return ()) + ] + , _intrigueQuote = "" + }) + , (2, IntrigueCard { _intrigueTitle = "Tax Collection" + , _intrigueType = Utility + , _intrigueAction = do + takeResources 4 [Gold] + name <- use activePlayerName + forEachOpponent $ do + join . solicitChoice ("Give " ++ name ++ " 4 Gold for 4 points?") $ + [ ("Yes", do { returnResources 4 [Gold] + ; forCurrentPlayer $ takeResources 4 [Gold] + ; scorePoints 4 + }) + , ("No", return ()) + ] , _intrigueQuote = "" }) ] diff --git a/src/Waterdeep/Types.hs b/src/Waterdeep/Types.hs index 46a4222..02d91e8 100644 --- a/src/Waterdeep/Types.hs +++ b/src/Waterdeep/Types.hs @@ -226,7 +226,7 @@ data Resource = Cleric | Fighter | Rogue | Wizard | Gold data QuestType = Piety | Warfare | Skullduggery | Arcana | Commerce | Mandatory deriving (Eq,Ord,Enum,Bounded,Show) -data IntrigueType = Utility | Attack +data IntrigueType = Utility | Attack | MandatoryQuest deriving (Eq,Ord,Enum,Bounded,Show) data FactionColor = Yellow | Black | Blue | Green | Red