aboutsummaryrefslogtreecommitdiff
path: root/src/scalevalapokalypsi/Model/Action.scala
blob: 52ba165e5a1da60d9e946adf9e42e3dfd289853e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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 => oldLocation.observeEvent(r))
				result.map((true, _))
			case "rest"  => Some((true, actor.rest()))
			case "get"   => Some((false, actor.pickUp(this.modifiers)))
			case "inventory" => Some((false, actor.inventory))
			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