Skip to content

Instantly share code, notes, and snippets.

@ChristopherDavenport
Last active December 11, 2018 20:26
Show Gist options
  • Save ChristopherDavenport/67cd986b3636be109a3f82d2b49abef2 to your computer and use it in GitHub Desktop.
Save ChristopherDavenport/67cd986b3636be109a3f82d2b49abef2 to your computer and use it in GitHub Desktop.
Fun Little Action Game
// fs2 1.0.0
import cats.effect._
import cats.effect.concurrent._
import cats.implicits._
import fs2._
import fs2.concurrent._
import scala.concurrent.duration._
object Main extends IOApp {
def run(args: List[String]) =
coolioStream[IO].compile.drain.map(_ => ExitCode.Success)
sealed trait MyEvents
final case class Heal(health: Int) extends MyEvents
final case class Damage(health: Int) extends MyEvents
def eventLoop[F[_]: Concurrent](
healthRef: Ref[F, Int],
eventQueue: Queue[F, MyEvents]): Stream[F, Unit] = {
Stream.eval(SignallingRef[F, Boolean](false)).flatMap{ref =>
eventQueue
.dequeue
.interruptWhen(ref)
.evalMap{
case Heal(h) => healthRef.update(_ + h)
case Damage(h) => healthRef.update(_ - h)
}.evalMap{_ =>
healthRef.get.flatMap{ health =>
if (health >= 0) Sync[F].delay(println(s"Current Health: $health"))
else Sync[F].delay(println("You Died!")) *> ref.set(true)
}
}
}
}
def readLineStream[F[_]: Sync]: Stream[F, Heal] = {
def getLine[F[_]: Sync] : F[String] =
Sync[F].delay(scala.io.StdIn.readLine)
Stream.eval(getLine[F]).as(Heal(10)).repeat
}
def coolioStream[F[_]: Concurrent: Timer]: Stream[F, Unit] = for {
health <- Stream.eval(Ref.of[F, Int](20))
queue <- Stream.eval(Queue.unbounded[F, MyEvents])
_ <- eventLoop(health, queue)
.concurrently(
Stream.awakeDelay[F](2.seconds).as(Damage(5)).to(queue.enqueue)
).concurrently(
Stream.awakeDelay[F](5.second).as(Heal(2)).to(queue.enqueue)
).concurrently(
readLineStream.to(queue.enqueue)
)
} yield ()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment