-
Notifications
You must be signed in to change notification settings - Fork 1
/
Main.hs
128 lines (114 loc) · 3.79 KB
/
Main.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
import Control.Monad.Random (Rand, getRandom, getRandomR, runRand)
import Control.Monad.State (State, get, put, runState)
import Data.Map (Map, (!), fromList, insert, mapWithKey, toList)
import System.Random
import Miso (width_, height_, div_, style_, button_, text, startApp, defaultEvents, noEff, Effect, App(..), View)
import Miso.String (MisoString, ms, pack)
import Miso.Svg hiding (height_, style_, width_)
import Board
import Flag
import Mine
import Msg
import Pos
import RightClick
import Smiley
type Game = (Board, Int)
cellSize :: Int
cellSize = 20
getColor :: Cell -> String
getColor (Cell _ exposed _ _) =
if exposed
then "#909090"
else "#CCCCCC"
showSquare :: Pos -> Cell -> View Msg
showSquare (xCoord, yCoord) cell =
rect_
[ x_ "0.05"
, y_ "0.05"
, width_ "0.9"
, height_ "0.9"
, style_ $ fromList [("fill", ms $ getColor cell)]
, onClick (LeftPick (xCoord, yCoord))
, onRightClick (RightPick (xCoord, yCoord))
]
[]
showText :: Pos -> Int -> [View Msg]
showText pos count =
let textColor =
case count of
1 -> "blue"
2 -> "green"
3 -> "red"
4 -> "brown"
_ -> "purple"
in [ text_
[ x_ "0.5"
, y_ "0.87"
, fontSize_ "1.0"
, fill_ textColor
, textAnchor_ "middle"
, onClick (LeftPick pos)
, onRightClick (RightPick pos)
]
[text $ ms $ show count]
]
showCellDetail :: Pos -> Cell -> [View Msg]
showCellDetail pos (Cell mined exposed flagged mineCount) =
case ( flagged, mined, exposed, 0 /= mineCount) of
( True, _, _, _) -> showFlag pos
( _, True, True, _) -> showMine pos
( _, _, True, True) -> showText pos mineCount
( _, _, _, _) -> []
showCell :: Pos -> Cell -> View Msg
showCell pos cell =
let (x, y) = pos
scale = show cellSize
in g_ [ transform_
(ms $ "scale (" ++ scale ++ ", " ++ scale ++ ") "
++ "translate (" ++ show x ++ ", " ++ show y ++ ") ")
]
(showSquare pos cell : showCellDetail pos cell)
centerStyle :: Map MisoString MisoString
centerStyle =
fromList [("width", "75%"), ("margin", "0 auto"), ("text-align", "center")]
viewGame :: Game -> View Msg
viewGame (board, _) =
div_
[]
[ div_ [style_ centerStyle] (showFace (gameOver board))
, div_ [style_ centerStyle] [text "Implemented using Miso"]
, div_
[style_ centerStyle]
[ svg_
[ version_ "1.1"
, width_ (ms $ show (w * cellSize))
, height_ (ms $ show (h * cellSize))
]
(map snd (toList (mapWithKey showCell board)))
]
, div_ [style_ centerStyle] [button_ [onClick Reset] [text "reset"]]
]
updateGame :: Msg -> Game -> Effect Msg Game
updateGame msg (board, seed) =
case msg of
Reset ->
let g0 = mkStdGen seed
(newBoard, g1) = runRand mkBoard g0
(newSeed, _) = runRand getRandom g1
in noEff (newBoard, newSeed)
_ ->
let (_, newBoard) = runState (updateBoard msg) board
in noEff (newBoard, seed)
main :: IO ()
main = do
seed <- getStdRandom random
let initialAction = Reset
model = (mempty, seed)
update = updateGame
view = viewGame
events = Data.Map.insert "contextmenu" False defaultEvents
subs = []
mountPoint = Nothing
startApp App {..}