aboutsummaryrefslogtreecommitdiff
path: root/src/scalevalapokalypsi/Model/Entities
diff options
context:
space:
mode:
Diffstat (limited to 'src/scalevalapokalypsi/Model/Entities')
-rw-r--r--src/scalevalapokalypsi/Model/Entities/Entity.scala70
-rw-r--r--src/scalevalapokalypsi/Model/Entities/NPCs/Bartender.scala52
-rw-r--r--src/scalevalapokalypsi/Model/Entities/NPCs/Cultist.scala53
-rw-r--r--src/scalevalapokalypsi/Model/Entities/NPCs/NPC.scala66
-rw-r--r--src/scalevalapokalypsi/Model/Entities/NPCs/Robber.scala72
-rw-r--r--src/scalevalapokalypsi/Model/Entities/NPCs/Zombie.scala70
-rw-r--r--src/scalevalapokalypsi/Model/Entities/Player.scala26
7 files changed, 317 insertions, 92 deletions
diff --git a/src/scalevalapokalypsi/Model/Entities/Entity.scala b/src/scalevalapokalypsi/Model/Entities/Entity.scala
index aa2a2e2..6a2072d 100644
--- a/src/scalevalapokalypsi/Model/Entities/Entity.scala
+++ b/src/scalevalapokalypsi/Model/Entities/Entity.scala
@@ -30,7 +30,8 @@ class Entity(
*
* @return the verse to sing against this entity
*/
- def getVerseAgainst: String = "Esimerkkirivi laulettavaksi"
+ def getVerseAgainst: Vector[String] =
+ Vector("Esimerkkirivi laulettavaksi")
def isAlive = this.hp > 0
@@ -42,7 +43,7 @@ class Entity(
this.condition(1)
)
else
- println(s"Could remove myself: ${this.adventure.removeEntity(this.name)}")
+ this.adventure.removeEntity(this.name)
Event(
Vector(this ->
"Olet täysin menettänyt toimintakykysi. Kaadut elottomana maahan."
@@ -97,9 +98,9 @@ class Entity(
val leaving = oldEntities.zip(
Vector.fill
(oldEntities.size)
- (s"${this.name} leaves this location.")
+ (s"${this.name} lähtee $direction")
)
- val self = Vector((this, s"You go $direction."))
+ val self = Vector((this, s"Menet $direction."))
Some(Event(
(leaving ++ self).toMap,
s"$name saapuu tänne."
@@ -112,8 +113,12 @@ class Entity(
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"")
+ Vector((
+ this,
+ s"Voimasi eivät riitä kannattelemaan esinettä ${i.name}, koska kannat liikaa"
+ )).toMap,
+ s""
+ )
else
if items.contains(i.name) then
val (current, _) = items(i.name)
@@ -121,13 +126,27 @@ class Entity(
else
this.items += i.name -> (1, i)
Event(
- immutable.Map.from(Vector((this, s"Poimit esineen ${i.name}"))),
+ Vector((this, s"Poimit esineen ${i.name}")).toMap,
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."
- )
+ 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 removeItem(itemName: String): Boolean =
+ this.items.get(itemName).map((count, item) =>
+ if count > 1 then
+ this.items.remove(itemName)
+ else
+ this.items(itemName) = (count - 1, item)
+ assert(this.items(itemName)(0) == count - 1)
+ Some(true)
+ ).isDefined
def drop(itemName: String): Event =
this.items.remove(itemName) match
@@ -138,12 +157,21 @@ class Entity(
this.items += itemName -> (current - 1, item)
this.currentLocation.addItem(item)
Event(
- immutable.Map.from(Vector((this, s"Pudotit esineen $itemName"))),
+ immutable.Map.from(
+ Vector((this, s"Pudotit esineen $itemName"))
+ ),
s"$name Pudotti esineen $itemName"
)
+ case Some((current, item)) =>
+ this.items.remove(item.name)
+ println(" [virhe] esineitä ei koskaan pitäisi olla nollaa")
+ Event(
+ Vector((this, "Sinulla ei ole tuota esinettä.")).toMap,
+ ""
+ )
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ä."
+ Vector((this, "Sinulla ei ole tätä esinettä!")).toMap,
+ s"$name yritti tonkia repustaan esineen $itemName mutta ei löytänyt sitä."
)
def sayTo(entity: Entity, message: String): Event =
@@ -154,7 +182,7 @@ class Entity(
(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}"
+ s"Kuulet henkilön ${this.name} sanovan jotain henkilölle ${entity.name}."
)
def ponder(message: String): Event =
@@ -185,7 +213,14 @@ class Entity(
* @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)
+ //def canDrop(itemName: String): Boolean = this.items.contains(itemName)
+
+ def useItem(itemName: String): Event =
+ val item: Option[Item] = this.items.get(itemName).map(_(1))
+ val event: Option[Event] = item.flatMap(_.use(this))
+ event.getOrElse(
+ Event(Vector(this -> "Sinulla ei ole tuota esinettä.").toMap, "")
+ )
/** Returns a brief description of the player’s state, for debugging purposes. */
override def toString = s"${this.name} at ${this.location.name}"
@@ -204,7 +239,4 @@ class Entity(
s"")
-
-
-
end Entity
diff --git a/src/scalevalapokalypsi/Model/Entities/NPCs/Bartender.scala b/src/scalevalapokalypsi/Model/Entities/NPCs/Bartender.scala
new file mode 100644
index 0000000..1743380
--- /dev/null
+++ b/src/scalevalapokalypsi/Model/Entities/NPCs/Bartender.scala
@@ -0,0 +1,52 @@
+/*
+package scalevalapokalypsi.Model.Entities.NPCs
+
+import scalevalapokalypsi.Model.{Area,Event,Item,Adventure}
+import scala.math.min
+
+class Bartender(
+ adventure: Adventure,
+ initialLocation: Area
+) extends NPC(
+ adventure,
+ "baarimikko",
+ initialLocation,
+ 100,
+ 100
+):
+
+
+ private var dialogIndex = 0
+
+ private val dialogs = Vector(
+ "Onnea matkaan. Tarjoan sinulle tuopin olutta rohkaisuksi.",
+ "Onnea matkaan."
+ )
+
+ def getDialog: String =
+
+ if dialogIndex == 0 then
+ this.location.addItem(Item(
+ "oluttuoppi",
+ "Tuopillinen kuohuvaa ja raikasta olutta. Se tuoksuu aika vahvalta.",
+ 1
+ ))
+ this.location.observeEvent(
+ Event(
+ Map.empty,
+ "Baarimikko kaataa tuoppiin olutta ja asettaa oluttuopin pöydälle."
+ )
+ )
+
+ dialogIndex = min(dialogIndex + 1, this.dialogs.length)
+
+ dialogs(dialogIndex - 1)
+
+ end getDialog
+
+
+ def act(): Unit = ()
+
+
+end Bartender
+*/
diff --git a/src/scalevalapokalypsi/Model/Entities/NPCs/Cultist.scala b/src/scalevalapokalypsi/Model/Entities/NPCs/Cultist.scala
new file mode 100644
index 0000000..fa5602e
--- /dev/null
+++ b/src/scalevalapokalypsi/Model/Entities/NPCs/Cultist.scala
@@ -0,0 +1,53 @@
+
+package scalevalapokalypsi.Model.Entities.NPCs
+
+import scala.collection.mutable.Buffer
+import scalevalapokalypsi.Model.*
+import scalevalapokalypsi.Model.Entities.*
+import scala.util.Random
+
+class Cultist(
+ adventure: Adventure,
+ identifier: String,
+ initialLocation: Area,
+ initialHP: Int = 100,
+ maxHP: Int = 100
+) extends NPC(adventure, identifier, initialLocation, initialHP, maxHP):
+
+ private val damage = 20
+
+ override def getDialog: String =
+ "Verta! Lisää verta!"
+
+ override def act(): Unit =
+ val possibleVictims = this.location
+ .getEntities
+ .filter(_ != this)
+ .filter(_ match
+ case c: Cultist => false
+ case other => true
+ )
+ .toVector
+ val index: Int =
+ if possibleVictims.isEmpty then 0
+ else Random.between(0, possibleVictims.length)
+ if !possibleVictims.isEmpty then
+ this.location.observeEvent(
+ this.curse(possibleVictims(index))
+ )
+
+
+ private def curse(entity: Entity): Event =
+ entity.takeDamage(this.damage)
+ Event(
+ Map.from(Vector((
+ entity,
+ s"${this.name} lausuu pimeän loitsun. Näet varjon pyyhältävän sinua kohti ja sinut valtaa kylmyys.\n" +
+ s"${entity.condition(0)}"
+ ))),
+ s"${this.name} käyttää kirousta henkilöön ${entity.name}\n" +
+ s"${entity.condition(1)}"
+ )
+
+end Cultist
+
diff --git a/src/scalevalapokalypsi/Model/Entities/NPCs/NPC.scala b/src/scalevalapokalypsi/Model/Entities/NPCs/NPC.scala
index 944f2e6..7d9996c 100644
--- a/src/scalevalapokalypsi/Model/Entities/NPCs/NPC.scala
+++ b/src/scalevalapokalypsi/Model/Entities/NPCs/NPC.scala
@@ -1,10 +1,8 @@
package scalevalapokalypsi.Model.Entities.NPCs
-import scala.collection.mutable.Buffer
import scalevalapokalypsi.Model.*
import scalevalapokalypsi.Model.Entities.*
-import scala.util.Random
/** A `NPC` object represents a non-playable in-game character controlled by
* the server using this objects `act` method. It can also be "talked to": it
@@ -25,67 +23,3 @@ abstract class NPC(
) 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(adventure, identifier, initialLocation, initialHP, 20):
-
- private val damage = 10
- private val dialogs = Vector(
- "örvlg",
- "grr",
- "äyyrrrgrlgb ww",
- "aaak brzzzwff ååö",
- "äkb glan abglum",
- "öub gpa"
- )
-
- override def getDialog: String =
- val dialogIndex = Random.between(0, this.dialogs.length)
- this.dialogs(dialogIndex)
-
- override def act(): Unit =
- val possibleVictims = this.location
- .getEntities
- .filter(_ != this)
- .toVector
- val index: Int =
- if possibleVictims.isEmpty then 0
- else Random.between(0, possibleVictims.length)
- if possibleVictims.isEmpty then
- val possibleDirections = this.location.getNeighborNames.toVector
- val directionIndex = Random.between(0, possibleDirections.length*2)
- possibleDirections
- .toVector
- .lift(directionIndex)
- .flatMap(this.go(_))
- .foreach(this.location.observeEvent(_))
- else
- this.location.observeEvent(
- this.attack(possibleVictims(index))
- )
-
-
- private def attack(entity: Entity): Event =
- if Random.nextBoolean() then
- entity.takeDamage(this.damage)
- Event(
- Map.from(Vector((
- entity,
- s"${this.name} puree sinua, hyi yäk!\n" +
- s"${entity.condition(0)}"
- ))),
- s"${this.name} puree henkilöä ${entity.name}.\n" +
- s"${entity.condition(1)}"
- )
- else
- Event(
- Map.from(Vector((
- entity,
- s"${this.name} yrittää purra sinua mutta kaatuu ohitsesi."
- ))),
- s"${this.name} yrittää purra henkilöä ${entity.name}, mutta epäonnistuu surkeasti."
- )
diff --git a/src/scalevalapokalypsi/Model/Entities/NPCs/Robber.scala b/src/scalevalapokalypsi/Model/Entities/NPCs/Robber.scala
new file mode 100644
index 0000000..fc009a6
--- /dev/null
+++ b/src/scalevalapokalypsi/Model/Entities/NPCs/Robber.scala
@@ -0,0 +1,72 @@
+
+package scalevalapokalypsi.Model.Entities.NPCs
+
+import scala.collection.mutable.Buffer
+import scalevalapokalypsi.Model.*
+import scalevalapokalypsi.Model.Entities.*
+import scala.util.Random
+
+class Robber(
+ adventure: Adventure,
+ name: String,
+ val weaponName: String,
+ val weaponDamage: Int,
+ val hitChance: Float,
+ initialLocation: Area,
+ initialHP: Int = 20
+) extends NPC(adventure, name, initialLocation, initialHP, 20):
+
+ private val dialogs = Vector(
+ "Rahat tai henki!",
+ "Anna tänne!",
+ "Syödään se ryöstön jälkeen!",
+ "Vesihiisi sihisi hississä ja muumit laaksosta poissaolollaan."
+ )
+
+ override def getDialog: String =
+ val dialogIndex = Random.between(0, this.dialogs.length)
+ this.dialogs(dialogIndex)
+
+ override def act(): Unit =
+ val possibleVictims = this.location
+ .getEntities
+ .filter(_ != this)
+ .filter(_ match
+ case z: Robber => false
+ case other => true
+ )
+ .toVector
+ val index: Int =
+ if possibleVictims.isEmpty then 0
+ else Random.between(0, possibleVictims.length)
+ if !possibleVictims.isEmpty then
+ this.location.observeEvent(
+ this.attack(possibleVictims(index))
+ )
+ //else
+ // this.location.getNeighborNames.filter(this.location.neighbor(_).map(_.getEntities.size > 0).getOrElse(false))
+
+
+ private def attack(entity: Entity): Event =
+ if Random.nextFloat() < this.hitChance then
+ entity.takeDamage(this.weaponDamage)
+ Event(
+ Map.from(Vector((
+ entity,
+ s"${this.name} lyö sinua ${this.weaponName}\n" +
+ s"${entity.condition(0)}"
+ ))),
+ s"${this.name} lyö henkilöä ${entity.name} ${this.weaponName}.\n" +
+ s"${entity.condition(1)}"
+ )
+ else
+ Event(
+ Map.from(Vector((
+ entity,
+ s"${this.name} yrittää lyödä sinua mutta väistät."
+ ))),
+ s"${this.name} yrittää lyödä henkilöä ${entity.name}, mutta tämä väistää."
+ )
+
+end Robber
+
diff --git a/src/scalevalapokalypsi/Model/Entities/NPCs/Zombie.scala b/src/scalevalapokalypsi/Model/Entities/NPCs/Zombie.scala
new file mode 100644
index 0000000..56cb160
--- /dev/null
+++ b/src/scalevalapokalypsi/Model/Entities/NPCs/Zombie.scala
@@ -0,0 +1,70 @@
+
+package scalevalapokalypsi.Model.Entities.NPCs
+
+import scala.collection.mutable.Buffer
+import scalevalapokalypsi.Model.*
+import scalevalapokalypsi.Model.Entities.*
+import scala.util.Random
+
+class Zombie(
+ adventure: Adventure,
+ identifier: String,
+ initialLocation: Area,
+ initialHP: Int = 20
+) extends NPC(adventure, identifier, initialLocation, initialHP, 20):
+
+ private val damage = 10
+ private val dialogs = Vector(
+ "örvlg",
+ "grr",
+ "äyyrrrgrlgb ww",
+ "aaak brzzzwff ååö",
+ "äkb glan abglum",
+ "öub gpa"
+ )
+
+ override def getDialog: String =
+ val dialogIndex = Random.between(0, this.dialogs.length)
+ this.dialogs(dialogIndex)
+
+ override def act(): Unit =
+ val possibleVictims = this.location
+ .getEntities
+ .filter(_ != this)
+ .filter(_ match
+ case z: Zombie => false
+ case other => true
+ )
+ .toVector
+ val index: Int =
+ if possibleVictims.isEmpty then 0
+ else Random.between(0, possibleVictims.length)
+ if !possibleVictims.isEmpty then
+ this.location.observeEvent(
+ this.attack(possibleVictims(index))
+ )
+
+
+ private def attack(entity: Entity): Event =
+ if Random.nextBoolean() then
+ entity.takeDamage(this.damage)
+ Event(
+ Map.from(Vector((
+ entity,
+ s"${this.name} puree sinua, hyi yäk!\n" +
+ s"${entity.condition(0)}"
+ ))),
+ s"${this.name} puree henkilöä ${entity.name}.\n" +
+ s"${entity.condition(1)}"
+ )
+ else
+ Event(
+ Map.from(Vector((
+ entity,
+ s"${this.name} yrittää purra sinua mutta kaatuu ohitsesi."
+ ))),
+ s"${this.name} yrittää purra henkilöä ${entity.name}, mutta epäonnistuu surkeasti."
+ )
+
+end Zombie
+
diff --git a/src/scalevalapokalypsi/Model/Entities/Player.scala b/src/scalevalapokalypsi/Model/Entities/Player.scala
index 9fc929d..62d4180 100644
--- a/src/scalevalapokalypsi/Model/Entities/Player.scala
+++ b/src/scalevalapokalypsi/Model/Entities/Player.scala
@@ -1,6 +1,7 @@
package scalevalapokalypsi.Model.Entities
import scala.collection.mutable.{Buffer, Map}
+import scala.collection.immutable
import scalevalapokalypsi.Model.*
/** A `Player` object represents a player character controlled by one real-life player
@@ -21,6 +22,15 @@ class Player(
private val observations: Buffer[String] = Buffer.empty
private val observedEvents: Buffer[Event] = Buffer.empty
private var pendingSingEffect: Option[SingEffect] = None
+// private var verseToSing: Option[String] = None
+
+ override def getVerseAgainst: Vector[String] =
+ Vector(
+ "Pian pimeässä suossa",
+ "lepäät levä ympärilläs",
+ "lauluasi lausumahan",
+ "et sikaa paremmin pysty"
+ )
override def observe(event: Event): Unit =
this.observedEvents.append(event)
@@ -44,8 +54,11 @@ class Player(
def setSingEffect(effect: SingEffect): Unit =
this.pendingSingEffect = Some(effect)
- def getSingEffectTarget: Option[Entity] =
- this.pendingSingEffect.map(_.target)
+ def getVerses: Option[Vector[String]] =
+ this.pendingSingEffect.map(_.getVerses)
+
+// def getSingEffectTarget: Option[Entity] =
+// this.pendingSingEffect.map(_.target)
/** Applies the pending sing effect and informs the surronding Entities
* about the effects of the song.
@@ -65,12 +78,11 @@ class Player(
else ("erinomaista", "merkittävä")
val quality =
s"Laulu on ${qualityDescriptions(0)} ja sen vaikutus on ${qualityDescriptions(1)}."
- val event = Event(Map.empty, s"$quality")
+ val event = Event(immutable.Map.empty, s"$quality")
this.location.observeEvent(event)
- this.pendingSingEffect.map(ef => ef(singQuality))
+ this.pendingSingEffect
+ .map(ef => ef(singQuality))
+ .map(this.location.observeEvent(_))
this.pendingSingEffect = None
-
-
-
end Player