你会如何在Ruby中设计这样的DSL?

时间:2022-12-09 12:40:32

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.

我读过Ruby非常适合特定领域的语言。在过去的几个月里,我一直在创建一个rpg类型的浏览器游戏。在某些时候,我希望用户能够完成任务并完成任务。任务可以是杀死x数量的怪物,杀死raid boss,也许收集一些物品等等。

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.

整个过程听起来很有趣,容易出错。我也在想,为此创建一个DSL是个好主意。一种用简单语言描述任务的方法。但我对此没有多少经验。

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

你认为这是个好主意吗?如果是这样,你有任何建议/教程建议吗?

2 个解决方案

#1


8  

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.

如果您正在设计DSL,那么您可能需要花一些时间考虑您尝试将语言映射到的域。 DSL很适合删除您为每项任务编写的重复样板,因此请专注于此。对于你的任务示例,你认为自己在任务之间需要哪些常见的东西?显然,很多事情将取决于任务如何在“幕后”实施。

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.

在这里,DSL可用于创建任务,为其命名,条件,奖励,并将其分配给任务给予者。

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.

至于编写DSL,你会想要了解ruby中的元编程。我知道why_the_lucky_stiff已经写了一两篇关于它的文章,而尖锐的指南有一章关于它(第6章中的Dwemthy的数组)。就个人而言,我总是很难理解为什么写的东西。我最终购买了Metaprogramming Ruby,我发现它非常有用。

#2


8  

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

#1


8  

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.

如果您正在设计DSL,那么您可能需要花一些时间考虑您尝试将语言映射到的域。 DSL很适合删除您为每项任务编写的重复样板,因此请专注于此。对于你的任务示例,你认为自己在任务之间需要哪些常见的东西?显然,很多事情将取决于任务如何在“幕后”实施。

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.

在这里,DSL可用于创建任务,为其命名,条件,奖励,并将其分配给任务给予者。

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.

至于编写DSL,你会想要了解ruby中的元编程。我知道why_the_lucky_stiff已经写了一两篇关于它的文章,而尖锐的指南有一章关于它(第6章中的Dwemthy的数组)。就个人而言,我总是很难理解为什么写的东西。我最终购买了Metaprogramming Ruby,我发现它非常有用。

#2


8  

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