diff options
Diffstat (limited to 'src/scalevalapokalypsi/Model')
-rw-r--r-- | src/scalevalapokalypsi/Model/Action.scala | 7 | ||||
-rw-r--r-- | src/scalevalapokalypsi/Model/Area.scala | 7 | ||||
-rw-r--r-- | src/scalevalapokalypsi/Model/Entities/Entity.scala | 41 | ||||
-rw-r--r-- | src/scalevalapokalypsi/Model/Entities/Player.scala | 53 | ||||
-rw-r--r-- | src/scalevalapokalypsi/Model/Event.scala | 28 | ||||
-rw-r--r-- | src/scalevalapokalypsi/Model/SingEffects.scala | 14 |
6 files changed, 121 insertions, 29 deletions
diff --git a/src/scalevalapokalypsi/Model/Action.scala b/src/scalevalapokalypsi/Model/Action.scala index cee0ee5..30fbf46 100644 --- a/src/scalevalapokalypsi/Model/Action.scala +++ b/src/scalevalapokalypsi/Model/Action.scala @@ -63,7 +63,8 @@ class Action(input: String): if end == "suohon" then val targetEntity = actor.location.getEntity(start) targetEntity - .foreach(e => actor.setSingEffect(defaultSingAttack(e))) + .foreach(e => actor.setSingEffect(DefaultSingAttack(e))) + targetEntity.foreach(_.observeString(s"${actor.name} laulaa sinua suohon!")) targetEntity.map(e => ( "Aloitat suohonlaulun.", s"${actor.name} aloittaa suohonlaulun." @@ -78,9 +79,9 @@ class Action(input: String): resOption.map(_(1)).filter(_.length > 0) .foreach(s => - actor.location.getEntities.filter(_ != actor).foreach(_.observe(s)) + actor.location.getEntities.filter(_ != actor).foreach(_.observeString(s)) if oldLocation != actor.location then - oldLocation.getEntities.foreach(_.observe(s)) + oldLocation.getEntities.foreach(_.observeString(s)) ) resOption.map(_(0)) diff --git a/src/scalevalapokalypsi/Model/Area.scala b/src/scalevalapokalypsi/Model/Area.scala index f534309..96392ba 100644 --- a/src/scalevalapokalypsi/Model/Area.scala +++ b/src/scalevalapokalypsi/Model/Area.scala @@ -33,6 +33,13 @@ class Area(val name: String, var description: String): def getEntities: Iterable[Entity] = this.entities.values def getEntity(name: String): Option[Entity] = this.entities.get(name) + /** Makes all entities in this area observe the given event. + * + * @param event the event to observe. + */ + def observeEvent(event: Event): Unit = + this.getEntities.foreach(_.observe(event)) + /** Tells whether this area has a neighbor in the given direction. * * @param direction the direction to check diff --git a/src/scalevalapokalypsi/Model/Entities/Entity.scala b/src/scalevalapokalypsi/Model/Entities/Entity.scala index 1592f2e..26dd7dc 100644 --- a/src/scalevalapokalypsi/Model/Entities/Entity.scala +++ b/src/scalevalapokalypsi/Model/Entities/Entity.scala @@ -20,25 +20,46 @@ class Entity( 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!") - - def condition: String = + + /** 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 - s"$name näyttää maansa myyneeltä." + ("Sinua heikottaa ja tunnet olevasi lähellä häviötä.", + s"$name näyttää maansa myyneeltä.") else if hp < maxHP * .50 then - s"$name näyttää sinnittelevän yhä." + ("Sinnittelet yhä, mutta kuntosi on laskenut suuresti.", + s"$name näyttää sinnittelevän yhä.") else if hp < maxHP * .75 then - s"$name näyttää aavistuksen lannistuneelta." + ("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 - s"$name on yhä täysissä voimissaan." + ("Olet täysin kunnossa.", s"$name näyttää kuin vastasyntyneeltä.") /** Does nothing, except possibly in inherited classes. */ - def observe(observation: String): Unit = - println("[debug] entity got observation & discarded it") + 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 @@ -83,7 +104,7 @@ class Entity( ) def sayTo(entity: Entity, message: String): (String, String) = - entity.observe(s"${this.name}: \"$message\"") + entity.observeString(s"${this.name}: \"$message\"") (s"You say so to ${entity.name}.", "") def say(message: String): (String, String) = diff --git a/src/scalevalapokalypsi/Model/Entities/Player.scala b/src/scalevalapokalypsi/Model/Entities/Player.scala index 7e441c1..f231c28 100644 --- a/src/scalevalapokalypsi/Model/Entities/Player.scala +++ b/src/scalevalapokalypsi/Model/Entities/Player.scala @@ -15,14 +15,20 @@ import scalevalapokalypsi.Model.* class Player(name: String, initialLocation: Area) extends Entity(name, initialLocation): private val observations: Buffer[String] = Buffer.empty - private var pendingSingEffect: Option[Float => String] = None + private val observedEvents: Buffer[Event] = Buffer.empty + private var pendingSingEffect: Option[SingEffect] = None - override def observe(observation: String): Unit = + override def observeString(observation: String): Unit = this.observations.append(observation) + override def observe(event: Event): Unit = + this.observedEvents.append(event) def readAndClearObservations(): Vector[String] = - val res = this.observations.toVector + val res1 = this.observations + val res2 = this.observedEvents.map(_.descriptionFor(this)) + val res = (res1 ++ res2).toVector observations.clear() + observedEvents.clear() res /** Returns whether this player has a pending sing effect. */ @@ -33,18 +39,37 @@ class Player(name: String, initialLocation: Area) extends Entity(name, initialLo * * @param effect the effect to apply based on the song. */ - def setSingEffect(effect: Float => String): Unit = + def setSingEffect(effect: SingEffect): Unit = this.pendingSingEffect = Some(effect) + + def getSingEffectTarget: Option[Entity] = + this.pendingSingEffect.map(_.target) - /** Applies the pending sing effect. - * - * @param singQuality the quality of the song - * @return a textual description of the effects of the song, - * or None if there was no pending sing effect. - */ - def applySingEffect(singQuality: Float): Option[String] = - val res = this.pendingSingEffect.map(f => f(singQuality)) + /** Applies the pending sing effect and informs the surronding Entities + * about the effects of the song. + * + * @param singQuality the quality of the song + */ + def applySingEffect(singQuality: Float): Unit = + val res = this.pendingSingEffect.map(ef => ef(singQuality)) this.pendingSingEffect = None - res - + val qualityDescriptions = + if singQuality < .10 then + ("säälittävää", "epsilonin suuruinen") + else if singQuality < .30 then + ("heikkoa", "vähäinen") + else if singQuality < .60 then + ("keskinkertaista", "huomattavissa") + else if singQuality < .80 then + ("hyvää", "huomattava") + else ("erinomaista", "merkittävä") + val quality = + s"Laulu on ${qualityDescriptions(0)} ja sen vaikutus on ${qualityDescriptions(1)}." + val event = res.map(ev => Event( + ev.target, + s"$quality\n${ev.inFirstPerson}", + s"$quality\n${ev.inThirdPerson}" + )) + event.foreach(this.location.observeEvent(_)) + end Player diff --git a/src/scalevalapokalypsi/Model/Event.scala b/src/scalevalapokalypsi/Model/Event.scala new file mode 100644 index 0000000..cba611d --- /dev/null +++ b/src/scalevalapokalypsi/Model/Event.scala @@ -0,0 +1,28 @@ +package scalevalapokalypsi.Model + +import scalevalapokalypsi.Model.Entities.Entity + +/** A description of an action. + * + * @param target the entity that was as a target in this event + * @param inFirstPerson textual description of the event in first person + * @param inThirdPerson textual description of the event in third person + */ +class Event( + val target: Entity, + val inFirstPerson: String, + val inThirdPerson: String +): + + /** Gets the description of this event as seen by the given + * entity. Note that this method does no checks whether the given entity + * could even see the event, only what it would have looked like to them. + * + * @param entity the entity whose perspective to use + * @return a textual description of the event + */ + def descriptionFor(entity: Entity): String = + if entity == target then inFirstPerson + else inThirdPerson + +end Event
\ No newline at end of file diff --git a/src/scalevalapokalypsi/Model/SingEffects.scala b/src/scalevalapokalypsi/Model/SingEffects.scala index 247d672..6702df5 100644 --- a/src/scalevalapokalypsi/Model/SingEffects.scala +++ b/src/scalevalapokalypsi/Model/SingEffects.scala @@ -2,6 +2,16 @@ package scalevalapokalypsi.Model import scalevalapokalypsi.Model.Entities.Entity -def defaultSingAttack(targetEntity: Entity)(singQuality: Float): String = +def defaultSingAttack(targetEntity: Entity)(singQuality: Float): Event = targetEntity.takeDamage((singQuality * 30).toInt) - targetEntity.condition
\ No newline at end of file + val condition = targetEntity.condition + Event(targetEntity, condition(0), condition(1)) + +trait SingEffect(val target: Entity): + def apply(singQuality: Float): Event + +class DefaultSingAttack(target: Entity) extends SingEffect(target): + def apply(singQuality: Float): Event = + this.target.takeDamage((singQuality * 50).toInt) // TODO: remove magic value + val condition = this.target.condition + Event(target, condition(0), condition(1)) |