gamefic-sdk 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/html/core/engine.js +16 -61
  3. data/html/sinatra/engine.js +51 -0
  4. data/html/skins/standard/index.html.erb +1 -1
  5. data/html/skins/standard/play.js +20 -4
  6. data/html/skins/standard/style.css +3 -0
  7. data/lib/gamefic-sdk.rb +2 -2
  8. data/lib/gamefic-sdk/debug/plot.rb +1 -1
  9. data/lib/gamefic-sdk/platform.rb +1 -0
  10. data/lib/gamefic-sdk/platform/sinatra.rb +100 -0
  11. data/lib/gamefic-sdk/platform/web.rb +19 -12
  12. data/lib/gamefic-sdk/platform/web/app_config.rb +5 -6
  13. data/lib/gamefic-sdk/platform/web/engine.rb +41 -0
  14. data/lib/gamefic-sdk/platform/web/user.rb +19 -0
  15. data/lib/gamefic-sdk/server.rb +67 -0
  16. data/lib/gamefic-sdk/shell.rb +50 -10
  17. data/lib/gamefic-sdk/shell/init.rb +7 -2
  18. data/lib/gamefic-sdk/version.rb +1 -1
  19. data/scripts/autosuggest.plot.rb +5 -11
  20. data/scripts/clothing/actions/wear.plot.rb +1 -1
  21. data/scripts/clothing/entities/clothing.plot.rb +1 -1
  22. data/scripts/clothing/entities/coat.plot.rb +1 -1
  23. data/scripts/clothing/entities/gloves.plot.rb +1 -1
  24. data/scripts/clothing/entities/hat.plot.rb +1 -1
  25. data/scripts/clothing/entities/pants.plot.rb +1 -1
  26. data/scripts/clothing/entities/shirt.plot.rb +1 -1
  27. data/scripts/clothing/entities/shoes.plot.rb +1 -1
  28. data/scripts/save-restore.plot.rb +1 -0
  29. data/scripts/snapshots.plot.rb +1 -1
  30. data/scripts/standard.plot.rb +1 -1
  31. data/scripts/standard/actions/close.plot.rb +2 -2
  32. data/scripts/standard/actions/drop.plot.rb +6 -2
  33. data/scripts/standard/actions/give.plot.rb +12 -17
  34. data/scripts/standard/actions/go.plot.rb +7 -6
  35. data/scripts/standard/actions/lock.plot.rb +3 -3
  36. data/scripts/standard/actions/look-under.plot.rb +1 -1
  37. data/scripts/standard/actions/look.plot.rb +13 -8
  38. data/scripts/standard/actions/nil.plot.rb +1 -1
  39. data/scripts/standard/actions/place.plot.rb +2 -1
  40. data/scripts/standard/actions/read.plot.rb +1 -1
  41. data/scripts/standard/actions/search.plot.rb +1 -0
  42. data/scripts/standard/actions/take.plot.rb +1 -1
  43. data/scripts/standard/actions/talk.plot.rb +4 -4
  44. data/scripts/standard/actions/unlock.plot.rb +6 -6
  45. data/scripts/standard/actions/use.plot.rb +4 -4
  46. data/scripts/standard/entities/character.plot.rb +0 -2
  47. data/scripts/standard/entities/container.plot.rb +1 -4
  48. data/scripts/standard/entities/door.plot.rb +1 -3
  49. data/scripts/standard/entities/entity.plot.rb +0 -1
  50. data/scripts/standard/entities/exterior.plot.rb +1 -1
  51. data/scripts/standard/entities/fixture.plot.rb +1 -1
  52. data/scripts/standard/entities/item.plot.rb +1 -1
  53. data/scripts/standard/entities/portal.plot.rb +2 -3
  54. data/scripts/standard/entities/receptacle.plot.rb +1 -2
  55. data/scripts/standard/entities/room.plot.rb +4 -6
  56. data/scripts/standard/entities/rubble.plot.rb +1 -1
  57. data/scripts/standard/entities/scenery.plot.rb +1 -1
  58. data/scripts/standard/entities/supporter.plot.rb +2 -2
  59. data/scripts/standard/modules/attachable.plot.rb +1 -1
  60. data/scripts/standard/modules/auto_takes.plot.rb +1 -1
  61. data/scripts/standard/modules/darkenable.plot.rb +1 -1
  62. data/scripts/standard/modules/enterable.plot.rb +1 -1
  63. data/scripts/standard/modules/explicit_exits.plot.rb +1 -1
  64. data/scripts/standard/modules/itemizable.plot.rb +1 -1
  65. data/scripts/standard/modules/lockable.plot.rb +1 -1
  66. data/scripts/standard/modules/openable.plot.rb +4 -1
  67. data/scripts/standard/modules/parent-room.plot.rb +1 -1
  68. data/scripts/standard/modules/portable.plot.rb +1 -1
  69. data/scripts/standard/modules/transparent.plot.rb +1 -1
  70. data/scripts/standard/plural/actions/place.plot.rb +2 -2
  71. data/scripts/standard/queries.plot.rb +21 -4
  72. data/scripts/standard/use.plot.rb +26 -8
  73. data/scripts/suggestible.plot.rb +17 -17
  74. metadata +58 -10
  75. data/lib/gamefic-sdk/platform/web/gamefic_opal.rb +0 -45
  76. data/scripts/standard/queries/from_expression.plot.rb +0 -16
  77. data/scripts/standard/queries/reachable.plot.rb +0 -48
  78. data/scripts/standard/queries/room.plot.rb +0 -17
  79. data/scripts/standard/queries/visible.plot.rb +0 -45
