|
@ -1,37 +1,65 @@ |
|
|
module Strategy0 where |
|
|
|
|
|
|
|
|
module Strategy0(Strategy0) where |
|
|
|
|
|
|
|
|
import qualified Data.PQueue.Prio.Max as PQ |
|
|
import qualified Data.PQueue.Prio.Max as PQ |
|
|
|
|
|
|
|
|
|
|
|
import System.Random(StdGen) |
|
|
import Data.Maybe (isJust) |
|
|
import Data.Maybe (isJust) |
|
|
|
|
|
|
|
|
import Datatypes |
|
|
import Datatypes |
|
|
import Datatypes.Game (Command(..)) |
|
|
import Datatypes.Game (Command(..)) |
|
|
import qualified Datatypes.Unit as Unit |
|
|
import qualified Datatypes.Unit as Unit |
|
|
import qualified Datatypes.Game as Game |
|
|
import qualified Datatypes.Game as Game |
|
|
import VM |
|
|
import VM |
|
|
|
|
|
import StrategyManager |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
commandsList :: [Command] |
|
|
commandsList :: [Command] |
|
|
commandsList = [MoveSE, MoveSW, MoveW, MoveE, RotateClockwise, RotateCounterclockwise] |
|
|
commandsList = [MoveSE, MoveSW, MoveW, MoveE, RotateClockwise, RotateCounterclockwise] |
|
|
|
|
|
|
|
|
type Queue = PQ.MaxPQueue (Int, Int, Int) Game |
|
|
type Queue = PQ.MaxPQueue (Int, Int, Int) Game |
|
|
|
|
|
data Strategy0 = Strategy0 (Queue, [Game]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
instance Strategy Strategy0 where |
|
|
|
|
|
initst = strategy0initst |
|
|
|
|
|
advance = strategy0advance |
|
|
|
|
|
getbest = strategy0getbest |
|
|
|
|
|
|
|
|
|
|
|
strategy0initst :: Game -> StdGen -> Maybe [Command] -> Strategy0 |
|
|
|
|
|
strategy0initst game _ _ = (Strategy0 (firstQueue, firstList)) where |
|
|
|
|
|
firstQueue = PQ.singleton (fullScore game, -(length $ Game.units game), snd . Unit.pivot . head . Game.units $ game) game |
|
|
|
|
|
firstList = [] |
|
|
|
|
|
|
|
|
|
|
|
strategy0advance :: Strategy0 -> Either Strategy0 ([Command],Int) |
|
|
|
|
|
strategy0advance (Strategy0 (queue,completed)) = |
|
|
|
|
|
let candidates = (tryPowerPhrases game) ++ (map (step game) commandsList) |
|
|
|
|
|
(newQueue, newCompleted) = updateCollections candidates remQueue (game:completed) |
|
|
|
|
|
in Left (Strategy0 (newQueue, newCompleted)) |
|
|
|
|
|
where |
|
|
|
|
|
((score, game), remQueue) = PQ.deleteFindMax queue |
|
|
|
|
|
updateCollections [] q l = (q, l) |
|
|
|
|
|
updateCollections ((g, n):rs) q l = case n of |
|
|
|
|
|
OK -> updateCollections rs (pushToQueue q g) l |
|
|
|
|
|
Lock _ -> updateCollections rs (pushToQueue q g) l |
|
|
|
|
|
GameOver -> updateCollections rs q (pushToList l g) |
|
|
|
|
|
_ -> updateCollections rs q l |
|
|
|
|
|
pushToQueue q x = PQ.insert (fullScore x, -(length $ Game.units x), snd . Unit.pivot . head . Game.units $ x) x q |
|
|
|
|
|
pushToList c x = x : c |
|
|
|
|
|
|
|
|
|
|
|
strategy0getbest :: Strategy0 -> ([Command], Int) |
|
|
|
|
|
strategy0getbest (Strategy0 (incomplete,completed)) = |
|
|
|
|
|
let (_, bestIncomplete) = PQ.findMax incomplete |
|
|
|
|
|
resultGame = findListMax (bestIncomplete:completed) |
|
|
|
|
|
in (reverse (Game.history resultGame), fullScore resultGame) |
|
|
|
|
|
|
|
|
fullScore :: Game -> Int |
|
|
fullScore :: Game -> Int |
|
|
fullScore game = Game.score game + (Game.powerCounterToScore $ Game.powerCounter game) |
|
|
fullScore game = Game.score game + (Game.powerCounterToScore $ Game.powerCounter game) |
|
|
|
|
|
|
|
|
strat0 :: Game -> ([Command],Int) |
|
|
|
|
|
strat0 game = let firstQueue = PQ.singleton (fullScore game, -(length $ Game.units game), snd . Unit.pivot . head . Game.units $ game) game |
|
|
|
|
|
(incomplete, completed) = findBest maxIter firstQueue [] |
|
|
|
|
|
(_, bestIncomplete) = PQ.findMax incomplete |
|
|
|
|
|
resultGame = findListMax (bestIncomplete:completed) |
|
|
|
|
|
in (reverse (Game.history resultGame), fullScore resultGame) |
|
|
|
|
|
where |
|
|
|
|
|
maxIter = 300000 |
|
|
|
|
|
|
|
|
|
|
|
findListMax :: [Game] -> Game |
|
|
findListMax :: [Game] -> Game |
|
|
findListMax (x:xs) = innerFindListMax x xs where |
|
|
findListMax (x:xs) = innerFindListMax x xs where |
|
|
innerFindListMax currentMax [] = currentMax |
|
|
innerFindListMax currentMax [] = currentMax |
|
|
innerFindListMax currentMax (y:ys) = innerFindListMax (if (fullScore currentMax) > (fullScore y) then currentMax else y) ys |
|
|
innerFindListMax currentMax (y:ys) = innerFindListMax (if (fullScore currentMax) > (fullScore y) then currentMax else y) ys |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
partition :: (a -> Bool) -> [a] -> ([a], [a]) |
|
|
partition :: (a -> Bool) -> [a] -> ([a], [a]) |
|
|
partition p items = innerPartition items [] [] where |
|
|
partition p items = innerPartition items [] [] where |
|
|
innerPartition [] ts fs = (ts, fs) |
|
|
innerPartition [] ts fs = (ts, fs) |
|
@ -55,20 +83,3 @@ tryPowerPhrases game = validResults where |
|
|
OK -> innerExpand nn ps |
|
|
OK -> innerExpand nn ps |
|
|
Lock _ -> innerExpand nn ps |
|
|
Lock _ -> innerExpand nn ps |
|
|
_ -> Nothing |
|
|
_ -> Nothing |
|
|
|
|
|
|
|
|
findBest :: Int -> Queue -> [Game] -> (Queue, [Game]) |
|
|
|
|
|
findBest 0 queue completed = (queue, completed) |
|
|
|
|
|
findBest i queue completed = |
|
|
|
|
|
let candidates = (tryPowerPhrases game) ++ (map (step game) commandsList) |
|
|
|
|
|
(newQueue, newCompleted) = updateCollections candidates remQueue (game:completed) |
|
|
|
|
|
in findBest (i - 1) newQueue newCompleted |
|
|
|
|
|
where |
|
|
|
|
|
((score, game), remQueue) = PQ.deleteFindMax queue |
|
|
|
|
|
updateCollections [] q l = (q, l) |
|
|
|
|
|
updateCollections ((g, n):rs) q l = case n of |
|
|
|
|
|
OK -> updateCollections rs (pushToQueue q g) l |
|
|
|
|
|
Lock _ -> updateCollections rs (pushToQueue q g) l |
|
|
|
|
|
GameOver -> updateCollections rs q (pushToList l g) |
|
|
|
|
|
_ -> updateCollections rs q l |
|
|
|
|
|
pushToQueue q x = PQ.insert (fullScore x, -(length $ Game.units x), snd . Unit.pivot . head . Game.units $ x) x q |
|
|
|
|
|
pushToList c x = x : c |
|
|
|