aboutsummaryrefslogtreecommitdiff
path: root/src/scalevalapokalypsi/Model
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.kronqvist@iki.fi>2024-11-17 17:06:56 +0200
committerJoel Kronqvist <joel.kronqvist@iki.fi>2024-11-17 17:06:56 +0200
commitc954ca4d1ec677a34a6d787a23f9d01396f7e585 (patch)
treec6b00b5046bde3a98c18f9557198f852b4ce9d46 /src/scalevalapokalypsi/Model
parenta6b0330c845d4edad87c7059bac56e194a276c6f (diff)
downloadscalevalapokalypsi-c954ca4d1ec677a34a6d787a23f9d01396f7e585.tar.gz
scalevalapokalypsi-c954ca4d1ec677a34a6d787a23f9d01396f7e585.zip
Template for singing, WIP.
* The line to sing is always the same. * The client recovers weirdly from singing before the next turn and my brain is currently too fried to figure out why
Diffstat (limited to 'src/scalevalapokalypsi/Model')
-rw-r--r--src/scalevalapokalypsi/Model/Action.scala40
-rw-r--r--src/scalevalapokalypsi/Model/Adventure.scala9
-rw-r--r--src/scalevalapokalypsi/Model/Area.scala2
-rw-r--r--src/scalevalapokalypsi/Model/Entities/Entity.scala30
-rw-r--r--src/scalevalapokalypsi/Model/Entities/Player.scala23
-rw-r--r--src/scalevalapokalypsi/Model/SingEffects.scala7
6 files changed, 91 insertions, 20 deletions
diff --git a/src/scalevalapokalypsi/Model/Action.scala b/src/scalevalapokalypsi/Model/Action.scala
index e59d5f1..cee0ee5 100644
--- a/src/scalevalapokalypsi/Model/Action.scala
+++ b/src/scalevalapokalypsi/Model/Action.scala
@@ -2,10 +2,13 @@ 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” */
+/** 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
@@ -19,12 +22,19 @@ class Action(input: String):
case "get" => actor.location.hasItem(this.modifiers)
case "drop" => actor.canDrop(this.modifiers)
case "say" => false
+ case "laula" => false
case other => false
- /** Causes the given player to take the action represented by this object, assuming
- * that the command was understood. Returns a description of what happened as a result
- * of the action (such as “You go west.”). The description is returned in an `Option`
- * wrapper; if the command was not recognized, `None` is returned. */
+ /** Causes the given player to take the action represented by this object,
+ * assuming that the command was understood. Returns a description of what
+ * happened as a result of the action (such as “You go west.”). The
+ * description is returned in an `Option` wrapper; if the command was not
+ * recognized, `None` is returned.
+ *
+ * @param actor the acting player
+ * @return A textual description of the action, or `None` if the action
+ * was not recognized.
+ */
def execute(actor: Player): Option[String] =
val oldLocation = actor.location
val resOption: Option[(String, String)] = this.verb match
@@ -46,6 +56,20 @@ class Action(input: String):
else
Some(actor.say(modifiers))
case "drop" => Some(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(e => (
+ "Aloitat suohonlaulun.",
+ s"${actor.name} aloittaa suohonlaulun."
+ ))
+ else
+ None
case "xyzzy" => Some((
"The grue tastes yummy.",
s"${actor.name} tastes some grue.")
diff --git a/src/scalevalapokalypsi/Model/Adventure.scala b/src/scalevalapokalypsi/Model/Adventure.scala
index 9d07ba6..0fbf6cd 100644
--- a/src/scalevalapokalypsi/Model/Adventure.scala
+++ b/src/scalevalapokalypsi/Model/Adventure.scala
@@ -36,14 +36,14 @@ class Adventure(val playerNames: Vector[String]):
"Et vielä voi tehdä sillä mitään, koska et edes osaa laula."
))
- val players: Map[String, Player] = Map()
- playerNames.foreach(this.addPlayer(_))
-
val entities: Map[String, Entity] = Map()
private val gruu = Entity("Gruu", northForest)
northForest.addEntity(gruu)
this.entities += gruu.name -> gruu
+ val players: Map[String, Player] = Map()
+ playerNames.foreach(this.addPlayer(_))
+
/** Adds a player entity with the specified name to the game.
*
* @param name the name of the player entity to add
@@ -52,9 +52,10 @@ class Adventure(val playerNames: Vector[String]):
def addPlayer(name: String): Player =
val newPlayer = Player(name, middle)
middle.addEntity(newPlayer)
+ this.entities += name -> newPlayer
players += name -> newPlayer
newPlayer
-
+
/** Gets the player entity with the specified name.
*
* @param name name of the player to find
diff --git a/src/scalevalapokalypsi/Model/Area.scala b/src/scalevalapokalypsi/Model/Area.scala
index a11b0e5..f534309 100644
--- a/src/scalevalapokalypsi/Model/Area.scala
+++ b/src/scalevalapokalypsi/Model/Area.scala
@@ -30,8 +30,8 @@ class Area(val name: String, var description: String):
def getNeighborNames: Iterable[String] = this.neighbors.keys
def getItemNames: Iterable[String] = this.items.keys
def getEntityNames: Iterable[String] = this.entities.values.map(_.name)
- def getEntity(name: String): Option[Entity] = this.entities.get(name)
def getEntities: Iterable[Entity] = this.entities.values
+ def getEntity(name: String): Option[Entity] = this.entities.get(name)
/** Tells whether this area has a neighbor in the given direction.
*
diff --git a/src/scalevalapokalypsi/Model/Entities/Entity.scala b/src/scalevalapokalypsi/Model/Entities/Entity.scala
index b90a61a..1592f2e 100644
--- a/src/scalevalapokalypsi/Model/Entities/Entity.scala
+++ b/src/scalevalapokalypsi/Model/Entities/Entity.scala
@@ -1,22 +1,44 @@
package scalevalapokalypsi.Model.Entities
-import scala.collection.mutable.Map
+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):
+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
+
+ def takeDamage(amount: Int): Unit =
+ hp -= amount
+ if hp < 0 then
+ println("Oh no, I died!")
+
+ def condition: String =
+ if hp < maxHP * .25 then
+ s"$name näyttää maansa myyneeltä."
+ else if hp < maxHP * .50 then
+ s"$name näyttää sinnittelevän yhä."
+ else if hp < maxHP * .75 then
+ s"$name näyttää aavistuksen lannistuneelta."
+ else
+ s"$name on yhä täysissä voimissaan."
/** Does nothing, except possibly in inherited classes. */
def observe(observation: String): Unit =
- println("no observation made.")
- ()
+ println("[debug] entity got observation & discarded it")
/** Returns the player’s current location. */
def location = this.currentLocation
diff --git a/src/scalevalapokalypsi/Model/Entities/Player.scala b/src/scalevalapokalypsi/Model/Entities/Player.scala
index 6e82837..7e441c1 100644
--- a/src/scalevalapokalypsi/Model/Entities/Player.scala
+++ b/src/scalevalapokalypsi/Model/Entities/Player.scala
@@ -15,6 +15,7 @@ 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
override def observe(observation: String): Unit =
this.observations.append(observation)
@@ -23,5 +24,27 @@ class Player(name: String, initialLocation: Area) extends Entity(name, initialLo
val res = this.observations.toVector
observations.clear()
res
+
+ /** Returns whether this player has a pending sing effect. */
+ def isSinging: Boolean = this.pendingSingEffect.isDefined
+ /** Makes this player start singing, i.e. gives it this sing effect to
+ * complete.
+ *
+ * @param effect the effect to apply based on the song.
+ */
+ def setSingEffect(effect: Float => String): Unit =
+ this.pendingSingEffect = Some(effect)
+
+ /** 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))
+ this.pendingSingEffect = None
+ res
+
end Player
diff --git a/src/scalevalapokalypsi/Model/SingEffects.scala b/src/scalevalapokalypsi/Model/SingEffects.scala
index 981b772..247d672 100644
--- a/src/scalevalapokalypsi/Model/SingEffects.scala
+++ b/src/scalevalapokalypsi/Model/SingEffects.scala
@@ -1,6 +1,7 @@
-/*package scalevalapokalypsi.Model
+package scalevalapokalypsi.Model
+
+import scalevalapokalypsi.Model.Entities.Entity
def defaultSingAttack(targetEntity: Entity)(singQuality: Float): String =
targetEntity.takeDamage((singQuality * 30).toInt)
- targetEntity.condition
-*/ \ No newline at end of file
+ targetEntity.condition \ No newline at end of file