Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would you design such a DSL in Ruby?

I've read that Ruby is great for domain specific languages. In the past few months i've been creating a browser game, an rpg type. At some point, i would want users to be able to take and finish quests. The quests could be anything from killing x amount of mobs, killing a raid boss, maybe gathering some items and such.

The whole process sounds intriguing and prone to errors. I was also thinking that it would be a good idea to create a DSL for that matter. A way to describe quests in a simple language. But i don't have much experience with that.

Do you think this is a good idea ? And if so, do you have any advice/tutorials to suggest ?

like image 479
Spyros Avatar asked Dec 05 '22 22:12

Spyros


2 Answers

If you're designing a DSL, then you probably need to take some time thinking about the domain you're trying to map the language to. DSLs are good for removing the repetitive boilerplate you would otherwise have to write for every task, so focus on that. For your quests examples, what common things do you see yourself needing between the quests? Obviously, a lot will depend on how the quests get implemented "behind the scenes" as well.

I can imagine a quest looking something like this though:

Qwest "Retrieve the Grail" do
  given_by :pope

  description "Some hethan dragon took my cup, go get it back!"

  condition "Slay a dragon" do
     dragon.is_dead?
  end

  condition "Grab the Grail" do
     player.inventory.contains :grail
  end

  reward :phat_loot
end

Here, the DSL could be used to create a Quest, give it a name, conditions, reward, and assign it to a quest giver.

As far as writing the DSL goes, you'll want to learn about metaprogramming in ruby. I know why_the_lucky_stiff has written an article or two about it, and the poignant guide has a chapter on it (Dwemthy’s Array in chapter 6). Personally I always had a hard time understanding the stuff why wrote. I end up buying Metaprogramming Ruby, and I've found it really useful.

like image 73
Andy Avatar answered Dec 25 '22 01:12

Andy


Here is a starter for you:

module RPG
  def quest
    puts "starting your quest"
    yield
  end

  def move direction
    puts "moving to the #{direction.to_s}"
    yield if block_given?
  end

  def door action
    puts "#{action.to_s} door"
    yield if block_given?
  end
end

The game writer can they write the following:

require 'rpg'

include RPG

quest do
  move :left
  move :right
  door :open do
    move :left
  end
end

Running yields:

> ruby game.rb 
starting your quest
moving to the left
moving to the right
opening door
moving to the left
like image 21
Wes Avatar answered Dec 24 '22 23:12

Wes