1 -- This file is part of Intricacy
2 -- Copyright (C) 2013 Martin Bays <mbays@sdf.org>
4 -- This program is free software: you can redistribute it and/or modify
5 -- it under the terms of version 3 of the GNU General Public License as
6 -- published by the Free Software Foundation, or any later version.
8 -- You should have received a copy of the GNU General Public License
9 -- along with this program. If not, see http://www.gnu.org/licenses/.
12 import Control
.Monad
.Writer
14 import qualified Data
.Map
as Map
23 type Lock
= (Frame
, GameState
)
24 liftLock
:: (GameState
-> GameState
) -> (Lock
-> Lock
)
25 liftLock g
(f
,st
) = (f
,g st
)
27 lockSize
(f
,_
) = frameSize f
29 baseLock
:: Int -> Lock
31 let frame
= BasicFrame size
32 in (frame
, baseState frame
)
34 deframe
:: Lock
-> Lock
35 deframe
= delTools
. liftLock
(setpp
0 nullpp
)
36 nullpp
= PlacedPiece
(PHS zero
) (Block
[])
38 reframe
:: Lock
-> Lock
39 reframe l
@(f
, st
) = addTools
$ delTools
$ liftLock
(setpp
0 (framePiece f
)) l
41 validLock
:: Lock
-> Bool
42 validLock lock
@(f
,st
) = and
43 [ st
== stepPhysics st
44 , lock
== reframe lock
48 type Solution
= [PlayerMove
]
50 checkSolution
:: Lock
-> Solution
-> Bool
51 checkSolution lock pms
=
52 let (frame
,st
) = reframe lock
53 tick
:: GameState
-> PlayerMove
-> GameState
54 tick st pm
= fst . runWriter
$ physicsTick pm st
55 in any (\st
' -> checkSolved
(frame
,st
')) $ scanl tick st pms
57 checkSolved
:: Lock
-> Bool
59 and [ isNothing $ Map
.lookup p
(stateBoard st
) | p
<- boltArea f
]
62 canonify
:: Lock
-> Lock
63 canonify
= addTools
. stabilise
. delTools
. delOOB
64 delTools
:: Lock
-> Lock
65 delTools
= liftLock delTools
' where
66 delTools
' :: GameState
-> GameState
68 fromMaybe st
$ listToMaybe
69 [ delTools
' $ delPiece idx st
70 |
(idx
,pp
) <- enumVec
$ placedPieces st
71 , isTool
$ placedPiece pp
]
72 addTools
:: Lock
-> Lock
74 let st
' = clearToolArea f st
75 in (f
, foldr addpp st
' $ initTools f
)
77 -- |An important property of the game physics is that any state stabilises in
78 -- finite time. Proof: in any spontaneous state change some spring gets closer
79 -- to being of natural length, and none get further from it.
80 stabilise
:: Lock
-> Lock
81 stabilise
= liftLock stabilise
' where
82 stabilise
' :: GameState
-> GameState
84 let st
' = stepPhysics st
85 in if st
== st
' then st
else stabilise
' st
'
87 delOOB
:: Lock
-> Lock
89 fromMaybe l
$ listToMaybe
90 [ delOOB
$ liftLock
(delPiece idx
) l
91 |
(idx
,_
) <- enumVec
$ placedPieces st
93 , all (not.inBounds f
) $ fullFootprint st idx
94 , null $ springsEndAtIdx st idx
]