tyrano_dsl 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.travis.yml +3 -0
  4. data/CODE_OF_CONDUCT.md +74 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +290 -0
  8. data/Rakefile +10 -0
  9. data/bin/setup +8 -0
  10. data/bin/tyrano_dsl.rb +21 -0
  11. data/lib/tyrano_dsl/elements/background.rb +31 -0
  12. data/lib/tyrano_dsl/elements/character.rb +49 -0
  13. data/lib/tyrano_dsl/elements/elements_module.rb +7 -0
  14. data/lib/tyrano_dsl/elements/jump_target.rb +18 -0
  15. data/lib/tyrano_dsl/elements/label.rb +19 -0
  16. data/lib/tyrano_dsl/elements/scene.rb +21 -0
  17. data/lib/tyrano_dsl/elements/stance.rb +26 -0
  18. data/lib/tyrano_dsl/elements/title_screen.rb +16 -0
  19. data/lib/tyrano_dsl/elements/variable.rb +22 -0
  20. data/lib/tyrano_dsl/elements/world.rb +62 -0
  21. data/lib/tyrano_dsl/elements_writers/background_writer.rb +30 -0
  22. data/lib/tyrano_dsl/elements_writers/character_writer.rb +32 -0
  23. data/lib/tyrano_dsl/elements_writers/characters_writer.rb +43 -0
  24. data/lib/tyrano_dsl/elements_writers/elements_writers_module.rb +27 -0
  25. data/lib/tyrano_dsl/elements_writers/scene_writer.rb +30 -0
  26. data/lib/tyrano_dsl/elements_writers/title_screen_writer.rb +87 -0
  27. data/lib/tyrano_dsl/elements_writers/variables_writer.rb +30 -0
  28. data/lib/tyrano_dsl/file_actions/clear_directory.rb +34 -0
  29. data/lib/tyrano_dsl/file_actions/create_file.rb +33 -0
  30. data/lib/tyrano_dsl/file_actions/file_copy.rb +36 -0
  31. data/lib/tyrano_dsl/file_actions/files_actions_module.rb +28 -0
  32. data/lib/tyrano_dsl/file_actions/json_patch.rb +47 -0
  33. data/lib/tyrano_dsl/main.rb +18 -0
  34. data/lib/tyrano_dsl/parsed_word.rb +22 -0
  35. data/lib/tyrano_dsl/parser.rb +58 -0
  36. data/lib/tyrano_dsl/parsing_context.rb +18 -0
  37. data/lib/tyrano_dsl/parsing_words/ask_question.rb +32 -0
  38. data/lib/tyrano_dsl/parsing_words/conditional_jump.rb +42 -0
  39. data/lib/tyrano_dsl/parsing_words/declare_background.rb +32 -0
  40. data/lib/tyrano_dsl/parsing_words/declare_character.rb +38 -0
  41. data/lib/tyrano_dsl/parsing_words/declare_label.rb +20 -0
  42. data/lib/tyrano_dsl/parsing_words/declare_variable.rb +30 -0
  43. data/lib/tyrano_dsl/parsing_words/display_text.rb +22 -0
  44. data/lib/tyrano_dsl/parsing_words/hide_character.rb +20 -0
  45. data/lib/tyrano_dsl/parsing_words/hide_message_window.rb +16 -0
  46. data/lib/tyrano_dsl/parsing_words/include_file.rb +26 -0
  47. data/lib/tyrano_dsl/parsing_words/jump.rb +22 -0
  48. data/lib/tyrano_dsl/parsing_words/parsing_words_module.rb +72 -0
  49. data/lib/tyrano_dsl/parsing_words/set_background.rb +21 -0
  50. data/lib/tyrano_dsl/parsing_words/set_character_stance.rb +23 -0
  51. data/lib/tyrano_dsl/parsing_words/set_title_screen_background.rb +25 -0
  52. data/lib/tyrano_dsl/parsing_words/show_character.rb +26 -0
  53. data/lib/tyrano_dsl/parsing_words/show_message_window.rb +16 -0
  54. data/lib/tyrano_dsl/parsing_words/start_scene.rb +30 -0
  55. data/lib/tyrano_dsl/parsing_words/update_variable.rb +37 -0
  56. data/lib/tyrano_dsl/tyrano_dsl.rb +3 -0
  57. data/lib/tyrano_dsl/tyrano_exception.rb +6 -0
  58. data/lib/tyrano_dsl/vocabulary.rb +84 -0
  59. data/lib/tyrano_dsl/writer.rb +114 -0
  60. data/lib/tyrano_dsl/writing_context.rb +123 -0
  61. data/lib/tyrano_dsl/writing_words/ask_question.rb +28 -0
  62. data/lib/tyrano_dsl/writing_words/conditional_jump.rb +37 -0
  63. data/lib/tyrano_dsl/writing_words/declare_background.rb +5 -0
  64. data/lib/tyrano_dsl/writing_words/declare_character.rb +5 -0
  65. data/lib/tyrano_dsl/writing_words/declare_label.rb +18 -0
  66. data/lib/tyrano_dsl/writing_words/declare_variable.rb +5 -0
  67. data/lib/tyrano_dsl/writing_words/display_text.rb +16 -0
  68. data/lib/tyrano_dsl/writing_words/hide_character.rb +13 -0
  69. data/lib/tyrano_dsl/writing_words/hide_message_window.rb +12 -0
  70. data/lib/tyrano_dsl/writing_words/include_file.rb +5 -0
  71. data/lib/tyrano_dsl/writing_words/jump.rb +18 -0
  72. data/lib/tyrano_dsl/writing_words/nop.rb +8 -0
  73. data/lib/tyrano_dsl/writing_words/set_background.rb +18 -0
  74. data/lib/tyrano_dsl/writing_words/set_character_stance.rb +20 -0
  75. data/lib/tyrano_dsl/writing_words/set_title_screen_background.rb +4 -0
  76. data/lib/tyrano_dsl/writing_words/show_character.rb +31 -0
  77. data/lib/tyrano_dsl/writing_words/show_message_window.rb +12 -0
  78. data/lib/tyrano_dsl/writing_words/start_scene.rb +9 -0
  79. data/lib/tyrano_dsl/writing_words/update_variable.rb +28 -0
  80. data/lib/tyrano_dsl/writing_words/writing_words_module.rb +43 -0
  81. data/tyrano_dsl.gemspec +37 -0
  82. metadata +210 -0
