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.

85 lines
4.0 KiB

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