aboutsummaryrefslogtreecommitdiff
path: root/src/scalevalapokalypsi/Model
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.kronqvist@iki.fi>2024-11-26 14:03:23 +0200
committerJoel Kronqvist <joel.kronqvist@iki.fi>2024-11-26 14:10:45 +0200
commit38900e0b291d5e0f59afaaa239cd237f733b6588 (patch)
treeee04f697ab17a75c9563ee87763cbcdcde8d297b /src/scalevalapokalypsi/Model
parent27dd937617cce1e43df1c16e12050f6e88763d54 (diff)
downloadscalevalapokalypsi-38900e0b291d5e0f59afaaa239cd237f733b6588.tar.gz
scalevalapokalypsi-38900e0b291d5e0f59afaaa239cd237f733b6588.zip
Dying properly
Diffstat (limited to 'src/scalevalapokalypsi/Model')
-rw-r--r--src/scalevalapokalypsi/Model/Action.scala11
-rw-r--r--src/scalevalapokalypsi/Model/Adventure.scala25
-rw-r--r--src/scalevalapokalypsi/Model/Entities/Entity.scala19
-rw-r--r--src/scalevalapokalypsi/Model/Entities/NPCs/NPC.scala8
-rw-r--r--src/scalevalapokalypsi/Model/Entities/Player.scala17
-rw-r--r--src/scalevalapokalypsi/Model/SingEffects.scala4
6 files changed, 60 insertions, 24 deletions
diff --git a/src/scalevalapokalypsi/Model/Action.scala b/src/scalevalapokalypsi/Model/Action.scala
index c7c8a65..21e1286 100644
--- a/src/scalevalapokalypsi/Model/Action.scala
+++ b/src/scalevalapokalypsi/Model/Action.scala
@@ -40,15 +40,14 @@ class Action(input: String):
case "inventory" => Some((false, actor.inventory))
case "sano" =>
val entityNames = actor.location.getEntityNames.map(_.toLowerCase)
- val recipientNamePair = entityNames.map(name =>
+ val recipientNamePair = entityNames.flatMap(name =>
val possibleNamesWithSuffix = (0 to "ille".length).map(i =>
- modifiers.takeRight(name.length + i)
+ modifiers.takeRight(name.length + i)
)
possibleNamesWithSuffix.find(s =>
- s.take(name.length) == name
- )
- .map(_.splitAt(name.length))
- ).flatten.headOption
+ s.take(name.length) == name
+ )
+ .map(_.splitAt(name.length))).headOption
val recipient = recipientNamePair.flatMap(p =>
actor.location.getEntity(p(0))
diff --git a/src/scalevalapokalypsi/Model/Adventure.scala b/src/scalevalapokalypsi/Model/Adventure.scala
index ba45abe..b10f7d9 100644
--- a/src/scalevalapokalypsi/Model/Adventure.scala
+++ b/src/scalevalapokalypsi/Model/Adventure.scala
@@ -46,7 +46,7 @@ class Adventure(val playerNames: Vector[String]):
("Rotten zombie", tangle, 10)
)
zombieAttrs.foreach(z =>
- val zombie = Zombie(z(0), z(1), z(2))
+ val zombie = Zombie(this, z(0), z(1), z(2))
npcs += z(0) -> zombie
z(1).addEntity(zombie)
)
@@ -54,7 +54,7 @@ class Adventure(val playerNames: Vector[String]):
def takeNpcTurns(): Unit =
npcs.values.foreach(_.act())
- private val gruu = Entity("Gruu", northForest)
+ private val gruu = Entity(this, "Gruu", northForest)
northForest.addEntity(gruu)
this.entities += gruu.name -> gruu
@@ -67,12 +67,29 @@ class Adventure(val playerNames: Vector[String]):
* @return the created player entity
*/
def addPlayer(name: String): Player =
- val newPlayer = Player(name, middle)
+ val newPlayer = Player(this, name, middle)
middle.addEntity(newPlayer)
this.entities += name -> newPlayer
players += name -> newPlayer
newPlayer
-
+
+ /** Removes the given entity without further observations. Makes sense in the
+ * game mostly if the entity's HP is nonpositive.
+ *
+ * Removes the entity both from the adventure and the game world
+ * (i.e. the entitys area).
+ *
+ * @param name the name of the entity to remove
+ * @return whether there was an entity to remove with the given name
+ */
+ def removeEntity(name: String): Boolean =
+ this.players.remove(name)
+ this.entities.remove(name).orElse(this.npcs.remove(name)) match
+ case Some(e) =>
+ e.location.removeEntity(name)
+ true
+ case None => false
+
/** Gets the player entity with the specified name.
*
* @param name name of the player to find
diff --git a/src/scalevalapokalypsi/Model/Entities/Entity.scala b/src/scalevalapokalypsi/Model/Entities/Entity.scala
index 336a6b1..aa2a2e2 100644
--- a/src/scalevalapokalypsi/Model/Entities/Entity.scala
+++ b/src/scalevalapokalypsi/Model/Entities/Entity.scala
@@ -12,6 +12,7 @@ import scala.collection.immutable
* @param initialLocation the Area where the entity is instantiated
*/
class Entity(
+ val adventure: Adventure,
val name: String,
initialLocation: Area,
initialHP: Int = 100,
@@ -31,10 +32,24 @@ class Entity(
*/
def getVerseAgainst: String = "Esimerkkirivi laulettavaksi"
+ def isAlive = this.hp > 0
+
def takeDamage(amount: Int): Unit =
hp -= amount
- if hp < 0 then
- println("Voi ei, kuolin!")
+ val event = if this.isAlive then
+ Event(
+ Vector(this -> this.condition(0)).toMap,
+ this.condition(1)
+ )
+ else
+ println(s"Could remove myself: ${this.adventure.removeEntity(this.name)}")
+ Event(
+ Vector(this ->
+ "Olet täysin menettänyt toimintakykysi. Kaadut elottomana maahan."
+ ).toMap,
+ s"${this.name} kaatuu elottomana maahan."
+ )
+ this.location.observeEvent(event)
/** Returns a description of the physical condition of this entity,
* i.e. the damage it has taken.
diff --git a/src/scalevalapokalypsi/Model/Entities/NPCs/NPC.scala b/src/scalevalapokalypsi/Model/Entities/NPCs/NPC.scala
index 21709ba..944f2e6 100644
--- a/src/scalevalapokalypsi/Model/Entities/NPCs/NPC.scala
+++ b/src/scalevalapokalypsi/Model/Entities/NPCs/NPC.scala
@@ -17,19 +17,21 @@ import scala.util.Random
* @param initialLocation the NPC’s initial location
*/
abstract class NPC(
+ adventure: Adventure,
name: String,
initialLocation: Area,
initialHP: Int,
maxHp: Int
-) extends Entity(name, initialLocation, initialHP, maxHp):
+) extends Entity(adventure, name, initialLocation, initialHP, maxHp):
def getDialog: String
def act(): Unit
class Zombie(
+ adventure: Adventure,
identifier: String,
initialLocation: Area,
initialHP: Int = 20
-) extends NPC(identifier, initialLocation, initialHP, 20):
+) extends NPC(adventure, identifier, initialLocation, initialHP, 20):
private val damage = 10
private val dialogs = Vector(
@@ -60,7 +62,7 @@ class Zombie(
.toVector
.lift(directionIndex)
.flatMap(this.go(_))
- .map(this.location.observeEvent(_))
+ .foreach(this.location.observeEvent(_))
else
this.location.observeEvent(
this.attack(possibleVictims(index))
diff --git a/src/scalevalapokalypsi/Model/Entities/Player.scala b/src/scalevalapokalypsi/Model/Entities/Player.scala
index d6b3529..9fc929d 100644
--- a/src/scalevalapokalypsi/Model/Entities/Player.scala
+++ b/src/scalevalapokalypsi/Model/Entities/Player.scala
@@ -12,7 +12,11 @@ import scalevalapokalypsi.Model.*
* @param name the player's name
* @param initialLocation the player’s initial location
*/
-class Player(name: String, initialLocation: Area) extends Entity(name, initialLocation):
+class Player(
+ adventure: Adventure,
+ name: String,
+ initialLocation: Area
+) extends Entity(adventure, name, initialLocation):
private val observations: Buffer[String] = Buffer.empty
private val observedEvents: Buffer[Event] = Buffer.empty
@@ -49,8 +53,6 @@ class Player(name: String, initialLocation: Area) extends Entity(name, initialLo
* @param singQuality the quality of the song
*/
def applySingEffect(singQuality: Float): Unit =
- val res = this.pendingSingEffect.map(ef => ef(singQuality))
- this.pendingSingEffect = None
val qualityDescriptions =
if singQuality < .10 then
("säälittävää", "epsilonin suuruinen")
@@ -63,11 +65,10 @@ class Player(name: String, initialLocation: Area) extends Entity(name, initialLo
else ("erinomaista", "merkittävä")
val quality =
s"Laulu on ${qualityDescriptions(0)} ja sen vaikutus on ${qualityDescriptions(1)}."
- val event = res.map(ev => Event(
- ev.inFirstPersons.map((k, v) => (k, s"$quality\n$v")),
- s"$quality\n${ev.inThirdPerson}"
- ))
- event.foreach(this.location.observeEvent(_))
+ val event = Event(Map.empty, s"$quality")
+ this.location.observeEvent(event)
+ this.pendingSingEffect.map(ef => ef(singQuality))
+ this.pendingSingEffect = None
diff --git a/src/scalevalapokalypsi/Model/SingEffects.scala b/src/scalevalapokalypsi/Model/SingEffects.scala
index 42f5188..23b7d37 100644
--- a/src/scalevalapokalypsi/Model/SingEffects.scala
+++ b/src/scalevalapokalypsi/Model/SingEffects.scala
@@ -10,4 +10,6 @@ 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(Map.from(Vector((target, condition(0)))), condition(1))
+ Event(Map.empty, "") // The conditions are automatically shown to
+ // clients through takeDamage, but other effects
+ // should explain the changes they have.