Как бы вы разработали такой DSL в Ruby? - PullRequest
4 голосов
/ 12 апреля 2011

Я читал, что Ruby отлично подходит для доменных языков.В последние несколько месяцев я создавал браузерную игру типа RPG.В какой-то момент я бы хотел, чтобы пользователи могли брать и завершать квесты.Квесты могут быть чем угодно: от убийства х мобов, убийства босса рейда, сбора некоторых предметов и т.Я также думал, что было бы неплохо создать DSL в этом отношении.Способ описания квестов на простом языке.Но у меня нет большого опыта с этим.

Как вы думаете, это хорошая идея?И если да, то есть ли у вас какие-либо советы / учебные пособия?

Ответы [ 2 ]

8 голосов
/ 12 апреля 2011

Если вы разрабатываете DSL, вам, вероятно, потребуется некоторое время, чтобы подумать о домене, на который вы пытаетесь отобразить язык. DSL хороши для удаления повторяющихся шаблонов, которые в противном случае вам пришлось бы писать для каждой задачи, поэтому сосредоточьтесь на этом. Для примеров ваших квестов, какие общие вещи вам нужны между квестами? Очевидно, многое будет зависеть от того, как квесты будут реализованы «за кулисами».

Я могу представить, что квест выглядит примерно так:

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

Здесь DSL можно использовать для создания квеста, присвоения ему имени, условий, награды и назначения его квестодателю.

Что касается написания DSL, вы захотите узнать о метапрограммировании в ruby. Я знаю why_the_lucky_stiff написал одну или две статьи об этом, и у острого руководства есть глава об этом ( Массив Двемти в главе 6 ). Лично мне всегда было трудно понять, почему написал. Я заканчиваю тем, что покупал Metaprogramming Ruby , и я нашел это действительно полезным.

8 голосов
/ 12 апреля 2011

Вот стартер для вас:

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

Автор игры может написать следующее:

require 'rpg'

include RPG

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

Текущая доходность:

> ruby game.rb 
starting your quest
moving to the left
moving to the right
opening door
moving to the left
...