Created
April 19, 2014 20:33
-
-
Save jsanders/11096688 to your computer and use it in GitHub Desktop.
A simple game from "Introduction to Functional Game Programming using Scala" talk at lambdaconf2014
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class IO[A] private (run0: => A) { | |
def run = run0 | |
def flatMap[B](f: A => IO[B]): IO[B] = { | |
IO(f(run).run) | |
} | |
def map[B](f: A => B): IO[B] = flatMap(a => IO(f(a))) | |
} | |
object IO { | |
def apply[A](a: => A): IO[A] = new IO(a) | |
} | |
def point[A](a: => A): IO[A] = IO(a) | |
def getLine: IO[String] = IO(readLine()) | |
def putStrLn(v: String): IO[Unit] = IO(println(v)) | |
def intro: IO[String] = { | |
for { | |
_ <- putStrLn("Welcome to Text Adventure RPG v1.0!") | |
_ <- putStrLn("Please enter the name of your character: ") | |
name <- getLine | |
_ <- putStrLn("Welcome, " + name + ", it's time for an adventure!") | |
} yield name | |
} | |
def gameLoop: IO[Unit] = { | |
for { | |
_ <- putStrLn("What would you like to do now: ") | |
input <- getLine | |
_ <- putStrLn("You want to " + input) | |
_ <- | |
if (input == "quit" || input == "exit") | |
putStrLn("Goodbye!") | |
else | |
gameLoop | |
} yield Unit | |
} | |
(for { | |
name <- intro | |
_ <- gameLoop | |
} yield name)//.run | |
case class State[S, A](run: S => (S, A)) { | |
def flatMap[B](f: A => State[S, B]): State[S, B] = State[S, B] { s => | |
val (s2, a) = run(s) | |
f(a).run(s2) | |
} | |
def map[B](f: A => B): State[S, B] = flatMap(a => State.point(f(a))) | |
} | |
object State { | |
def point[S, A](a: => A): State[S, A] = State(s => (s, a)) | |
} | |
case class Player(health: Int) | |
case class GameState(player: Player) | |
type Game[A] = State[GameState, A] | |
def hurtPlayer(hp: Int): Game[Int] = State { s => | |
val newHealth = s.player.health - hp | |
val newState = s.copy(player = s.player.copy(health = newHealth)) | |
(newState, newHealth) | |
} | |
val InitialState = GameState(Player(100)) | |
val gameState = for { | |
_ <- hurtPlayer(10) | |
_ <- hurtPlayer(40) | |
h <- hurtPlayer(60) | |
} yield h | |
println(gameState.run(InitialState)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment