Created
May 31, 2017 19:39
-
-
Save programaths/e96e86be51d6a7424f6e9787a40271df to your computer and use it in GitHub Desktop.
An example of text adventure in Kotlin
This file contains hidden or 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
| /* | |
| * This file implement a very simple text game engine and a DSL. | |
| */ | |
| fun main(args: Array<String>) { | |
| val game=Branch("You awake in a dark forest. Where do you want to go ?"){ | |
| WalkNorth() leadsTo TerminalBranch("You went too far in the dark and have been killed by a somber creature") | |
| WalkSouth() leadsTo TerminalBranch("You just fel from a cliff. Dumb move !") | |
| WalkEast() leadsTo Branch("""In front of you is a yellowish box. | |
| It really stand out from the night."""){ | |
| OpenAction() leadsTo TerminalBranch("A snake pop out of the box and bite you. You die of a painful poisoning!") | |
| val startOfBridgeref:RefBranch=RefBranch(Branch()) | |
| val startOfBridge=Branch("You are facing a very old bridge."){ | |
| WalkNorth() leadsTo Branch("you are in the middle of a very old bridge"){ | |
| WalkSouth() leadsTo startOfBridgeref | |
| WalkNorth() leadsTo Branch("Congratulation, you crossed the bridge and are out of the forest !") | |
| } | |
| } | |
| startOfBridgeref.ref=startOfBridge // Little hack to pass a reference to a closure | |
| WalkNorth() leadsTo startOfBridge | |
| } | |
| } | |
| game.process() | |
| } | |
| interface Action{ | |
| val label:String | |
| fun accept(input :String):Boolean | |
| } | |
| abstract class SimpleAction(override val label: String):Action{ | |
| override fun accept(input: String) = label == input | |
| } | |
| class OpenAction:SimpleAction("OPEN") | |
| class CloseAction:SimpleAction("CLOSE") | |
| class HitAction:SimpleAction("HIT") | |
| abstract class WalkAction(val direction:String):Action{ | |
| override val label: String = "WALK $direction" | |
| override fun accept(input: String): Boolean { | |
| val (iaction,idirection)=input.replace(Regex.fromLiteral(" {2,}")," ").split(" ") | |
| return iaction=="WALK" && direction==idirection | |
| } | |
| } | |
| class WalkNorth:WalkAction("NORTH") | |
| class WalkSouth:WalkAction("SOUTH") | |
| class WalkEast:WalkAction("EAST") | |
| class WalkWest:WalkAction("WEST") | |
| interface IBranch { | |
| val description: String | |
| val fn: IBranch.() -> Unit | |
| fun process() | |
| infix fun Action.leadsTo(brc: IBranch) | |
| } | |
| open class Branch(override val description:String="", override val fn:IBranch.()->Unit={}) : IBranch { | |
| val actions:MutableList<Pair<Action,IBranch>> = mutableListOf() | |
| var visited=false | |
| override fun process() { | |
| if (!visited) this.fn() | |
| visited=true | |
| println(description) | |
| print("The following are available: \n- ${actions.map { it.first.label }.joinToString("\n- ")}\n> ") | |
| var input= readLine() ?: "" | |
| var processed = actions.find { it.first.accept(input) }?.second?.run { process(); true }?:false | |
| while (!processed){ | |
| input= readLine() ?: "" | |
| processed = actions.find { it.first.accept(input) }?.second?.run { process(); true }?:false | |
| } | |
| } | |
| override infix fun Action.leadsTo(brc:IBranch){ | |
| actions.add(this to brc) | |
| } | |
| } | |
| class RefBranch(var ref:Branch=Branch()):IBranch { | |
| override val fn: IBranch.() -> Unit | |
| get() = ref.fn | |
| override val description: String | |
| get() = ref.description | |
| override fun process() { | |
| ref.process() | |
| } | |
| override fun Action.leadsTo(brc: IBranch) { | |
| ref.actions.add(this to brc) | |
| } | |
| } | |
| class TerminalBranch(val ending:String):Branch(){ | |
| override fun process(){ | |
| println(ending) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment