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/.
11 module EditGameState
(modTile
, mergeTiles
) where
13 import Control
.Applicative
14 import Data
.Function
(on
)
15 import qualified Data
.Map
as Map
26 modTile
:: Maybe Tile
-> HexPos
-> HexPos
-> Bool -> GameState
-> GameState
27 modTile tile pos lastPos painting st
=
28 let board
= stateBoard st
29 curOwnedTile
= Map
.lookup pos board
30 (st
',mowner
) = case curOwnedTile
of
31 Nothing
-> (st
,Nothing
)
32 Just
(owner
,SpringTile _ _
) -> (delConnectionsIn pos st
, Just owner
)
33 Just
(owner
,_
) -> delPiecePos owner pos st
-- XXX may invalidate board's indices to st
34 board
' = stateBoard st
'
35 addPiece p
= addpp
$ PlacedPiece pos p
37 (o
,_
) <- Map
.lookup lastPos board
42 (_,t') <- curOwnedTile
43 guard $ ((==) `on` tileType) t t'
46 lastElem os
= isJust $ do
47 lastOwner
<- lastMOwner
48 guard $ lastOwner `
elem` os
49 lastWasDiff
= isNothing $ do
50 lastOwner
<- lastMOwner
52 guard $ owner
== lastOwner
53 lastOK
= painting || lastWasDiff
54 validSpringRootTile ot
= case snd ot
of
58 -- |Find next adjacent, skipping over current entity.
59 nextOfAdjacents adjs loop
= listToMaybe $ fromMaybe adjs
$ do
61 i
<- elemIndex owner adjs
62 return $ (dropWhile (== owner
) $ drop i adjs
) ++
63 if loop
&& i
> 0 then adjs
else []
65 Just o | protectedPiece o
-> st
67 -- _ | same && (pos /= lastPos) -> id
69 let adjacentBlocks
= nub [ idx |
71 , Just
(idx
, BlockTile _
) <- [Map
.lookup (dir
+^ pos
) board
']
72 , not $ protectedPiece idx
]
73 addToIdx
= if lastOK
&& lastElem adjacentBlocks
75 else nextOfAdjacents adjacentBlocks
False
77 Nothing
-> addPiece
$ Block
[zero
]
78 Just b
-> addBlockPos b pos
79 Just
(ArmTile armdir _
) ->
80 let adjacentPivots
= [ idx |
81 dir
<- if armdir
== zero
then hexDirs
else [armdir
, neg armdir
]
82 , Just
(idx
, PivotTile _
) <- [Map
.lookup (dir
+^ pos
) board
'] ]
83 addToIdx
= if lastOK
&& lastElem adjacentPivots
85 else nextOfAdjacents adjacentPivots
True
88 Just p
-> addPivotArm p pos
89 Just
(SpringTile _ _
) ->
90 let possibleSprings
= [ Connection root end
$ Spring sdir natLen |
92 , let epos
= sdir
+^ pos
93 , Just
(eidx
, BlockTile _
) <- [Map
.lookup epos board
']
94 , not $ protectedPiece eidx
95 , (ridx
, rpos
) <- maybeToList $ castRay
(neg sdir
+^ pos
) (neg sdir
) board
'
96 , Just
True == (validSpringRootTile `
liftM` Map
.lookup rpos board
')
97 , let natLen
= hexLen
(rpos
-^ epos
) - 1
101 conn@(Connection _ _ (Spring sdir' _)) <-
102 springsAtIdx st' eidx ++ springsEndAtIdx st' ridx
103 , not $ sdir' `elem` [sdir,neg sdir] ]
105 , not $ connGraphPathExists st
' eidx ridx
106 , let end
= (eidx
, epos
-^
(placedPos
$ getpp st
' eidx
))
107 , let root
= (ridx
, rpos
-^
(placedPos
$ getpp st
' ridx
))
109 nextSpring
= listToMaybe $ fromMaybe possibleSprings
$ do
110 (_
,SpringTile _ _
) <- curOwnedTile
-- XXX: therefore the indices of st are still valid
111 i
<- findIndex (`
elem` connections st
) possibleSprings
112 return $ drop (i
+1) possibleSprings
113 in case nextSpring
of
115 Just conn
-> addConn conn
116 Just
(PivotTile _
) -> addPiece
$ Pivot
[]
117 Just
(WrenchTile _
) -> addPiece
$ Wrench zero
118 Just HookTile
-> let arm
= listToMaybe [ dir |
120 , isNothing $ Map
.lookup (dir
+^ pos
) board
' ]
121 in case arm
of Just armdir
-> addPiece
$ Hook armdir NullHF
123 Just
(BallTile
) -> addPiece Ball
127 -- | merge tile/piece with a neighbouring piece. If we merge a piece with
128 -- connections, the connections are deleted: otherwise we'd need some fiddly
129 -- conditions to ensure connection graph acyclicity.
130 mergeTiles
:: HexPos
-> HexDir
-> Bool -> GameState
-> GameState
131 mergeTiles pos dir mergePiece st
= fromMaybe st
$ do
132 let board
= stateBoard st
133 (idx
,tile
) <- Map
.lookup pos board
134 (idx
',tile
') <- Map
.lookup (dir
+^pos
) board
136 guard $ all (not . protectedPiece
) [idx
,idx
']
139 BlockTile _
<- Just tile
'
140 let st
' = if mergePiece
142 else fst $ delPiecePos idx pos st
143 (idx
'',_
) <- Map
.lookup (dir
+^pos
) $ stateBoard st
'
144 return $ if mergePiece
145 then foldr (addBlockPos idx
'') st
'
146 $ plPieceFootprint
$ getpp st idx
147 else addBlockPos idx
'' pos st
'
149 PivotTile _
<- Just tile
'
150 let st
' = fst $ delPiecePos idx pos st
151 (idx
'',_
) <- Map
.lookup (dir
+^pos
) $ stateBoard st
'
152 return $ addPivotArm idx
'' pos st
'