Subato

StrategicGames

In dieser Aufgabe beschäftigen wir uns .


> {-# LANGUAGE MultiParamTypeClasses #-} > > module StrategicGames where > import Data.List(maximumBy,transpose) > import Data.List.Lens > import Control.Lens.Combinators > import Control.Lens.Operators > import Control.Parallel.Strategies > import Data.List.Extra > import Control.Exception > import Control.Monad > data Player = One |Two | None deriving (Eq) > nextPlayer One = Two > nextPlayer Two = One > instance Show Player where > show One = "X" > show Two = "0" > show _ = " " > class Show m => Game g m where > start :: (g m) > currentPlayer :: (g m) -> Player > moves :: (g m) -> [m] > makeMove :: g m -> m -> g m > hasWinner :: g m -> Bool > gameOver :: g m -> Bool > gameOver g = null (moves g)||hasWinner g > score :: g m -> Int > score g > |hasWinner g = -(winscore g) > |otherwise = 0 > winscore :: g m -> Int > winscore _ = 1000000 > searchDepth :: g m -> Int > searchDepth g = 10 > ai :: g m -> AI (g m) > ai _ = alphaBeta > evalMoves :: g m -> [(m,Int)] > evalMoves g = parMap > (evalTuple2 r0 rdeepseq) > (\m-> (m, (ai g) (searchDepth g) (makeMove g m))) > (moves g) > bestMove :: g m -> m > bestMove g > = fst > $maximumBy (\(_,v1) (_,v2) ->if v1<v2 then LT else GT) > $evalMoves g > type AI a = Int -> a -> Int > data Tree a = Node a [Tree a] deriving Show > createGameTree g = > Node g [createGameTree (makeMove g m) |m <- moves g] > minimax depth g = -(minimax' depth $ createGameTree g) > where > minimax' _ (Node g []) = score g > minimax' 0 (Node g _) = score g > minimax' d (Node _ cs) > = maximum $ map (negate . (minimax' d)) $ cs > alphaBeta depth g > = -alphaBeta' depth (-ws) (ws) (createGameTree g) > where > ws = winscore g > > alphaBeta' 0 _ _ (Node g _) = score g > alphaBeta' _ _ _ (Node g []) = score g > alphaBeta' d alpha beta (Node _ cs) = falte (alpha,beta) crs > where > crs = map (\c-> -(alphaBeta' (d-1)(-beta)(-alpha) c)) cs > > falte ab@(alpha,beta) (wert:werte) > |wert >= beta = beta > |wert > alpha = falte (wert,beta) werte > |otherwise = falte ab werte > falte (alpha,_) [] = alpha > playUserMove a = > catch > (do > print a > putStrLn "Geben Sie jetzt Ihren Zug ein!" > putStrLn "Mögliche Züge:" > sequence $ map (putStrLn.show)$moves a > line <- getLine > let a1 = makeMove a $read line > print a1 > return a1 > ) > (\e-> do > print (e :: SomeException) > playUserMove a > ) > playAIMove a = do > putStrLn "Nun überlege ich meinen Zug.." > return$ makeMove a$ bestMove a > playGame a > |gameOver a = putStrLn "Das war ein Remis." > playGame a = do > a1 <- playUserMove a > if (hasWinner a1) then putStrLn "Gratulation! Sie haben gewonnen." > else if not$gameOver a1 > then do > a2 <- playAIMove a1 > if (hasWinner a2) > then do > print a2 > putStrLn "Dieses Spiel hat der Rechner gewonnen." > else playGame a2 > else playGame a1 > data TicTacToe a = TTT Player [Player] > instance Show (TicTacToe m) where > show (TTT npl board) = "" > newtype P = P(Int, Int) deriving (Show,Read,Eq) > instance Game TicTacToe P where > start = TTT One [] --ToDo > currentPlayer ttt = None --todo > moves ttt = [] --ToDo > makeMove ttt m = ttt --ToDo > hasWinner ttt = False > playTicTacToe = playGame (start :: TicTacToe P) > data Muehle m = Brett > { brett::[[Player]] > , zuSetzen1::Int > , zuSetzen2::Int > , current::Player > , aufFeld1::Int > , aufFeld2::Int > , nextMoves::[MuehleZug] > } > data MuehleZug = Setze (Int,Int) (Maybe (Int,Int)) > |Schiebe (Int,Int)(Int,Int) (Maybe (Int,Int)) > deriving (Show,Eq,Read) > instance Show (Muehle m) where > show (Brett{brett=brett, zuSetzen1=spieler1, zuSetzen2=spieler2}) = > replaceall replacements template > ++ take spieler1 (repeat 'X') ++ "\n" > ++ take spieler2 (repeat 'O') ++ "\n" > where > template > ="v----------a----------d\n"++ > "| | |\n"++ > "| w------b------e |\n"++ > "| | | | |\n"++ > "| | x--c--f | |\n"++ > "| | | | | |\n"++ > "s---t---u i---h---g\n"++ > "| | | | | |\n"++ > "| | r--o--l | |\n"++ > "| | | | |\n"++ > "| q------n------k |\n"++ > "| | |\n"++ > "p----------m----------j\n" > > replacements = map (\(c,pl)-> replace [c] (show pl)) > $zip ['a'..] (concat brett) > replaceall rplfs str = foldl (\b f -> f b) str rplfs > setxy (x,y) brett pl = brett & element x .~ (brett!!x & element y .~pl) > mkIndex brett = map (\(x,rs)-> map (\(y,p)->((x,y),p))$zip [0,1..] rs) > $zip [0,1..] brett > getNeighbours (x,y) br > |mod x 2==0 && y==1 > = [br !!mod (x+1)8!!y,br !!mod (x-1) 8!!y,br !!x!!0,br !!x!!2] > |mod x 2==0 > = [br !!mod (x+1)8!!y,br !!mod (x-1) 8!!y,br !!x!!1] > |otherwise > = [br !!mod (x+1)8!!y,br !!mod (x-1) 8!!y] > inMuehle (x,y) br > |p==None = False > |mod x 2==0 > = all ((==)r) rs > || br!!(mod (x-1) 8)!!y==p && br!!(mod (x+1) 8)!!y==p > |otherwise > = br!!(mod (x+1) 8)!!y==p && br!!(mod (x+2) 8)!!y==p > ||br!!(mod (x-1) 8)!!y==p && br!!(mod (x-2) 8)!!y==p > where > xs@(r:rs) = br!!x > p = xs!!y > nLets n [] = [] > nLets n xs = take n xs:nLets n (drop (n-1) xs) > everySnd [] = [] > everySnd [x] = [x] > everySnd (x:_:xs) = x:everySnd xs > muehlen br = (everySnd br) > ++ (concat$map ((nLets 3).(\xs->last xs:xs)) (transpose br)) > calcMoves b = b{nextMoves=muehleMoves b} > instance Game Muehle MuehleZug where > start = > calcMoves$Brett (take 8$repeat [None,None,None]) 9 9 One 0 0 [] > currentPlayer = current > moves g = nextMoves g > makeMove g@(Brett{brett=br,zuSetzen1=p1,zuSetzen2=p2,current=cpl}) > (Setze (x,y) rm) > = calcMoves$ > if cpl==One > then Brett nb (p1-1) p2 np > (1+aufFeld1 g) (maybe (aufFeld2 g)(\_->(aufFeld2 g)-1) rm) [] > else Brett nb p1 (p2-1) np > (maybe (aufFeld1 g)(\_->(aufFeld1 g)-1) rm) (1+aufFeld2 g) [] > where > gesetzt = setxy (x,y) br cpl > nb = maybe gesetzt (\xy -> (setxy xy gesetzt None)) rm > np = nextPlayer cpl > makeMove g@(Brett{brett=br,zuSetzen1=p1,zuSetzen2=p2,current=cpl}) > (Schiebe (x,y) (u,v) rm) > = calcMoves > $Brett nb 0 0 (nextPlayer cpl) > (if cpl==One > then (aufFeld1 g) > else (maybe (aufFeld1 g) (\_->(aufFeld1 g)-1)rm ) ) > (if cpl==Two > then (aufFeld2 g) > else (maybe (aufFeld2 g) (\_->(aufFeld2 g)-1)rm ) ) > [] > where > gesetzt = setxy (u,v) (setxy (x,y) br None) cpl > nb = maybe gesetzt (\xy -> (setxy xy gesetzt None)) rm > hasWinner g = null$moves g > score g@(Brett{brett=br,current=cu}) > |hasWinner g = -(winscore g) > |otherwise = 1000*currents-1000*others > + calcPairs cu - calcPairs (nextPlayer cu) > where > brc = concat br > mue = muehlen br > others = length$filter (== (nextPlayer cu)) brc > currents = length$filter (== cu) brc > pair p xs = (length$filter (==p) xs)==2 > && (length$filter (==None) xs)==1 > calcPairs p = 10*(length$filter (pair p) mue) > searchDepth Brett{zuSetzen1=0,zuSetzen2=0,aufFeld1=a1,aufFeld2=a2} > |a1<=4 && a2<=4 = 4 > |a1<=4 || a2<=4 = 4 > searchDepth Brett{zuSetzen1=p1,zuSetzen2=p2} > |p1+p2 < 6 = 6 > |p1+p2 < 4 = 8 > |p1+p2 < 2 = 10 > searchDepth _ = 4 > muehleMoves g@(Brett{brett=br,zuSetzen1=p1,zuSetzen2=p2,current=cpl}) > |p1==0&&3 > aufFeld1 g || p2==0&&3 > aufFeld2 g = [] > |p1+p2>0 = setzen > |3==if cpl == One then aufFeld1 g else aufFeld2 g = springen > |otherwise = schieben > where > indexed = mkIndex br > coindexed = concat indexed > myIndex = map (\(from,(to,_)) -> (from,to)) > $filter (\(_,(_,pl))-> pl==None) > $concat > $map (\(pos,_)->(map (\x->(pos,x))$ getNeighbours pos indexed)) > $filter (\(pos,p)->p==cpl) > $coindexed > schieben = concat$map (mkRvs.mkSchiebe) myIndex > mkSchiebe (from,to) = Schiebe from to Nothing > mkRvs s > |inMuehle to newBrett = [setRm (Just rm) s|(rm,_)<-removeables] > |otherwise = [s] > where > to = getTo s > > Brett{brett=newBrett,current=newCurrent} = makeMove g s > newIndexed = concat$mkIndex newBrett > removeables > = filter(\(pos,p)-> p==newCurrent > &&not (inMuehle pos newBrett)) newIndexed > getTo (Schiebe _ to _) = to > getTo (Setze to _) = to > setRm rm (Schiebe from to _) = Schiebe from to rm > setRm rm (Setze to _) = Setze to rm > springen = concat$map (mkRvs.mkSchiebe) mySprungIndex > > mySprungIndex = map (\(from,(to,_)) -> (from,to)) > $concat > $map > (\(pos,_)-> > (map (\x->(pos,x))$filter (\(_,pl)->pl==None)coindexed)) > $filter (\(pos,p)->p==cpl) > $coindexed > setzen = concat$map (mkRvs.(\pos->Setze pos Nothing)) > $map fst$filter (\(_,p)->p==None)$concat$indexed >
lhs
You are not logged in and therefore you cannot submit a solution.