Runelang: A Summoning Circle Generator

Last time we had Runelang: A Bind Rune Generator. This time, let’s make ‘summoning circles’. Basically, we want to make a circle with stars and other circles inscribed and around the borders with various ‘mystic’ text in the mix. Something like this:

  • generate_summoning_circle
    • random chance of boder
    • random chance of one or more inscribed stars
    • random chance of recurring on the border (calling generate_summoning_circle again)
    • random chance of recurring in the middle

Generate Bind Rune

Codewise, I only have one (relatively complicated) function this time:

function generate_summoning_circle(depth, options) {
  let LANGUAGES = ["GREEK_UPPER", "ASTROLOGICAL", "RUNIC"]

  options ||= {}
  depth ||= 0
  block("group {")

  let border_text_chance = options["border_text_chance"] || 0.5
  let star_chance = depth == 0 ? 1.0 : options["star_chance"] || 0.5
  let second_star_chance = depth == 0 ? 1.0 : options["second_star_chance"] || 0.5
  let border_recur_chance = options["border_recur_chance"] || 0.5 ** depth
  let inner_recur_chance = options["inner_recur_chance"] || 0.5 ** depth
  let inner_text_chance = options["inner_text_chance"] || 0.5 // if not inner recur

  // Border
  if (random_float() < border_text_chance) {
    line(`doubleTextCircle(${choose(...LANGUAGES)})`)
  } else {
    line("double(0.1) circle")
  }

  // Stars
  if (random_float() < star_chance) {
    let points = [5, 7, 11, 13][random_int(0, 3)]
    line(`star(${points})`)

    if (random_float() < second_star_chance) {
      let points = [5, 7, 11, 13][random_int(0, 3)]
      line(`invert star(${points})`)
    }
  }

  // Outer circles
  if (random_float() < border_recur_chance) {
    let points = [5, 7, 11, 13][random_int(0, 3)]
    if (depth <= random_int(1, 3)) {
      block("radial(scale: 1/4) [")
      for (let i = 0; i < points; i++) {
        generate_summoning_circle(depth + 1)
      }
      end_block("]")
    }
  }

  // Inscribed circles
  if (random_float() < inner_recur_chance) {
    block("scale(0.5) {")
    generate_summoning_circle(depth + 1)
    end_block("}")
  } else if (random_float() < inner_text_chance) {
    line(`text(chooseOne(${choose(...LANGUAGES)}))`)
  }

  end_block("}")
}

Most of it’s in the comments and configuration variables, but the idea for each part is random_float() < ***_chance, randomly choosing which features to draw. And then in ‘outer circles’ and ‘inscribed circles’, you have the recursive calls to generate_summoning_circle. You do have to be careful with those chances. If they’re too high, you’ll recur an awfully long way down and end up bringing your browser to a screaming halt. But until then, it’s all good. :D

Demo

Demo time!

Output

Source

Log (most recent messages first):