@@ -1,4 +1,4 @@
1
- respond :go, Query::Reachable.new(Portal) do |actor, portal|
1
+ respond :go, Use.family(Portal) do |actor, portal|
2
2
  if actor.parent != actor.room
3
3
  actor.perform :leave
4
4
  end
@@ -15,11 +15,11 @@ respond :go, Query::Reachable.new(Portal) do |actor, portal|
15
15
  end
16
16
  end
17
17
 
18
- respond :go, Query::Reachable.new(Door, :locked?) do |actor, door|
18
+ respond :go, Use.family(Door, :locked?) do |actor, door|
19
19
  actor.tell "#{The door} is locked."
20
20
  end
21
21
 
22
- respond :go, Query::Reachable.new(Door, :closed?) do |actor, door|
22
+ respond :go, Use.family(Door, :closed?) do |actor, door|
23
23
  if door.automatic?
24
24
  actor.perform :open, door
25
25
  if door.open?
@@ -44,9 +44,10 @@ respond :go, Use.text do |actor, text|
44
44
  destinations.push portal.destination
45
45
  d_map[portal.destination] = portal
46
46
  }
47
- matches = Query::Base.new.execute(destinations, text)
48
- if matches.objects.length == 1
49
- actor.perform :go, d_map[matches.objects[0]]
47
+ matches = destinations.select{|o| o.match? text }
48
+ matches = destinations.select{|o| o.match? text, fuzzy: true } if matches.empty?
49
+ if matches.length == 1
50
+ actor.perform :go, d_map[matches[0]]
50
51
  else
51
52
  actor.proceed
52
53
  end
@@ -2,11 +2,11 @@ respond :lock, Query::Text.new() do |actor, string|
2
2
  actor.tell "#{you.pronoun.Subj} #{you.contract you.verb.do + ' not'} see any \"#{string}\" here."
3
3
  end
4
4
 
5
- respond :lock, Query::Reachable.new() do |actor, thing|
5
+ respond :lock, Use.family() do |actor, thing|
6
6
  actor.tell "#{you.pronoun.Subj} #{you.contract you.verb.can + ' not'} lock #{the thing}."
7
7
  end
8
8
 
9
- respond :lock, Query::Reachable.new(Lockable, :has_lock_key?) do |actor, container|
9
+ respond :lock, Use.family(Lockable, :has_lock_key?) do |actor, container|
10
10
  # Portable containers need to be picked up before they are locked.
11
11
  if container.portable? and container.parent != actor
12
12
  actor.perform :take, container
@@ -36,7 +36,7 @@ respond :lock, Query::Reachable.new(Lockable, :has_lock_key?) do |actor, contain
36
36
  end
37
37
  end
38
38
 
39
- respond :lock, Query::Reachable.new(Lockable, :has_lock_key?), Query::Children.new do |actor, container, key|
39
+ respond :lock, Use.family(Lockable, :has_lock_key?), Query::Children.new do |actor, container, key|
40
40
  if container.locked == false
