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

Various commons additions #97

Merged
merged 15 commits into from Feb 16, 2021
Merged
@@ -1,16 +1,25 @@
package io.github.scalaquest.core.model.behaviorBased.commons

import io.github.scalaquest.core.model.behaviorBased.BehaviorBasedModel
import io.github.scalaquest.core.model.behaviorBased.commons.builders.CommonBuildersExt
import io.github.scalaquest.core.model.behaviorBased.commons.groundBehaviors.CommonGroundBehaviorsExt
import io.github.scalaquest.core.model.behaviorBased.commons.grounds.CommonGroundExt
import io.github.scalaquest.core.model.behaviorBased.commons.itemBehaviors.CommonItemBehaviorsExt
import io.github.scalaquest.core.model.behaviorBased.commons.items.CommonItemsExt
import io.github.scalaquest.core.model.behaviorBased.commons.reactions.CommonReactionsExt

/**
* A mixable trait that contains a set of common [[BehaviorBasedModel.BehaviorBasedItem]],
* [[BehaviorBasedModel.ItemBehavior]], [[BehaviorBasedModel.GroundBehavior]] of common use, some
* common [[BehaviorBasedModel.Reaction]] generated by the Behaviours, some useful builder for the
* items in [[CommonBuildersExt]] and a accessible point with a mixin mechanism from the
* [[BehaviorBasedModel]].
*/
trait CommonsExt
extends BehaviorBasedModel
with CommonItemBehaviorsExt
with CommonItemsExt
with CommonGroundBehaviorsExt
with CommonGroundExt
with CommonReactionsExt
with CommonBuildersExt
Expand Up @@ -2,12 +2,50 @@ package io.github.scalaquest.core.model.behaviorBased.commons.actioning

import io.github.scalaquest.core.model.{Action, Direction}

