diff options
author | Joel Kronqvist <joel.kronqvist@iki.fi> | 2024-11-17 14:19:58 +0200 |
---|---|---|
committer | Joel Kronqvist <joel.kronqvist@iki.fi> | 2024-11-17 14:20:27 +0200 |
commit | 5060c66738898913ca880d83b0fdcd5be2e0b59d (patch) | |
tree | bd4ecd70ebb8cc0342bd0a29c91c5b27fed38fb6 | |
parent | 4de67b497e0e229fe4a42f66f833640b6e50fd5a (diff) | |
download | scalevalapokalypsi-5060c66738898913ca880d83b0fdcd5be2e0b59d.tar.gz scalevalapokalypsi-5060c66738898913ca880d83b0fdcd5be2e0b59d.zip |
Small style fixes (mostly shortening comment lines written by others...)
-rw-r--r-- | src/scalevalapokalypsi/.bsp/scala.json | 41 | ||||
-rw-r--r-- | src/scalevalapokalypsi/Model/Action.scala | 4 | ||||
-rw-r--r-- | src/scalevalapokalypsi/Model/Adventure.scala | 16 | ||||
-rw-r--r-- | src/scalevalapokalypsi/Model/Area.scala | 56 | ||||
-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.scala | 27 | ||||
-rw-r--r-- | src/scalevalapokalypsi/Model/Item.scala | 12 | ||||
-rw-r--r-- | src/scalevalapokalypsi/Model/SingEffects.scala | 6 | ||||
-rw-r--r-- | src/scalevalapokalypsi/Server/Client.scala | 3 | ||||
-rw-r--r-- | src/scalevalapokalypsi/Server/Server.scala | 10 | ||||
-rw-r--r-- | src/scalevalapokalypsi/main.scala | 8 |
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") |