@@ -0,0 +1,16 @@
1
+ require_relative '../vocabulary'
2
+ require_relative 'parsing_words_module'
3
+
4
+ module TyranoDsl::ParsingWords::ShowMessageWindow
5
+
6
+ include TyranoDsl::ParsingWords::ParsingWordsModule
7
+
8
+ # @return [void]
9
+ # @raise [TyranoDsl::TyranoException]
10
+ def show_message_window
11
+ add_parsed_word(
12
+ TyranoDsl::Vocabulary::SHOW_MESSAGE_WINDOW,
13
+ )
14
+ end
15
+
16
+ end
@@ -0,0 +1,30 @@
1
+ require_relative 'parsing_words_module'
2
+ require_relative '../vocabulary'
3
+ require_relative '../elements/scene'
4
+
5
+ module TyranoDsl::ParsingWords::StartScene
6
+
7
+ include TyranoDsl::ParsingWords::ParsingWordsModule
8
+
9
+ # @param [String] scene_name
10
+ # @return [void]
11
+ # @raise [TyranoDsl::TyranoException]
12
+ def start_scene(scene_name)
13
+ if context.world.scenes.key? scene_name
14
+ raise TyranoDsl::TyranoException, "Duplicated scene [#{scene_name}]"
15
+ end
16
+ unless context.world.title_screen.first_scene_name
17
+ context.world.title_screen.first_scene_name = scene_name
18
+ end
19
+ context.world.scenes[scene_name] =
20
+ TyranoDsl::Elements::Scene.new(
21
+ scene_name,
22
+ context.world.scenes.length + 1
23
+ )
24
+ add_parsed_word(
25
+ TyranoDsl::Vocabulary::START_SCENE,
26
+ name: scene_name
27
+ )
28
+ end
29
+
30
+ end
@@ -0,0 +1,37 @@
1
+ require_relative '../vocabulary'
2
+ require_relative 'parsing_words_module'
3
+
4
+ module TyranoDsl::ParsingWords::UpdateVariable
5
+
6
+ include TyranoDsl::ParsingWords::ParsingWordsModule
7
+
8
+ VALID_OPERATORS = [
9
+ '=',
10
+ '+=',
11
+ '-=',
12
+ '*=',
13
+ '/=',
14
+ '%=',
15
+ ]
16
+
17
+ # @param [String] variable
18
+ # @param [String] operator
19
+ # @param [String|Symbol|Float] value
20
+ # @return [void]
21
+ # @raise [TyranoDsl::TyranoException]
22
+ def update_variable(variable, operator, value)
23
+ check_variable_exist(variable)
24
+ if value.is_a?(String) || value.is_a?(Symbol)
25
+ check_variable_exist(value)
26
+ end
27
+ unless VALID_OPERATORS.include? operator
28
+ raise TyranoDsl::TyranoException, "Unknown operator [#{operator}]"
29
+ end
30
+ add_parsed_word(
31
+ TyranoDsl::Vocabulary::UPDATE_VARIABLE,
32
+ variable: variable,
33
+ operator: operator,
34
+ value: value
35
+ )
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ module TyranoDsl
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,6 @@
1
+ require_relative 'tyrano_dsl'
2
+
3
+ # When something goes wrong.
4
+ class TyranoDsl::TyranoException < RuntimeError
5
+
6
+ end
@@ -0,0 +1,84 @@
1
+ require_relative 'tyrano_dsl'
2
+
3
+ # All the available words of the DSL
4
+ module TyranoDsl::Vocabulary
5
+
6
+ # Declare a background
7
+ ASK_QUESTION = :ask_question
8
+ # Conditional jump
9
+ CONDITIONAL_JUMP = :conditional_jump
10
+ # Declare a background
11
+ DECLARE_BACKGROUND = :declare_background
12
+ # Declare a character
13
+ DECLARE_CHARACTER = :declare_character
14
+ # Declare a label
15
+ DECLARE_LABEL = :declare_label
16
+ # Declare a variable
17
+ DECLARE_VARIABLE = :declare_variable
18
+ # Display some text
19
+ DISPLAY_TEXT = :display_text
20
+ # Hide a character
21
+ HIDE_CHARACTER = :hide_character
22
+ # Hide the message window
23
+ HIDE_MESSAGE_WINDOW = :hide_message_window
24
+ # Include another file
25
+ INCLUDE_FILE = :include_file
26
+ # Jump to a scene
27
+ JUMP = :jump
28
+ # Set the current background
29
+ SET_BACKGROUND = :set_background
30
+ # Set the background of the title screen
31
+ SET_TITLE_SCREEN_BACKGROUND = :set_title_screen_background
32
+ # Set the stance of a character
33
+ SET_CHARACTER_STANCE = :set_character_stance
34
+ # Show a character
35
+ SHOW_CHARACTER = :show_character
36
+ # Show the message window
37
+ SHOW_MESSAGE_WINDOW = :show_message_window
38
+ # Start a scene
39
+ START_SCENE = :start_scene
40
+ # Update a variable
41
+ UPDATE_VARIABLE = :update_variable
42
+
43
+ # All the available words
44
+ ALL_WORDS = [
45
+ ASK_QUESTION,
46
+ CONDITIONAL_JUMP,
47
+ DECLARE_BACKGROUND,
48
+ DECLARE_CHARACTER,
49
+ DECLARE_LABEL,
50
+ DECLARE_VARIABLE,
51
+ DISPLAY_TEXT,
52
+ HIDE_CHARACTER,
53
+ HIDE_MESSAGE_WINDOW,
54
+ INCLUDE_FILE,
55
+ JUMP,
56
+ SET_BACKGROUND,
57
+ SET_TITLE_SCREEN_BACKGROUND,
58
+ SET_CHARACTER_STANCE,
59
+ SHOW_CHARACTER,
60
+ SHOW_MESSAGE_WINDOW,
61
+ START_SCENE,
62
+ UPDATE_VARIABLE,
63
+ ].sort.freeze
64
+
65
+ # Get the word class corresponding to the words
66
+ # @param [String] class_file_path name of the class
67
+ def self.get_words_class(class_file_path)
68
+ TyranoDsl::Vocabulary::ALL_WORDS.each do |word|
69
+ full_path = "#{class_file_path}/#{word}"
70
+ require_relative full_path
71
+ full_class_name = "TyranoDsl::" + full_path.
72
+ split('_').
73
+ collect(&:capitalize).
74
+ join.
75
+ split('/').
76
+ collect do |c|
77
+ c[0] = c[0].upcase
78
+ c
79
+ end.join('::')
80
+ word_class = Kernel.const_get(full_class_name)
81
+ yield(word, word_class)
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,114 @@
1
+ require 'logger'
2
+
3
+ require_relative 'elements_writers/background_writer'
4
+ require_relative 'elements_writers/character_writer'
5
+ require_relative 'elements_writers/characters_writer'
6
+ require_relative 'elements_writers/title_screen_writer'
7
+ require_relative 'elements_writers/variables_writer'
8
+ require_relative 'tyrano_dsl'
9
+ require_relative 'vocabulary'
10
+ require_relative 'writing_context'
11
+
12
+ # Write the content that have been parsed
13
+ class TyranoDsl::Writer
14
+
15
+ def initialize
16
+ @logger = Logger.new(STDOUT)
17
+ @words = {}
18
+ TyranoDsl::Vocabulary.get_words_class('writing_words') do |word, word_class|
19
+ @words[word] = word_class.new
20
+ end
21
+ end
22
+
23
+ # @param [TyranoDsl::Elements::World] world
24
+ # @param [Array<TyranoDsl::ParsedWord>] parsed_words
25
+ # @return [TyranoDsl::WritingContext]
26
+ # @raise [TyranoDsl::TyranoException]
27
+ def write(world, parsed_words)
28
+ log {'Writing content'}
29
+ writing_context = TyranoDsl::WritingContext.new(world)
30
+ write_title_screen(writing_context, world)
31
+ write_backgrounds(writing_context, world)
32
+ write_characters(writing_context, world)
33
+ write_scenes(writing_context, world, parsed_words)
34
+ write_variables(writing_context, world)
35
+ writing_context.end_writing
36
+ log {'Content written'}
37
+ writing_context
38
+ end
39
+
40
+ private
41
+
42
+ # @param [TyranoDsl::WritingContext] writing_context
43
+ # @param [TyranoDsl::Elements::World] world
44
+ # @return [void]
45
+ # @raise [TyranoDsl::TyranoException]
46
+ def write_title_screen(writing_context, world)
47
+ title_screen_writer = TyranoDsl::ElementsWriters::TitleScreenWriter.new
48
+ concat_file_actions(writing_context, title_screen_writer.write(world))
49
+ end
50
+
51
+ # @param [TyranoDsl::WritingContext] writing_context
52
+ # @param [TyranoDsl::Elements::World] world
53
+ # @return [void]
54
+ # @raise [TyranoDsl::TyranoException]
55
+ def write_characters(writing_context, world)
56
+ character_writer = TyranoDsl::ElementsWriters::CharacterWriter.new
57
+ concat_file_actions(writing_context, character_writer.init_actions)
58
+ world.characters.each_value do |character|
59
+ concat_file_actions(writing_context, character_writer.write(character))
60
+ end
61
+ characters_writer = TyranoDsl::ElementsWriters::CharactersWriter.new
62
+ concat_file_actions(writing_context, characters_writer.write(world))
63
+ end
64
+
65
+ # @param [TyranoDsl::WritingContext] writing_context
66
+ # @param [TyranoDsl::Elements::World] world
67
+ # @return [void]
68
+ # @raise [TyranoDsl::TyranoException]
69
+ def write_backgrounds(writing_context, world)
70
+ background_writer = TyranoDsl::ElementsWriters::BackgroundWriter.new
71
+ concat_file_actions(writing_context, background_writer.init_actions)
72
+ world.backgrounds.each_value do |background|
73
+ concat_file_actions(writing_context, background_writer.write(background))
74
+ end
75
+ end
76
+
77
+ # @param [TyranoDsl::WritingContext] writing_context
78
+ # @param [TyranoDsl::Elements::World] world
79
+ # @return [void]
80
+ # @raise [TyranoDsl::TyranoException]
81
+ def write_variables(writing_context, world)
82
+ variables_writer = TyranoDsl::ElementsWriters::VariablesWriter.new
83
+ concat_file_actions(writing_context, variables_writer.write(world))
84
+ end
85
+
86
+ # @param [TyranoDsl::WritingContext] writing_context
87
+ # @param [Array] file_actions
88
+ # @return [void]
89
+ def concat_file_actions(writing_context, file_actions)
90
+ writing_context.file_actions.concat(file_actions)
91
+ end
92
+
93
+ # @param [TyranoDsl::WritingContext] writing_context
94
+ # @param [Array<TyranoDsl::ParsedWord>] parsed_words
95
+ # @param [TyranoDsl::Elements::World] world
96
+ # @return [void]
97
+ # @raise [TyranoDsl::TyranoException]
98
+ def write_scenes(writing_context, world, parsed_words)
99
+ parsed_words.each do |parsed_word|
100
+ action_word = @words[parsed_word.word]
101
+ action_word.run(
102
+ writing_context,
103
+ world,
104
+ parsed_word.word_location,
105
+ parsed_word.parameters
106
+ )
107
+ end
108
+ end
109
+
110
+ def log
111
+ @logger.info(self.class) {yield}
112
+ end
113
+
114
+ end
@@ -0,0 +1,123 @@
1
+ require 'logger'
2
+ require 'set'
3
+
4
+ require_relative 'elements_writers/scene_writer'
5
+ require_relative 'tyrano_exception'
6
+ require_relative 'tyrano_dsl'
7
+
8
+ # Context for writing
9
+ class TyranoDsl::WritingContext
10
+
11
+ # @return [Array<String>]
12
+ attr_reader :current_scene_assets
13
+ # @return [Array<String>]
14
+ attr_reader :current_scene_content
15
+ # @return [Hash{String => Object}]
16
+ attr_reader :file_actions
17
+ # @return [TyranoDsl::Elements::World]
18
+ attr_reader :world
19
+
20
+ # @param [TyranoDsl::Elements::World] world
21
+ def initialize(world)
22
+ @logger = Logger.new(STDOUT)
23
+ @world = world
24
+ @file_actions = []
25
+ @current_scene_content = nil
26
+ @current_scene_name = nil
27
+ @current_scene_assets = nil
28
+ @current_scene_labels = nil
29
+ @scene_writer = TyranoDsl::ElementsWriters::SceneWriter.new
30
+ end
31
+
32
+ # Append some content to the current scene
33
+ #
34
+ # @param [Array<String>] word_location
35
+ # @param [Array<String>] content
36
+ # @return [void]
37
+ # @raise [TyranoDsl::TyranoException]
38
+ def append_content(word_location, content)
39
+ check_in_scene(word_location)
40
+ @current_scene_content << content
41
+ end
42
+
43
+ # Add an asset to be loaded in the current scene
44
+ #
45
+ # @param [Array<String>] word_location
46
+ # @param [String] asset_content
47
+ # @return [void]
48
+ # @raise [TyranoDsl::TyranoException]
49
+ def add_asset_loading(word_location, asset_content)
50
+ check_in_scene(word_location)
51
+ @current_scene_assets << asset_content
52
+ end
53
+
54
+ # Add an label in the current scene
55
+ #
56
+ # @param [Array<String>] word_location
57
+ # @param [String] label_name
58
+ # @return [void]
59
+ # @raise [TyranoDsl::TyranoException]
60
+ def add_label(word_location, label_name)
61
+ check_in_scene(word_location)
62
+ if @current_scene_labels.include? label_name
63
+ raise TyranoDsl::TyranoException, "Duplicated label [#{label_name}]"
64
+ end
65
+ @current_scene_labels << label_name
66
+ end
67
+
68
+ # Initialize a new scene
69
+ # @param [String] scene_name the scene name
70
+ # @return [void]
71
+ def init_new_scene(scene_name)
72
+ write_current_scene
73
+ @current_scene_content = []
74
+ @current_scene_name = scene_name
75
+ @current_scene_assets = Set.new
76
+ @current_scene_labels = []
77
+ end
78
+
79
+ # Bookkeeping stuff to end the writing
80
+ # @raise [TyranoDsl::TyranoException]
81
+ # @return [void]
82
+ def end_writing
83
+ write_current_scene
84
+ @current_scene_content = nil
85
+ @current_scene_name = nil
86
+ @current_scene_assets = nil
87
+ @current_scene_labels = nil
88
+ @world.validate
89
+ log {"Writing is over, #{@file_actions.length} actions created"}
90
+ end
91
+
92
+ private
93
+
94
+ def write_current_scene
95
+ if @current_scene_name
96
+ current_scene = @world.scenes[@current_scene_name]
97
+ @file_actions.concat @scene_writer.write(
98
+ current_scene,
99
+ @current_scene_content,
100
+ @current_scene_assets
101
+ )
102
+ @current_scene_labels.each do |label|
103
+ current_scene.labels << label
104
+ end
105
+ end
106
+ end
107
+
108
+ def log
109
+ @logger.info(self.class) {yield}
110
+ end
111
+
112
+ # @param [Array<String>] word_location
113
+ # @return [void]
114
+ # @raise [TyranoDsl::TyranoException]
115
+ def check_in_scene(word_location)
116
+ unless @current_scene_content
117
+ exception = TyranoDsl::TyranoException.new('This action should take place in a scene')
118
+ exception.set_backtrace word_location
119
+ raise exception
120
+ end
121
+ end
122
+
123
+ end
@@ -0,0 +1,28 @@
1
+ require_relative 'writing_words_module'
2
+
3
+ class TyranoDsl::WritingWords::AskQuestion
4
+
5
+ include TyranoDsl::WritingWords::WritingWordsModule
6
+
7
+ def run(writing_context, world, word_location, parameters)
8
+ content = []
9
+ parameters[:possible_answers].each do |possible_answer|
10
+ text = possible_answer[:text]
11
+ scene_name = possible_answer[:scene]
12
+ label_name = possible_answer[:label]
13
+ top = possible_answer[:top]
14
+ left = possible_answer[:left]
15
+ target_scene = fetch_scene(world, word_location, scene_name)
16
+
17
+ label = label_name ? world.labels[label_name].target_name : ''
18
+
19
+ content << "[glink color=\"black\" storage=\"#{target_scene.target_name}\" target=\"#{label}\" size=\"20\" x=\"#{left}\" y=\"#{top}\" text=\"#{h(text)}\"]\n"
20
+ end
21
+ content << "[s]\n"
22
+ writing_context.append_content(
23
+ word_location,
24
+ content.join
25
+ )
26
+ end
27
+
28
+ end