aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.kronqvist@iki.fi>2024-11-17 14:19:58 +0200
committerJoel Kronqvist <joel.kronqvist@iki.fi>2024-11-17 14:20:27 +0200
commit5060c66738898913ca880d83b0fdcd5be2e0b59d (patch)
treebd4ecd70ebb8cc0342bd0a29c91c5b27fed38fb6
parent4de67b497e0e229fe4a42f66f833640b6e50fd5a (diff)
downloadscalevalapokalypsi-5060c66738898913ca880d83b0fdcd5be2e0b59d.tar.gz
scalevalapokalypsi-5060c66738898913ca880d83b0fdcd5be2e0b59d.zip
Small style fixes (mostly shortening comment lines written by others...)
-rw-r--r--src/scalevalapokalypsi/.bsp/scala.json41
-rw-r--r--src/scalevalapokalypsi/Model/Action.scala4
-rw-r--r--src/scalevalapokalypsi/Model/Adventure.scala16
-rw-r--r--src/scalevalapokalypsi/Model/Area.scala56
-rw-r--r--src/scalevalapokalypsi/Model/Entities/Entity.scala (renamed from src/scalevalapokalypsi/Model/Entity.scala)53
-rw-r--r--src/scalevalapokalypsi/Model/Entities/Player.scala27
-rw-r--r--src/scalevalapokalypsi/Model/Item.scala12
-rw-r--r--src/scalevalapokalypsi/Model/SingEffects.scala6
-rw-r--r--src/scalevalapokalypsi/Server/Client.scala3
-rw-r--r--src/scalevalapokalypsi/Server/Server.scala10
-rw-r--r--src/scalevalapokalypsi/main.scala8
11 files changed, 153 insertions, 83 deletions
diff --git a/src/scalevalapokalypsi/.bsp/scala.json b/src/scalevalapokalypsi/.bsp/scala.json
new file mode 100644
index 0000000..7a79192
--- /dev/null
+++ b/src/scalevalapokalypsi/.bsp/scala.json
@@ -0,0 +1,41 @@
+{
+ "name": "scala",
+ "argv": [
+ "/home/school/.cache/coursier/arc/https/github.com/scala/scala3/releases/download/3.5.1/scala3-3.5.1-x86_64-pc-linux.tar.gz/scala3-3.5.1-x86_64-pc-linux/bin/scala-cli",
+ "--cli-default-scala-version",
+ "3.5.1",
+ "--repository",
+ "file:///home/school/.cache/coursier/arc/https/github.com/scala/scala3/releases/download/3.5.1/scala3-3.5.1-x86_64-pc-linux.tar.gz/scala3-3.5.1-x86_64-pc-linux/maven2",
+ "--prog-name",
+ "scala",
+ "bsp",
+ "--json-options",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/.scala-build/ide-options-v2.json",
+ "--json-launcher-options",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/.scala-build/ide-launcher-options.json",
+ "--envs-file",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/.scala-build/ide-envs.json",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/main.scala",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/Client/Client.scala",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/Client/ReceivedLineParser.scala",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/Client/StdinLineReader.scala",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/Client/Turn.scala",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/Model/Action.scala",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/Model/Adventure.scala",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/Model/Area.scala",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/Model/Entities",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/Model/Item.scala",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/Model/SingEffects.scala",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/Server/Client.scala",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/Server/Clients.scala",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/Server/ConnectionGetter.scala",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/Server/Server.scala",
+ "/home/school/Dev/scalevalapokalypsi/src/scalevalapokalypsi/utils/utils.scala"
+ ],
+ "version": "1.4.3",
+ "bspVersion": "2.1.1",
+ "languages": [
+ "scala",
+ "java"
+ ]
+} \ No newline at end of file
diff --git a/src/scalevalapokalypsi/Model/Action.scala b/src/scalevalapokalypsi/Model/Action.scala
index 32f513d..e59d5f1 100644
--- a/src/scalevalapokalypsi/Model/Action.scala
+++ b/src/scalevalapokalypsi/Model/Action.scala
@@ -1,5 +1,7 @@
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.
@@ -50,8 +52,6 @@ class Action(input: String):
)
case other => None
-// println(resOption)
-// println(actor.location.getEntities)
resOption.map(_(1)).filter(_.length > 0)
.foreach(s =>
actor.location.getEntities.filter(_ != actor).foreach(_.observe(s))
diff --git a/src/scalevalapokalypsi/Model/Adventure.scala b/src/scalevalapokalypsi/Model/Adventure.scala
index 2bf6cfe..e751280 100644
--- a/src/scalevalapokalypsi/Model/Adventure.scala
+++ b/src/scalevalapokalypsi/Model/Adventure.scala
@@ -1,15 +1,17 @@
package scalevalapokalypsi.Model
import scala.collection.mutable.Map
+import scalevalapokalypsi.Model.Entities.*
-/** The class `Adventure` represents text adventure games. An adventure consists of a player and
- * a number of areas that make up the game world. It provides methods for playing the game one
- * turn at a time and for checking the state of the game.
+/** The class `Adventure` holds data of the game world and provides methods
+ * for implementing a user interface for it.
*
- * N.B. This version of the class has a lot of “hard-coded” information that pertains to a very
- * specific adventure game that involves a small trip through a twisted forest. All newly created
- * instances of class `Adventure` are identical to each other. To create other kinds of adventure
- * games, you will need to modify or replace the source code of this class. */
+ * Data about the game world includes remote players, other entities and areas.
+ * The methods are documented below.
+ *
+ * @param playerNames a vector of the names of players to create and add
+ * to the adventure straight away
+ */
class Adventure(val playerNames: Vector[String]):
private val middle = Area("Forest", "You are somewhere in the forest. There are a lot of trees here.\nBirds are singing.")
diff --git a/src/scalevalapokalypsi/Model/Area.scala b/src/scalevalapokalypsi/Model/Area.scala
index c891af8..a11b0e5 100644
--- a/src/scalevalapokalypsi/Model/Area.scala
+++ b/src/scalevalapokalypsi/Model/Area.scala
@@ -1,22 +1,29 @@
package scalevalapokalypsi.Model
import scala.collection.mutable.Map
-
-/** The class `Area` represents locations in a text adventure game world. A game world
- * consists of areas. In general, an “area” can be pretty much anything: a room, a building,
- * an acre of forest, or something completely different. What different areas have in
- * common is that players can be located in them and that they can have exits leading to
- * other, neighboring areas. An area also has a name and a description.
+import scalevalapokalypsi.Model.Entities.*
+
+/** The class `Area` represents locations in a text adventure game world. A game
+ * world consists of areas. In general, an “area” can be pretty much anything:
+ * a room, a building, an acre of forest, or something completely different.
+ * What different areas have in common is that players can be located in them
+ * and that they can have exits leading to other, neighboring areas. An area
+ * also has a name and a description.
+ *
* @param name the name of the area
- * @param description a basic description of the area (typically not including information about items) */
+ * @param description a basic description of the area (typically not including
+ * information about items)
+ */
class Area(val name: String, var description: String):
private val neighbors = Map[String, Area]()
private val items: Map[String, Item] = Map()
private val entities: Map[String, Entity] = Map()
- /** Returns the area that can be reached from this area by moving in the given direction. The result
- * is returned in an `Option`; `None` is returned if there is no exit in the given direction. */
+ /** Returns the area that can be reached from this area by moving in the
+ * given direction. The result is returned in an `Option`; `None` is
+ * returned if there is no exit in the given direction.
+ */
def neighbor(direction: String): Option[Area] =
this.neighbors.get(direction)
@@ -34,15 +41,19 @@ class Area(val name: String, var description: String):
def hasNeighbor(direction: String): Boolean =
this.neighbors.contains(direction)
- /** Adds an exit from this area to the given area. The neighboring area is reached by moving in
- * the specified direction from this area. */
+ /** Adds an exit from this area to the given area. The neighboring area is
+ * reached by moving in the specified direction from this area. */
def setNeighbor(direction: String, neighbor: Area) =
this.neighbors += direction -> neighbor
- /** Adds exits from this area to the given areas. Calling this method is equivalent to calling
- * the `setNeighbor` method on each of the given direction–area pairs.
- * @param exits contains pairs consisting of a direction and the neighboring area in that direction
- * @see [[setNeighbor]] */
+ /** Adds exits from this area to the given areas. Calling this method is
+ * equivalent to calling the `setNeighbor` method on each of the given
+ * direction–area pairs.
+ *
+ * @param exits contains pairs consisting of a direction and the
+ * neighboring area in that direction
+ * @see [[setNeighbor]]
+ */
def setNeighbors(exits: Vector[(String, Area)]) =
this.neighbors ++= exits
@@ -85,12 +96,15 @@ class Area(val name: String, var description: String):
def removeEntity(entityName: String): Option[Entity] =
this.entities.remove(entityName.toLowerCase())
- /** Returns a multi-line description of the area as a player sees it. This includes a basic
- * description of the area as well as information about exits and items. If there are no
- * items present, the return value has the form "DESCRIPTION\n\nExits available:
- * DIRECTIONS SEPARATED BY SPACES". If there are one or more items present, the return
- * value has the form "DESCRIPTION\nYou see here: ITEMS SEPARATED BY SPACES\n\nExits available:
- * DIRECTIONS SEPARATED BY SPACES". The items and directions are listed in an arbitrary order. */
+ /** Returns a multi-line description of the area as a player sees it. This
+ * includes a basic description of the area as well as information about
+ * exits and items. If there are no items present, the return value has the
+ * form "DESCRIPTION\n\nExits available:
+ * DIRECTIONS SEPARATED BY SPACES". If there are one or more items present,
+ * the return value has the form "DESCRIPTION\nYou see here: ITEMS
+ * SEPARATED BY SPACES\n\nExits available: DIRECTIONS SEPARATED BY SPACES".
+ * The items and directions are listed in an arbitrary order.
+ */
def fullDescription: String =
val exitList = this.neighbors.keys.mkString(" ")
val itemList = this.items.keys.mkString(" ")
diff --git a/src/scalevalapokalypsi/Model/Entity.scala b/src/scalevalapokalypsi/Model/Entities/Entity.scala
index 083c37f..ff5b320 100644
--- a/src/scalevalapokalypsi/Model/Entity.scala
+++ b/src/scalevalapokalypsi/Model/Entities/Entity.scala
@@ -1,29 +1,7 @@
-package scalevalapokalypsi.Model
+package scalevalapokalypsi.Model.Entities
-import scala.collection.mutable.{Buffer,Map}
-
-
-
-/** A `Player` object represents a player character controlled by one real-life player
- * of the program.
- *
- * A player object’s state is mutable: the player’s location and possessions can change,
- * for instance.
- *
- * @param startingArea the player’s initial location */
-class Player(name: String, initialLocation: Area) extends Entity(name, initialLocation):
-
- private val observations: Buffer[String] = Buffer.empty
-
- override def observe(observation: String): Unit =
- this.observations.append(observation)
-
- def readAndClearObservations(): Vector[String] =
- val res = this.observations.toVector
- observations.clear()
- res
-
-end Player
+import scala.collection.mutable.Map
+import scalevalapokalypsi.Model.*
/** An in-game entity.
*
@@ -35,9 +13,6 @@ class Entity(val name: String, initialLocation: Area):
private var quitCommandGiven = false // one-way flag
private val inventory: Map[String, Item] = Map()
- /** Determines if the player has indicated a desire to quit the game. */
- def hasQuit = this.quitCommandGiven // TODO: This is probably unneccessary?
-
/** Does nothing, except possibly in inherited classes. */
def observe(observation: String): Unit =
println("no observation made.")
@@ -46,9 +21,11 @@ class Entity(val name: String, initialLocation: Area):
/** 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." */
+ /** 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): (String, String) =
val destination = this.location.neighbor(direction)
if destination.isDefined then
@@ -68,14 +45,20 @@ class Entity(val name: String, initialLocation: Area):
case Some(i) =>
this.inventory += i.name -> i
(s"You pick up the ${i.name}", s"$name picks up the ${i.name}")
- case None => (s"There is no $itemName here to pick up.", "WHAAAT THIS SHOULDN'T HAPPEN???")
+ case None => (
+ s"There is no $itemName here to pick up.",
+ s"${this.name} tries to pick up something but gets just dirt in their hands."
+ )
def drop(itemName: String): (String, String) =
this.inventory.remove(itemName) match
case Some(item) =>
this.currentLocation.addItem(item)
(s"You drop the $itemName", s"$name drops the $itemName")
- case None => ("You don't have that!", s"$name reaches their backpack to drop $itemName but miserably fails to find it there.")
+ case None => (
+ "You don't have that!",
+ s"$name reaches their backpack to drop $itemName but miserably fails to find it there."
+ )
def sayTo(entity: Entity, message: String): (String, String) =
entity.observe(s"Alice: \"$message\"")
@@ -92,12 +75,12 @@ class Entity(val name: String, initialLocation: Area):
*/
def canDrop(itemName: String): Boolean = this.inventory.contains(itemName)
- /** Causes the player to rest for a short while (this has no substantial effect in game terms).
+ /** Causes the player to rest for a turn.
* Returns a description of what happened. */
def rest(): (String, String) =
("You rest for a while. Better get a move on, though.", "")
/** Returns a brief description of the player’s state, for debugging purposes. */
- override def toString = "Now at: " + this.location.name
+ override def toString = s"${this.name} at ${this.location.name}"
end Entity
diff --git a/src/scalevalapokalypsi/Model/Entities/Player.scala b/src/scalevalapokalypsi/Model/Entities/Player.scala
new file mode 100644
index 0000000..6e82837
--- /dev/null
+++ b/src/scalevalapokalypsi/Model/Entities/Player.scala
@@ -0,0 +1,27 @@
+package scalevalapokalypsi.Model.Entities
+
+import scala.collection.mutable.Buffer
+import scalevalapokalypsi.Model.*
+
+/** A `Player` object represents a player character controlled by one real-life player
+ * of the program.
+ *
+ * A player object’s state is mutable: the player’s location and possessions can change,
+ * for instance.
+ *
+ * @param name the player's name
+ * @param initialLocation the player’s initial location
+ */
+class Player(name: String, initialLocation: Area) extends Entity(name, initialLocation):
+
+ private val observations: Buffer[String] = Buffer.empty
+
+ override def observe(observation: String): Unit =
+ this.observations.append(observation)
+
+ def readAndClearObservations(): Vector[String] =
+ val res = this.observations.toVector
+ observations.clear()
+ res
+
+end Player
diff --git a/src/scalevalapokalypsi/Model/Item.scala b/src/scalevalapokalypsi/Model/Item.scala
index 7979480..c1ebaa1 100644
--- a/src/scalevalapokalypsi/Model/Item.scala
+++ b/src/scalevalapokalypsi/Model/Item.scala
@@ -2,15 +2,13 @@ package scalevalapokalypsi.Model
import scala.annotation.targetName
-/** The class `Item` represents items in a text adventure game. Each item has a name
- * and a longer description. (In later versions of the adventure game, items may
- * have other features as well.)
- *
- * N.B. It is assumed, but not enforced by this class, that items have unique names.
- * That is, no two items in a game world have the same name.
+/** The class `Item` represents items in a text adventure game. Each item has a
+ * name and a longer description. (In later versions of the adventure game,
+ * items may have other features as well.)
*
* @param name the item’s name
- * @param description the item’s description */
+ * @param description the item’s description
+ */
class Item(val name: String, val description: String):
/** Returns a short textual representation of the item (its name, that is). */
diff --git a/src/scalevalapokalypsi/Model/SingEffects.scala b/src/scalevalapokalypsi/Model/SingEffects.scala
new file mode 100644
index 0000000..981b772
--- /dev/null
+++ b/src/scalevalapokalypsi/Model/SingEffects.scala
@@ -0,0 +1,6 @@
+/*package scalevalapokalypsi.Model
+
+def defaultSingAttack(targetEntity: Entity)(singQuality: Float): String =
+ targetEntity.takeDamage((singQuality * 30).toInt)
+ targetEntity.condition
+*/ \ No newline at end of file
diff --git a/src/scalevalapokalypsi/Server/Client.scala b/src/scalevalapokalypsi/Server/Client.scala
index 6ce2522..8716ca9 100644
--- a/src/scalevalapokalypsi/Server/Client.scala
+++ b/src/scalevalapokalypsi/Server/Client.scala
@@ -4,7 +4,8 @@ import java.net.Socket
import scala.math.min
import scalevalapokalypsi.constants.*
import ServerProtocolState.*
-import scalevalapokalypsi.Model.{Action,Player,Entity}
+import scalevalapokalypsi.Model.Action
+import scalevalapokalypsi.Model.Entities.Player
class Client(val socket: Socket):
private var incompleteMessage: Array[Byte] =
diff --git a/src/scalevalapokalypsi/Server/Server.scala b/src/scalevalapokalypsi/Server/Server.scala
index 13ca2f5..f18d5c0 100644
--- a/src/scalevalapokalypsi/Server/Server.scala
+++ b/src/scalevalapokalypsi/Server/Server.scala
@@ -3,15 +3,15 @@ package scalevalapokalypsi.Server
// TODO: TLS/SSL / import javax.net.ssl.SSLServerSocketFactory
-import java.lang.Thread.{currentThread, sleep}
-import java.io.IOException
-import java.net.{ServerSocket, Socket}
+import scalevalapokalypsi.Model.Adventure
+import scalevalapokalypsi.Model.Entities.Player
import scalevalapokalypsi.constants.*
-import scalevalapokalypsi.Model.{Adventure,Entity,Player}
import scalevalapokalypsi.utils.stringToByteArray
+import java.io.IOException
import java.lang.System.currentTimeMillis
-import scala.util.Try
+import java.lang.Thread.sleep
+import java.net.{ServerSocket, Socket}
/** `Server` exists to initialize a server for the game
diff --git a/src/scalevalapokalypsi/main.scala b/src/scalevalapokalypsi/main.scala
index 9633f73..50e89e5 100644
--- a/src/scalevalapokalypsi/main.scala
+++ b/src/scalevalapokalypsi/main.scala
@@ -2,10 +2,8 @@ package scalevalapokalypsi
import scalevalapokalypsi.Client.newClient
import scalevalapokalypsi.Server.Server
-import java.lang.Thread
-import scala.concurrent.Future
-import scala.concurrent.ExecutionContext.Implicits.global
+import java.lang.Thread
import scala.io.StdIn.readLine
// TODO: add proper logic for starting the game
@@ -17,11 +15,11 @@ import scala.io.StdIn.readLine
println("Server started in background.")
print("Choose a name:\n> ")
val name = readLine()
- newClient(name, "127.0.0.1", 2267).map(_.startClient())
+ newClient(name, "127.0.0.1", 2267).foreach(_.startClient())
case Some(2) =>
print("Choose a name:\n> ")
val name = readLine()
- newClient(name, "127.0.0.1", 2267).map(_.startClient())
+ newClient(name, "127.0.0.1", 2267).foreach(_.startClient())
case _ => println("Invalid input")