package scalevalapokalypsi.Model.Entities import scala.collection.mutable.{Buffer, Map} import scalevalapokalypsi.Model.* import scala.collection.immutable /** 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 observe(event: Event): Unit = () /** 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): Option[Event] = val destination = this.location.neighbor(direction) val oldEntities = this.location.getEntities.filter(_ != this) val newEntities = destination.map(_.getEntities) 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)) val leaving = oldEntities.zip( Vector.fill (oldEntities.size) (s"${this.name} leaves this location.") ) //val arriving = newEntities.map(n => n.zip( // Vector.fill // (n.size) // (s"${this.name} arrives here.") //)).getOrElse(Vector()) val self = Vector((this, s"You go $direction.")) Some(Event( (leaving ++ self).toMap, s"$name arrives here." )) else None def pickUp(itemName: String): Event = this.currentLocation.removeItem(itemName) match case Some(i) => this.inventory += i.name -> i Event( immutable.Map.from(Vector((this, s"You pick up the ${i.name}"))), s"$name picks up the ${i.name}" ) case None => Event( immutable.Map.from(Vector((this, 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): Event = this.inventory.remove(itemName) match case Some(item) => this.currentLocation.addItem(item) Event( immutable.Map.from(Vector((this, s"You drop the $itemName"))), s"$name drops the $itemName" ) case None => Event( immutable.Map.from(Vector((this, "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): Event = if entity == this then this.ponder(message: String) else Event( immutable.Map.from(Vector( (this, s"Sanot niin henkilölle ${entity.name}."), (entity, s"${this.name}: “${message}”") )), s"Kuulet henkilön ${this.name} sanovan jotain henkilölle ${entity.name}" ) def ponder(message: String): Event = Event( immutable.Map.from(Vector( (this, s"Mietit itseksesi: “$message”") )), s"${this.name} näyttää pohtivan jotain itsekseen." ) def say(message: String): Event = Event( immutable.Map.from(Vector((this, "Sanot niin ääneen."))), s"$name: “$message”" ) /** Causes the player to rest for a turn. * Returns a description of what happened. */ def rest(): Event = Event( immutable.Map.from(Vector((this, "Lepäät hetken."))), s"${this.name} levähtää." ) /** 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) /** Returns a brief description of the player’s state, for debugging purposes. */ override def toString = s"${this.name} at ${this.location.name}" end Entity