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, val maxInventoryWeight: Int = 10 ): private var currentLocation: Area = initialLocation private var quitCommandGiven = false // one-way flag private var hp = initialHP private var items: Map[String, (Int, Item)] = Map() // 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("Voi ei, kuolin!") /** 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): 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 self = Vector((this, s"You go $direction.")) Some(Event( (leaving ++ self).toMap, s"$name saapuu tänne." )) else None def pickUp(itemName: String): Event = this.currentLocation.removeItem(itemName) match case Some(i) => val inventoryWeight = items.values.map(p => p(1).weight).sum if inventoryWeight + i.weight > maxInventoryWeight then Event( immutable.Map.from(Vector((this, s"Voimasi eivät riitä kannattelemaan esinettä ${i.name}, koska kannat liikaa"))), s"") else if items.contains(i.name) then val (current, _) = items(i.name) this.items += i.name -> (current + 1, i) else this.items += i.name -> (1, i) Event( immutable.Map.from(Vector((this, s"Poimit esineen ${i.name}"))), s"$name poimi esineen ${i.name}" ) case None => Event( immutable.Map.from(Vector((this, s"Täällä ei ole esinettä $itemName noukittavaksi."))), s"${this.name} yritti ottaa jotakin, mutta sai vain likaa käsilleen." ) def drop(itemName: String): Event = this.items.remove(itemName) match case Some((current, item)) if current > 0 => if current - 1 == 0 then this.items -= item.name else this.items += itemName -> (current - 1, item) this.currentLocation.addItem(item) Event( immutable.Map.from(Vector((this, s"Pudotit esineen $itemName"))), s"$name Pudotti esineen $itemName" ) case None => Event( immutable.Map.from(Vector((this, "Sinulla ei ole tätä esinettä!"))), s"$name yritti tonkia rpustaan esineen $itemName mutta ei löytänyt sitä." ) 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.items.contains(itemName) /** Returns a brief description of the player’s state, for debugging purposes. */ override def toString = s"${this.name} at ${this.location.name}" def inventory: Event = if this.items.isEmpty then Event( immutable.Map.from(Vector((this, s"Sinulla ei ole esineitä"))), s"") else var inventoryList = List[String]() for (name, (count, item)) <- this.items do inventoryList = inventoryList :+ s"$name $count (${item.description})" Event( immutable.Map.from(Vector((this, s"Kannat repussasi:\n" + inventoryList.mkString("\n")))), s"") end Entity