Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ScalaDoc for Model, Resolver, Interpreter, Reducer; package refactoring #37

Merged
merged 15 commits into from
Jan 24, 2021
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion cli/src/main/scala/io/github/scalaquest/cli/CLI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ object CLI {
})
_ <- putStrLn(out)
_ <-
if (!nextState.game.ended) UIO.succeed(nextState) flatMap gameLoop(game, pusher)
if (!nextState.matchState.ended) UIO.succeed(nextState) flatMap gameLoop(game, pusher)
else ZIO.unit
} yield ()

Expand Down
4 changes: 2 additions & 2 deletions core/src/main/scala/io/github/scalaquest/core/Game.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.github.scalaquest.core

import io.github.scalaquest.core.model.std.StdModel
import io.github.scalaquest.core.model.behaviorBased.impl.SimpleModel
import io.github.scalaquest.core.model.{Message, Model}
import io.github.scalaquest.core.pipeline.Pipeline.PipelineBuilder

Expand Down Expand Up @@ -35,7 +35,7 @@ object Game {
}

object ExampleUsage {
implicit val model: StdModel.type = StdModel
implicit val model: SimpleModel.type = SimpleModel
val pipelineBuilder: PipelineBuilder[model.S, model.type] = ???

val game: Game[model.type] = Game fromModel model withPipelineBuilder pipelineBuilder
Expand Down
25 changes: 25 additions & 0 deletions core/src/main/scala/io/github/scalaquest/core/model/Action.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
package io.github.scalaquest.core.model

/**
* An action is a base representation of a single 'move' into the Game. To be significant, could be
* associated to one or more [[Model.Item]].
*/
trait Action

/**
* Companion object for the [[Action]] trait, including some commonly actions.
*/
object Action {

/**
* Some commonly used [[Action]] s.
*/
object Common {
import io.github.scalaquest.core.model.Room.Direction

case object Take extends Action
case object Open extends Action
case object Close extends Action
case object Enter extends Action
case object Eat extends Action
case object Inspect extends Action
case class Go(direction: Direction) extends Action
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package io.github.scalaquest.core.model

trait ItemRef

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.github.scalaquest.core.model

/**
* Represents the current state of the match.
* @tparam I
* the specific implementation of the [[Model.Item]].
*/
trait MatchState[I <: Model#Item] {

/**
* The player involved into the match. As it is a core concept, an instance of [[Player]] is
* included into the [[MatchState]].
* @return
* The current [[Player]].
*/
def player: Player[I]

/**
* Indicates whether the match has reached the end. When true, the entire match ende after the
* current pipeline round.
* @return
* True if the match has to end after the current round, false otherwise.
*/
def ended: Boolean

/**
* Represents the configuration match, in terms of [[Room]] s and [[Model.Item]].
* @return
* a [[Map]] representing all [[Room]] s of the match, and the [[Model.Item]] s in them.
*/
def geography: Map[Room, Set[I]]
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
package io.github.scalaquest.core.model

/**
* A representation a single line of output to render to the user at the end of the pipeline round.
*/
trait Message
67 changes: 61 additions & 6 deletions core/src/main/scala/io/github/scalaquest/core/model/Model.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,75 @@ trait Model {

type Reaction = S => S

trait State { self: S =>
def game: GameState[I]
/**
* Represents a snapshot of the current game, at an higher level in comparison to [[MatchState]],
* including the state of the game. The key fact is that this level of abstraction can handle also
* [[Message]] s, that is a representation of the output to render to the user at the end of the
* pipeline round.
*/
abstract class State { self: S =>

/**
* The state of the game, in a vision scoped to the [[Player]] capabilities.
*
* @return
* The [[MatchState]] of the match.
*/
def matchState: MatchState[I]

/**
* A representation of the output to render to the user at the end of the pipeline round.
* @return
* A [[Seq]] of [[Message]] s.
*/
def messages: Seq[Message]

/**
* A method that extracts a [[Map]] that links all the [[Item]] inside the [[State]] to their
* [[ItemRef]] s. This should be implemented for each concrete [[Model]] implementation.
* @return
* A [[Map]] from [[ItemRef]] to [[Item]].
*/
def extractRefs: Map[ItemRef, I]
}

trait Item { item: I =>
def use(action: Action, state: S, sideItem: Option[I] = None): Option[Reaction]
/**
* Represents a single object against which the [[Player]] can interact.
*/
abstract class Item { item: I =>

/**
* The unique identifier of the [[Item]]. This is necessary, as passing from a state to another,
* the reference to an object changes, the [[State]] works in an immutable fashion.
*/
def itemRef: ItemRef
override def hashCode(): Int = itemRef.hashCode()

/**
* The hash code of the [[Item]] is overridden in a way that delegates to the Item's [[ItemRef]]
* the creation of the hash code. This enables the possibility of make a match between a same
* [[Item]] from different [[State]] s.
* @return
* The Item's [[ItemRef]] hashcode.
*/
final override def hashCode(): Int = itemRef.hashCode()

/**
* Define a way make the item interact with the [[State]]. The interaction is founded into the
* [[Action]] (ex. 'open the door'), but it can include also an additional [[Item]] ('open the
* door with the key'). The item should react to each combination with an appropriate
* [[Reaction]].
* @param action
* An action from a statement (ex. <b>open</b> the door with a key).
* @param state
* the starting state, useful to give a context to the decision to take.
* @param sideItem
* A side [[Item]] from a statement (ex. open the door with <b>a key</b>).
* @return
*/
def use(action: Action, state: S, sideItem: Option[I] = None): Option[Reaction]
}

trait Ground { ground: G =>
abstract class Ground { ground: G =>
def use(action: Action, state: S): Option[Reaction]
}
}
17 changes: 17 additions & 0 deletions core/src/main/scala/io/github/scalaquest/core/model/Player.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
package io.github.scalaquest.core.model

/**
* Represents the main properties of the character impersonated by the user.
* @tparam I
* a subtype of [[Model.Item]], the one effectively used into the model implementation.
*/
trait Player[I <: Model#Item] {

/**
* [[Model.Item]] s that the player brings with him. In a contrete story, this not necessarily a
* real bag: it is simply an intuitive term to refer to this set of items.
* @return
*/
def bag: Set[I]

/**
* The current location of the player into the map.
* @return
* The current location of the player into the map.
*/
def location: Room
}
41 changes: 33 additions & 8 deletions core/src/main/scala/io/github/scalaquest/core/model/Room.scala
Original file line number Diff line number Diff line change
@@ -1,18 +1,43 @@
package io.github.scalaquest.core.model

import io.github.scalaquest.core.model.Direction.Direction
import io.github.scalaquest.core.model.std.StdRoom

object Direction extends Enumeration {
type Direction = Value
val NORTH, SOUTH, WEST, EAST, UP, DOWN = Value
}
import io.github.scalaquest.core.model.Room.Direction

/**
* A geographical portion of the match map.
*
* This is one of the basic block for the story build by the storyteller, as it is used to identify
* [[Player]] 's and [[Model.Item]] s' location, in a given moment of the story.
*/
trait Room {

/**
* A textual identifier for the room.
* @return
* A textual identifier for the room.
*/
def name: String

/**
* Identifies rooms near to the current one, at the cardinal points.
*/
def neighbors(direction: Direction): Option[Room]
}

case class SimpleRoom(name: String, _neighbors: () => Map[Direction, Room]) extends Room {
override def neighbors(direction: Direction): Option[Room] = _neighbors() get direction
}

object Room {
def apply(name: String, neighbors: () => Map[Direction, Room]): Room = StdRoom(name, neighbors)
def apply(name: String, neighbors: () => Map[Direction, Room]): Room = SimpleRoom(name, neighbors)

sealed trait Direction

object Direction {
case object North extends Direction
case object South extends Direction
case object East extends Direction
case object West extends Direction
case object Up extends Direction
case object Down extends Direction
}
}