/**
* [[Action]] s already implemented in the game.
*/
object CommonActions {
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

/**
* Used to take a takeable Item.
*/
case object Take extends Action

/**
* Used to open an openable Item.
*/
case object Open extends Action

/**
* Used to close an openable Item.
*/
case object Close extends Action

/**
* Used to enter in a Room.
*/
case object Enter extends Action

/**
* Used to eat an eatable Item.
*/
case object Eat extends Action

/**
* Used to Inspect a Room.
*/
case object Inspect extends Action

/**
* Used to inspect the player's bag.
*/
case object InspectBag extends Action

/**
* Used to move the player in the selected direction.
* @param direction
* the direction where the player is moved.
*/
case class Go(direction: Direction) extends Action
}
Expand Up @@ -4,6 +4,9 @@ import io.github.scalaquest.core.dictionary.verbs.{Ditransitive, Intransitive, T
import io.github.scalaquest.core.model.Direction
import io.github.scalaquest.core.model.behaviorBased.commons.actioning.CommonActions._

/**
* [[Verb]] s already implemented in the game.
*/
object CommonVerbs {

private def gos: Set[Verb] = {
Expand Down Expand Up @@ -31,6 +34,7 @@ object CommonVerbs {
Transitive("open", Open),
Transitive("enter", Enter),
Ditransitive("enter", Enter, Some("with")),
Intransitive("inspect", Inspect)
Intransitive("inspect", Inspect),
Intransitive("inspect", InspectBag, Some("bag"))
) ++ gos
}
@@ -0,0 +1,12 @@
package io.github.scalaquest.core.model.behaviorBased.commons.builders

import io.github.scalaquest.core.model.behaviorBased.BehaviorBasedModel
import io.github.scalaquest.core.model.behaviorBased.commons.builders.impl.{
DoorKeyBuilderExt,
OpKeyBuilderExt
}

/**
* Utilities to easily build various parts, for the storyteller.
*/
trait CommonBuildersExt extends BehaviorBasedModel with DoorKeyBuilderExt with OpKeyBuilderExt
@@ -1,12 +1,15 @@
package io.github.scalaquest.core.model.behaviorBased.simple.builders.impl
package io.github.scalaquest.core.model.behaviorBased.commons.builders.impl

import io.github.scalaquest.core.model.behaviorBased.BehaviorBasedModel
import io.github.scalaquest.core.model.behaviorBased.commons.CommonsExt
import io.github.scalaquest.core.model.behaviorBased.commons.items.CommonItemsExt
import io.github.scalaquest.core.model.{Direction, ItemDescription}

trait DoorKeyBuilderExt extends BehaviorBasedModel with CommonsExt {
/**
* A convenient implementation for a room, and if present, a key connected to it.
*/
trait DoorKeyBuilderExt extends BehaviorBasedModel with CommonItemsExt {

def doorKeyBuilder(
def lockedDoorBuilder(
keyDesc: ItemDescription,
keyAddBehaviorsBuilders: Seq[I => ItemBehavior] = Seq.empty,
consumeKey: Boolean = false,
Expand Down
@@ -1,12 +1,15 @@
package io.github.scalaquest.core.model.behaviorBased.simple.builders.impl
package io.github.scalaquest.core.model.behaviorBased.commons.builders.impl

import io.github.scalaquest.core.model.ItemDescription
import io.github.scalaquest.core.model.behaviorBased.BehaviorBasedModel
import io.github.scalaquest.core.model.behaviorBased.commons.CommonsExt
import io.github.scalaquest.core.model.behaviorBased.commons.items.CommonItemsExt

trait OpKeyBuilderExt extends BehaviorBasedModel with CommonsExt {
/**
* A convenient implementation for an openble item, and if present, a key connected to it.
*/
trait OpKeyBuilderExt extends BehaviorBasedModel with CommonItemsExt {

def openableWithKeyBuilder(
def openableBuilder(
keyDesc: ItemDescription,
keyAddBehaviorsBuilders: Seq[I => ItemBehavior] = Seq.empty,
consumeKey: Boolean = false,
Expand Down
Expand Up @@ -2,13 +2,20 @@ package io.github.scalaquest.core.model.behaviorBased.commons.groundBehaviors

import io.github.scalaquest.core.model.behaviorBased.BehaviorBasedModel
import io.github.scalaquest.core.model.behaviorBased.commons.groundBehaviors.impl.{
InspectableExt,
InspectableBagExt,
InspectableLocationExt,
NavigableExt
}

/**
* When mixed into a Model, it enables the implementation for the common behaviors provided by
* ScalaQuest Core. It requires the storyteller to implement all the required [[monocle.Lens]], used
* by the implementation to access and re-generate the concrete State.
*
* This trait enable the player to inspect his bag, a room and he can also move in another room.
*/
trait CommonGroundBehaviorsExt extends BehaviorBasedModel with NavigableExt with InspectableExt
trait CommonGroundBehaviorsExt
extends BehaviorBasedModel
with NavigableExt
with InspectableLocationExt
with InspectableBagExt
@@ -0,0 +1,51 @@
package io.github.scalaquest.core.model.behaviorBased.commons.groundBehaviors.impl

import io.github.scalaquest.core.model.behaviorBased.BehaviorBasedModel
import io.github.scalaquest.core.model.behaviorBased.commons.actioning.CommonActions.InspectBag
import io.github.scalaquest.core.model.behaviorBased.commons.pushing.CommonMessagesExt
import io.github.scalaquest.core.model.behaviorBased.commons.reactions.CommonReactionsExt
import io.github.scalaquest.core.model.behaviorBased.simple.impl.StateUtilsExt

/**
* The trait makes possible to mix into a [[BehaviorBasedModel]] the InspectableBag behavior for the
* Ground.
*/
trait InspectableBagExt
extends BehaviorBasedModel
with StateUtilsExt
with CommonMessagesExt
with CommonReactionsExt {

/**
* A [[GroundBehavior]] that enables the possibility to know the items present into the Bag.
*/
abstract class InspectableBag extends GroundBehavior

/**
* A standard implementation for [[InspectableBag]].
*
* @param onInspectExtra
* [[Reaction]] to be executed when the player successfully inspected the bag. It can be
* omitted.
*/
case class SimpleInspectableBag(onInspectExtra: Option[Reaction] = None) extends InspectableBag {

override def triggers: GroundTriggers = { case (InspectBag, _) => inspectBag }

private def inspectBag: Reaction =
_.applyReactions(
Reactions.inspectBag,
onInspectExtra.getOrElse(Reactions.empty)
)
}

/**
* Companion object for [[InspectableBag]]. Shortcut for the standard implementation.
*/
object InspectableBag {

def apply(onInspectExtra: Option[Reaction] = None): InspectableBag =
SimpleInspectableBag(onInspectExtra)
}

}
Expand Up @@ -7,45 +7,47 @@ import io.github.scalaquest.core.model.behaviorBased.commons.reactions.CommonRea
import io.github.scalaquest.core.model.behaviorBased.simple.impl.StateUtilsExt

/**
* The trait makes possible to mix into a [[BehaviorBasedModel]] the Inspectable behavior for the
* Ground.
* The trait makes possible to mix into a [[BehaviorBasedModel]] the InspectableLocation behavior
* for the Ground.
*/
trait InspectableExt
trait InspectableLocationExt
extends BehaviorBasedModel
with StateUtilsExt
with CommonMessagesExt
with CommonReactionsExt {

/**
* A [[GroundBehavior]] that enables the possibility to know the items present into the current
* Room.
* [[Room]].
*/
abstract class Inspectable extends GroundBehavior
abstract class InspectableLocation extends GroundBehavior

/**
* A standard implementation for [[Inspectable]].
* A standard implementation for [[InspectableLocation]].
*
* @param onInspectExtra
* [[Reaction]] to be executed when the player succdessfully inspected the room. It can be
* [[Reaction]] to be executed when the player successfully inspected the room. It can be
* omitted.
*/
case class SimpleInspectable(onInspectExtra: Option[Reaction] = None) extends Inspectable {
case class SimpleInspectableLocation(onInspectExtra: Option[Reaction] = None)
extends InspectableLocation {

override def triggers: GroundTriggers = { case (Inspect, _) => inspectLocation }

def inspectLocation: Reaction =
private def inspectLocation: Reaction =
_.applyReactions(
Reactions.inspectLocation,
onInspectExtra.getOrElse(Reactions.empty)
)
}

/**
* Companion object for [[Inspectable]]. Shortcut for the standard implementation.
* Companion object for [[InspectableLocation]]. Shortcut for the standard implementation.
*/
object Inspectable {
object InspectableLocation {

def apply(onInspectExtra: Option[Reaction] = None): Inspectable =
SimpleInspectable(onInspectExtra)
def apply(onInspectExtra: Option[Reaction] = None): InspectableLocation =
SimpleInspectableLocation(onInspectExtra)
}

}
Expand Up @@ -7,7 +7,7 @@ import io.github.scalaquest.core.model.behaviorBased.commons.reactions.CommonRea
import io.github.scalaquest.core.model.behaviorBased.simple.impl.StateUtilsExt

/**
* The trait makes possible to mix into a [[BehaviorBasedModel]] the Navigatable behavior for the
* The trait makes possible to mix into a [[BehaviorBasedModel]] the Navigable behavior for the
* [[BehaviorBasedModel.Ground]].
*/
trait NavigableExt
Expand Down
Expand Up @@ -14,6 +14,6 @@ trait CommonGroundExt extends BehaviorBasedModel with CommonGroundBehaviorsExt {
extends BehaviorBasedGround {

override val behaviors: Seq[GroundBehavior] =
additionalBehaviors ++ Seq(Inspectable(), Navigable())
additionalBehaviors ++ Seq(InspectableLocation(), InspectableBag(), Navigable())
}
}
Expand Up @@ -55,6 +55,9 @@ trait OpenableExt
case (Open, item, maybeKey, state)
if state.isInLocation(item) && canBeOpened(maybeKey)(state) && !isOpen =>
open

case (Open, _, _, _) if !isOpen => failToOpen
case (Open, _, _, _) if isOpen => alreadyOpened
}

/**
Expand All @@ -79,8 +82,8 @@ trait OpenableExt
*/
override def canBeOpened(usedKey: Option[I] = None)(implicit state: S): Boolean = {
usedKey match {
case Some(key) => requiredKey.contains(key) && state.isInScope(key)
case None => requiredKey.fold(true)(state.isInBag(_))
case Some(key) => requiredKey.contains(key)
case None => requiredKey.fold(true)(_ => false)
}
}

Expand All @@ -98,6 +101,12 @@ trait OpenableExt
onOpenExtra.getOrElse(Reactions.empty)
)
}

def failToOpen: Reaction =
state => messageLens.modify(_ :+ Messages.FailedToOpen(subject))(state)

def alreadyOpened: Reaction =
state => messageLens.modify(_ :+ Messages.AlreadyOpened(subject))(state)
}

/**
Expand Down
Expand Up @@ -47,7 +47,8 @@ trait RoomLinkExt
endRoomDirection: Direction,
openable: Option[Openable] = None,
onEnterExtra: Option[Reaction] = None
) extends RoomLink
)(implicit subject: I)
extends RoomLink
with Delegate {

/**
Expand All @@ -66,7 +67,10 @@ trait RoomLinkExt
open

// "Enter the item"
case (Enter, i, None, s) if s.isInLocation(i) && openable.fold(true)(_.isOpen) => enter
case (Enter, _, None, s) if s.isInLocation(subject) && openable.fold(true)(_.isOpen) =>
enter
case (Enter, _, _, _) =>
messageLens.modify(_ :+ Messages.FailedToEnter(subject))
}

override def enter: Reaction =
Expand All @@ -86,7 +90,7 @@ trait RoomLinkExt
)

state.applyReactions(
openable.fold(Reactions.empty)(o => o.open),
openable.fold(Reactions.empty)(_.open),
addDirection
)
}
Expand All @@ -105,6 +109,7 @@ trait RoomLinkExt
openableBuilder: Option[I => Openable] = None,
onEnterExtra: Option[Reaction] = None
): I => RoomLink =
item => SimpleRoomLink(endRoom, endRoomDirection, openableBuilder.map(_(item)), onEnterExtra)
item =>
SimpleRoomLink(endRoom, endRoomDirection, openableBuilder.map(_(item)), onEnterExtra)(item)
}
}
Expand Up @@ -2,8 +2,9 @@ package io.github.scalaquest.core.model.behaviorBased

/**
* Contains a set of common [[BehaviorBasedModel.BehaviorBasedItem]],
* [[BehaviorBasedModel.ItemBehavior]], [[BehaviorBasedModel.GroundBehavior]] of common use,
* accessible with a mixin mechanism from the [[BehaviorBasedModel]].
* [[BehaviorBasedModel.ItemBehavior]], [[BehaviorBasedModel.GroundBehavior]] of common use, some
* common [[BehaviorBasedModel.Reaction]] generated by the Behaviours, some useful builder for the
* items and a accessible point with a mixin mechanism from the [[BehaviorBasedModel]].
*
* Usage example:
* {{{
Expand Down