diff --git a/build.sbt b/build.sbt
index cf57f57876754569aa1677f4eba934d1424fe530..9cb8d9ae305236a44f3f29733817abcf161c88a7 100644
--- a/build.sbt
+++ b/build.sbt
@@ -2,11 +2,14 @@ lazy val root = (project in file(".")).
   settings(
     name := "Reversi",
     version := "2023.0",
-    scalaVersion := "3.1.0"
+    scalaVersion := "3.2.0"
   )
 
 run / fork := true
 
 libraryDependencies += "org.scalafx" %% "scalafx" % "20.0.0-R31"
 libraryDependencies += "org.scalameta" %% "munit" % "0.7.29" % Test
+
+libraryDependencies += "com.typesafe.play" %% "play-ahc-ws-standalone" % "2.2.0-M2"
+
 testFrameworks += new TestFramework("munit.Framework")
diff --git a/src/main/scala/cosc250/reversi/App.scala b/src/main/scala/cosc250/reversi/App.scala
index 470630c6b4fececdaaac2f31ea226bc7ab9fd58e..b8fd4faae96985768fe90989ca9a149423695bbd 100644
--- a/src/main/scala/cosc250/reversi/App.scala
+++ b/src/main/scala/cosc250/reversi/App.scala
@@ -11,139 +11,55 @@ import scalafx.geometry.*
 import scalafx.collections.*
 import scalafx.animation.*
 import scalafx.beans.property.*
+import javafx.application.Platform
+
+import java.util.{TimerTask, Timer}
+
 
 object App extends JFXApp3 {
 
     override def start() = {
+
+        val r = Rectangle(200, 200)
+        val b = Button("Click me")
+        var hue = 1
+        var rot = 0d
+
         stage = new JFXApp3.PrimaryStage {
             title.value = "Reversi"
             width = 480
             height = 600
             scene = new Scene {
-                content = new UI().subscene                    
+                content = new VBox(
+                    r, b
+                )                    
             }
         }
-    }
-
-}
-
-class UI() {
-
-    // A constant for how bix the squares are
-    val squareSize = 40
-
-    /** Represents a square on the board. */
-    class Square(col:Int, row:Int) {
-
-        private val square = new Rectangle {
-            width = squareSize
-            height = squareSize
-            fill = if (col + row) % 2 == 0 then Color.hsb(114, 0.85, 0.33) else Color.hsb(114, 0.65, 0.43)
-        }
+        stage.setOnCloseRequest((_) => System.exit(0))
 
-        val ui = new Group {
-            translateX = col * squareSize
-            translateY = row * squareSize
-            children = Seq(
-                square
-            )
-        }
-
-        def clear():Unit = {
-            ui.children = Seq(square)
-        }
+        val timerTask = new TimerTask { 
+            override def run():Unit = 
+                hue = (hue + 1) % 255
+                rot = (rot + 3) % 360
 
-        def place(p:Player) = {
-            ui.children = Seq(
-                square,
-                new Circle {
-                    centerX = squareSize / 2
-                    centerY = squareSize / 2
-                    radius = squareSize / 3
-                    fill = if p == Player.White then Color.White else Color.Black
+                Platform.runLater { () =>
+                    r.fill = Color.hsb(hue, 1, 1)
+                    r.rotate = rot
                 }
-            )
-        }
-    }
-
-    private val squares = for y <- 0 until boardSize yield
-        for x <- 0 until boardSize yield 
-            new Square(x, y)
-
-
-    var game = newGame
-
-    private def showGameState(g:GameState):Unit = {
-        for 
-            y <- 0 until boardSize
-            x <- 0 until boardSize
-        do
-            if g.board.contains((x, y)) then
-                squares(y)(x).place(g.board((x, y)))
-            else 
-                squares(y)(x).clear()
-    }
-
-    private def showGame(gs:Seq[GameState]):Unit = {
-        showGameState(gs.last)
-        history.items = ObservableBuffer((for 
-            (g, i) <- gs.zipWithIndex 
-            (p, loc) <- g.lastMove
-        yield
-            (i, loc, p)
-        )*)
-    }
-
-
-    val history = new ListView[(Int, Player, Location)] {
-        orientation = Orientation.Vertical
-        cellFactory = (cell, data) => {
-            val (i, p, (x, y)) = data
-            val col = "abcdefgh"(x)
-            cell.text = s"$i. $col${y+1}"
-            cell.textFill = if p == Player.Black then Color.Black else Color.White
-            cell.onMouseClicked = { _ =>
-                lastTime = System.nanoTime()
-                game = rewindTo(game, i)
-                showGame(game)                
-            }
-
-            cell.style = 
-                if i % 2 == 0 then "-fx-background-color: #1D7A12;"
-                else  "-fx-background-color: #1A6E10;"
         }
+        val timer = new Timer()
+        timer.schedule(timerTask, 1000/60, 1000/60);
+
+        b.setOnAction((_) => 
+            new Thread(() => {
+                try {
+                    Thread.sleep(10000);
+                } catch  {
+                    case _ => // ignore
+                }
+            }).start();
+            
+        )
     }
 
-    private def step():Unit = {
-        println(s"Lookahead ${lookAhead.value.value}")
-        game = play(game, lookAhead.value.value)
-        showGame(game)
-    }
-
-    private var lastTime = 0L
-    private val playing = BooleanProperty(false)
-
-    private val lookAhead = new Spinner[Int](0, 5, 0)
-
-    AnimationTimer({ now =>
-        if playing.value && (now > lastTime + 1e9) then 
-            lastTime = now
-            step()
-    }).start()
-
-    private val startStop = new Button {
-        text <== (for p <- playing yield if p then "Stop" else "Start")
-        onAction = { _ => playing.value = !playing.value }
-    }
-
-    val subscene = new HBox(
-        new VBox(
-            new Group(squares.flatten.map(_.ui).toSeq*),
-            new HBox(5, startStop, Label("Lookahead"), lookAhead)
-        ),
-        history
-    )
-
-
-
-}
\ No newline at end of file
+}
diff --git a/src/main/scala/cosc250/reversi/FuturesDemo.scala b/src/main/scala/cosc250/reversi/FuturesDemo.scala
new file mode 100644
index 0000000000000000000000000000000000000000..1326e24d805fc8c2c3add4a4f149be16efa2abf8
--- /dev/null
+++ b/src/main/scala/cosc250/reversi/FuturesDemo.scala
@@ -0,0 +1,19 @@
+package cosc250.reversi
+
+import scala.util.*
+import scala.concurrent.* 
+import scala.concurrent.ExecutionContext.Implicits.global
+
+
+
+@main def futuresDemo() = {
+
+    val promise = Promise[Int]()
+    val future = promise.future
+
+    println(s"Before the future is completed. Future is completed ${future.isCompleted}")
+    future.onComplete { case Success(v) => println(s"Future completed with value $v") }
+    promise.success(2)
+    //println(s"After the future is completed. Future is completed ${future.isCompleted}")
+
+}
diff --git a/src/main/scala/cosc250/reversi/Reversi.scala b/src/main/scala/cosc250/reversi/Reversi.scala
deleted file mode 100644
index 945b2012f97bfcfdcf5c6821f3584f235027396d..0000000000000000000000000000000000000000
--- a/src/main/scala/cosc250/reversi/Reversi.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-package cosc250.reversi
-
-import scala.collection.immutable.Queue
-
-enum Player:
-    case Black
-    case White
-
-/** The board size is always 8 by 8 */
-val boardSize = 8
-
-/** A location on the board. Zero-indexed */
-type Location = (Int, Int)
-
-/**
-  * The state of the board
-  * 
-  * @param lastMove - the location of the last move
-  * @param board - maps the locations of pieces on the board (note that if a piece has not been played in a square, it won't be in the map)
-  * @param turn - whose turn it is next
-  */
-case class GameState(lastMove:Option[(Location, Player)], board:Map[Location, Player], turn:Player) {
-
-    /** The number of black pieces */
-    def blackPieces:Int = ???
-
-    /** The number of white pieces */
-    def whitePieces:Int = ???
-
-    /** True if neither player can play a move */
-    def gameOver:Boolean = ???
-
-    /** Whether a particular move is valid */
-    def isValidMove(location:Location):Boolean = 
-        ???
-
-    /** Performs a move */
-    def move(location:Location):GameState = 
-        ???
-        
-
-    // Other methods you write
-
-}
-
-object GameState {
-    def newGame = GameState(None, Map.empty, Player.Black)
-}
-
-/** A game is a sequence of game-states (so it remembers past moves). The most recent move is at the end. */
-type Game = Seq[GameState]
-
-/** Creates a new game, containing just the start game state */
-def newGame:Seq[GameState] = Seq(GameState.newGame)
-
-/** Called by the UI on each animation tick to make your AI play the game */
-def play(state:Seq[GameState], lookAhead:Int):Seq[GameState] = 
-    ???
-    
-/** Called by the UI when the user clicks back in the game histry */
-def rewindTo(state:Seq[GameState], move:Int):Seq[GameState] = 
-    ???
-
diff --git a/src/main/scala/cosc250/reversi/ws.scala b/src/main/scala/cosc250/reversi/ws.scala
new file mode 100644
index 0000000000000000000000000000000000000000..a46a2ece5ef3c19f0d5e64ebdfc9570a40d39025
--- /dev/null
+++ b/src/main/scala/cosc250/reversi/ws.scala
@@ -0,0 +1,41 @@
+package cosc250.reversi
+
+import akka.actor.ActorSystem
+import akka.stream._
+import play.api.libs.ws._
+import play.api.libs.ws.ahc.StandaloneAhcWSClient
+import scala.concurrent.ExecutionContext.Implicits.global
+
+
+import scala.util.Random
+
+import scala.concurrent.Future
+
+@main def wsmain(): Unit = {
+    // A little boilerplate - this is needed by the web client we're using
+  given actorSystem:ActorSystem = ActorSystem()
+  given materializer:Materializer = SystemMaterializer(actorSystem).materializer
+
+  // Now we can create our web client and make a request
+  val wsClient = StandaloneAhcWSClient()
+
+  def zen():Future[String] =
+    val randomStr = Random.nextString(4) // Makes sure we don't get a cached reply
+    wsClient.url(s"https://api.github.com/zen?$randomStr").get().map(_.body)
+
+  def nZens(n:Int):Future[Seq[String]] = {
+    val futures:Seq[Future[String]] = for
+      i <- 1 to n
+    yield zen()
+
+    Future.sequence(futures)
+  }
+
+  val f = for
+    first <- zen()
+    second <- zen()
+  yield s"$first, and then $second"
+
+  // Print this statement immediately
+  println("This prints immediately")
+}
\ No newline at end of file
diff --git a/src/test/scala/cosc250/reversi/ReversiSuite.scala b/src/test/scala/cosc250/reversi/ReversiSuite.scala
index 121660610870dfe844baf6fcce8c8ecd70714279..bb381ca3cc7b77bf6b0524eefff45359a2ef1782 100644
--- a/src/test/scala/cosc250/reversi/ReversiSuite.scala
+++ b/src/test/scala/cosc250/reversi/ReversiSuite.scala
@@ -9,23 +9,4 @@ package cosc250.reversi
   */
 class ReversiSuite extends munit.FunSuite {
 
-  // A place for you to write tests. Some suggested tests to start with have been sketched below
-
-  test("Counts pieces") {
-    assertEquals(2, GameState(None, Map((3, 3) -> Player.Black, (3, 4) -> Player.Black), Player.White).blackPieces)
-    assertEquals(2, GameState(None, Map((3, 3) -> Player.White, (3, 4) -> Player.White), Player.White).whitePieces)
-
-    // add some more!
-  }
-
-  test("Should be able to detect if a move is valid") {
-    ???
-  }
-
-  test("Should be able to count the score for one player") {
-    ???
-  }
-
-  // You'll need to write some additional tests
-
 }