tyrano_dsl 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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