gamefic 0.2.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/gamefic/action.rb +87 -56
- data/lib/gamefic/ansi.rb +55 -0
- data/lib/gamefic/character.rb +130 -76
- data/lib/gamefic/command.rb +19 -0
- data/lib/gamefic/core_ext/array.rb +51 -40
- data/lib/gamefic/core_ext/string.rb +4 -0
- data/lib/gamefic/describable.rb +108 -46
- data/lib/gamefic/direction.rb +46 -0
- data/lib/gamefic/director/delegate.rb +91 -0
- data/lib/gamefic/director/order.rb +10 -0
- data/lib/gamefic/director/parser.rb +119 -0
- data/lib/gamefic/director.rb +16 -197
- data/lib/gamefic/engine/cgi.rb +221 -0
- data/lib/gamefic/engine/tty.rb +237 -0
- data/lib/gamefic/engine.rb +88 -67
- data/lib/gamefic/entity.rb +96 -69
- data/lib/gamefic/grammar/conjugator.rb +20 -0
- data/lib/gamefic/grammar/gender.rb +11 -0
- data/lib/gamefic/grammar/person.rb +10 -0
- data/lib/gamefic/grammar/plural.rb +13 -0
- data/lib/gamefic/grammar/pronouns.rb +60 -0
- data/lib/gamefic/grammar/tense.rb +6 -0
- data/lib/gamefic/grammar/verb_set.rb +43 -0
- data/lib/gamefic/grammar/verbs.rb +25 -0
- data/lib/gamefic/grammar/word_adapter.rb +36 -0
- data/lib/gamefic/grammar.rb +13 -0
- data/lib/gamefic/html.rb +53 -0
- data/lib/gamefic/keywords.rb +51 -33
- data/lib/gamefic/node.rb +65 -58
- data/lib/gamefic/plot/article_mount.rb +22 -0
- data/lib/gamefic/plot/command_mount.rb +88 -0
- data/lib/gamefic/plot/entity_mount.rb +45 -0
- data/lib/gamefic/plot/query_mount.rb +9 -0
- data/lib/gamefic/plot/scene_mount.rb +181 -0
- data/lib/gamefic/plot/you_mount.rb +22 -0
- data/lib/gamefic/plot.rb +296 -247
- data/lib/gamefic/query/ambiguous_children.rb +5 -0
- data/lib/gamefic/query/base.rb +265 -0
- data/lib/gamefic/query/children.rb +10 -0
- data/lib/gamefic/query/expression.rb +47 -0
- data/lib/gamefic/query/family.rb +10 -0
- data/lib/gamefic/query/many_children.rb +7 -0
- data/lib/gamefic/query/matches.rb +11 -0
- data/lib/gamefic/query/parent.rb +10 -0
- data/lib/gamefic/query/plural_children.rb +14 -0
- data/lib/gamefic/query/self.rb +10 -0
- data/lib/gamefic/query/siblings.rb +10 -0
- data/lib/gamefic/query/text.rb +43 -0
- data/lib/gamefic/query.rb +19 -203
- data/lib/gamefic/rule.rb +18 -0
- data/lib/gamefic/scene/active.rb +25 -0
- data/lib/gamefic/scene/concluded.rb +22 -0
- data/lib/gamefic/scene/multiplechoice.rb +74 -0
- data/lib/gamefic/scene/paused.rb +26 -0
- data/lib/gamefic/scene/yesorno.rb +43 -0
- data/lib/gamefic/scene.rb +125 -0
- data/lib/gamefic/script/base.rb +33 -0
- data/lib/gamefic/script/file.rb +14 -0
- data/lib/gamefic/script/text.rb +14 -0
- data/lib/gamefic/script.rb +9 -0
- data/lib/gamefic/serialized.rb +24 -0
- data/lib/gamefic/shell.rb +9 -247
- data/lib/gamefic/snapshots.rb +134 -0
- data/lib/gamefic/source/base.rb +12 -0
- data/lib/gamefic/source/file.rb +23 -0
- data/lib/gamefic/source/text.rb +16 -0
- data/lib/gamefic/source.rb +9 -0
- data/lib/gamefic/stage.rb +75 -0
- data/lib/gamefic/syntax.rb +106 -124
- data/lib/gamefic/tester.rb +20 -0
- data/lib/gamefic/version.rb +3 -0
- data/lib/gamefic.rb +18 -12
- metadata +102 -70
- data/lib/gamefic/base.rb +0 -10
- data/lib/gamefic/before.rb +0 -12
- data/lib/gamefic/import/basics/actions/close.rb +0 -16
- data/lib/gamefic/import/basics/actions/commands.rb +0 -3
- data/lib/gamefic/import/basics/actions/drop-in.rb +0 -17
- data/lib/gamefic/import/basics/actions/drop-on.rb +0 -16
- data/lib/gamefic/import/basics/actions/drop.rb +0 -30
- data/lib/gamefic/import/basics/actions/enter.rb +0 -16
- data/lib/gamefic/import/basics/actions/go.rb +0 -35
- data/lib/gamefic/import/basics/actions/inventory.rb +0 -8
- data/lib/gamefic/import/basics/actions/leave.rb +0 -29
- data/lib/gamefic/import/basics/actions/look-in-at.rb +0 -27
- data/lib/gamefic/import/basics/actions/look-under.rb +0 -3
- data/lib/gamefic/import/basics/actions/look.rb +0 -71
- data/lib/gamefic/import/basics/actions/nil.rb +0 -25
- data/lib/gamefic/import/basics/actions/open.rb +0 -23
- data/lib/gamefic/import/basics/actions/quit.rb +0 -3
- data/lib/gamefic/import/basics/actions/take.rb +0 -107
- data/lib/gamefic/import/basics/entities/container.rb +0 -8
- data/lib/gamefic/import/basics/entities/entity.rb +0 -11
- data/lib/gamefic/import/basics/entities/fixture.rb +0 -5
- data/lib/gamefic/import/basics/entities/item.rb +0 -5
- data/lib/gamefic/import/basics/entities/portal.rb +0 -40
- data/lib/gamefic/import/basics/entities/room.rb +0 -30
- data/lib/gamefic/import/basics/entities/scenery.rb +0 -5
- data/lib/gamefic/import/basics/entities/supporter.rb +0 -6
- data/lib/gamefic/import/basics/entities/thing.rb +0 -16
- data/lib/gamefic/import/basics/queries/reachable.rb +0 -38
- data/lib/gamefic/import/basics/queries/room.rb +0 -8
- data/lib/gamefic/import/basics/queries/visible.rb +0 -32
- data/lib/gamefic/import/basics/rules/has-enough-light.rb +0 -14
- data/lib/gamefic/import/basics.old/actions/container.rb +0 -112
- data/lib/gamefic/import/basics.old/actions/inventory.rb +0 -50
- data/lib/gamefic/import/basics.old/actions/look.rb +0 -53
- data/lib/gamefic/import/basics.old/actions/meta.rb +0 -6
- data/lib/gamefic/import/basics.old/actions/traversal.rb +0 -35
- data/lib/gamefic/import/basics.old/actions.rb +0 -1
- data/lib/gamefic/import/basics.old/entities/container.rb +0 -3
- data/lib/gamefic/import/basics.old/entities/fixture.rb +0 -3
- data/lib/gamefic/import/basics.old/entities/item.rb +0 -3
- data/lib/gamefic/import/basics.old/entities/portal.rb +0 -43
- data/lib/gamefic/import/basics.old/entities/room.rb +0 -27
- data/lib/gamefic/import/basics.old/entities/scenery.rb +0 -3
- data/lib/gamefic/import/basics.old/entities/supporter.rb +0 -3
- data/lib/gamefic/import/basics.old/entities.rb +0 -1
- data/lib/gamefic/import/basics.old/room_modes.rb +0 -48
- data/lib/gamefic/import/basics.rb +0 -6
- data/lib/gamefic/import/room_modes.rb +0 -48
- data/lib/gamefic/import/standard.rb +0 -1
- data/lib/gamefic/meta.rb +0 -12
- data/lib/gamefic/optionset.rb +0 -114
- data/lib/gamefic/requirement.rb +0 -14
- data/lib/gamefic/story.rb +0 -14
- data/lib/gamefic/thing.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f89e42b74949fc2f51e9e5b277ab1c2cf8278f62
|
4
|
+
data.tar.gz: 94b6aed64c5b1805c98fde960a125b9c1f716cda
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3279a5663b92106d222f2468d9a0add3c05fedeceedcc2077f050764d5c6c5077ae38c72a1bdd475ee04bb734c57046c1976311569626246a2299e6cd22249c5
|
7
|
+
data.tar.gz: 9f32e56986a439a517d7d5783a4f37cf05e8e6884caf60caff044015c40baf8754c830b5f29bb3c98fac430e0c69419cf9dd09bf4e96b80666b1c0599f4fe2bc
|
data/lib/gamefic/action.rb
CHANGED
@@ -1,65 +1,96 @@
|
|
1
1
|
module Gamefic
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
# Actions manage the execution of commands that Characters can perform.
|
4
|
+
#
|
5
|
+
class Action
|
6
|
+
attr_reader :order_key, :queries
|
7
|
+
attr_writer :meta
|
6
8
|
@@order_key_seed = 0
|
7
|
-
|
8
|
-
|
9
|
+
|
10
|
+
def initialize(plot, verb, *queries, &proc)
|
11
|
+
if !verb.kind_of?(Symbol)
|
12
|
+
verb = verb.to_s
|
13
|
+
verb = nil if verb == ''
|
14
|
+
end
|
15
|
+
@plot = plot
|
9
16
|
@order_key = @@order_key_seed
|
10
17
|
@@order_key_seed += 1
|
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
|
-
|
18
|
+
@proc = proc
|
19
|
+
if (verb.kind_of?(Symbol) == false and !verb.nil?)
|
20
|
+
raise "Action verbs must be symbols"
|
21
|
+
end
|
22
|
+
if !@proc.nil?
|
23
|
+
if (queries.length + 1 != @proc.arity) and (queries.length == 0 and @proc.arity != -1)
|
24
|
+
raise "Number of queries is not compatible with proc arguments"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
@verb = verb
|
28
|
+
@queries = queries
|
29
|
+
if !plot.nil?
|
30
|
+
plot.send :add_action, self
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Get the specificity of the Action.
|
35
|
+
# Specificity indicates how narrowly the Action's queries filter matches.
|
36
|
+
# Actions with higher specificity are given higher priority when searching
|
37
|
+
# for the Action that matches a character command. For example, an Action
|
38
|
+
# with a Query that filters for a specific class of Entity has a higher
|
39
|
+
# specificity than an Action with a Query that accepts arbitrary text.
|
40
|
+
#
|
41
|
+
# @return [Fixnum]
|
42
|
+
def specificity
|
43
|
+
spec = 0
|
44
|
+
if verb.nil?
|
45
|
+
spec = -100
|
46
|
+
end
|
47
|
+
magnitude = 1
|
48
|
+
@queries.each { |q|
|
49
|
+
if q.kind_of?(Query::Base)
|
50
|
+
spec += (q.specificity * magnitude)
|
51
|
+
else
|
52
|
+
spec += magnitude
|
53
|
+
end
|
54
|
+
#magnitude = magnitude * 10
|
55
|
+
}
|
56
|
+
return spec
|
57
|
+
end
|
58
|
+
|
59
|
+
# Get the verb associated with this Action.
|
60
|
+
# The verb is represented by a Symbol in the imperative form, such as
|
61
|
+
# :take or :look_under.
|
62
|
+
#
|
63
|
+
# @return [Symbol] The Symbol representing the verb.
|
64
|
+
def verb
|
65
|
+
@verb
|
66
|
+
end
|
67
|
+
|
68
|
+
# Execute this Action. This method is typically called by the Plot when
|
69
|
+
# a Character performs a command.
|
48
70
|
def execute *args
|
49
|
-
@proc.call
|
71
|
+
@proc.call(*args)
|
72
|
+
end
|
73
|
+
|
74
|
+
def signature
|
75
|
+
sig = ["#{@verb}"]
|
76
|
+
@queries.each { |q|
|
77
|
+
sig.push q.signature
|
78
|
+
}
|
79
|
+
"#{sig.join(', ').gsub(/Gamefic::(Query::)?/, '')}(#{specificity})"
|
80
|
+
end
|
81
|
+
|
82
|
+
# Is this a meta Action?
|
83
|
+
# If an Action is flagged meta, it usually means that it provides
|
84
|
+
# information about the game or manages some aspect of the user interface.
|
85
|
+
# It shouldn't represent an Action that the player's character performs in
|
86
|
+
# the game world. Examples include Actions to display credits or
|
87
|
+
# instructions.
|
88
|
+
#
|
89
|
+
# @return [Boolean]
|
90
|
+
def meta?
|
91
|
+
@meta ||= false
|
50
92
|
end
|
51
|
-
|
52
|
-
|
53
|
-
arr = Array.new
|
54
|
-
arr.push entity
|
55
|
-
cls = entity.class
|
56
|
-
while cls != Object
|
57
|
-
arr.push cls
|
58
|
-
cls = cls.superclass
|
59
|
-
end
|
60
|
-
arr.push String
|
61
|
-
arr.push nil
|
62
|
-
end
|
63
|
-
end
|
93
|
+
|
94
|
+
end
|
64
95
|
|
65
96
|
end
|
data/lib/gamefic/ansi.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
module Gamefic
|
2
|
+
|
3
|
+
# Constants for ANSI codes, plus Extras for custom formatting.
|
4
|
+
module Ansi
|
5
|
+
module Code
|
6
|
+
class Nonstandard < String
|
7
|
+
|
8
|
+
end
|
9
|
+
module Attribute
|
10
|
+
NORMAL = 0
|
11
|
+
BOLD = 1
|
12
|
+
UNDERSCORE = 4
|
13
|
+
BLINK = 5
|
14
|
+
REVERSE = 7
|
15
|
+
CONCEALED = 8
|
16
|
+
end
|
17
|
+
module Foreground
|
18
|
+
BLACK = 30
|
19
|
+
RED = 31
|
20
|
+
GREEN = 32
|
21
|
+
YELLOW = 33
|
22
|
+
BLUE = 34
|
23
|
+
MAGENTA = 35
|
24
|
+
CYAN = 36
|
25
|
+
WHITE = 37
|
26
|
+
end
|
27
|
+
module Background
|
28
|
+
BLACK = 40
|
29
|
+
RED = 41
|
30
|
+
GREEN = 42
|
31
|
+
YELLOW = 43
|
32
|
+
BLUE = 44
|
33
|
+
MAGENTA = 45
|
34
|
+
CYAN = 46
|
35
|
+
WHITE = 47
|
36
|
+
end
|
37
|
+
module Extra
|
38
|
+
BLOCK = Nonstandard.new("block")
|
39
|
+
HREF = Nonstandard.new("href")
|
40
|
+
IMAGE = Nonstandard.new("image")
|
41
|
+
SRC = Nonstandard.new("src")
|
42
|
+
UPPERCASE = Nonstandard.new("uppercase")
|
43
|
+
COMMAND = Nonstandard.new("command")
|
44
|
+
IGNORED = Nonstandard.new("ignored")
|
45
|
+
LINE = Nonstandard.new("line")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
def self.graphics_mode(*settings)
|
49
|
+
ansi = settings.flatten.that_are_not(Code::Nonstandard)
|
50
|
+
return '' if ansi.length == 0
|
51
|
+
"\e[#{ansi.join(';')}m"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
data/lib/gamefic/character.rb
CHANGED
@@ -1,82 +1,136 @@
|
|
1
|
-
|
1
|
+
require 'gamefic/director'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
module Gamefic
|
4
|
+
class Character < Entity
|
5
|
+
attr_reader :queue, :user
|
6
|
+
# @return [Gamefic::Director::Order]
|
7
|
+
attr_reader :last_order
|
8
|
+
# @return [Entity,nil]
|
9
|
+
attr_reader :last_object
|
10
|
+
attr_accessor :object_of_pronoun, :scene
|
11
|
+
|
12
|
+
def initialize(plot, args = {})
|
13
|
+
@queue = Array.new
|
14
|
+
super
|
15
|
+
@buffer_stack = 0
|
16
|
+
@buffer = ""
|
17
|
+
end
|
18
|
+
|
19
|
+
# Connect a User.
|
20
|
+
#
|
21
|
+
# @param user [User]
|
22
|
+
def connect(user)
|
23
|
+
@user = user
|
24
|
+
end
|
25
|
+
|
26
|
+
# Disconnect the current User.
|
27
|
+
#
|
28
|
+
def disconnect
|
29
|
+
# TODO: We might need some cleanup here. Like, move the character out of the game, or set a timeout to allow dropped users to reconnect... figure it out.
|
30
|
+
@user = nil
|
31
|
+
end
|
32
|
+
|
33
|
+
# Perform a command.
|
34
|
+
# The command can be specified as a String or a set of tokens. Either form
|
35
|
+
# should yield the same result, but using tokens can yield better
|
36
|
+
# performance since it doesn't need to parse the command first.
|
37
|
+
#
|
38
|
+
# The command will be executed immediately regardless of game state.
|
39
|
+
#
|
40
|
+
# @example Send a command as a string
|
41
|
+
# character.perform "take the key"
|
42
|
+
#
|
43
|
+
# @example Send a command as a set of tokens
|
44
|
+
# character.perform :take, @key
|
45
|
+
#
|
46
|
+
def perform(*command)
|
47
|
+
Director.dispatch(self, *command)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Quietly perform a command.
|
51
|
+
# This method executes the command exactly as #perform does, except it
|
52
|
+
# buffers the resulting output instead of sending it to the user.
|
53
|
+
#
|
54
|
+
# @return [String] The output that resulted from performing the command.
|
55
|
+
def quietly(*command)
|
56
|
+
if @buffer_stack == 0
|
57
|
+
@buffer = ""
|
58
|
+
end
|
59
|
+
@buffer_stack += 1
|
60
|
+
self.perform *command
|
61
|
+
@buffer_stack -= 1
|
62
|
+
@buffer
|
63
|
+
end
|
64
|
+
|
65
|
+
# Send a message to the Character.
|
66
|
+
# This method will automatically wrap the message in HTML paragraphs.
|
67
|
+
# To send a message without paragraph formatting, use #stream instead.
|
68
|
+
#
|
69
|
+
# @param message [String]
|
70
|
+
def tell(message)
|
71
|
+
if user != nil and message.to_s != ''
|
72
|
+
if @buffer_stack > 0
|
73
|
+
@buffer += message
|
74
|
+
else
|
75
|
+
message = "<p>#{message}</p>"
|
76
|
+
# This method uses String#gsub instead of String#gsub! for
|
77
|
+
# compatibility with Opal.
|
78
|
+
message = message.gsub(/\n\n/, '</p><p>')
|
79
|
+
message = message.gsub(/\n/, '<br/>')
|
80
|
+
user.stream.send message
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Send a message to the Character as raw text.
|
86
|
+
# Unlike #tell, this method will not wrap the message in HTML paragraphs.
|
87
|
+
#
|
88
|
+
# @param message [String]
|
89
|
+
def stream(message)
|
90
|
+
user.stream.send message
|
91
|
+
end
|
92
|
+
|
93
|
+
def destroy
|
94
|
+
if @user != nil
|
95
|
+
@user.quit
|
96
|
+
end
|
9
97
|
super
|
10
|
-
end
|
11
|
-
def connect(user)
|
12
|
-
@user = user
|
13
|
-
end
|
14
|
-
def disconnect
|
15
|
-
# TODO: We might need some cleanup here. Like, move the character out of the game, or set a timeout to allow dropped users to reconnect... figure it out.
|
16
|
-
@user = nil
|
17
|
-
end
|
18
|
-
def perform(command)
|
19
|
-
#if command != nil
|
20
|
-
# @queue.push command
|
21
|
-
#end
|
22
|
-
@last_command = command
|
23
|
-
if state.busy? == false
|
24
|
-
Director.dispatch(self, command)
|
25
|
-
else
|
26
|
-
@queue.push command
|
27
|
-
end
|
28
|
-
end
|
29
|
-
#def inject(command)
|
30
|
-
# Director.dispatch(self, command)
|
31
|
-
#end
|
32
|
-
def tell(message, refresh = false)
|
33
|
-
if user != nil and message.to_s != ''
|
34
|
-
user.stream.send "#{message}\n"
|
35
|
-
if (refresh == true)
|
36
|
-
user.refresh
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
def state=(new_state)
|
41
|
-
@state = new_state
|
42
|
-
end
|
43
|
-
def destroy
|
44
|
-
if @user != nil
|
45
|
-
@user.quit
|
46
|
-
end
|
47
|
-
super
|
48
|
-
end
|
49
|
-
def update
|
50
|
-
super
|
51
|
-
@state.update
|
52
|
-
end
|
53
|
-
end
|
54
|
-
class CharacterState
|
55
|
-
def initialize(character)
|
56
|
-
@character = character
|
57
|
-
post_initialize
|
58
|
-
end
|
59
|
-
def post_initialize
|
60
|
-
# TODO: Required by subclasses?
|
61
|
-
end
|
62
|
-
def busy?
|
63
|
-
false
|
64
|
-
end
|
65
|
-
def update
|
66
|
-
while (line = @character.queue.shift)
|
67
|
-
@character.perform line
|
68
|
-
if @character.state != self
|
69
|
-
break
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
def prompt
|
74
|
-
"> "
|
75
98
|
end
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
99
|
+
|
100
|
+
# Proceed to the next Action in the current stack.
|
101
|
+
# This method is typically used in Action blocks to cascade through
|
102
|
+
# multiple implementations of the same verb.
|
103
|
+
#
|
104
|
+
# @example Proceed through two implementations of a verb
|
105
|
+
# introduction do |actor|
|
106
|
+
# actor[:has_eaten] = false # Initial value
|
107
|
+
# end
|
108
|
+
# respond :eat do |actor|
|
109
|
+
# actor[:has_eaten] = true
|
110
|
+
# end
|
111
|
+
# respond :eat do |actor|
|
112
|
+
# # This version will be executed first because it was implemented last
|
113
|
+
# actor.tell "You eat something."
|
114
|
+
# actor[:has_eaten] # Will be false on the first run
|
115
|
+
# actor.proceed # Execute the previous implementation
|
116
|
+
# actor[:has_eaten] #=> true
|
117
|
+
# end
|
118
|
+
#
|
119
|
+
def proceed
|
120
|
+
return if delegate_stack.last.nil?
|
121
|
+
delegate_stack.last.proceed
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
def delegate_stack
|
126
|
+
@delegate_stack ||= []
|
127
|
+
end
|
128
|
+
def last_order=(order)
|
129
|
+
return if order.nil?
|
130
|
+
@last_order = order
|
131
|
+
if !order.action.meta? and !order.arguments[0].nil? and !order.arguments[0][0].nil? and order.arguments[0][0].kind_of?(Entity)
|
132
|
+
@last_object = order.arguments[0][0]
|
133
|
+
end
|
80
134
|
end
|
81
135
|
end
|
82
136
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Gamefic
|
2
|
+
# A Command is a collection of tokens parsed from a Syntax.
|
3
|
+
# The Director uses Commands to find and execute corresponding Actions.
|
4
|
+
#
|
5
|
+
class Command
|
6
|
+
# @!attribute [r] verb
|
7
|
+
# @return [Symbol] A Symbol representing the command's verb or verbal phrase.
|
8
|
+
attr_reader :verb
|
9
|
+
|
10
|
+
# @!attribute [r] arguments
|
11
|
+
# @return [Array<String>] An Array of arguments to be mapped to an Action's Queries.
|
12
|
+
attr_reader :arguments
|
13
|
+
|
14
|
+
def initialize verb, arguments
|
15
|
+
@verb = verb
|
16
|
+
@arguments = arguments
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,47 +1,58 @@
|
|
1
1
|
class Array
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
# @return [Array]
|
3
|
+
def that_are(cls)
|
4
|
+
if (cls.kind_of?(Class) or cls.kind_of?(Module))
|
5
|
+
return self.clone.delete_if { |i| i.kind_of?(cls) == false }
|
5
6
|
elsif cls.kind_of?(Symbol)
|
6
|
-
return self.clone.delete_if { |i| i.
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
7
|
+
return self.clone.delete_if { |i| i.send(cls) == false }
|
8
|
+
else
|
9
|
+
if self.include?(cls)
|
10
|
+
return [cls]
|
11
|
+
end
|
12
|
+
return Array.new
|
13
|
+
end
|
14
|
+
end
|
15
|
+
# @return [Array]
|
16
|
+
def that_are_not(cls)
|
17
|
+
if (cls.kind_of?(Class) or cls.kind_of?(Module))
|
18
|
+
return self.clone.delete_if { |i| i.kind_of?(cls) == true }
|
17
19
|
elsif cls.kind_of?(Symbol)
|
18
|
-
return self.clone.delete_if { |i| i.
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
return self.clone.delete_if { |i| i.send(cls) == true }
|
21
|
+
else
|
22
|
+
return self.clone - [cls]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
def random
|
26
|
+
return self[rand(self.length)]
|
27
|
+
end
|
26
28
|
def pop_random
|
27
29
|
delete_at(rand(self.length))
|
28
30
|
end
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
31
|
+
# @return [Array]
|
32
|
+
def shuffle
|
33
|
+
self.sort { |a, b|
|
34
|
+
rand(3) <=> rand(3)
|
35
|
+
}
|
36
|
+
end
|
37
|
+
# @return [Array]
|
38
|
+
def shuffle!
|
39
|
+
self.sort! { |a, b|
|
40
|
+
rand(3) <=> rand(3)
|
41
|
+
}
|
42
|
+
end
|
43
|
+
# Get a string representation of the array that separated elements with
|
44
|
+
# commas and adds a conjunction before the last element.
|
45
|
+
# @return [String]
|
46
|
+
def join_and(sep = ', ', andSep = ' and ', serial = true)
|
47
|
+
if self.length < 3
|
48
|
+
self.join(andSep)
|
49
|
+
else
|
50
|
+
start = self - [self.last]
|
51
|
+
start.join(sep) + "#{serial ? sep.strip : ''}#{andSep}#{self.last}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
# @return [String]
|
55
|
+
def join_or(sep = ', ', orSep = ' or ', serial = true)
|
56
|
+
join_and(sep, orSep, serial)
|
57
|
+
end
|
47
58
|
end
|
@@ -1,10 +1,14 @@
|
|
1
1
|
class String
|
2
|
+
# Capitalize the first letter without changing the rest of the string.
|
3
|
+
# (String#capitalize makes the rest of the string lower-case.)
|
2
4
|
def capitalize_first
|
3
5
|
"#{self[0,1].upcase}#{self[1,self.length]}"
|
4
6
|
end
|
7
|
+
# @return [String]
|
5
8
|
def cap_first
|
6
9
|
self.capitalize_first
|
7
10
|
end
|
11
|
+
# @return [Array]
|
8
12
|
def split_words
|
9
13
|
self.gsub(/ +/, ' ').strip.split
|
10
14
|
end
|