diff --git a/DESCRIPTION b/DESCRIPTION
index d661fa7..976aa75 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,6 +1,6 @@
 Package: wallis
 Title: Room squares in R
-Version: 0.0.0.9004
+Version: 0.0.0.9005
 Authors@R: 
     person("Matthew", "Henderson", , "matthew.james.henderson@gmail.com", role = c("aut", "cre"),
            comment = c(ORCID = "0000-0001-7949-8208"))
diff --git a/NAMESPACE b/NAMESPACE
index 7965d7e..5160ef5 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -2,6 +2,9 @@
 
 export(empty_cells)
 export(empty_room)
+export(is_maximal_proom)
+export(is_partial_room)
+export(is_room)
 export(n_filled_cells)
 export(plot_room_square)
 export(unused_pairs)
diff --git a/R/avail.R b/R/avail.R
new file mode 100644
index 0000000..89543a6
--- /dev/null
+++ b/R/avail.R
@@ -0,0 +1,11 @@
+#' Is pair p available in R at cell e?
+#'
+#' @param R A partial Room square.
+#' @param p A pair.
+#' @param e An empty cell of R.
+#'
+#' @return True if and only if the pair p can be placed in cell e in R.
+avail <- function(R, p, e) {
+  available <- R[R$row == e[1] & R$col == e[2], "avail"]$avail[[1]]
+  p[1] %in% available && p[2] %in% available
+}
diff --git a/R/distinct-pairs.R b/R/distinct-pairs.R
new file mode 100644
index 0000000..b61ace0
--- /dev/null
+++ b/R/distinct-pairs.R
@@ -0,0 +1,12 @@
+#' Pairs used in R
+#'
+#' @param R A Room square.
+#'
+#' @return A list of the distinct pairs that appear in R.
+distinct_pairs <- function(R) {
+  R |>
+    tidyr::pivot_wider() |>
+    dplyr::filter(!is.na(first)) |>
+    dplyr::filter(!is.na(second)) |>
+    dplyr::distinct(first, second)
+}
\ No newline at end of file
diff --git a/R/room.R b/R/room.R
new file mode 100644
index 0000000..7d55531
--- /dev/null
+++ b/R/room.R
@@ -0,0 +1,72 @@
+#' Is R a partial Room square?
+#'
+#' @param R A partial Room square.
+#'
+#' @return True if and only if R is a partial Room square, False otherwise.
+#' @export
+is_partial_room <- function(R) {
+  expected_number_of_distinct_pairs <- choose(max(R$col) + 1, 2)
+  nfc <- n_filled_cells(R)
+  is_row_latin(R) && 
+    is_col_latin(R) && 
+    n_filled_cells(R) <= expected_number_of_distinct_pairs
+}
+
+#' Is R a Room square?
+#'
+#' @param R A Room square.
+#'
+#' @return True if and only if R is a Room square, False otherwise.
+#' @export
+is_room <- function(R) {
+  nfc <- n_filled_cells(R)
+  is_partial_room(R) && nrow(distinct_pairs(R)) == nfc
+}
+
+#' Is R a maximal partial Room square?
+#'
+#' @param R A partial Room square.
+#'
+#' @return True if and only if R is a maximal partial Room square, False otherwise.
+#' @export
+is_maximal_proom <- function(R) {
+  
+  result <- is_partial_room(R)
+  
+  n <- max(R$col)
+  
+  R <- R |>
+    dplyr::mutate(
+      see = purrr::map2(row, col, see2, R = R)
+    ) |>
+    dplyr::mutate(
+      avail = purrr::map(see, setdiff, x = 0:(n - 1))
+    )
+  
+  # iterate through the set of unusued pairs trying to place them
+  # return true if and only if no pairs can be placed
+  for(p in unused_pairs(R)) {
+    
+    E <- empty_cells(R) 
+    # try to find a hole
+    x <- NULL
+    
+    # iterate through empty cells in given order
+    for(cell in E) {
+      
+      if(avail(R, p, cell)) {
+        x <- cell
+      }
+      
+    }
+    
+    # if we were successful then this is not a maximal proom
+    if(!is.null(x))  {
+      result <- FALSE
+      break()
+    }
+    
+  }
+  
+  return(result)
+}
\ No newline at end of file
diff --git a/R/see.R b/R/see.R
new file mode 100644
index 0000000..207a6a2
--- /dev/null
+++ b/R/see.R
@@ -0,0 +1,28 @@
+#' Symbols visible from cell e
+#'
+#' @param R A Room square.
+#' @param e A cell in R.
+#'
+#' @return A list of symbols visible in R from cell e.
+see <- function(R, e) {
+  first <- R[R$row == e[1] | R$col == e[2], "first"]$first
+  first_non_na <- first[!is.na(first)]
+  second <- R[R$row == e[1] | R$col == e[2], "second"]$second
+  second_non_na <- second[!is.na(second)]
+  sort(unique(c(first_non_na, second_non_na)))
+}
+
+#' Symbols visible from cell (row, col) in R
+#'
+#' @param R A Room square.
+#' @param row A row index.
+#' @param col A column index.
+#'
+#' @return A list of symbols visible in R from cell (col, rol).
+see2 <- function(R, row, col) {
+  first <- R[R$row == row | R$col == col, "first"]$first
+  first_non_na <- first[!is.na(first)]
+  second <- R[R$row == row | R$col == col, "second"]$second
+  second_non_na <- second[!is.na(second)]
+  sort(unique(c(first_non_na, second_non_na)))
+}
\ No newline at end of file
diff --git a/man/avail.Rd b/man/avail.Rd
new file mode 100644
index 0000000..2320798
--- /dev/null
+++ b/man/avail.Rd
@@ -0,0 +1,21 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/avail.R
+\name{avail}
+\alias{avail}
+\title{Is pair p available in R at cell e?}
+\usage{
+avail(R, p, e)
+}
+\arguments{
+\item{R}{A partial Room square.}
+
+\item{p}{A pair.}
+
+\item{e}{An empty cell of R.}
+}
+\value{
+True if and only if the pair p can be placed in cell e in R.
+}
+\description{
+Is pair p available in R at cell e?
+}
diff --git a/man/distinct_pairs.Rd b/man/distinct_pairs.Rd
new file mode 100644
index 0000000..d46e557
--- /dev/null
+++ b/man/distinct_pairs.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/distinct-pairs.R
+\name{distinct_pairs}
+\alias{distinct_pairs}
+\title{Pairs used in R}
+\usage{
+distinct_pairs(R)
+}
+\arguments{
+\item{R}{A Room square.}
+}
+\value{
+A list of the distinct pairs that appear in R.
+}
+\description{
+Pairs used in R
+}
diff --git a/man/is_maximal_proom.Rd b/man/is_maximal_proom.Rd
new file mode 100644
index 0000000..afb86db
--- /dev/null
+++ b/man/is_maximal_proom.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/room.R
+\name{is_maximal_proom}
+\alias{is_maximal_proom}
+\title{Is R a maximal partial Room square?}
+\usage{
+is_maximal_proom(R)
+}
+\arguments{
+\item{R}{A partial Room square.}
+}
+\value{
+True if and only if R is a maximal partial Room square, False otherwise.
+}
+\description{
+Is R a maximal partial Room square?
+}
diff --git a/man/is_partial_room.Rd b/man/is_partial_room.Rd
new file mode 100644
index 0000000..8ea2c91
--- /dev/null
+++ b/man/is_partial_room.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/room.R
+\name{is_partial_room}
+\alias{is_partial_room}
+\title{Is R a partial Room square?}
+\usage{
+is_partial_room(R)
+}
+\arguments{
+\item{R}{A partial Room square.}
+}
+\value{
+True if and only if R is a partial Room square, False otherwise.
+}
+\description{
+Is R a partial Room square?
+}
diff --git a/man/is_room.Rd b/man/is_room.Rd
new file mode 100644
index 0000000..d0e1e57
--- /dev/null
+++ b/man/is_room.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/room.R
+\name{is_room}
+\alias{is_room}
+\title{Is R a Room square?}
+\usage{
+is_room(R)
+}
+\arguments{
+\item{R}{A Room square.}
+}
+\value{
+True if and only if R is a Room square, False otherwise.
+}
+\description{
+Is R a Room square?
+}
diff --git a/man/see.Rd b/man/see.Rd
new file mode 100644
index 0000000..df902f3
--- /dev/null
+++ b/man/see.Rd
@@ -0,0 +1,19 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/see.R
+\name{see}
+\alias{see}
+\title{Symbols visible from cell e}
+\usage{
+see(R, e)
+}
+\arguments{
+\item{R}{A Room square.}
+
+\item{e}{A cell in R.}
+}
+\value{
+A list of symbols visible in R from cell e.
+}
+\description{
+Symbols visible from cell e
+}
diff --git a/man/see2.Rd b/man/see2.Rd
new file mode 100644
index 0000000..2ff029b
--- /dev/null
+++ b/man/see2.Rd
@@ -0,0 +1,21 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/see.R
+\name{see2}
+\alias{see2}
+\title{Symbols visible from cell (row, col) in R}
+\usage{
+see2(R, row, col)
+}
+\arguments{
+\item{R}{A Room square.}
+
+\item{row}{A row index.}
+
+\item{col}{A column index.}
+}
+\value{
+A list of symbols visible in R from cell (col, rol).
+}
+\description{
+Symbols visible from cell (row, col) in R
+}