You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

90 lines
4.1 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. {-# LANGUAGE DeriveGeneric #-}
  2. module Strategy0(Strategy0) where
  3. import qualified Data.PQueue.Prio.Max as PQ
  4. import GHC.Generics (Generic)
  5. import Control.DeepSeq
  6. import System.Random(StdGen)
  7. import Data.Maybe (isJust)
  8. import Datatypes
  9. import Datatypes.Game (Command(..))
  10. import qualified Datatypes.Unit as Unit
  11. import qualified Datatypes.Game as Game
  12. import VM
  13. import StrategyManager
  14. commandsList :: [Command]
  15. commandsList = [MoveSE, MoveSW, MoveW, MoveE, RotateClockwise, RotateCounterclockwise]
  16. type Queue = PQ.MaxPQueue (Int, Int, Int) Game
  17. data Strategy0 = Strategy0 (Queue, [Game])
  18. deriving Generic
  19. instance Strategy Strategy0 where
  20. initst = strategy0initst
  21. advance = strategy0advance
  22. getbest = strategy0getbest
  23. instance NFData Strategy0
  24. strategy0initst :: Game -> StdGen -> [[Command]] -> Strategy0
  25. strategy0initst game _ _ = (Strategy0 (firstQueue, firstList)) where
  26. firstQueue = PQ.singleton (fullScore game, -(length $ Game.units game), snd . Unit.pivot . head . Game.units $ game) game
  27. firstList = []
  28. strategy0advance :: Strategy0 -> Either Strategy0 ([Command],Int)
  29. strategy0advance (Strategy0 (queue,completed)) =
  30. let candidates = (tryPowerPhrases game) ++ (map (step game) commandsList)
  31. (newQueue, newCompleted) = updateCollections candidates remQueue (game:completed)
  32. in Left (Strategy0 (newQueue, newCompleted))
  33. where
  34. ((score, game), remQueue) = PQ.deleteFindMax queue
  35. updateCollections [] q l = (q, l)
  36. updateCollections ((g, n):rs) q l = case n of
  37. OK -> updateCollections rs (pushToQueue q g) l
  38. Lock _ -> updateCollections rs (pushToQueue q g) l
  39. GameOver -> updateCollections rs q (pushToList l g)
  40. _ -> updateCollections rs q l
  41. pushToQueue q x = PQ.insert (fullScore x, -(length $ Game.units x), snd . Unit.pivot . head . Game.units $ x) x q
  42. pushToList c x = x : c
  43. strategy0getbest :: Strategy0 -> ([Command], Int)
  44. strategy0getbest (Strategy0 (incomplete,completed)) =
  45. let (_, bestIncomplete) = PQ.findMax incomplete
  46. resultGame = findListMax (bestIncomplete:completed)
  47. in (reverse (Game.history resultGame), fullScore resultGame)
  48. fullScore :: Game -> Int
  49. fullScore game = Game.score game + (Game.powerCounterToScore $ Game.powerCounter game)
  50. findListMax :: [Game] -> Game
  51. findListMax (x:xs) = innerFindListMax x xs where
  52. innerFindListMax currentMax [] = currentMax
  53. innerFindListMax currentMax (y:ys) = innerFindListMax (if (fullScore currentMax) > (fullScore y) then currentMax else y) ys
  54. partition :: (a -> Bool) -> [a] -> ([a], [a])
  55. partition p items = innerPartition items [] [] where
  56. innerPartition [] ts fs = (ts, fs)
  57. innerPartition (x:xs) ts fs = if p x
  58. then innerPartition xs (x:ts) fs
  59. else innerPartition xs ts (x:fs)
  60. tryPowerPhrases :: Game -> [(Game, Notes)]
  61. tryPowerPhrases game = validResults where
  62. allResults = map (innerExpand (game, OK)) Game.powerPhrasesAsCommands
  63. validResults = map (\(Just x) -> x) $ filter (\x -> isJust x) allResults
  64. innerExpand (game, note) [] = Just (game, note)
  65. innerExpand (game, note) [p] = let nn@(newGame, newNote) = step game p
  66. in case newNote of
  67. OK -> Just nn
  68. Lock _ -> Just nn
  69. GameOver -> Just nn
  70. _ -> Nothing
  71. innerExpand (game, note) (p:ps) = let nn@(newGame, newNote) = step game p
  72. in case newNote of
  73. OK -> innerExpand nn ps
  74. Lock _ -> innerExpand nn ps
  75. _ -> Nothing