module Game.LambdaHack.Common.Point
( Point, toPoint, showPoint
, origin, chessDist, adjacent, vicinity, vicinityCardinal
, inside, displacementXYZ, bla
) where
import Data.Binary
import qualified Data.Ix as Ix
import qualified Data.List as L
import Data.Text (Text)
import qualified System.Random as R
import Game.LambdaHack.Common.Msg
import Game.LambdaHack.Common.PointXY
import Game.LambdaHack.Common.VectorXY
import Control.Exception.Assert.Sugar
newtype Point = Point Int
deriving (Eq, Ord, Ix.Ix, Enum, R.Random)
instance Binary Point where
put (Point n) = put n
get = fmap Point get
instance Show Point where
show (Point n) = show n
showPoint :: X -> Point -> Text
showPoint lxsize = showT . fromPoint lxsize
toPoint :: X -> PointXY -> Point
toPoint lxsize (PointXY (x, y)) =
assert (lxsize > x && x >= 0 && y >= 0 `blame` "invalid point coordinates"
`twith` (lxsize, x, y))
$ Point $ x + y * lxsize
fromPoint :: X -> Point -> PointXY
fromPoint lxsize (Point p) =
assert (p >= 0 `blame` "negative point value" `twith` (lxsize, p))
$ PointXY (p `rem` lxsize, p `quot` lxsize)
origin :: Point
origin = Point 0
chessDist :: X -> Point -> Point -> Int
chessDist lxsize pos0 pos1
| PointXY (x0, y0) <- fromPoint lxsize pos0
, PointXY (x1, y1) <- fromPoint lxsize pos1 =
chessDistXY $ VectorXY (x1 x0, y1 y0)
adjacent :: X -> Point -> Point -> Bool
adjacent lxsize s t = chessDist lxsize s t == 1
vicinity :: X -> Y -> Point -> [Point]
vicinity lxsize lysize p =
map (toPoint lxsize) $
vicinityXY (0, 0, lxsize 1, lysize 1) $
fromPoint lxsize p
vicinityCardinal :: X -> Y -> Point -> [Point]
vicinityCardinal lxsize lysize p =
map (toPoint lxsize) $
vicinityCardinalXY (0, 0, lxsize 1, lysize 1) $
fromPoint lxsize p
inside :: X -> Point -> (X, Y, X, Y) -> Bool
inside lxsize p = insideXY $ fromPoint lxsize p
displacementXYZ :: X -> Point -> Point -> VectorXY
displacementXYZ lxsize pos0 pos1
| PointXY (x0, y0) <- fromPoint lxsize pos0
, PointXY (x1, y1) <- fromPoint lxsize pos1 =
VectorXY (x1 x0, y1 y0)
bla :: X -> Y -> Int -> Point -> Point -> Maybe [Point]
bla _ _ _ source target | source == target = Nothing
bla lxsize lysize eps source target = Just $
let s = fromPoint lxsize source
e = fromPoint lxsize target
inBounds p@(PointXY (x, y)) =
lxsize > x && x >= 0 && lysize > y && y >= 0 && p /= s
in L.map (toPoint lxsize) $ L.takeWhile inBounds $ L.tail $ blaXY eps s e