41
41
  if container.lock_key == key
42
42
  #if container.is?(:not_auto_lockable)
@@ -1,6 +1,6 @@
1
1
  script 'standard/actions/look'
2
2
 
3
- respond :look_under, Query::Reachable.new() do |actor, thing|
3
+ respond :look_under, Use.family() do |actor, thing|
4
4
  actor.tell "There's nothing to see under #{the thing}."
5
5
  end
6
6
 
@@ -3,7 +3,7 @@ respond :look, Use.parent(Supporter) do |actor, supporter|
3
3
  actor.tell "#{you.pronoun.Subj} are currently on #{the supporter}."
4
4
  end
5
5
 
6
- respond :look, Query::Self.new do |actor, _|
6
+ respond :look, Use.itself do |actor, _|
7
7
  actor.tell actor.description
8
8
  actor.perform :inventory
9
9
  end
@@ -43,11 +43,12 @@ respond :look, Use.room do |actor, room|
43
43
  portals = room.children.that_are(Portal).that_are(:itemized?)
44
44
  if portals.length > 0
45
45
  if portals.length == 1
46
- actor.tell "There is an exit #{portals[0].direction}."
46
+ p = portals[0]
47
+ actor.tell "There is an exit #{p.direction || p.name || "to #{the p.destination}"}."
47
48
  else
48
49
  dirs = []
49
50
  portals.each { |p|
50
- dirs.push (p.direction || p.name)
51
+ dirs.push (p.direction || p.name || "to #{the p.destination}")
51
52
  }
52
53
  actor.tell "There are exits #{dirs.join_and(', ')}."
53
54
  end
@@ -63,7 +64,7 @@ end
63
64
  xlate "look", "look around"
64
65
  xlate "l", "look around"
65
66
 
66
- respond :look, Query::Visible.new() do |actor, thing|
67
+ respond :look, Use.available() do |actor, thing|
67
68
  actor.tell thing.description
