diff --git a/.idea/comp1206-cw.iml b/.idea/comp1206-cw.iml
new file mode 100644
index 0000000000000000000000000000000000000000..d6ebd4805981b8400db3e3291c74a743fef9a824
--- /dev/null
+++ b/.idea/comp1206-cw.iml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/tetrecs/.idea/uiDesigner.xml b/tetrecs/.idea/uiDesigner.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e96534fb27b68192f27f985d3879e173ec77adb8
--- /dev/null
+++ b/tetrecs/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Palette2">
+    <group name="Swing">
+      <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
+      </item>
+      <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
+        <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
+        <initial-values>
+          <property name="text" value="Button" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="RadioButton" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="CheckBox" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="Label" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
+          <preferred-size width="-1" height="20" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
+      </item>
+    </group>
+  </component>
+</project>
\ No newline at end of file
diff --git a/tetrecs/src/main/java/uk/ac/soton/comp1206/component/GameBlock.java b/tetrecs/src/main/java/uk/ac/soton/comp1206/component/GameBlock.java
index 272c52512ac6e503de2371e21119a018c7cd5bd6..50106edfd52b16ad225fe70cba9d56721809e5ca 100644
--- a/tetrecs/src/main/java/uk/ac/soton/comp1206/component/GameBlock.java
+++ b/tetrecs/src/main/java/uk/ac/soton/comp1206/component/GameBlock.java
@@ -11,179 +11,186 @@ import org.apache.logging.log4j.Logger;
 
 /**
  * The Visual User Interface component representing a single block in the grid.
- *
+ * <p>
  * Extends Canvas and is responsible for drawing itself.
- *
+ * <p>
  * Displays an empty square (when the value is 0) or a coloured square depending on value.
- *
+ * <p>
  * The GameBlock value should be bound to a corresponding block in the Grid model.
  */
 public class GameBlock extends Canvas {
 
-    private static final Logger logger = LogManager.getLogger(GameBlock.class);
-
-    /**
-     * The set of colours for different pieces
-     */
-    public static final Color[] COLOURS = {
-            Color.TRANSPARENT,
-            Color.DEEPPINK,
-            Color.RED,
-            Color.ORANGE,
-            Color.YELLOW,
-            Color.YELLOWGREEN,
-            Color.LIME,
-            Color.GREEN,
-            Color.DARKGREEN,
-            Color.DARKTURQUOISE,
-            Color.DEEPSKYBLUE,
-            Color.AQUA,
-            Color.AQUAMARINE,
-            Color.BLUE,
-            Color.MEDIUMPURPLE,
-            Color.PURPLE
-    };
-
-    private final GameBoard gameBoard;
-
-    private final double width;
-    private final double height;
-
-    /**
-     * The column this block exists as in the grid
-     */
-    private final int x;
-
-    /**
-     * The row this block exists as in the grid
-     */
-    private final int y;
-
-    /**
-     * The value of this block (0 = empty, otherwise specifies the colour to render as)
-     */
-    private final IntegerProperty value = new SimpleIntegerProperty(0);
-
-    /**
-     * Create a new single Game Block
-     * @param gameBoard the board this block belongs to
-     * @param x the column the block exists in
-     * @param y the row the block exists in
-     * @param width the width of the canvas to render
-     * @param height the height of the canvas to render
-     */
-    public GameBlock(GameBoard gameBoard, int x, int y, double width, double height) {
-        this.gameBoard = gameBoard;
-        this.width = width;
-        this.height = height;
-        this.x = x;
-        this.y = y;
-
-        //A canvas needs a fixed width and height
-        setWidth(width);
-        setHeight(height);
-
-        //Do an initial paint
-        paint();
-
-        //When the value property is updated, call the internal updateValue method
-        value.addListener(this::updateValue);
-    }
-
-    /**
-     * When the value of this block is updated,
-     * @param observable what was updated
-     * @param oldValue the old value
-     * @param newValue the new value
-     */
-    private void updateValue(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
-        paint();
-    }
-
-    /**
-     * Handle painting of the block canvas
-     */
-    public void paint() {
-        //If the block is empty, paint as empty
-        if(value.get() == 0) {
-            paintEmpty();
-        } else {
-            //If the block is not empty, paint with the colour represented by the value
-            paintColor(COLOURS[value.get()]);
-        }
-    }
-
-    /**
-     * Paint this canvas empty
-     */
-    private void paintEmpty() {
-        var gc = getGraphicsContext2D();
-
-        //Clear
-        gc.clearRect(0.0D, 0.0D, this.width, this.height);
-
-        //Fill
-        Color gradStart = Color.color(0.0D, 0.0D, 0.6D, 0.3D);
-        Color gradEnd = Color.color(0.0D, 0.0D, 0.2D, 0.5D);
-        gc.setFill(new LinearGradient(0.0D, 0.0D, 1.0D, 1.0D, true, CycleMethod.REFLECT, new Stop(0.0D, gradStart), new Stop(1.0D, gradEnd)));
-        gc.fillRect(0.0D, 0.0D, this.width, this.height);
-
-        //Border
-        gc.setStroke(Color.WHITE);
-        gc.setGlobalAlpha(0.7);
-        gc.strokeRect(0,0,width,height);
-    }
-
-    /**
-     * Paint this canvas with the given colour
-     * @param colour the colour to paint
-     */
-    private void paintColor(Paint colour) {
-        var gc = getGraphicsContext2D();
-
-        //Clear
-        gc.clearRect(0,0,width,height);
-
-        //Colour fill
-        gc.setFill(colour);
-        gc.setGlobalAlpha(1);
-        gc.fillRect(0,0, width, height);
-
-        //Border
-        gc.setStroke(Color.BLACK);
-        gc.strokeRect(0,0,width,height);
-    }
-
-    /**
-     * Get the column of this block
-     * @return column number
-     */
-    public int getX() {
-        return x;
-    }
-
-    /**
-     * Get the row of this block
-     * @return row number
-     */
-    public int getY() {
-        return y;
-    }
-
-    /**
-     * Get the current value held by this block, representing it's colour
-     * @return value
-     */
-    public int getValue() {
-        return this.value.get();
-    }
-
-    /**
-     * Bind the value of this block to another property. Used to link the visual block to a corresponding block in the Grid.
-     * @param input property to bind the value to
-     */
-    public void bind(ObservableValue<? extends Number> input) {
-        value.bind(input);
+  private static final Logger logger = LogManager.getLogger(GameBlock.class);
+
+  /**
+   * The set of colours for different pieces
+   */
+  public static final Color[] COLOURS = {
+      Color.TRANSPARENT,
+      Color.DEEPPINK,
+      Color.RED,
+      Color.ORANGE,
+      Color.YELLOW,
+      Color.YELLOWGREEN,
+      Color.LIME,
+      Color.GREEN,
+      Color.DARKGREEN,
+      Color.DARKTURQUOISE,
+      Color.DEEPSKYBLUE,
+      Color.AQUA,
+      Color.AQUAMARINE,
+      Color.BLUE,
+      Color.MEDIUMPURPLE,
+      Color.PURPLE
+  };
+
+  private final GameBoard gameBoard;
+
+  private final double width;
+  private final double height;
+
+  /**
+   * The column this block exists as in the grid
+   */
+  private final int x;
+
+  /**
+   * The row this block exists as in the grid
+   */
+  private final int y;
+
+  /**
+   * The value of this block (0 = empty, otherwise specifies the colour to render as)
+   */
+  private final IntegerProperty value = new SimpleIntegerProperty(0);
+
+  /**
+   * Create a new single Game Block
+   *
+   * @param gameBoard the board this block belongs to
+   * @param x         the column the block exists in
+   * @param y         the row the block exists in
+   * @param width     the width of the canvas to render
+   * @param height    the height of the canvas to render
+   */
+  public GameBlock(GameBoard gameBoard, int x, int y, double width, double height) {
+    this.gameBoard = gameBoard;
+    this.width = width;
+    this.height = height;
+    this.x = x;
+    this.y = y;
+
+    //A canvas needs a fixed width and height
+    setWidth(width);
+    setHeight(height);
+
+    //Do an initial paint
+    paint();
+
+    //When the value property is updated, call the internal updateValue method
+    value.addListener(this::updateValue);
+  }
+
+  /**
+   * When the value of this block is updated,
+   *
+   * @param observable what was updated
+   * @param oldValue   the old value
+   * @param newValue   the new value
+   */
+  private void updateValue(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
+    paint();
+  }
+
+  /**
+   * Handle painting of the block canvas
+   */
+  public void paint() {
+    //If the block is empty, paint as empty
+    if (value.get() == 0) {
+      paintEmpty();
+    } else {
+      //If the block is not empty, paint with the colour represented by the value
+      paintColor(COLOURS[value.get()]);
     }
+  }
+
+  /**
+   * Paint this canvas empty
+   */
+  private void paintEmpty() {
+    var gc = getGraphicsContext2D();
+
+    //Clear
+    gc.clearRect(0.0D, 0.0D, this.width, this.height);
+
+    //Fill
+    Color gradStart = Color.color(0.0D, 0.0D, 0.6D, 0.3D);
+    Color gradEnd = Color.color(0.0D, 0.0D, 0.2D, 0.5D);
+    gc.setFill(new LinearGradient(0.0D, 0.0D, 1.0D, 1.0D, true, CycleMethod.REFLECT, new Stop(0.0D, gradStart), new Stop(1.0D, gradEnd)));
+    gc.fillRect(0.0D, 0.0D, this.width, this.height);
+
+    //Border
+    gc.setStroke(Color.WHITE);
+    gc.setGlobalAlpha(0.7);
+    gc.strokeRect(0, 0, width, height);
+  }
+
+  /**
+   * Paint this canvas with the given colour
+   *
+   * @param colour the colour to paint
+   */
+  private void paintColor(Paint colour) {
+    var gc = getGraphicsContext2D();
+
+    //Clear
+    gc.clearRect(0, 0, width, height);
+
+    //Colour fill
+    gc.setFill(colour);
+    gc.setGlobalAlpha(1);
+    gc.fillRect(0, 0, width, height);
+
+    //Border
+    gc.setStroke(Color.BLACK);
+    gc.strokeRect(0, 0, width, height);
+  }
+
+  /**
+   * Get the column of this block
+   *
+   * @return column number
+   */
+  public int getX() {
+    return x;
+  }
+
+  /**
+   * Get the row of this block
+   *
+   * @return row number
+   */
+  public int getY() {
+    return y;
+  }
+
+  /**
+   * Get the current value held by this block, representing it's colour
+   *
+   * @return value
+   */
+  public int getValue() {
+    return this.value.get();
+  }
+
+  /**
+   * Bind the value of this block to another property. Used to link the visual block to a corresponding block in the Grid.
+   *
+   * @param input property to bind the value to
+   */
+  public void bind(ObservableValue<? extends Number> input) {
+    value.bind(input);
+  }
 
 }
diff --git a/tetrecs/src/main/java/uk/ac/soton/comp1206/component/GameBoard.java b/tetrecs/src/main/java/uk/ac/soton/comp1206/component/GameBoard.java
index b587148c66b16f7940a4ec76a0a9e762c44016b5..1131d32556301904654d3e80be903938882a54a5 100644
--- a/tetrecs/src/main/java/uk/ac/soton/comp1206/component/GameBoard.java
+++ b/tetrecs/src/main/java/uk/ac/soton/comp1206/component/GameBoard.java
@@ -1,175 +1,199 @@
 package uk.ac.soton.comp1206.component;
 
+import javafx.scene.input.MouseButton;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.layout.GridPane;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import uk.ac.soton.comp1206.event.BlockClickedListener;
+import uk.ac.soton.comp1206.event.RightClickListener;
 import uk.ac.soton.comp1206.game.Grid;
 
 /**
  * A GameBoard is a visual component to represent the visual GameBoard.
  * It extends a GridPane to hold a grid of GameBlocks.
- *
+ * <p>
  * The GameBoard can hold an internal grid of it's own, for example, for displaying an upcoming block. It also be
  * linked to an external grid, for the main game board.
- *
+ * <p>
  * The GameBoard is only a visual representation and should not contain game logic or model logic in it, which should
  * take place in the Grid.
  */
 public class GameBoard extends GridPane {
 
-    private static final Logger logger = LogManager.getLogger(GameBoard.class);
-
-    /**
-     * Number of columns in the board
-     */
-    private final int cols;
-
-    /**
-     * Number of rows in the board
-     */
-    private final int rows;
-
-    /**
-     * The visual width of the board - has to be specified due to being a Canvas
-     */
-    private final double width;
-
-    /**
-     * The visual height of the board - has to be specified due to being a Canvas
-     */
-    private final double height;
-
-    /**
-     * The grid this GameBoard represents
-     */
-    final Grid grid;
-
-    /**
-     * The blocks inside the grid
-     */
-    GameBlock[][] blocks;
-
-    /**
-     * The listener to call when a specific block is clicked
-     */
-    private BlockClickedListener blockClickedListener;
-
-
-    /**
-     * Create a new GameBoard, based off a given grid, with a visual width and height.
-     * @param grid linked grid
-     * @param width the visual width
-     * @param height the visual height
-     */
-    public GameBoard(Grid grid, double width, double height) {
-        this.cols = grid.getCols();
-        this.rows = grid.getRows();
-        this.width = width;
-        this.height = height;
-        this.grid = grid;
-
-        //Build the GameBoard
-        build();
+  private static final Logger logger = LogManager.getLogger(GameBoard.class);
+
+  /**
+   * Number of columns in the board
+   */
+  private final int cols;
+
+  /**
+   * Number of rows in the board
+   */
+  private final int rows;
+
+  /**
+   * The visual width of the board - has to be specified due to being a Canvas
+   */
+  private final double width;
+
+  /**
+   * The visual height of the board - has to be specified due to being a Canvas
+   */
+  private final double height;
+
+  /**
+   * The grid this GameBoard represents
+   */
+  final Grid grid;
+
+  /**
+   * The blocks inside the grid
+   */
+  GameBlock[][] blocks;
+
+  /**
+   * The listener to call when a specific block is clicked
+   */
+  protected BlockClickedListener blockClickedListener;
+
+  protected RightClickListener rightClickListener;
+
+  /**
+   * Create a new GameBoard, based off a given grid, with a visual width and height.
+   *
+   * @param grid   linked grid
+   * @param width  the visual width
+   * @param height the visual height
+   */
+  public GameBoard(Grid grid, double width, double height) {
+    this.cols = grid.getCols();
+    this.rows = grid.getRows();
+    this.width = width;
+    this.height = height;
+    this.grid = grid;
+
+    //Build the GameBoard
+    build();
+  }
+
+  /**
+   * Create a new GameBoard with it's own internal grid, specifying the number of columns and rows, along with the
+   * visual width and height.
+   *
+   * @param cols   number of columns for internal grid
+   * @param rows   number of rows for internal grid
+   * @param width  the visual width
+   * @param height the visual height
+   */
+  public GameBoard(int cols, int rows, double width, double height) {
+    this.cols = cols;
+    this.rows = rows;
+    this.width = width;
+    this.height = height;
+    this.grid = new Grid(cols, rows);
+
+    //Build the GameBoard
+    build();
+  }
+
+  /**
+   * Get a specific block from the GameBoard, specified by it's row and column
+   *
+   * @param x column
+   * @param y row
+   * @return game block at the given column and row
+   */
+  public GameBlock getBlock(int x, int y) {
+    return blocks[x][y];
+  }
+
+  /**
+   * Build the GameBoard by creating a block at every x and y column and row
+   */
+  protected void build() {
+    logger.info("Building grid: {} x {}", cols, rows);
+
+    setMaxWidth(width);
+    setMaxHeight(height);
+
+    setGridLinesVisible(true);
+
+    blocks = new GameBlock[cols][rows];
+
+    for (var y = 0; y < rows; y++) {
+      for (var x = 0; x < cols; x++) {
+        createBlock(x, y);
+      }
     }
-
-    /**
-     * Create a new GameBoard with it's own internal grid, specifying the number of columns and rows, along with the
-     * visual width and height.
-     *
-     * @param cols number of columns for internal grid
-     * @param rows number of rows for internal grid
-     * @param width the visual width
-     * @param height the visual height
-     */
-    public GameBoard(int cols, int rows, double width, double height) {
-        this.cols = cols;
-        this.rows = rows;
-        this.width = width;
-        this.height = height;
-        this.grid = new Grid(cols,rows);
-
-        //Build the GameBoard
-        build();
-    }
-
-    /**
-     * Get a specific block from the GameBoard, specified by it's row and column
-     * @param x column
-     * @param y row
-     * @return game block at the given column and row
-     */
-    public GameBlock getBlock(int x, int y) {
-        return blocks[x][y];
-    }
-
-    /**
-     * Build the GameBoard by creating a block at every x and y column and row
-     */
-    protected void build() {
-        logger.info("Building grid: {} x {}",cols,rows);
-
-        setMaxWidth(width);
-        setMaxHeight(height);
-
-        setGridLinesVisible(true);
-
-        blocks = new GameBlock[cols][rows];
-
-        for(var y = 0; y < rows; y++) {
-            for (var x = 0; x < cols; x++) {
-                createBlock(x,y);
-            }
-        }
-    }
-
-    /**
-     * Create a block at the given x and y position in the GameBoard
-     * @param x column
-     * @param y row
-     */
-    protected GameBlock createBlock(int x, int y) {
-        var blockWidth = width / cols;
-        var blockHeight = height / rows;
-
-        //Create a new GameBlock UI component
-        GameBlock block = new GameBlock(this, x, y, blockWidth, blockHeight);
-
-        //Add to the GridPane
-        add(block,x,y);
-
-        //Add to our block directory
-        blocks[x][y] = block;
-
-        //Link the GameBlock component to the corresponding value in the Grid
-        block.bind(grid.getGridProperty(x,y));
-
-        //Add a mouse click handler to the block to trigger GameBoard blockClicked method
-        block.setOnMouseClicked((e) -> blockClicked(e, block));
-
-        return block;
-    }
-
-    /**
-     * Set the listener to handle an event when a block is clicked
-     * @param listener listener to add
-     */
-    public void setOnBlockClick(BlockClickedListener listener) {
-        this.blockClickedListener = listener;
+  }
+
+  /**
+   * Create a block at the given x and y position in the GameBoard
+   *
+   * @param x column
+   * @param y row
+   */
+  protected GameBlock createBlock(int x, int y) {
+    var blockWidth = width / cols;
+    var blockHeight = height / rows;
+
+    //Create a new GameBlock UI component
+    GameBlock block = new GameBlock(this, x, y, blockWidth, blockHeight);
+
+    //Add to the GridPane
+    add(block, x, y);
+
+    //Add to our block directory
+    blocks[x][y] = block;
+
+    //Link the GameBlock component to the corresponding value in the Grid
+    block.bind(grid.getGridProperty(x, y));
+
+    //Add a mouse click handler to the block to trigger GameBoard blockClicked method
+    //block.setOnMouseClicked((e) -> blockClicked(e, block));
+
+    block.setOnMouseClicked(e -> {
+      if (e.getButton() == MouseButton.PRIMARY) {
+        blockClicked(block);
+      } else {
+        blockRightClicked(block);
+      }
+    });
+    return block;
+  }
+
+  /**
+   * Set the listener to handle an event when a block is clicked
+   *
+   * @param listener listener to add
+   */
+  public void setOnBlockClick(BlockClickedListener listener) {
+    this.blockClickedListener = listener;
+  }
+
+  public void setOnRightClick(RightClickListener listener) {
+    this.rightClickListener = listener;
+  }
+
+  /**
+   * Triggered when a block is clicked. Call the attached listener.
+   *
+   * @param block block clicked on
+   */
+  private void blockClicked(GameBlock block) {
+    logger.info("Block clicked: {}", block);
+
+    if (blockClickedListener != null) {
+      blockClickedListener.blockClicked(block);
     }
+  }
 
-    /**
-     * Triggered when a block is clicked. Call the attached listener.
-     * @param event mouse event
-     * @param block block clicked on
-     */
-    private void blockClicked(MouseEvent event, GameBlock block) {
-        logger.info("Block clicked: {}", block);
-
-        if(blockClickedListener != null) {
-            blockClickedListener.blockClicked(block);
-        }
+  private void blockRightClicked(GameBlock block) {
+    if (this.rightClickListener != null) {
+      this.rightClickListener.rightClicked();
     }
+  }
 
 }
diff --git a/tetrecs/src/main/java/uk/ac/soton/comp1206/component/PieceBoard.java b/tetrecs/src/main/java/uk/ac/soton/comp1206/component/PieceBoard.java
index c2d35fd34beeccee411ac277c9a55fc9069c180a..5abd200729cf1db9f272d2e508fd3cfa532cf91e 100644
--- a/tetrecs/src/main/java/uk/ac/soton/comp1206/component/PieceBoard.java
+++ b/tetrecs/src/main/java/uk/ac/soton/comp1206/component/PieceBoard.java
@@ -1,16 +1,29 @@
 package uk.ac.soton.comp1206.component;
 
+import uk.ac.soton.comp1206.event.BlockClickedListener;
 import uk.ac.soton.comp1206.game.GamePiece;
 
 public class PieceBoard extends GameBoard {
 
-  private GamePiece pieceToDisplay;
-
   public PieceBoard(double width, double height) {
     super(3, 3, width, height);
   }
 
+  public void displayPiece(GamePiece piece, int placeX, int placeY) {
+    clear();
+    this.grid.playPiece(piece, placeX + 1, placeY + 1);
+  }
+
   public void displayPiece(GamePiece piece) {
-    this.pieceToDisplay = piece;
+    displayPiece(piece, 0, 0);
+  }
+
+  public void clear() {
+    this.grid.clear();
+  }
+
+  public void setOnClick(BlockClickedListener handler) {
+    this.blockClickedListener = handler;
   }
+
 }
diff --git a/tetrecs/src/main/java/uk/ac/soton/comp1206/event/NextPieceListener.java b/tetrecs/src/main/java/uk/ac/soton/comp1206/event/NextPieceListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..09971bd2dae205469f3af8bfafb4915169e935f0
--- /dev/null
+++ b/tetrecs/src/main/java/uk/ac/soton/comp1206/event/NextPieceListener.java
@@ -0,0 +1,7 @@
+package uk.ac.soton.comp1206.event;
+
+import uk.ac.soton.comp1206.game.GamePiece;
+
+public interface NextPieceListener {
+  void nextPiece(GamePiece paramGamePiece);
+}
diff --git a/tetrecs/src/main/java/uk/ac/soton/comp1206/event/RightClickListener.java b/tetrecs/src/main/java/uk/ac/soton/comp1206/event/RightClickListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..9b2c5abb20bc053d570ece6d50f1230353e4f2a8
--- /dev/null
+++ b/tetrecs/src/main/java/uk/ac/soton/comp1206/event/RightClickListener.java
@@ -0,0 +1,5 @@
+package uk.ac.soton.comp1206.event;
+
+public interface RightClickListener {
+  void rightClicked();
+}
diff --git a/tetrecs/src/main/java/uk/ac/soton/comp1206/game/Game.java b/tetrecs/src/main/java/uk/ac/soton/comp1206/game/Game.java
index af904f43d19766988f4cea34288d1b0582a9e4a7..fb971dd7fc20711414c1b9c6b9b8767c450dbc2d 100644
--- a/tetrecs/src/main/java/uk/ac/soton/comp1206/game/Game.java
+++ b/tetrecs/src/main/java/uk/ac/soton/comp1206/game/Game.java
@@ -5,6 +5,7 @@ import javafx.beans.property.SimpleIntegerProperty;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import uk.ac.soton.comp1206.component.GameBlock;
+import uk.ac.soton.comp1206.event.NextPieceListener;
 import uk.ac.soton.comp1206.utility.Multimedia;
 
 import java.util.ArrayList;
@@ -43,6 +44,8 @@ public class Game {
 
     private int remainder = 0;
 
+    protected NextPieceListener nextPieceHandler = null;
+
     /**
      * Create a new game with the specified rows and columns. Creates a corresponding grid model.
      * @param cols number of columns
@@ -77,7 +80,6 @@ public class Game {
 
         this.nextPiece = spawnPiece();
         nextPiece();
-        this.currentPiece = spawnPiece();
     }
 
     /**
@@ -93,14 +95,19 @@ public class Game {
         logger.info("Block clicked at x = {}  y = {}",x,y);
         boolean placed = grid.playPiece(currentPiece, x, y);
         if (placed) {
+            logger.info("Placing block at x:{} y:{}",x,y);
+            Multimedia.playSound("place.wav");
             this.afterPiece();
             this.nextPiece();
+        } else {
+            logger.info("Cannot place piece here");
+            Multimedia.playSound("fail.wav");
         }
     }
 
     public GamePiece spawnPiece() {
         Random rand = new Random();
-        GamePiece piece = GamePiece.createPiece(3, rand.nextInt(3));
+        GamePiece piece = GamePiece.createPiece(rand.nextInt(15), rand.nextInt(3));
         logger.info("Spawning piece: {}" , piece);
         return piece;
     }
@@ -109,6 +116,10 @@ public class Game {
         this.currentPiece = this.nextPiece;
         this.nextPiece = spawnPiece();
 
+        if (this.nextPieceHandler != null) {
+            this.nextPieceHandler.nextPiece(this.currentPiece);
+        }
+
         logger.info("Current piece is : {}", this.currentPiece);
         logger.info("Next piece is: {}", this.nextPiece);
 
@@ -195,6 +206,12 @@ public class Game {
         }
     }
 
+    public void swapPiece() {
+        GamePiece tempPiece = this.currentPiece;
+        this.currentPiece = this.nextPiece;
+        this.nextPiece = tempPiece;
+    }
+
     /**
      * Get the grid model inside this game representing the game state of the board
      * @return game grid model
@@ -219,6 +236,22 @@ public class Game {
         return rows;
     }
 
+    public GamePiece getCurrentPiece() {
+        return currentPiece;
+    }
+
+    public GamePiece getNextPiece() {
+        return nextPiece;
+    }
+
+    public void setOnNextPiece(NextPieceListener handler) {
+        this.nextPieceHandler = handler;
+    }
+
+    public void rotatePiece(int rotations) {
+        this.currentPiece.rotate(rotations);
+     }
+
     public IntegerProperty getLevel() {
         return level;
     }
diff --git a/tetrecs/src/main/java/uk/ac/soton/comp1206/game/Grid.java b/tetrecs/src/main/java/uk/ac/soton/comp1206/game/Grid.java
index 7905236966906c866d7b7a80091eaa2baa898609..1e66ea3ae457426cbc9587f4ee9f0885da94d37f 100644
--- a/tetrecs/src/main/java/uk/ac/soton/comp1206/game/Grid.java
+++ b/tetrecs/src/main/java/uk/ac/soton/comp1206/game/Grid.java
@@ -101,8 +101,6 @@ public class Grid {
                 int value = blocks[x][y];
                 if (value == 0) continue;
                 if (get(x + placeX, y + placeY) != 0) {
-                    logger.info("Cannot place piece here");
-                    Multimedia.playSound("fail.wav");
                     return false;
                 }
             }
@@ -113,8 +111,6 @@ public class Grid {
     public boolean playPiece(GamePiece gamePiece, int placeX, int placeY) {
         if (!this.canPlayPiece(gamePiece, placeX, placeY)) return false;
 
-        logger.info("Placing block at x:{} y:{}",placeX,placeY);
-        Multimedia.playSound("place.wav");
         int[][] blocks = gamePiece.getBlocks();
         placeX = placeX - 1;
         placeY = placeY - 1;
@@ -129,6 +125,14 @@ public class Grid {
         return true;
     }
 
+    public void clear() {
+        for (int y = 0; y < this.rows; y++) {
+            for (int x = 0; x < this.cols; x++) {
+                this.grid[x][y].set(0);
+            }
+        }
+    }
+
     /**
      * Get the number of columns in this game
      * @return number of columns
diff --git a/tetrecs/src/main/java/uk/ac/soton/comp1206/scene/ChallengeScene.java b/tetrecs/src/main/java/uk/ac/soton/comp1206/scene/ChallengeScene.java
index b5fbf9609d5a9633d074bac1042d3971476f5bf4..d2461ba4f84ec4c067861b96091b054b833ac55a 100644
--- a/tetrecs/src/main/java/uk/ac/soton/comp1206/scene/ChallengeScene.java
+++ b/tetrecs/src/main/java/uk/ac/soton/comp1206/scene/ChallengeScene.java
@@ -15,6 +15,7 @@ import uk.ac.soton.comp1206.component.GameBlock;
 import uk.ac.soton.comp1206.component.GameBoard;
 import uk.ac.soton.comp1206.component.PieceBoard;
 import uk.ac.soton.comp1206.game.Game;
+import uk.ac.soton.comp1206.game.GamePiece;
 import uk.ac.soton.comp1206.ui.GamePane;
 import uk.ac.soton.comp1206.ui.GameWindow;
 import uk.ac.soton.comp1206.utility.Multimedia;
@@ -29,6 +30,10 @@ public class ChallengeScene extends BaseScene {
     private static final Logger logger = LogManager.getLogger(MenuScene.class);
     protected Game game;
 
+    protected GameBoard board;
+    protected PieceBoard currentPieceBoard;
+    protected PieceBoard nextPieceBoard;
+
     /**
      * Create a new Single Player challenge scene
      * @param gameWindow the Game Window
@@ -50,7 +55,6 @@ public class ChallengeScene extends BaseScene {
         root = new GamePane(gameWindow.getWidth(),gameWindow.getHeight());
 
         StackPane challengePane = new StackPane();
-        challengePane.setBackground(new Background(new BackgroundFill[] { new BackgroundFill((Paint) Color.BLACK, CornerRadii.EMPTY, Insets.EMPTY) }));
         challengePane.setMaxWidth(gameWindow.getWidth());
         challengePane.setMaxHeight(gameWindow.getHeight());
         challengePane.getStyleClass().add("menu-background");
@@ -114,11 +118,12 @@ public class ChallengeScene extends BaseScene {
     public HBox buildBoards() {
         HBox boards = new HBox();
 
-        var board = new GameBoard(game.getGrid(),gameWindow.getWidth()/2,gameWindow.getWidth()/2);
+        this.board = new GameBoard(game.getGrid(),gameWindow.getWidth()/2,gameWindow.getWidth()/2);
         //Handle block on gameboard grid being clicked
-        board.setOnBlockClick(this::blockClicked);
+        this.board.setOnBlockClick(this::blockClicked);
+        this.board.setOnRightClick(this::rotateBlock);
 
-        boards.getChildren().add(board);
+        boards.getChildren().add(this.board);
 
         VBox gameInfo = new VBox();
 
@@ -143,11 +148,13 @@ public class ChallengeScene extends BaseScene {
         incomingTitle.getStyleClass().add("heading");
         gameInfo.getChildren().add(incomingTitle);
 
-        PieceBoard currentPieceBoard = new PieceBoard(gameWindow.getWidth()/6, gameWindow.getWidth()/6);
-        gameInfo.getChildren().add(currentPieceBoard);
+        this.currentPieceBoard = new PieceBoard(gameWindow.getWidth()/6, gameWindow.getWidth()/6);
+        this.currentPieceBoard.setOnClick(this::rotateBlock);
+        gameInfo.getChildren().add(this.currentPieceBoard);
 
-        PieceBoard nextPieceBoard = new PieceBoard(gameWindow.getWidth()/10, gameWindow.getWidth()/10);
-        gameInfo.getChildren().add(nextPieceBoard);
+        this.nextPieceBoard = new PieceBoard(gameWindow.getWidth()/10, gameWindow.getWidth()/10);
+        this.nextPieceBoard.setOnClick(this::swapPiece);
+        gameInfo.getChildren().add(this.nextPieceBoard);
 
         gameInfo.setAlignment(Pos.CENTER);
         gameInfo.setSpacing(10);
@@ -160,6 +167,13 @@ public class ChallengeScene extends BaseScene {
         return boards;
     }
 
+    private void swapPiece(GameBlock gameBlock) {
+        logger.info("Swapping current and next piece");
+        this.currentPieceBoard.displayPiece(this.game.getNextPiece());
+        this.nextPieceBoard.displayPiece(this.game.getCurrentPiece());
+        this.game.swapPiece();
+    }
+
     /**
      * Handle when a block is clicked
      * @param gameBlock the Game Block that was clocked
@@ -168,14 +182,27 @@ public class ChallengeScene extends BaseScene {
         game.blockClicked(gameBlock);
     }
 
+    private void rotateBlock(int rotations) {
+        logger.info("Rotating block");
+        Multimedia.playSound("rotate.wav");
+        this.game.rotatePiece(rotations);
+        this.currentPieceBoard.displayPiece(this.game.getCurrentPiece());
+    }
+
+    private void rotateBlock(GameBlock gameBlock) {
+        rotateBlock(1);
+    }
+
+    private void rotateBlock() {
+        rotateBlock(1);
+    }
 
     /**
      * Setup the game object and model
      */
     public void setupGame() {
         logger.info("Starting a new challenge");
-        Multimedia.playBackgroundMusic("game_start.wav", false);
-        Multimedia.getBackgroundPlayer().setOnEndOfMedia(() -> Multimedia.playBackgroundMusic("game.wav", true));
+
         //Start new game
         game = new Game(5, 5);
     }
@@ -186,7 +213,16 @@ public class ChallengeScene extends BaseScene {
     @Override
     public void initialise() {
         logger.info("Initialising Challenge");
+        Multimedia.playBackgroundMusic("game_start.wav", false);
+        Multimedia.getBackgroundPlayer().setOnEndOfMedia(() -> Multimedia.playBackgroundMusic("game.wav", true));
+
+        this.game.setOnNextPiece(this::nextPiece);
         game.start();
     }
 
+    protected void nextPiece(GamePiece nextPiece) {
+        logger.info("Next piece to place: " + nextPiece);
+        this.currentPieceBoard.displayPiece(nextPiece);
+        this.nextPieceBoard.displayPiece(this.game.getNextPiece());
+    }
 }
diff --git a/tetrecs/target/classes/uk/ac/soton/comp1206/component/GameBoard.class b/tetrecs/target/classes/uk/ac/soton/comp1206/component/GameBoard.class
index 5f8a073ae3bae068119a84b6ff70d71bff47c4bc..7d7f7ec15155e1956eee50ce3814870034b662b0 100644
Binary files a/tetrecs/target/classes/uk/ac/soton/comp1206/component/GameBoard.class and b/tetrecs/target/classes/uk/ac/soton/comp1206/component/GameBoard.class differ
diff --git a/tetrecs/target/classes/uk/ac/soton/comp1206/game/Game.class b/tetrecs/target/classes/uk/ac/soton/comp1206/game/Game.class
index 54142e5420e92cd5cec8ffadb11a9b80935bf8b5..9bee46cc02c85f4d236ae529187f1b0a6ca79b2f 100644
Binary files a/tetrecs/target/classes/uk/ac/soton/comp1206/game/Game.class and b/tetrecs/target/classes/uk/ac/soton/comp1206/game/Game.class differ
diff --git a/tetrecs/target/classes/uk/ac/soton/comp1206/game/Grid.class b/tetrecs/target/classes/uk/ac/soton/comp1206/game/Grid.class
index 002e059f2affcc6dc3522671f50858fd1a9f5865..915e5a5f1411e7a79631ab290a29233d57d65412 100644
Binary files a/tetrecs/target/classes/uk/ac/soton/comp1206/game/Grid.class and b/tetrecs/target/classes/uk/ac/soton/comp1206/game/Grid.class differ
diff --git a/tetrecs/target/classes/uk/ac/soton/comp1206/scene/ChallengeScene.class b/tetrecs/target/classes/uk/ac/soton/comp1206/scene/ChallengeScene.class
index db3f11b372bf64a21aa8eddfd74d0f4317da0970..307d07de2a84933ea7a5dc80b9504e5c98c000a8 100644
Binary files a/tetrecs/target/classes/uk/ac/soton/comp1206/scene/ChallengeScene.class and b/tetrecs/target/classes/uk/ac/soton/comp1206/scene/ChallengeScene.class differ
diff --git a/tetrecs/tetrecs.iml b/tetrecs/tetrecs.iml
new file mode 100644
index 0000000000000000000000000000000000000000..34834c254facdd44a9b4d1422658a5542f952166
--- /dev/null
+++ b/tetrecs/tetrecs.iml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
+  <component name="CheckStyle-IDEA-Module">
+    <option name="configuration">
+      <map />
+    </option>
+  </component>
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_17">
+    <output url="file://$MODULE_DIR$/target/classes" />
+    <output-test url="file://$MODULE_DIR$/target/test-classes" />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+      <excludeFolder url="file://$MODULE_DIR$/${project.build.directory}/classes" />
+      <excludeFolder url="file://$MODULE_DIR$/${project.build.directory}/test-classes" />
+      <excludeFolder url="file://$MODULE_DIR$/target" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Maven: org.openjfx:javafx-controls:17.0.2" level="project" />
+    <orderEntry type="library" name="Maven: org.openjfx:javafx-controls:win:17.0.2" level="project" />
+    <orderEntry type="library" name="Maven: org.openjfx:javafx-graphics:17.0.2" level="project" />
+    <orderEntry type="library" name="Maven: org.openjfx:javafx-graphics:win:17.0.2" level="project" />
+    <orderEntry type="library" name="Maven: org.openjfx:javafx-base:17.0.2" level="project" />
+    <orderEntry type="library" name="Maven: org.openjfx:javafx-base:win:17.0.2" level="project" />
+    <orderEntry type="library" name="Maven: org.openjfx:javafx-fxml:17.0.2" level="project" />
+    <orderEntry type="library" name="Maven: org.openjfx:javafx-fxml:win:17.0.2" level="project" />
+    <orderEntry type="library" name="Maven: org.openjfx:javafx-media:17.0.2" level="project" />
+    <orderEntry type="library" name="Maven: org.openjfx:javafx-media:win:17.0.2" level="project" />
+    <orderEntry type="library" name="Maven: com.neovisionaries:nv-websocket-client:2.14" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.17.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-core:2.17.1" level="project" />
+  </component>
+</module>
\ No newline at end of file