module Game.ZeilenSpalten.HTML (
komplett,
erzeuge,
main,
) where
import Game.ZeilenSpalten hiding (spiel)
import qualified Game.Tree as GameTree
import Game.Utility (readMaybe, nullToMaybe, )
import Text.Html((<<), (+++), concatHtml, toHtml)
import qualified Text.Html as Html
import qualified Network.CGI as CGI
import qualified Data.List as List
import Data.Array ((!), bounds, )
import Data.Maybe (maybeToList, isNothing, )
import Control.Monad (guard, )
import System.Random (randomIO, )
spielerFarbe :: Spieler -> String
spielerFarbe Zeile = Html.blue
spielerFarbe Spalte = Html.red
labelAnchor :: String -> Html.Html -> Html.Html
labelAnchor ref label =
Html.anchor label Html.! [Html.href ref]
type Beschreibung = ((Koordinate,Koordinate), Int, Spieler, Bool, [Zug])
spielstand :: Beschreibung -> Spielstand -> Html.Html
spielstand (groesse, saat, beginner, _, zuege) s =
let z = zahlenfeld s
y = spielfeld s
(ps,pz) = punkte s
aktiv = koordinate s
((i0,j0),(i1,j1)) = bounds z
aktivesFeld (i,j) = variableKoordinate (j,i) == aktiv
variableKoordinate (i,j) =
case amZug s of
Spalte -> j
Zeile -> i
anc ij =
labelAnchor ("ZeilenSpalten?" ++
erzeugeAnfrage
(groesse, saat, beginner, True,
zuege ++ [variableKoordinate ij]))
farbe grund ij =
maybe grund spielerFarbe (y!ij)
feld =
Html.table
(concatHtml $ map (\j -> Html.tr
(concatHtml $ map (\i ->
let ij = (i,j)
af = aktivesFeld ij
fb = if af then Html.yellow else Html.white
canc = if af && isNothing (y!ij) then anc ij else id
zahl = toHtml (show (z!ij))
in Html.td (canc zahl)
Html.! [Html.bgcolor (farbe fb ij)])
[i0..i1]))
[j0..j1])
Html.! [Html.border 2]
in Html.center
(Html.simpleTable [] []
[[toHtml ("Spalter: " ++ show ps),
feld,
toHtml ("Zeiler: " ++ show pz)]])
_spiel :: String -> Html.Html
_spiel s =
let (groesse, saat, beginner, macheGegenzug, zuege) = read s
(_,computerZug) = berechneSpielstandUndZug groesse saat beginner zuege
zuegeMitComputer = zuege ++ maybeToList computerZug
(stand,_) =
berechneSpielstandUndZug groesse saat beginner zuegeMitComputer
in Html.center (spielstand
(groesse, saat, beginner, macheGegenzug, zuegeMitComputer) stand)
spiel :: String -> Html.Html
spiel s =
case interpretiereAnfrage s of
Just (groesse, saat, beginner, macheGegenzug, zuege) ->
let spielbaum =
GameTree.build moeglicheZuege
(grundstellung groesse saat beginner)
spielaktuell =
GameTree.selectDeepSubTree zuege spielbaum
optZug = optimalerZug spielaktuell
(spielunterbaum,zuegeMitComputer) =
maybe
(spielaktuell, zuege)
(\zug -> (GameTree.selectSubTree zug spielaktuell, zuege++[zug]))
(guard macheGegenzug >> optZug)
stand = GameTree.state spielunterbaum
in spielstand
(groesse, saat, beginner, macheGegenzug, zuegeMitComputer) stand
Nothing ->
toHtml $ "Mit dem Spielstand " ++ show s ++ " kann ich nichts anfangen."
start :: Int -> Html.Html
start saat =
toHtml "Es beginnt" +++
Html.simpleTable [] []
(map (\orient ->
map (\(gegenzug,spieler) ->
labelAnchor
("ZeilenSpalten?"++
erzeugeAnfrage ((10,10),saat,orient,gegenzug,[]))
<< ("der "++spieler++" auf einer "++show orient++"."))
[(False,"Mensch"),(True,"Computer")])
[Spalte,Zeile]) Html.! [Html.border 2]
komplett :: Html.Html -> Html.Html
komplett body =
Html.header (Html.thetitle << "Zeilen und Spalten") +++
Html.body body +++
Html.br +++ labelAnchor "ZeilenSpalten" << "Nochmal von vorne!"
erzeuge :: Maybe String -> IO Html.Html
erzeuge =
maybe (fmap start randomIO) (return . spiel)
erzeugeAnfrage :: Beschreibung -> String
erzeugeAnfrage ((breite,hoehe),saat,orient,gegenzug,zuege) =
CGI.formEncode $
("breite", show breite) :
("hoehe", show hoehe) :
("saat", show saat) :
("orient", show orient) :
("gegenzug", show gegenzug) :
(if null zuege then [] else [("zuege", unwords $ map show zuege)]) ++
[]
interpretiereAnfrage :: String -> Maybe Beschreibung
interpretiereAnfrage anfrage =
let paare = CGI.formDecode anfrage
in do breite <- readMaybe =<< List.lookup "breite" paare
hoehe <- readMaybe =<< List.lookup "hoehe" paare
saat <- readMaybe =<< List.lookup "saat" paare
orient <- readMaybe =<< List.lookup "orient" paare
gegenzug <- readMaybe =<< List.lookup "gegenzug" paare
zuege <-
case List.lookup "zuege" paare of
Nothing -> Just []
Just zuegeText ->
mapM (\zugText ->
case zugText of
_:_:_:_ -> Nothing
_ -> readMaybe zugText) $
words zuegeText
return ((breite,hoehe), saat, orient, gegenzug, zuege)
main :: IO ()
main =
putStr . Html.renderHtml . komplett =<< erzeuge . nullToMaybe =<< getLine