Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Removed the constOffset function for lookup tables.

This was a hangover from C-like data structures and requirements for
positive index values. Might as well use Haskell's support for arbitrary
array bounds directly; it simplifies the API in quite a few places.
  • Loading branch information...
commit 3fcfd821c0d13428a81a37ee286e0eeeac0e8fde 1 parent 1d1a361
@malcolmt authored
View
14 src/ChessTools/Board.hs
@@ -80,7 +80,7 @@ boardArraySize s@(BoardSize _ v vBuf) = rowLength s * (v + 2 * vBuf)
-- | Return the 'LookupTable' value for a pair of indexes. The first index is
-- the \"/from/\" location, the second is the \"/to/\" location.
fetch :: LookupTable -> Int -> Int -> Int
-fetch (LookupTable off arr) s1 s2 = arr ! (off + s1 - s2)
+fetch (LookupTable arr) s1 s2 = arr ! (s1 - s2)
-- | Returns a list of representative 'Square' pairs that cover all the lookup
-- table index values. On a square board, there are @(2x-1)^2@ possible index
@@ -108,19 +108,19 @@ repIndexList s@(BoardSize h v _) = CL $ map head $ groupBy compFirst $ sort l
-- algorithmic complexity description).
-- | File separation between two squares.
-fileTable :: BoardSize -> CoveringIndexList -> LookupTable
-fileTable b cl = distanceTableWith f b cl
+fileTable :: CoveringIndexList -> LookupTable
+fileTable cl = distanceTableWith f cl
where f (Square s1) (Square s2) = abs (fst s1 - fst s2)
-- | Rank separation between two squares.
-rankTable :: BoardSize -> CoveringIndexList -> LookupTable
-rankTable b cl = distanceTableWith f b cl
+rankTable :: CoveringIndexList -> LookupTable
+rankTable cl = distanceTableWith f cl
where f (Square s1) (Square s2) = abs (snd s1 - snd s2)
-- | Square diagonal distance between two squares (this is using the chessboard
-- metric, not the Euclidean one).
-squareTable :: BoardSize -> CoveringIndexList -> LookupTable
-squareTable b cl = distanceTableWith f b cl
+squareTable :: CoveringIndexList -> LookupTable
+squareTable cl = distanceTableWith f cl
where f (Square s1) (Square s2) =
max (abs (fst s1 - fst s2)) (abs (snd s1 - snd s2))
View
29 src/ChessTools/Board/Internal.hs
@@ -53,11 +53,15 @@ instance Ord Square where
-- on two squares on the board. These could be distances between the squares in
-- some form (file or rank separation) or whether some kind of piece can move
-- between those two squares (using 0 values for invalid moves).
-data LookupTable = LookupTable Int (Array Int Int)
+data LookupTable = LookupTable (Array Int Int)
-- | Used to hold a representative set of squares when computing 'LookupTable'
-- results. Create one with 'repIndexList' and use it in all lookup table
-- creation functions.
+--
+-- For internal code using this, the main invariant to note is that the offset
+-- component (the first 'Int') is in sorted order. This is used by, for
+-- example, the 'lookupBounds' function.
newtype CoveringIndexList = CL [(Int, (Square, Square))]
-- | Convert a 'Square' to an index into a board array. The index is the same
@@ -87,23 +91,18 @@ rowLength s = 2 * boardHorizSize s - 1
leftBuf :: BoardSize -> Int
leftBuf s = boardHorizSize s `div` 2
--- | Given two square indices, @sq1@ and @sq2@, the value
--- @(constOffset + sq1 - sq2)@ is always inside a lookup table's bounds.
-constOffset :: BoardSize -> Int
-constOffset s = ur - ll
- where BoardSize h v _ = s
- ur = squareToIndex s $ Square (h - 1, v - 1)
- ll = squareToIndex s $ Square (0, 0)
-
+-- | Returns a pair that can be used to specify the bounds for a
+-- 'Data.Array.Array'.
+lookupBounds :: CoveringIndexList -> (Int, Int)
+lookupBounds (CL cs) = (fst $ head cs, fst $ last cs)
-- | Utility function for computing the file, rank and square distance tables.
-- In each case, the computations are almost identical, differing only by the
-- type of calculation performed on the two squares. That calculation function
-- is passed in as the first argument to 'distanceTableWith'.
-distanceTableWith :: (Square -> Square -> Int) -> BoardSize ->
- CoveringIndexList -> LookupTable
-distanceTableWith cmp b (CL cs) =
- LookupTable offset (array (0, 2 * offset) $ map f cs)
- where offset = constOffset b
- f (d, (sq1, sq2)) = (offset + d, cmp sq1 sq2)
+distanceTableWith :: (Square -> Square -> Int) -> CoveringIndexList ->
+ LookupTable
+distanceTableWith cmp cl@(CL cs) =
+ LookupTable (array (lookupBounds cl) $ map f cs)
+ where f (d, (sq1, sq2)) = (d, cmp sq1 sq2)
View
1  test/Suite.hs
@@ -22,7 +22,6 @@ tests = [
testProperty "array size" prop_board_array_size
],
testGroup "Lookup arrays" [
- testProperty "valid lookup indices" prop_lookup_index_is_positive,
testProperty "repIndexList represents"
prop_repIndexList_is_representative,
testProperty "file lookup 1" prop_check_file_distance_1,
View
25 test/TestBoard.hs
@@ -85,21 +85,14 @@ prop_board_array_size bs = boardArraySize bs == expected
where BoardSize h v vbuf = bs
expected = h * v + v * (h - 1) + 2 * vbuf * (2 * h - 1)
--- For any two squares s1 and s2, the value of constOffset + s1 - s2 should be
--- between 0 and the lookup array maximum size.
-prop_lookup_index_is_positive = forAll boardAndTwoSquareGen $ \(b, s1, s2) ->
- let idx1 = squareToIndex b s1
- idx2 = squareToIndex b s2
- offset = constOffset b + idx1 - idx2
- in offset >= 0 && offset < 2 * offset + 1
-
-- The list returned from repIndexList should actually be representative. That
-- is, it should contain as many values as the size of the lookup array and all
-- of the distance values in it should be unique.
prop_repIndexList_is_representative = forAll smallBoardGen $ \bs ->
- let CL xs = repIndexList bs
- in length xs == 2 * constOffset bs + 1 &&
+ let cl@(CL xs) = repIndexList bs
+ (l, u) = lookupBounds cl
+ in length xs == u - l + 1 &&
(length . group . sort $ map fst xs) == length xs
@@ -112,12 +105,12 @@ board1 = BoardSize 8 8 2
board2 = BoardSize 8 9 2
repList1 = repIndexList board1
repList2 = repIndexList board2
-fTable1 = fileTable board1 repList1
-fTable2 = fileTable board2 repList2
-rTable1 = rankTable board1 repList1
-rTable2 = rankTable board2 repList2
-sTable1 = squareTable board1 repList1
-sTable2 = squareTable board2 repList2
+fTable1 = fileTable repList1
+fTable2 = fileTable repList2
+rTable1 = rankTable repList1
+rTable2 = rankTable repList2
+sTable1 = squareTable repList1
+sTable2 = squareTable repList2
fileCheckFunc (Square s1) (Square s2) = abs $ fst s1 - fst s2
rankCheckFunc (Square s1) (Square s2) = abs $ snd s1 - snd s2
Please sign in to comment.
Something went wrong with that request. Please try again.