-- updates the floor sets and increments the floor number
-- is represents the item set of items that will move
-- warning: it doesn't check if the move is valid by any means
moveUp :: State -> ItemSet -> State
moveUp (State f v) is = let
        -- shift for the current floor
        shift1 = f * stateFloorSize
        -- shift for the upper floor
        shift2 = shift1 + stateFloorSize
    in
        State (f + 1) (v `xor` (is `unsafeShiftL` shift1) `xor` (is `unsafeShiftL` shift2))
moveUp :: State -> ItemSet -> State
moveUp (State f v) is = let
        -- shift for the current floor
        shift1 = f * stateFloorSize
        -- shift for the upper floor
        shift2 = shift1 + stateFloorSize
    in
        State (f + 1) (v `xor` (is `unsafeShiftL` shift1) `xor` (is `unsafeShiftL` shift2))
moveUp (State f v) is = let
        -- shift for the current floor
        shift1 = f * stateFloorSize
        -- shift for the upper floor
        shift2 = shift1 + stateFloorSize
    in
        State (f + 1) (v `xor` (is `unsafeShiftL` shift1) `xor` (is `unsafeShiftL` shift2))