Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Программирование с нуля - это совсем просто! 139) Программирование ролевой игры: Квесты-3


Школа программирования

139) Программирование ролевой игры: Квесты-3

Кстати, как-то незаметно, наша рассылка стала Золотой. С чем мы друг друга и поздравляем :)

Последний выпуск по ролевой игре был N 133.

Теперь приступим к формированию конкретного квеста убийства монстра. Нам требуется найти хотя бы одного здорового монстра, и каким-то способом отделить его от остальных. Самый простой способ - модифицировать имя монстра (поле Name), например, дополнив его оригинальным именем, что добавляет игре шарм, внося индивидуальные черточки.

Существует немало алгоритмов генерации внешне "осмысленных" имен, достаточно гладко звучащих и читающихся на русском языке, и в то же время не несущих никакой смысловой нагрузки. Рассмотрим такой алгоритм на нашем примере.

Пусть функция GenerateMonsterName выдает случайное имя. Эта функция будет определена в модуле Quest, где она и востребована. Если внимательно посмотреть на слова русского языка, то очень многие из них можно свести к схеме чередования гласных и согласных букв - чаще всего используется одна гласная (гораздо реже - две) и одна или две согласные. Тогда определим эти четыре базовые элемента слов "гласные" (одна гласная в 90% случаев и две гласные в 20%) и "согласные" (одна согласная в 75%, две согласные в 25%), и просто будем их чередовать несколько раз (случайно, от трех до шести). Получившееся в результате и будем считать именем

Вот полный текст этой функции:

  { ----------------- }
  function GenerateMonsterName: string;

  const sGlasn: string = ' бвгджзйклмнпрстфхцчшщ ' ;
        sSoglasn: string = ' аеиоуэюя ' ;

  var G: Boolean;
      i,n: Integer;
      s: string;

   function GetNextS( g: Boolean ): string;
   var s: string;
       k,i,n: Integer;
   begin
   if g then
      begin
      if random(10)=0
         then k := 2
         else k := 1;
      s := ' ' ;
      for i := 1 to k do
        begin
        n := random(length(sGlasn))+1;
        s := s+sGlasn[n];
        end;
      end else

      begin
      if random(100)<75
         then k := 1
         else k := 2;
      s := ' ' ;
      for i := 1 to k do
        begin
        n := random(length(sSoglasn))+1;
        s := s+sSoglasn[n];
        end;
      end;

   GetNextS := s;
   end;

  begin

  G := random(2)=0;
  n := 3+random(4);
  s := ' ' ;
  for i := 1 to n do
    begin
    s := s + GetNextS(G);
    G := not G;
    end;

  GenerateMonsterName:=s;
  end;

Разберем его более подробно. Сама функция довольно коротка. Переменная G определяет, с какого элемента - "гласного" или "согласного", начнется имя. Ведь это важно - случайно менять тип первой буквы и всю следующую за ней последовательность. Переменная n хранит число элементов в слове (3-6), после чего в цикле n раз значение строки s наращивается с помощью функции GetNextS, которая возвращает один элемент - "гласное" или "согласное". Эта функция локальна, так как нужна лишь для текущих нужд. Ее параметр g определяет запрос гласного или согласного элемента, а переменная k рассчитывается как длина этого элемента (один или два символа). После этого из констант, раздельно хранящих все (почти все - мягкий и твердый знак и букву "ы" мы исключили) гласные и согласные буквы, случайным образом извлекается n-й символ - k раз.

