1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
package scalevalapokalypsi.Model
import scalevalapokalypsi.Model.Entities.*
import scalevalapokalypsi.Model.Entities.NPCs.*
/** 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.
*
* @param input a textual in-game command such as “go east” or “rest”
*/
class Action(input: String):
private val commandText = input.trim.toLowerCase
private val verb = commandText.takeWhile( _ != ' ' )
private val modifiers = commandText.drop(verb.length).trim
/** Causes the given player to take the action represented by this object,
* assuming that the command was understood. Informs the player and the
* entities surrounding it about the result. Returns true if the command
* was understood and possible, false otherwise.
*
* @param actor the acting player
* @return Boolean indicating whether the action possibly taken takes a
* turn or not.
*/
def execute(actor: Player): Boolean =
val oldLocation = actor.location
val resOption: Option[(Boolean, Event)] = this.verb match
case "go" =>
val result = actor.go(this.modifiers)
result.foreach(r =>
if actor.location != oldLocation then
oldLocation.observeEvent(r)
)
result.map((true, _))
case "rest" => Some((true, actor.rest()))
case "get" => Some((false, actor.pickUp(this.modifiers)))
case "sano" =>
val entityNames = actor.location.getEntityNames.map(_.toLowerCase)
val recipientNamePair = entityNames.map(name =>
val possibleNamesWithSuffix = (0 to "ille".length).map(i =>
modifiers.takeRight(name.length + i)
)
possibleNamesWithSuffix.find(s =>
s.take(name.length) == name
)
.map(_.splitAt(name.length))
).flatten.headOption
val recipient = recipientNamePair.flatMap(p =>
actor.location.getEntity(p(0))
)
val message = recipientNamePair
.map(p => modifiers.dropRight(p(0).length + p(1).length))
.filter(_.takeRight(1) == " ")
.map(_.dropRight(1))
message.map(m =>
recipient.map(e => (false, actor.sayTo(e, m)))
).getOrElse(
Some((false, actor.say(modifiers)))
)
case "puhu" =>
val recipient = modifiers
.indices.take("ille".length + 1)
.map(i => modifiers.take(modifiers.length - i))
.find(name => actor.location.getEntity(name).isDefined)
.flatMap(name => actor.location.getEntity(name))
val dialog = recipient match
case Some(npc: NPC) =>
s"${npc.name}: ”${npc.getDialog}”"
case Some(player: Player) =>
"Et voi puhua pelaajille, vain sanoa asioita heille."
case Some(other) =>
"Et voi puhua tälle olennolle."
case None =>
"Kyseistä puhujaa ei löytynyt."
val fromThirdPerson = recipient
.filter(a => a.isInstanceOf[NPC])
.map(a => s"${actor.name} puhuu $modifiers")
Some(
(
false,
Event(Vector((
actor, dialog
)).toMap, fromThirdPerson.getOrElse(""))
)
)
case "drop" => Some((false, actor.drop(this.modifiers)))
case "laula" =>
val end = modifiers.takeRight("suohon".length)
val start =
modifiers.take(modifiers.length - "suohon".length).trim
if end == "suohon" then
val targetEntity = actor.location.getEntity(start)
targetEntity
.foreach(e => actor.setSingEffect(DefaultSingAttack(e)))
targetEntity.map(t =>
(false, Event(
Map.from(Vector((t, s"${actor.name} laulaa sinua suohon!"))),
s"${actor.name} laulaa henkilöä ${t.name} suohon."
))
)
else
None
case "xyzzy" => Some((false, Event(
Map.from(Vector((actor, "The grue tastes yummy."))),
s"${actor.name} tastes some grue.")
))
case other => None
val res: (Boolean, Event) = resOption
.getOrElse((false, Event(
Map.from(Vector((actor, "Tuo ei ole asia, jonka voit tehdä."))),
""
)))
actor.location.observeEvent(res(1))
res(0)
/** Returns a textual description of the action object, for debugging purposes. */
override def toString = s"$verb (modifiers: $modifiers)"
end Action
|