From d3889ef3cd3dbeb375fe74aaec9fd1f4f03d8942 Mon Sep 17 00:00:00 2001 From: Karl Ostmo Date: Mon, 23 Oct 2023 10:22:02 -0700 Subject: [PATCH] Achievement for pointless swapping (#1588) # Demo scripts/play.sh -i creative --seed 0 Then: turn right; move; turn right; move; t <- grab; move; swap t; ![image](https://github.com/swarm-game/swarm/assets/261693/eb2fb7bf-26e7-43c3-8b0b-2c92f35f9244) --- src/Swarm/Game/Achievement/Definitions.hs | 1 + src/Swarm/Game/Achievement/Description.hs | 7 +++++ src/Swarm/Game/Step.hs | 31 +++++++++++++---------- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/Swarm/Game/Achievement/Definitions.hs b/src/Swarm/Game/Achievement/Definitions.hs index 37a635843..5f1ef834e 100644 --- a/src/Swarm/Game/Achievement/Definitions.hs +++ b/src/Swarm/Game/Achievement/Definitions.hs @@ -107,6 +107,7 @@ data GameplayAchievement | DestroyedBase | LoseScenario | GetDisoriented + | SwapSame deriving (Eq, Ord, Show, Bounded, Enum, Generic) instance FromJSON GameplayAchievement diff --git a/src/Swarm/Game/Achievement/Description.hs b/src/Swarm/Game/Achievement/Description.hs index e3778b044..237c45679 100644 --- a/src/Swarm/Game/Achievement/Description.hs +++ b/src/Swarm/Game/Achievement/Description.hs @@ -88,3 +88,10 @@ describe = \case "`turn down` without a compass. Congratulations, you are \"disoriented\". How are you supposed to move now?" Easy True + GameplayAchievement SwapSame -> + AchievementInfo + "Fair Trade" + (Just $ Freeform "The *Law of Equivalent Exchange*... taken literally.") + "`swap` an item for itself." + Easy + True diff --git a/src/Swarm/Game/Step.hs b/src/Swarm/Game/Step.hs index ec914efc4..a694edff3 100644 --- a/src/Swarm/Game/Step.hs +++ b/src/Swarm/Game/Step.hs @@ -1159,8 +1159,8 @@ execConst c vs s k = do return $ Out VUnit s k _ -> badConst - Grab -> doGrab Grab' - Harvest -> doGrab Harvest' + Grab -> mkReturn <$> doGrab Grab' + Harvest -> mkReturn <$> doGrab Harvest' Ignite -> case vs of [VDir d] -> do Combustion.igniteCommand c d @@ -1172,14 +1172,16 @@ execConst c vs s k = do -- Make sure the robot has the thing in its inventory e <- hasInInventoryOrFail name -- Grab - r <- doGrab Swap' - case r of - Out {} -> do - -- Place the entity and remove it from the inventory - updateEntityAt loc (const (Just e)) - robotInventory %= delete e - _ -> pure () - return r + newE <- doGrab Swap' + + -- Place the entity and remove it from the inventory + updateEntityAt loc (const (Just e)) + robotInventory %= delete e + + when (e == newE) $ + grantAchievement SwapSame + + return $ mkReturn newE _ -> badConst Turn -> case vs of [VDir d] -> do @@ -2510,9 +2512,12 @@ execConst c vs s k = do `holdsOrFail` ["You don't have", indefinite eName, "to", cmd <> "."] return e + mkReturn :: Valuable a => a -> CESK + mkReturn x = Out (asValue x) s k + -- The code for grab and harvest is almost identical, hence factored -- out here. - doGrab :: (HasRobotStepState sig m, Has (Lift IO) sig m) => GrabbingCmd -> m CESK + doGrab :: (HasRobotStepState sig m, Has (Lift IO) sig m) => GrabbingCmd -> m Entity doGrab cmd = do let verb = verbGrabbingCmd cmd verbed = verbedGrabbingCmd cmd @@ -2556,8 +2561,8 @@ execConst c vs s k = do robotInventory %= insert e' updateDiscoveredEntities e' - -- Return the name of the item obtained. - return $ Out (VText (e' ^. entityName)) s k + -- Return the item obtained. + return e' ------------------------------------------------------------ -- The "watch" command