Данная функция нужна нам, чтобы придать оригинальное имя монстру, выбранному для уничтожения. В процедуре GenerateQuest он уже определен - осталось лишь модифицировать его имя (поле Name; только существующее название, фактически порода монстра, не уничтожается, а для полноты картины лишь дополняется "человеческим" именем) и сформировать значение квеста - свободного элемента массива Quests. Денежный приз и опыт сформируем в зависимости от уровня героя и числа пунктов опыта, которые надо на этом уровне набрать (15-30% от максимума). Также необходимо запретить использовать одного и того же монстра в качестве жертвы в нескольких квестах.

  { ----------------- }
  procedure GenerateQuest(qi,hn: Integer; qt: TQType);
  var i,j: Integer;
  label NextMon;
  begin
  for i := 1 to MaxMonsters-MaxNPCNum do
    if Monsters[i].HP > 0 then
       begin
       for j := 1 to MaxQuests do
         if Quests[j].TargetId=i then
            goto NextMon;

       Monsters[i].Name := Monsters[i].Name + ' , ' +
       GenerateMonsterName;
       Quests[qi].QType := qt;
       Quests[qi].MainInd := hn;
       Quests[qi].TargetId := i;
       Quests[qi].Money := (Heroes[CurHero].Level+1)*(80+random(21));
       Quests[qi].XP := round( Heroes[CurHero].MaxExp*
                                ((15+random(16))/100) );
       ShowInfo(STR_QUESTOK);
       Exit;

     NextMon:
       end;
  end;

Текстовая константа:

  STR_QUESTOK = ' Вы получили квест! ' ;

Денег в случае успеха герой получит соответственно текущему уровню, умноженному на 80-100 золотых, а опыта - от 15 до 30% от максимально возможного на данный момент (MaxExp). В момент получения квеста герою выдается короткое сообщение, которое по большому счету не очень соответствует важности момента, и доведение его до ума (в частности, можно и мирному персонажу дать имя) оставляем читателю.

Отметим, что к данному моменту в программе могут возникнуть проблемы с объемом доступной памяти. Сегмент данных в ДОС-приложениях составляет 64 килобайта :) , и возможно за счет констант и нововведений, связанных с квестами, этот объем к данному моменту оказался полностью исчерпан. Можно сократить размер карты (уровня) - с 32*32 до 30*30 элементов. В дальнейшем, когда мы перенесем эту программу в Windows с минимальной модификацией кода, такие проблемы снимутся автоматически.

В следующем выпуске детализируем информацию о квестах.

Исходный код текущей версии для Turbo Pascal (всегда проверен и работоспособен, главный файл - main.pas):

тут, 21116.zip, 18263 байта


(c) 2004-2006 Сергей Бобровский bobrovsky as russianenterprisesolutions.com

Школа программирования с нуля
Все предыдущие выпуски базового курса всегда тут:
http://www.infiltration.ru/p/


Вышел мой учебный курс "Технологии Delphi. Разработка приложений для бизнеса".
http://shop.piter.com/book/978591180282/

Учебный курс рассчитан не только на разработчиков, но и на всех тех, кто хочет стать ИТ-менеджером. Для этого как минимум нужно иметь общее представление о современных технологиях разработки и их истории и владеть соответствующей терминологией.
В книге описаны десятки технологий, каждой из которых посвящены отдельные книги. Таким образом, купив одну мою книгу, вы существенно сэкономите :) В книге полностью описан язык Delphi (версия 2006, полностью совместимая с Turbo Delphi) для обеих платформ - Win32 и .NET. Охвачены также темы работы с файлами на этих платформах, создания файл-серверных, клиент-серверных, распределенных приложений, веб-программ (Indy, ASP.NET, веб-сервисы). Описаны языки SQL и OCL. Немало глав посвящены истории программирования и различных технологий. Особое внимание уделено созданию программ с помощью технологии ECO и языка моделирования UML - программы фактически рисуются, и теперь даже для создания корпоративных приложений и их переноса в Интернет не обязательно знать программирование!
Отдельная часть отведена технологиям организации групповой работы, управления требованиями, контроля версий, локализации и тестирования.
Тут подробнее про книгу.

Другие мои книги, которые пока доступны в продаже:


Дизайн рассылки: Алексей Голубев - Web-дизайн и web-программирование


В избранное