dev #25
					 6 changed files with 59 additions and 21 deletions
				
			
		|  | @ -91,4 +91,10 @@ isInventoryFull p = inventorySize <= length (inventory p) | ||||||
| 
 | 
 | ||||||
| -- Check if the inventory of the player contains an item. | -- Check if the inventory of the player contains an item. | ||||||
| inventoryContains :: ItemId -> Player -> Bool | inventoryContains :: ItemId -> Player -> Bool | ||||||
| inventoryContains id p = any ((== id) . itemId) $ inventory p | inventoryContains id p = any ((== id) . itemId) $ inventory p | ||||||
|  | 
 | ||||||
|  | -- Retrieve an item from inventory | ||||||
|  | itemFromInventory :: ItemId -> [Item] -> (Maybe Item, [Item]) | ||||||
|  | itemFromInventory iid list = (match, filteredList) | ||||||
|  |     where match = find ((== iid) . itemId) list | ||||||
|  |           filteredList = filter ((/= iid) . itemId) list | ||||||
|  | @ -4,11 +4,11 @@ module RPGEngine.Input.ActionSelection | ||||||
| 
 | 
 | ||||||
| import RPGEngine.Input.Core (InputHandler, handleKey, composeInputHandlers, ListSelector (selection)) | import RPGEngine.Input.Core (InputHandler, handleKey, composeInputHandlers, ListSelector (selection)) | ||||||
| 
 | 
 | ||||||
| import RPGEngine.Data (Game (..), State (..), Direction (..), Action (..), ItemId, EntityId, Level (..), Player (inventory, playerHp, Player), Item (..), HP) | import RPGEngine.Data (Game (..), State (..), Direction (..), Action (..), ItemId, EntityId, Level (..), Player (inventory, playerHp, Player), Item (..), HP, Entity (..)) | ||||||
| import Graphics.Gloss.Interface.IO.Game (Key(SpecialKey), SpecialKey (KeyUp, KeyDown)) | import Graphics.Gloss.Interface.IO.Game (Key(SpecialKey), SpecialKey (KeyUp, KeyDown)) | ||||||
| import Graphics.Gloss.Interface.IO.Interact | import Graphics.Gloss.Interface.IO.Interact | ||||||
|     ( SpecialKey(..), KeyState(..) ) |     ( SpecialKey(..), KeyState(..) ) | ||||||
| import RPGEngine.Data.Level (getWithId) | import RPGEngine.Data.Level (getWithId, itemFromInventory) | ||||||
| import Data.Foldable (find) | import Data.Foldable (find) | ||||||
| 
 | 
 | ||||||
| ------------------------------ Exported ------------------------------ | ------------------------------ Exported ------------------------------ | ||||||
|  | @ -72,13 +72,30 @@ useItem :: ItemId -> State -> State -- TODO | ||||||
| useItem _ s = s -- TODO | useItem _ s = s -- TODO | ||||||
| 
 | 
 | ||||||
| -- Attack an entity using an item | -- Attack an entity using an item | ||||||
|  | -- Should receive a Playing state | ||||||
| decreaseHp :: EntityId -> ItemId -> State -> State | decreaseHp :: EntityId -> ItemId -> State -> State | ||||||
| decreaseHp _ _ s = s | decreaseHp eid iid s@Playing{ level = level, player = player } = newState | ||||||
| -- TODO DecreaseHp of monster |     where newState = s{ level = newLevel, player = newPlayer } | ||||||
| -- TODO Check if monster is dead |           -- Change player | ||||||
| -- TODO Entity attack player |           (Just usingItem) = find ((== iid) . itemId) (inventory player) | ||||||
| -- TODO Decrease durability of item |           usedItem         = decreaseDurability usingItem | ||||||
| -- TODO Break item if durability below zero |           newInventory     = filter (/= usingItem) $ inventory player | ||||||
|  |           newPlayer = player{ inventory = putItemBack usedItem newInventory, playerHp = newHp } | ||||||
|  |           putItemBack Nothing inv     = inv | ||||||
|  |           putItemBack (Just item) inv = item:inv | ||||||
|  |           newHp                       = changeHealth (playerHp player) damageGetAmount -- Damage dealt by entity | ||||||
|  |           damageDealAmount = itemValue usingItem | ||||||
|  |           -- Change entity | ||||||
|  |           (Just (Right attackedEntity)) = getWithId eid level | ||||||
|  |           newLevel = level{ entities = putEntityBack dealtWithEntity newEntities } | ||||||
|  |           newEntities = filter ((/= eid) . entityId) $ entities level | ||||||
|  |           dealtWithEntity = decreaseHealth attackedEntity damageDealAmount  | ||||||
|  |           putEntityBack Nothing    list = list | ||||||
|  |           putEntityBack (Just ent) list = ent:list | ||||||
|  |           damageGetAmount = inverse (entityValue attackedEntity) | ||||||
|  |           inverse (Just val) = Just (-val) | ||||||
|  |           inverse Nothing    = Nothing | ||||||
|  | decreaseHp _ _ _ = Error "something went wrong while attacking" | ||||||
| 
 | 
 | ||||||
| -- Heal a bit | -- Heal a bit | ||||||
| -- Should receive a Player | -- Should receive a Player | ||||||
|  | @ -97,6 +114,12 @@ decreaseDurability item@Item{ useTimes = Nothing  } = Just item -- Infinite uses | ||||||
| decreaseDurability item@Item{ useTimes = Just val } | 0 < val - 1 = Just item{ useTimes = Just (val - 1) } | decreaseDurability item@Item{ useTimes = Just val } | 0 < val - 1 = Just item{ useTimes = Just (val - 1) } | ||||||
|                                                     | otherwise = Nothing -- Broken |                                                     | otherwise = Nothing -- Broken | ||||||
| 
 | 
 | ||||||
|  | decreaseHealth :: Entity -> Maybe Int -> Maybe Entity | ||||||
|  | decreaseHealth entity@Entity{ entityHp = Nothing  } _ = Just entity | ||||||
|  | decreaseHealth entity@Entity{ entityHp = Just val } (Just i) | 0 < val - i = Just entity{ entityHp = Just (val - i) } | ||||||
|  |                                                              | otherwise   = Nothing | ||||||
|  | decreaseHealth entity _ = Just entity | ||||||
|  | 
 | ||||||
| -- Change given health by a given amount | -- Change given health by a given amount | ||||||
| changeHealth :: HP -> HP -> HP | changeHealth :: HP -> HP -> HP | ||||||
| changeHealth (Just health) (Just difference) = Just (health + difference) | changeHealth (Just health) (Just difference) = Just (health + difference) | ||||||
|  |  | ||||||
|  | @ -139,7 +139,7 @@ action = try $ do | ||||||
|     let answer | script == "leave"            = Leave |     let answer | script == "leave"            = Leave | ||||||
|                | script == "retrieveItem"     = RetrieveItem arg |                | script == "retrieveItem"     = RetrieveItem arg | ||||||
|                | script == "useItem"          = UseItem arg |                | script == "useItem"          = UseItem arg | ||||||
|                | script == "decreaseHp"       = DecreaseHp first second |                | script == "decreaseHp"       = DecreaseHp first (filter (/= ' ') second) -- TODO Work this hack away | ||||||
|                | script == "increasePlayerHp" = IncreasePlayerHp arg |                | script == "increasePlayerHp" = IncreasePlayerHp arg | ||||||
|                | otherwise                    = DoNothing |                | otherwise                    = DoNothing | ||||||
|         (first, ',':second) = break (== ',') arg |         (first, ',':second) = break (== ',') arg | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import RPGEngine | import RPGEngine ( playRPGEngine ) | ||||||
| 
 | 
 | ||||||
| ----------------------------- Constants ------------------------------ | ----------------------------- Constants ------------------------------ | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,7 +6,6 @@ import RPGEngine.Data | ||||||
| import RPGEngine.Parse.Core | import RPGEngine.Parse.Core | ||||||
| import RPGEngine.Parse.TextToStructure | import RPGEngine.Parse.TextToStructure | ||||||
| import RPGEngine.Parse.StructureToGame | import RPGEngine.Parse.StructureToGame | ||||||
| import RPGEngine.Parse.TextToStructure (gameFile) |  | ||||||
| 
 | 
 | ||||||
| spec :: Spec | spec :: Spec | ||||||
| spec = do | spec = do | ||||||
|  | @ -40,7 +39,7 @@ spec = do | ||||||
|             pendingWith "Still need to write this" |             pendingWith "Still need to write this" | ||||||
|         it "Game with multiple levels" $ do |         it "Game with multiple levels" $ do | ||||||
|             pendingWith "Still need to write this" |             pendingWith "Still need to write this" | ||||||
|      | 
 | ||||||
|     describe "Player" $ do |     describe "Player" $ do | ||||||
|         it "cannot die" $ do |         it "cannot die" $ do | ||||||
|             let input   = "player: { hp: infinite, inventory: [] }" |             let input   = "player: { hp: infinite, inventory: [] }" | ||||||
|  | @ -65,7 +64,7 @@ spec = do | ||||||
|                 } |                 } | ||||||
|                 Right (Entry (Tag "player") struct) = parseWith structure input |                 Right (Entry (Tag "player") struct) = parseWith structure input | ||||||
|             structureToPlayer struct `shouldBe` correct |             structureToPlayer struct `shouldBe` correct | ||||||
|          | 
 | ||||||
|         it "with inventory" $ do |         it "with inventory" $ do | ||||||
|             let input   = "player: { hp: 50, inventory: [ { id: \"dagger\", x: 0, y: 0, name: \"Dolk\", description: \"Basis schade tegen monsters\", useTimes: infinite, value: 10, actions: {} } ] }" |             let input   = "player: { hp: 50, inventory: [ { id: \"dagger\", x: 0, y: 0, name: \"Dolk\", description: \"Basis schade tegen monsters\", useTimes: infinite, value: 10, actions: {} } ] }" | ||||||
|                 correct = Player { |                 correct = Player { | ||||||
|  | @ -95,7 +94,7 @@ spec = do | ||||||
|                 correct = Item { |                 correct = Item { | ||||||
|                     itemId          = "dagger", |                     itemId          = "dagger", | ||||||
|                     itemX           = 0, |                     itemX           = 0, | ||||||
|                     itemY           = 0,  |                     itemY           = 0, | ||||||
|                     itemName        = "Dagger", |                     itemName        = "Dagger", | ||||||
|                     itemDescription = "Basic dagger you found somewhere", |                     itemDescription = "Basic dagger you found somewhere", | ||||||
|                     itemValue       = Just 10, |                     itemValue       = Just 10, | ||||||
|  | @ -104,7 +103,7 @@ spec = do | ||||||
|                 } |                 } | ||||||
|                 Right struct = parseWith structure input |                 Right struct = parseWith structure input | ||||||
|             structureToItem struct `shouldBe` correct |             structureToItem struct `shouldBe` correct | ||||||
|          | 
 | ||||||
|         it "with actions" $ do |         it "with actions" $ do | ||||||
|             let input   = "{ id: \"key\", x: 3, y: 1, name: \"Doorkey\", description: \"Unlocks a secret door\", useTimes: 1, value: 0, actions: { [not(inventoryFull())] retrieveItem(key), [] leave() } }" |             let input   = "{ id: \"key\", x: 3, y: 1, name: \"Doorkey\", description: \"Unlocks a secret door\", useTimes: 1, value: 0, actions: { [not(inventoryFull())] retrieveItem(key), [] leave() } }" | ||||||
|                 correct = Item { |                 correct = Item { | ||||||
|  | @ -122,30 +121,36 @@ spec = do | ||||||
|                 } |                 } | ||||||
|                 Right struct = parseWith structure input |                 Right struct = parseWith structure input | ||||||
|             structureToItem struct `shouldBe` correct |             structureToItem struct `shouldBe` correct | ||||||
|      | 
 | ||||||
|     describe "Actions" $ do |     describe "Actions" $ do | ||||||
|         it "no conditions" $ do |         it "no conditions" $ do | ||||||
|             let input   = "{[] leave()}" |             let input   = "{[] leave()}" | ||||||
|                 correct = [([], Leave)] |                 correct = [([], Leave)] | ||||||
|                 Right struct = parseWith structure input |                 Right struct = parseWith structure input | ||||||
|             structureToActions struct `shouldBe` correct |             structureToActions struct `shouldBe` correct | ||||||
|          | 
 | ||||||
|         it "single condition" $ do |         it "single condition" $ do | ||||||
|             let input   = "{ [inventoryFull()] useItem(itemId)}" |             let input   = "{ [inventoryFull()] useItem(itemId)}" | ||||||
|                 correct = [([InventoryFull], UseItem "itemId")] |                 correct = [([InventoryFull], UseItem "itemId")] | ||||||
|                 Right struct = parseWith structure input |                 Right struct = parseWith structure input | ||||||
|             structureToActions struct `shouldBe` correct |             structureToActions struct `shouldBe` correct | ||||||
|          | 
 | ||||||
|         it "multiple conditions" $ do |         it "multiple conditions" $ do | ||||||
|             let input   = "{ [not(inventoryFull()), inventoryContains(itemId)] increasePlayerHp(itemId)}" |             let input   = "{ [not(inventoryFull()), inventoryContains(itemId)] increasePlayerHp(itemId)}" | ||||||
|                 correct = [([Not InventoryFull, InventoryContains "itemId"], IncreasePlayerHp "itemId")] |                 correct = [([Not InventoryFull, InventoryContains "itemId"], IncreasePlayerHp "itemId")] | ||||||
|                 Right struct = parseWith structure input |                 Right struct = parseWith structure input | ||||||
|             structureToActions struct `shouldBe` correct |             structureToActions struct `shouldBe` correct | ||||||
|  |          | ||||||
|  |         it "DecreaseHp(entityid, itemid)" $ do | ||||||
|  |             let input   = "{ [] decreaseHp(devil, sword) }" | ||||||
|  |                 correct = [([], DecreaseHp "devil" "sword")] | ||||||
|  |                 Right struct = parseWith structure input | ||||||
|  |             structureToActions struct `shouldBe` correct | ||||||
| 
 | 
 | ||||||
|     describe "Entities" $ do |     describe "Entities" $ do | ||||||
|         it "Simple entity" $ do |         it "Simple entity" $ do | ||||||
|             pendingWith "still need to write this" |             pendingWith "still need to write this" | ||||||
|      | 
 | ||||||
|     describe "Level" $ do |     describe "Level" $ do | ||||||
|         it "Simple layout" $ do |         it "Simple layout" $ do | ||||||
|             let input   = "{ layout: { | * * * * * *\n| * s . . e *\n| * * * * * *\n }, items: [], entities: [] }" |             let input   = "{ layout: { | * * * * * *\n| * s . . e *\n| * * * * * *\n }, items: [], entities: [] }" | ||||||
|  |  | ||||||
|  | @ -146,10 +146,14 @@ spec = do | ||||||
|                 correct = Right $ Regular $ Action $ UseItem "secondId" |                 correct = Right $ Regular $ Action $ UseItem "secondId" | ||||||
|             parseWith regular input `shouldBe` correct |             parseWith regular input `shouldBe` correct | ||||||
| 
 | 
 | ||||||
|             let input   = "decreaseHp(entityId,objectId)" |             let input   = "decreaseHp(entityId, objectId)" | ||||||
|                 correct = Right $ Regular $ Action $ DecreaseHp "entityId" "objectId" |                 correct = Right $ Regular $ Action $ DecreaseHp "entityId" "objectId" | ||||||
|             parseWith regular input `shouldBe` correct |             parseWith regular input `shouldBe` correct | ||||||
| 
 | 
 | ||||||
|  |             let input   = "decreaseHp(entityId,objectId)" | ||||||
|  |                 correct = Right $ Regular $ Action $ DecreaseHp "entityId" "objectId" | ||||||
|  |             parseWith regular input `shouldBe` correct | ||||||
|  |              | ||||||
|             let input   = "increasePlayerHp(objectId)" |             let input   = "increasePlayerHp(objectId)" | ||||||
|                 correct = Right $ Regular $ Action $ IncreasePlayerHp "objectId" |                 correct = Right $ Regular $ Action $ IncreasePlayerHp "objectId" | ||||||
|             parseWith regular input `shouldBe` correct |             parseWith regular input `shouldBe` correct | ||||||
|  |  | ||||||
		Reference in a new issue