aboutsummaryrefslogtreecommitdiff
path: root/src/scalevalapokalypsi/Model/Entities/Entity.scala
blob: 26dd7dcd75a984203565072d7a819b21110784a4 (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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package scalevalapokalypsi.Model.Entities

import scala.collection.mutable.{Buffer,Map}
import scalevalapokalypsi.Model.*


/** An in-game entity.
  *
  * @param name the name of the entity
  * @param initialLocation the Area where the entity is instantiated
  */
class Entity(
	val name: String,
	initialLocation: Area,
	initialHP: Int = 100,
	val maxHP: Int = 100
):

	private var currentLocation: Area = initialLocation
	private var quitCommandGiven = false // one-way flag
	private val inventory: Map[String, Item] = Map()
	private var hp = initialHP

	// TODO: add logic for choosing from multiplu lines - can depend on HP etc.
	/** Gets a verse to sing when attacking against this entity.
	  *
	  * @return the verse to sing against this entity
	  */
	def getVerseAgainst: String = "Esimerkkirivi laulettavaksi"

	def takeDamage(amount: Int): Unit =
		hp -= amount
		if hp < 0 then
			println("Oh no, I died!")

	/** Returns a description of the physical condition of this entity,
	  * i.e. the damage it has taken.
	  *
	  * @return a pair of strings, both of which describe the condition of this
	  *         entity, the first of which is in first person and the second in
	  *         third person.
	  */
	def condition: (String, String) =
		if hp < maxHP * .25 then
			("Sinua heikottaa ja tunnet olevasi lähellä häviötä.",
				s"$name näyttää maansa myyneeltä.")
		else if hp < maxHP * .50 then
			("Sinnittelet yhä, mutta kuntosi on laskenut suuresti.",
				s"$name näyttää sinnittelevän yhä.")
		else if hp < maxHP * .75 then
			("Tunnet koettelemusten vaikutuksen, mutta et anna niiden lannistaa itseäsi",
				s"$name näyttää aavistuksen lannistuneelta.")
		else if hp < maxHP then
			("Olet voimissasi.", s"$name on yhä voimissaan.")
		else
			("Olet täysin kunnossa.", s"$name näyttää kuin vastasyntyneeltä.")

	/** Does nothing, except possibly in inherited classes. */
	def observeString(observation: String): Unit =
		println("    [debug] entity got observation string & discarded it")
	def observe(event: Event): Unit =
		println("    [debug] entity got observation event & discarded it")

	/** Returns the player’s current location. */
	def location = this.currentLocation

	/** Attempts to move the player in the given direction. This is successful
	  * if there is an exit from the player’s current location towards the
	  * direction name. Returns a description of the result: "You go DIRECTION."
	  * or "You can't go DIRECTION."
	  */
	def go(direction: String): (String, String) =
		val destination = this.location.neighbor(direction)
		if destination.isDefined then
			val removeSuccess = this.currentLocation.removeEntity(this.name)
			assert(removeSuccess.isDefined) // Production - assertions off
			this.currentLocation = destination.getOrElse(this.currentLocation)
			destination.foreach(_.addEntity(this))
			(s"You go $direction.", s"$name goes $direction")
		else
			(
				s"You can't go $direction.",
				s"$name tries to go $direction and stumbles in their feet."
			)

	def pickUp(itemName: String): (String, String) =
		this.currentLocation.removeItem(itemName) match
			case Some(i) =>
				this.inventory += i.name -> i
				(s"You pick up the ${i.name}", s"$name picks up the ${i.name}")
			case None => (
				s"There is no $itemName here to pick up.",
				s"${this.name} tries to pick up something but gets just dirt in their hands."
			)

	def drop(itemName: String): (String, String) =
		this.inventory.remove(itemName) match
			case Some(item) =>
				this.currentLocation.addItem(item)
				(s"You drop the $itemName", s"$name drops the $itemName")
			case None => (
				"You don't have that!",
				s"$name reaches their backpack to drop $itemName but miserably fails to find it there."
			)

	def sayTo(entity: Entity, message: String): (String, String) =
		entity.observeString(s"${this.name}: \"$message\"")
		(s"You say so to ${entity.name}.", "")

	def say(message: String): (String, String) =
		("You say that aloud.", s"$name: \"$message\"")

	/** Tells whether this entity can drop the specified item
	 * (if an action were to specify so).
	 *
	 * @param itemName the name to check
	 * @return whether this entity has this item and can drop it
	 */
	def canDrop(itemName: String): Boolean = this.inventory.contains(itemName)

	/** Causes the player to rest for a turn.
	  * Returns a description of what happened. */
	def rest(): (String, String) =
		("You rest for a while. Better get a move on, though.", "")

	/** Returns a brief description of the player’s state, for debugging purposes. */
	override def toString = s"${this.name} at ${this.location.name}"

end Entity