matchProp tt tg              = case tt of
    MentsuJantou       -> isPair tg
    MentsuOrJantou     -> True

    MentsuShuntsu      -> case tg of
        GroupComplete mentsu -> isShuntsu mentsu
        _                    -> False

    MentsuKoutsu       -> case tg of
        GroupComplete mentsu -> isKoutsu mentsu
        _                    -> False

    MentsuKantsu       -> case tg of
        GroupComplete mentsu -> isKantsu mentsu
        _                    -> False

    MentsuKoutsuKantsu -> case tg of
        GroupComplete mentsu -> isKantsu mentsu || isKoutsu mentsu
        _                    -> False

    TileTerminal        -> any T.terminal tiles
    TileSameAs tile     -> headEx tiles == tile
    TileContained tile  -> tile `elem` tiles
    TileSuited          -> T.isSuited (headEx tiles)
    TileSameSuit tile   -> T.suitedSame tile (headEx tiles)
    TileSameNumber tile -> isJust (T.tileNumber tile) && T.tileNumber tile == T.tileNumber (headEx tiles)
    TileNumber n        -> T.tileNumber (headEx tiles) == Just n
    TileHonor           -> not $ T.isSuited (headEx tiles)
    TileSangenpai       -> T.sangenpai (headEx tiles)
    TileKazehai         -> T.kazehai (headEx tiles)
    TileAnd x y         -> matchProp x tg && matchProp y tg
    TileOr x y          -> matchProp x tg || matchProp y tg
    TileNot x           -> not $ matchProp x tg
    TileConcealed       -> case tg of
        GroupComplete mentsu -> isNothing $ mentsuShout mentsu
        _                    -> True
    PropAny             -> True
  where
    tiles = tileGroupTiles tg
matchProp tt tg              = case tt of
    MentsuJantou       -> isPair tg
    MentsuOrJantou     -> True

    MentsuShuntsu      -> case tg of
        GroupComplete mentsu -> isShuntsu mentsu
        _                    -> False

    MentsuKoutsu       -> case tg of
        GroupComplete mentsu -> isKoutsu mentsu
        _                    -> False

    MentsuKantsu       -> case tg of
        GroupComplete mentsu -> isKantsu mentsu
        _                    -> False

    MentsuKoutsuKantsu -> case tg of
        GroupComplete mentsu -> isKantsu mentsu || isKoutsu mentsu
        _                    -> False

    TileTerminal        -> any T.terminal tiles
    TileSameAs tile     -> headEx tiles == tile
    TileContained tile  -> tile `elem` tiles
    TileSuited          -> T.isSuited (headEx tiles)
    TileSameSuit tile   -> T.suitedSame tile (headEx tiles)
    TileSameNumber tile -> isJust (T.tileNumber tile) && T.tileNumber tile == T.tileNumber (headEx tiles)
    TileNumber n        -> T.tileNumber (headEx tiles) == Just n
    TileHonor           -> not $ T.isSuited (headEx tiles)
    TileSangenpai       -> T.sangenpai (headEx tiles)
    TileKazehai         -> T.kazehai (headEx tiles)
    TileAnd x y         -> matchProp x tg && matchProp y tg
    TileOr x y          -> matchProp x tg || matchProp y tg
    TileNot x           -> not $ matchProp x tg
    TileConcealed       -> case tg of
        GroupComplete mentsu -> isNothing $ mentsuShout mentsu
        _                    -> True
    PropAny             -> True
  where
    tiles = tileGroupTiles tg
matchProp tt tg              = case tt of
    MentsuJantou       -> isPair tg
    MentsuOrJantou     -> True

    MentsuShuntsu      -> case tg of
        GroupComplete mentsu -> isShuntsu mentsu
        _                    -> False

    MentsuKoutsu       -> case tg of
        GroupComplete mentsu -> isKoutsu mentsu
        _                    -> False

    MentsuKantsu       -> case tg of
        GroupComplete mentsu -> isKantsu mentsu
        _                    -> False

    MentsuKoutsuKantsu -> case tg of
        GroupComplete mentsu -> isKantsu mentsu || isKoutsu mentsu
        _                    -> False

    TileTerminal        -> any T.terminal tiles
    TileSameAs tile     -> headEx tiles == tile
    TileContained tile  -> tile `elem` tiles
    TileSuited          -> T.isSuited (headEx tiles)
    TileSameSuit tile   -> T.suitedSame tile (headEx tiles)
    TileSameNumber tile -> isJust (T.tileNumber tile) && T.tileNumber tile == T.tileNumber (headEx tiles)
    TileNumber n        -> T.tileNumber (headEx tiles) == Just n
    TileHonor           -> not $ T.isSuited (headEx tiles)
    TileSangenpai       -> T.sangenpai (headEx tiles)
    TileKazehai         -> T.kazehai (headEx tiles)
    TileAnd x y         -> matchProp x tg && matchProp y tg
    TileOr x y          -> matchProp x tg || matchProp y tg
    TileNot x           -> not $ matchProp x tg
    TileConcealed       -> case tg of
        GroupComplete mentsu -> isNothing $ mentsuShout mentsu
        _                    -> True
    PropAny             -> True
  where
    tiles = tileGroupTiles tg