package scalevalapokalypsi.Model import scalevalapokalypsi.Model.Entities.* /** The class `Action` represents actions that a player may take in a text * adventure game. `Action` objects are constructed on the basis of textual * commands and are, in effect, parsers for such commands. An action object is * immutable after creation. * * @param input a textual in-game command such as “go east” or “rest” */ class Action(input: String): private val commandText = input.trim.toLowerCase private val verb = commandText.takeWhile( _ != ' ' ) private val modifiers = commandText.drop(verb.length).trim /** Causes the given player to take the action represented by this object, * assuming that the command was understood. Informs the player and the * entities surrounding it about the result. Returns true if the command * was understood and possible, false otherwise. * * @param actor the acting player * @return Boolean indicating whether the action possibly taken takes a * turn or not. */ def execute(actor: Player): Boolean = val oldLocation = actor.location val resOption: Option[(Boolean, Event)] = this.verb match case "go" => val result = actor.go(this.modifiers) result.foreach(r => if actor.location != oldLocation then oldLocation.observeEvent(r) ) result.map((true, _)) case "rest" => Some((true, actor.rest())) case "get" => Some((false, actor.pickUp(this.modifiers))) case "say" => val to = "to" val recipient = modifiers.reverse.takeWhile(_ != ' ').reverse val recipientEntity = actor.location.getEntity(recipient) val maybeTo = modifiers.slice( modifiers.length - recipient.length - s"$to ".length, modifiers.length - recipient.length - 1 ) val message = modifiers.take(modifiers.length - recipient.length - 4) if maybeTo == to then recipientEntity.map(e => (false, actor.sayTo(e, message))) else Some((false, actor.say(modifiers))) case "drop" => Some((false, actor.drop(this.modifiers))) case "laula" => val end = modifiers.takeRight("suohon".length) val start = modifiers.take(modifiers.length - "suohon".length).trim if end == "suohon" then val targetEntity = actor.location.getEntity(start) targetEntity .foreach(e => actor.setSingEffect(DefaultSingAttack(e))) targetEntity.map(t => (false, Event( Map.from(Vector((t, s"${actor.name} laulaa sinua suohon!"))), s"${actor.name} laulaa henkilöä ${t.name} suohon." )) ) else None case "xyzzy" => Some((false, Event( Map.from(Vector((actor, "The grue tastes yummy."))), s"${actor.name} tastes some grue.") )) case other => None val res: (Boolean, Event) = resOption .getOrElse((false, Event( Map.from(Vector((actor, "Tuo ei ole asia, jonka voit tehdä."))), "" ))) actor.location.observeEvent(res(1)) res(0) /** Returns a textual description of the action object, for debugging purposes. */ override def toString = s"$verb (modifiers: $modifiers)" end Action