Skip to content

Instantly share code, notes, and snippets.

@ybakos
Created May 1, 2011 00:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ybakos/950140 to your computer and use it in GitHub Desktop.
Save ybakos/950140 to your computer and use it in GitHub Desktop.
package org.testgame
trait Named {
def name: String
}
trait Described {
def description: String
}
trait Item extends Named with Described {
override def toString = "%s: %s".format(name, description)
}
object Items {
val HealthPotion = Potion("Dale's Pale Ale", "Super hoppy and gets you drunk!")
}
case class Potion(name: String, description: String) extends Item
object Container {
def empty: Container = Container(Map.empty[Item, Int])
}
case class Container(items: Map[Item, Int]) {
def + (item: Item): Container = Container(items.get(item) match {
case None => items + (item -> 1)
case Some(count) => items + (item -> (count + 1))
})
def - (item: Item): Container = items.get(item) match {
case None => this
case Some(count) if (count <= 1) => Container(items - item)
case Some(count) => Container(items + (item -> (count - 1)))
}
override def toString = "\nINVENTORY\n" + items.zipWithIndex.foldLeft("(empty)") { (string, tuple) =>
val ((item, count), index) = tuple
"%d %s\n".format(count, item)
}
}
case class LocationId(name: String) extends Named
case class Location(id: LocationId, description: String, items: Container) extends Named with Described {
def name: String = id.name
}
object Locations {
val GrassyFields = Location(LocationId("grassy fields"),
"You are standing in grassy fields. The hot sun is beating down on you.",
Container.empty + Items.HealthPotion
)
}
case class Health(value: Int)
object Health {
val Min = Health(0)
val Max = Health(100)
}
sealed trait Character {
def health: Int
def inventory: Container
}
case class Player(name: String, health: Health, location: Location, inventory: Container)
case class World(player: Player) {
def actions: List[Action] = Exit :: Look :: ListInventory :: pickupActions
private def pickupActions: List[Action] = {
player.location.items.items.map {
case ((item, count)) => Pickup(item)
}.toList
}
}
object World {
def apply(name: String): World =
World(Player(
name = name,
health = Health.Max,
location = Locations.GrassyFields,
inventory = Container.empty
))
}
sealed trait Action extends (World => World) with Described
case class Pickup(item: Item) extends Action {
def description = "Pick up " + item.name
def apply(old: World): World = {
import old.player
import player.inventory
import player.location
old.copy(
player = player.copy(
inventory = inventory + item,
location = location.copy(
items = location.items - item
)
)
)
}
}
case object ListInventory extends Action {
def description = "List inventory"
def apply(old: World): World = {
println(old.player.inventory)
old
}
}
case object Look extends Action {
def description = "Look around"
def apply(old: World): World = {
println(old.player.location.description)
println(old.player.location.items)
old
}
}
case object Exit extends Action {
def description = "Exit the game"
def apply(old: World): World = {
println("Are you sure you want to exit the game? (y/n)")
readChar().toLower match {
case 'y' => System.exit(0)
}
old
}
}
object SwordWarrior {
def main(args: Array[String]) {
println("Welcome to SwordWarrior!")
println("What is your name? ")
val name = readLine()
println("Welcome, " + name)
val world = World(name)
run(world)
}
def betterReadInt() = {
try {
Some(readInt())
}
catch {
case _ => None
}
}
def run(world: World): World = {
println("What would you like to do now? ")
val actions = world.actions
actions.zipWithIndex.foreach {
case (action, index) =>
println(index + ". " + action.description)
}
val newWorld = (betterReadInt() match {
case Some(choice) if (choice < 0 || choice >= actions.length) =>
println("That is not a choice you have, " + world.player.name)
world
case None =>
println("That is not a number!")
world
case Some(choice) =>
val chosenAction = actions(choice)
println("You have chosen to: " + chosenAction.description)
chosenAction(world)
})
run(newWorld)
}
}
// SwordWarrior.main(args) // So I can just scala SwordWarrior.scala
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment