{-# LANGUAGE TupleSections #-} module Dodge.Combine ( combinePoss , combineSizes , combineItemListYou , combineItemListYou' , toggleCombineInv , enterCombineInv ) where import Dodge.Combine.Combinations import Dodge.Base.You import Dodge.Data import Dodge.Item.Amount import Dodge.Inventory.ItemSpace --import Dodge.Combine.Data import Multiset import SimpleTrie import Control.Lens import Data.Bifunctor import qualified Data.IntMap.Strict as IM --import qualified Data.IntSet as IS import qualified Data.Map.Strict as M import Data.Map.Merge.Strict import Data.Maybe import Data.List (scanl',sortOn) combinationsTrie :: Trie (Int,CombineType) Item combinationsTrie = foldr (uncurry insertInTrie . first (sortOn snd)) emptyTrie itemCombinations -- this can probably be improved by going through accessing the combinations -- trie going through each combine type in your inventory in order, rather than -- creating all multisets of combine types. lookupItems :: [(M.Map ModuleSlot ItemModule,CombineType,Int,Int)] -> [ ([(M.Map ModuleSlot ItemModule,Int)],Item) ] lookupItems xs = lookupItemsUsingTrie (sortOn (\(_,ct,_,_) -> ct) xs) combinationsTrie lookupItemsUsingTrie :: [(M.Map ModuleSlot ItemModule,CombineType,Int,Int)] -> Trie (Int,CombineType) Item -> [ ([(M.Map ModuleSlot ItemModule,Int)],Item) ] lookupItemsUsingTrie [] t = maybeToList $ ([],) <$> _trieMVal t lookupItemsUsingTrie ((mods,ct,i,n):xs) t = do n' <- [1..min n 4] let is = replicate n' (mods,i) concatMap (map (first (is ++)) . lookupItemsUsingTrie xs) $ maybeToList (_trieChildren t M.!? (n',ct)) invertListInvMult :: IM.IntMap Item -> [[(M.Map ModuleSlot ItemModule,CombineType,Int,Int)]] invertListInvMult = powlistUpToN 4 . invertListInv invertListInv :: IM.IntMap Item -> [(M.Map ModuleSlot ItemModule,CombineType,Int,Int)] invertListInv = IM.foldrWithKey (\k it -> ((_itModules it,_itType it, k, itStackAmount it) :) ) [] -- gives a list of indices-item pairs. -- Note that within the pair, indices can be repeated if two or more of an item -- are needed combineItemListYou :: World -> [([Int],Item)] combineItemListYou = map (second fst) . combineItemListYou' combineItemListYou' :: World -> [([Int],(Item,[String]))] combineItemListYou' = map addModules . concatMap lookupItems . invertListInvMult . yourInv addModules :: ([(M.Map ModuleSlot ItemModule,Int)],Item) -> ([Int],(Item,[String])) addModules (ps,it) = (is , (applyModules newm it, ss)) where (ms,is) = unzip ps m = ([],_itModules it) (ss,newm) = foldr f m ms f m' (s,m'') = (s ++ s',m''') where (s',m''') = combineModules m' m'' applyModules :: M.Map ModuleSlot ItemModule -> Item -> Item applyModules ms it = foldr f (it & itModules .~ ms) ms where f m = fromMaybe id (m ^? modModification) -- (is , ) <$> [ (it & itModules .~ themodules,s) | (themodules,s) <- combinedmodules] -- where -- (ms,is) = unzip ps -- combinedmodules = foldr f [(_itModules it,[])] ms -- f :: M.Map ModuleSlot ItemModule -> [(M.Map ModuleSlot ItemModule,[String])] -> [(M.Map ModuleSlot ItemModule,[String])] -- f ims imss = concatMap (g ims) imss -- g ims (ims',s) = map (second (s++)) $ combineModules ims ims' combineModules :: M.Map ModuleSlot ItemModule -> M.Map ModuleSlot ItemModule -> ([String],M.Map ModuleSlot ItemModule) combineModules = mergeA (traverseMaybeMissing f) (traverseMissing g) (zipWithAMatched h) where f _ ItemModule{_modName=ss} = ("WARNING:REMOVES":ss,Nothing) f _ _ = ([],Nothing) g _ m = ([], m) h _ ItemModule{_modName=ss} im@ItemModule{} = ("WARNING:REMOVES":ss,im) h _ _ im@ItemModule{} = ([],im) h _ im _ = ([],im) toggleCombineInv :: World -> World toggleCombineInv w = case _hudElement (_hud w) of DisplayInventory CombineInventory {} -> w & hud . hudElement .~ DisplayInventory NoSubInventory _ -> w & enterCombineInv enterCombineInv :: World -> World enterCombineInv w = w & hud . hudElement .~ DisplayInventory (CombineInventory mi) where mi = 0 <$ listToMaybe (combineItemListYou w) combineSizes :: World -> [Int] --combineSizes = map (ceiling . _itInvSize . snd) . combineItemListYou combineSizes = map (itSlotsTaken . snd) . combineItemListYou combinePoss :: World -> [Int] combinePoss = scanl' (+) 0 . combineSizes