68
69
  thing.children.that_are(:attached?).that_are(:itemized?).each { |item|
69
70
  actor.tell "#{An item} is attached to #{the thing}."
@@ -71,17 +72,21 @@ respond :look, Query::Visible.new() do |actor, thing|
71
72
  end
72
73
 
73
74
  respond :look, Use.text do |actor, string|
74
- actor.tell "You don't see any \"#{string}\" here."
75
+ if string == 'around'
76
+ actor.perform :look, actor.parent
77
+ else
78
+ actor.tell "You don't see any \"#{string}\" here."
79
+ end
75
80
  end
76
81
 
77
- respond :look, Use.reachable(Receptacle) do |actor, receptacle|
82
+ respond :look, Use.available(Receptacle) do |actor, receptacle|
78
83
  if receptacle.has_description?
79
84
  actor.tell receptacle.description
80
85
  end
81
86
  actor.perform :search, receptacle
82
87
  end
83
88
 
84
- respond :look, Query::Visible.new(Supporter) do |actor, supporter|
89
+ respond :look, Use.available(Supporter) do |actor, supporter|
85
90
  actor.proceed
86
91
  supported = supporter.children.that_are_not(:attached?)
87
92
  if supported.length > 0
@@ -89,7 +94,7 @@ respond :look, Query::Visible.new(Supporter) do |actor, supporter|
89
94
  end
90
95
  end
91
96
 
92
- respond :look, Query::Reachable.new(Door) do |actor, door|
97
+ respond :look, Use.available(Door) do |actor, door|
93
98
  if door.has_description?
94
99
  actor.proceed
95
100
  end
@@ -26,7 +26,7 @@ meta nil, Query::Text.new() do |actor, string|
26
26
  end
27
27
  end
28
28
 
29
- meta nil, Query::Text.new("it") do |actor, string|
29
+ meta nil, Query::Text.new(/^it$/) do |actor, string|
30
30
  words = string.split_words
31
31
  if verbs(to_s: true).include?(words[0])
32
32
  actor.tell "I'm not sure what you mean by \"it.\""
@@ -7,7 +7,8 @@ respond :place, Use.visible, Use.reachable(Supporter) do |actor, thing, supporte
7
7
  actor.perform :take, thing
8
8
  end
9
9
  if thing.parent == actor
10
- actor.perform :place, thing
10
+ thing.parent = supporter
11
+ actor.tell "You put #{the thing} on #{the supporter}."
11
12
  end
12
13
  end
13
14
 
@@ -1,3 +1,3 @@
1
- respond :read, Query::Visible.new do |actor, thing|
1
+ respond :read, Use.family do |actor, thing|
2
2
  actor.perform :look, thing
3
3
  end
@@ -9,6 +9,7 @@ respond :search, Use.reachable(Receptacle) do |actor, receptacle|
9
9
  end
10
10
 
11
11
  respond :search, Use.reachable(Container) do |actor, container|
12
+ next unless container.kind_of?(Container)
12
13
  if container.open? or container.transparent?
13
14
  actor.proceed
14
15
  else
@@ -35,7 +35,7 @@ respond :take, Use.reachable(Entity, :portable?) do |actor, thing|
35
35
  end
36
36
  end
37
37
 
38
- respond :take, Use.reachable(Gamefic::Rubble) do |actor, rubble|
38
+ respond :take, Use.reachable(Rubble) do |actor, rubble|
39
39
  actor.tell "#{you.pronoun.Subj} #{you.contract(you.verb.do + ' not')} have any use for #{the rubble}."
40
40
  end
41
41
 
@@ -2,15 +2,15 @@ respond :talk do |actor|
2
2
  actor.tell "#{you.pronoun.Subj} #{you.verb.talk} to #{you.pronoun.reflex}."
3
3
  end
4
4
 
5
- respond :talk, Query::Self.new do |actor, yourself|
5
+ respond :talk, Use.itself do |actor, yourself|
6
6
  actor.perform :talk
7
7
  end
8
8
 
9
- respond :talk, Query::Reachable.new do |actor, thing|
9
+ respond :talk, Use.family do |actor, thing|
10
10
  actor.tell "Nothing happens."
11
11
  end
12
12
 
13
- respond :talk, Query::Reachable.new(Character) do |actor, character|
13
+ respond :talk, Use.family(Character) do |actor, character|
14
14
  if actor == character
15
15
  actor.perform :talk
16
16
  else
@@ -18,7 +18,7 @@ respond :talk, Query::Reachable.new(Character) do |actor, character|
18
18
  end
19
19
  end
20
20
 
21
- respond :talk, Query::Reachable.new(Character), Query::Text.new do |actor, character, text|
21
+ respond :talk, Use.family(Character), Query::Text.new do |actor, character, text|
22
22
  actor.perform :talk, character
23
23
  end
24
24
 
@@ -2,11 +2,11 @@ respond :unlock, Query::Text.new() do |actor, string|
2
2
  actor.tell "#{you.pronoun.Subj} #{you.contract you.verb.do + ' not'} see any \"#{string}\" here."
3
3
  end
4
4
 
5
- respond :unlock, Query::Reachable.new() do |actor, thing|
5
+ respond :unlock, Use.family() do |actor, thing|
6
6
  actor.tell "#{you.pronoun.Subj} can't unlock #{the thing}."
7
7
  end
8
8
 
9
- respond :unlock, Query::Reachable.new(Lockable) do |actor, container|
9
+ respond :unlock, Use.family(Lockable) do |actor, container|
10
10
  # Portable containers need to be picked up before they are unlocked.
11
11
  if container.portable? and container.parent != actor
12
12
  actor.perform :take, container
@@ -36,11 +36,11 @@ respond :unlock, Query::Reachable.new(Lockable) do |actor, container|
36
36
  end
37
37
  end
38
38
 
39
- respond :unlock, Query::Reachable.new(Lockable), Query::Text.new do |actor, container, thing|
39
+ respond :unlock, Use.family(Lockable), Query::Text.new do |actor, container, thing|
40
40
  actor.tell "#{you.pronoun.Subj} #{you.contract you.verb.do + ' not'} have anything called '#{thing}.'"
41
41
  end
42
42
 
43
- respond :unlock, Query::Reachable.new(Lockable, :has_lock_key?), Query::Children.new do |actor, container, key|
43
+ respond :unlock, Use.family(Lockable, :has_lock_key?), Query::Children.new do |actor, container, key|
44
44
  if container.is?(:locked)
45
45
  if container.key == key
46
46
  #if container.is?(:not_auto_lockable)
@@ -58,7 +58,7 @@ respond :unlock, Query::Reachable.new(Lockable, :has_lock_key?), Query::Children
58
58
  end
59
59
  end
60
60
 
61
- respond :open, Query::Reachable.new(Lockable, :has_lock_key?), Query::Children.new do |actor, container, key|
61
+ respond :open, Use.family(Lockable, :has_lock_key?), Query::Children.new do |actor, container, key|
62
62
  if container.is?(:locked)
63
63
  actor.perform :unlock, container, key
64
64
  if !container.is?(:locked)
@@ -69,7 +69,7 @@ respond :open, Query::Reachable.new(Lockable, :has_lock_key?), Query::Children.n
69
69
  end
70
70
  end
71
71
 
72
- respond :use, Query::Children.new, Query::Reachable.new(Lockable, :has_lock_key?) do |actor, key, container|
72
+ respond :use, Query::Children.new, Use.family(Lockable, :has_lock_key?) do |actor, key, container|
73
73
  actor.perform :unlock, container, key
74
74
  end
75
75
 
@@ -1,4 +1,4 @@
1
- respond :use, Query::Reachable.new do |actor, tool|
1
+ respond :use, Use.family do |actor, tool|
2
2
  actor.tell "I don't know how to use #{the tool}. (A more specific command might work.)"
3
3
  end
4
4
 
@@ -6,7 +6,7 @@ respond :use, Gamefic::Query::Text.new do |actor, thing|
6
6
  actor.tell "#{you.pronoun.Subj} #{you.contract you.verb.do + ' not'} see any '#{thing}' #{you.pronoun.subj} can use here."
7
7
  end
8
8
 
9
- respond :use, Query::Reachable.new, Query::Reachable.new do |actor, tool, object|
9
+ respond :use, Use.family, Use.family do |actor, tool, object|
10
10
  actor.tell "#{you.contract you.pronoun.Subj + ' ' + you.verb.be} not carrying the #{tool}."
11
11
  end
12
12
 
@@ -14,11 +14,11 @@ respond :use, Gamefic::Query::Children.new, Gamefic::Query::Text.new do |actor,
14
14
  actor.tell "#{you.pronoun.Subj} #{you.contract you.verb.do + ' not'} see any '#{object}' here."
15
15
  end
16
16
 
17
- respond :use, Query::Text.new, Query::Reachable.new do |actor, tool, object|
17
+ respond :use, Query::Text.new, Use.family do |actor, tool, object|
18
18
  actor.tell "#{you.pronoun.Subj} #{you.contract you.verb.do + ' not'} have anything called '#{tool}.'"
19
19
  end
20
20
 
21
- respond :use, Query::Children.new, Query::Reachable.new do |actor, tool, object|
21
+ respond :use, Query::Children.new, Use.family do |actor, tool, object|
22
22
  actor.tell "I don't know how to use #{the tool} on #{the object}. (A more specific command might work.)"
23
23
  end
24
24
 
@@ -4,6 +4,4 @@ class Gamefic::Character
4
4
  include Itemizable
5
5
  include AutoTakes
6
6
 
7
- serialize :attached?, :itemized?
8
-
9
7
  end
@@ -1,11 +1,8 @@
1
1
  script 'standard/entities/receptacle'
2
2
 
3
- class Gamefic::Container < Gamefic::Receptacle
3
+ class Container < Receptacle
4
4
  include Enterable
5
5
  include Openable
6
6
  include Lockable
7
7
  include Transparent
8
-
9
- serialize :enterable?, :open?, :locked?, :lock_key, :transparent?
10
-
11
8
  end
@@ -1,11 +1,9 @@
1
1
  script 'standard/entities/portal'
2
2
 
3
- class Gamefic::Door < Gamefic::Portal
3
+ class Door < Portal
4
4
  include Openable
5
5
  include Lockable
6
6
 
7
- serialize :open?, :locked?, :lock_key, :automatic?
8
-
9
7
  def post_initialize
10
8
  super
11
9
  if @name.nil? and !@direction.nil?
@@ -5,7 +5,6 @@ class Gamefic::Entity
5
5
  include Attachable
6
6
 
7
7
  attr_writer :locale_description
8
- serialize :locale_description, :portable?, :itemized?, :attached?
9
8
 
10
9
  def locale_description
11
10
  @locale_description ||= ""
@@ -1,5 +1,5 @@
1
1
  script 'standard/entities/room'
2
2
 
3
- class Gamefic::Exterior < Gamefic::Room
3
+ class Exterior < Room
4
4
 
5
5
  end
@@ -1,3 +1,3 @@
1
- class Gamefic::Fixture < Gamefic::Entity
1
+ class Fixture < Gamefic::Entity
2
2
 
3
3
  end
@@ -1,4 +1,4 @@
1
- class Gamefic::Item < Gamefic::Entity
1
+ class Item < Gamefic::Entity
2
2
  def pre_initialize
3
3
  self.portable = true
4
4
  end
@@ -1,6 +1,5 @@
1
- class Gamefic::Portal < Gamefic::Entity
1
+ class Portal < Gamefic::Entity
2
2
  attr_accessor :destination
3
- serialize :destination, :direction
4
3
 
5
4
  # Find the portal in the destination that returns to this portal's parent
6
5
  #
@@ -32,7 +31,7 @@ class Gamefic::Portal < Gamefic::Entity
32
31
  end
33
32
 
34
33
  def name
35
- @name || direction.name
34
+ @name || (direction.nil? ? destination.name : direction.name)
36
35
  end
37
36
 
38
37
  def synonyms
@@ -1,4 +1,3 @@
1
- class Gamefic::Receptacle < Gamefic::Entity
1
+ class Receptacle < Gamefic::Entity
2
2
  include Enterable
3
- serialize :enterable?, :enter_verb, :leave_verb, :inside_verb
4
3
  end
@@ -1,9 +1,7 @@
1
- class Gamefic::Room < Gamefic::Entity
1
+ class Room < Gamefic::Entity
2
2
  include Darkenable
3
3
  include ExplicitExits
4
-
5
- serialize :dark?, :explicit_exits?
6
-
4
+
7
5
  def connect(destination, direction = nil, type = Portal, two_way = true)
8
6
  if direction.kind_of?(Hash)
9
7
  connect2(destination, direction)
@@ -31,9 +29,9 @@ class Gamefic::Room < Gamefic::Entity
31
29
  private
32
30
  def connect2 destination, direction:nil, type:Portal, two_way:true
33
31
  if direction.nil?
34
- portal = type.new :parent => self, :destination => destination, :name => destination.definitely
32
+ portal = type.new :parent => self, :destination => destination
35
33
  if two_way == true
36
- portal2 = type.new :parent => destination, :destination => self, :name => self.definitely
34
+ portal2 = type.new :parent => destination, :destination => self
37
35
  end
38
36
  else
39
37
  if direction.kind_of?(String)
@@ -6,6 +6,6 @@ script 'standard/entities/scenery'
6
6
  # like a table or the sky; and Rubble is something that might
7
7
  # be portable but is otherwise useless, like trash or debris.
8
8
 
9
- class Gamefic::Rubble < Gamefic::Scenery
9
+ class Rubble < Scenery
10
10
 
11
11
  end
@@ -1,4 +1,4 @@
1
- class Gamefic::Scenery < Gamefic::Entity
1
+ class Scenery < Gamefic::Entity
2
2
  def pre_initialize
3
3
  self.itemized = false
4
4
  end
@@ -1,6 +1,6 @@
1
- class Gamefic::Supporter < Gamefic::Entity
1
+ class Supporter < Gamefic::Entity
2
2
  include Enterable
3
- serialize :enterable?
3
+
4
4
  def initialize(args = {})
5
5
  self.enter_verb = "get on"
6
6
  self.leave_verb = "get off"
@@ -1,4 +1,4 @@
1
- module Gamefic::Attachable
1
+ module Attachable
2
2
  def attached?
3
3
  if @attached.nil?
4
4
  @attached = false
@@ -1,4 +1,4 @@
1
- module Gamefic::AutoTakes
1
+ module AutoTakes
2
2
  def auto_takes?(entity)
3
3
  return true if entity.parent == self
4
4
  if AutoTakes.enabled?
@@ -1,4 +1,4 @@
1
- module Gamefic::Darkenable
1
+ module Darkenable
2
2
  attr_writer :dark
3
3
  def dark?
4
4
  @dark ||= false