Class: Lich::Gemstone::PlaceholderTemplate

Inherits:
Object
  • Object
show all
Defined in:
documented/gemstone/creature.rb

Overview

Message template with placeholders for rendering and regex matching.

Stores a template string with ... placeholders and a map of placeholder names to their valid options (e.g., pronoun => ["he", "she", "it", ...]). Supports rendering with substitutions and regex generation for matching actual game output against the template variants.

Instance Method Summary collapse

Constructor Details

#initialize(template, placeholders = {}) ⇒ void

Initializes a placeholder template.

Parameters:

  • template (String, Array) —

    the message template (e.g. "The pronoun attacks.")

  • placeholders (Hash) (defaults to: {}) —

    map of placeholder names (Symbols) to valid option arrays



1070
1071
1072
1073
1074
# File 'documented/gemstone/creature.rb', line 1070

def initialize(template, placeholders = {})
  @template = template
  @placeholders = placeholders
  @regex_cache = {}
end

Instance Method Details

#match(str, literals = {}) ⇒ Object

Public: Messaging#match calls this on the template it holds. It sat below the private keyword, so every templated message raised NoMethodError on match - the placeholder machinery could render a line but never recognize one.



1142
1143
1144
1145
1146
1147
1148
# File 'documented/gemstone/creature.rb', line 1142

def match(str, literals = {})
  regex = to_regex(literals)
  m = regex.match(str)
  return nil unless m

  m.names.any? ? m.named_captures.transform_keys(&:to_sym) : m.captures
end

#placeholders ⇒ Hash

Returns the placeholder map.

Returns:

  • (Hash) —

    the placeholder definitions



1086
1087
1088
# File 'documented/gemstone/creature.rb', line 1086

def placeholders
  @placeholders
end

#template ⇒ String, Array

Returns the template string or array.

Returns:

  • (String, Array) —

    the template



1079
1080
1081
# File 'documented/gemstone/creature.rb', line 1079

def template
  @template
end

#to_display(subs = {}) ⇒ String

Renders the template as a displayable string.

Substitutes each placeholder with the provided value (or a random option from the placeholder's valid set, or empty string if none available).

Examples:

tpl = PlaceholderTemplate.new("The {pronoun} strikes.", {pronoun: ["he", "she"]})
tpl.to_display({pronoun: "he"}) #=> "The he strikes."
tpl.to_display({}) #=> "The [random he or she] strikes."

Parameters:

  • subs (Hash) (defaults to: {}) —

    substitution values keyed by placeholder name (Symbol)

Returns:

  • (String) —

    the rendered message



1101
1102
1103
1104
1105
1106
1107
1108
# File 'documented/gemstone/creature.rb', line 1101

def to_display(subs = {})
  line = @template.dup
  @placeholders.each do |key, options|
    value = subs[key] || options.sample || ""
    line.gsub!("{#{key}}", value.to_s)
  end
  line
end

#to_regex(literals = {}) ⇒ Regexp

Generates a compiled regex that matches the template's possible expansions.

Each placeholder becomes a non-capturing group of its options (or a group named after the placeholder for later extraction). Results are cached per literal set. Handles array templates by creating a union of their regexes.

Examples:

tpl = PlaceholderTemplate.new("The {pronoun} strikes.", {pronoun: ["he", "she"]})
tpl.to_regex.match("The he strikes.") #=> <MatchData>
tpl.to_regex.match("The she strikes.") #=> <MatchData>
tpl.to_regex.match("The it strikes.") #=> nil

Parameters:

  • literals (Hash) (defaults to: {}) —

    literal values for placeholders (override options)

Returns:

  • (Regexp) —

    a compiled regex matching template variants



1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
# File 'documented/gemstone/creature.rb', line 1123

def to_regex(literals = {})
  # Use cache to avoid rebuilding regex on every call
  cache_key = literals.hash
  return @regex_cache[cache_key] if @regex_cache[cache_key]

  regex = if @template.is_a?(Array)
            regexes = @template.map { |t| self.class.new(t, @placeholders).to_regex(literals) }
            Regexp.union(*regexes)
          else
            build_regex(literals)
          end

  @regex_cache[cache_key] = regex
end