Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АрхитектураБиологияГеографияДругоеИностранные языки
ИнформатикаИсторияКультураЛитератураМатематика
МедицинаМеханикаОбразованиеОхрана трудаПедагогика
ПолитикаПравоПрограммированиеПсихологияРелигия
СоциологияСпортСтроительствоФизикаФилософия
ФинансыХимияЭкологияЭкономикаЭлектроника

Листинг 13.4. Умная «Муха» (BFLY.C).

Листинг 12.4. Функция ответа (PRES.C). | Листинг 12.5. Перепрограммируем системные часы (OUTATIME.C). | Листинг 12.6. Трехмерное звездное небо (STARS.C). | Листинг 12.7. Киберточка (CYBER.C)._____________________ | ИСКУССТВЕННЫЙ ИНТЕЛЛЕКТ | Алгоритм 13.1. Алгоритм Преследования. | Листинг 13.1. Программа Терминатор (TERM.С). | Алгоритм 13.2. Алгоритм Уклонения. | Алгоритм 13.3. Шаблоны со случайным выбором. | Листинг 13.2. Муха (FLY.C). |


Читайте также:
  1. II. Плодотворная ориентация деятельная любящая разумная
  2. БЕЗУМНАЯ ЗАТЕЯ
  3. Безумная любовь - Френсис Чан
  4. Безумная твоя любовь
  5. Дача умная и глупая
  6. ДАЧА УМНАЯ И ГЛУПАЯ
  7. Листинг 11.2. Структура данных игрока.

// ВКЛЮЧАЕМЫЕ ФАЙЛЫ /////////////////////////////////////

#include <stdio.h>

#include <graph.h>

#include <math.h>

// ОПРЕДЕЛЕНИЯ //////////////////////////////

#define STATE_CHASE 1

#define STATE_RANDOM 2

#define STATE_EVADE 3

#define STATE_PATTERN 4

// ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ ///////////////////////

// Указатель на системную переменную, содержащую значение таймера.

// Содержимое этой 32-битовой ячейки обновляется 18.2 раза

//в секунду

unsigned int far *clock=(unsigned int far *)0х0000046C;

// Х- и Y-компоненты шаблонов траекторий, по которым

// будет двигаться "Муха"

int patterns_x[33[20]={1,1,1,1,1,2,2,-1,-2,-3,-1,

0,0,1, 2, 2, -2,-2,-1,0,

0,0,1,2,3,4,5,4,3,2,1,3,3,3,3,

2,1,-2,-2,-1,

0,-1,-2,-3,-3,-2,-2,

0,0,0,0,0,0,1,0,0,0,1,0,1};

int patterns_y[3][20]={0,0,0,0,-l,-l,-l,-l,-l, 0,0,0,0,0,2,2,2,2,2,2, 1,1,1,1,1,1,2,2,2,2,2, 3,3,3,3,3,0,0,0,0, 1,1,1,2,2,-1,-1,-1,-2,-2, -1, -1, 0,0,0,1,1,1,1,1};

///////////////////////////////////

void Timer(int clicks)

{

//Эта функция использует значение таймера для формирования

// задержки. Необходимое время задержки задается в "тиках"

// интервалах в 1/18.2 сек. Переменная, содержащая 32-битовое

// текущее значение системного таймера, расположена

// по адресу 0000:046Ch

unsigned int now;

// получить текущее время

now = *clock;

// Ничего не делать до тех пор. пока значение таймера не

// увеличится на требуемое количество "тиков".

// Примечание: один "тик" соответствует примерно 55мс.

while(abs(clock - now) < clicks){}

} // конец функции Timer

// ОСНОВНАЯ ФУНКЦИЯ /////////////////////////////////

void main(void)

{

int px=160,py=100, // начальные координаты игрока

ex=0,ey=0; // начальные координаты противника

int done=0, // флаг окончания работы программы

doing_pattern=0, // флаг выполнения шаблона

current_pattern, // номер текущего шаблона

pattern element, // текущая команда шаблона

select_state=0, // флаг необходимости смены состояния

clicks=20, // количество циклов, в течение которых

// сохраняется текущее состояние

fly_state = STATE CHASE; // "Муха" начинает с преследования

float distance; // используется при расчете

// расстояния между игроком и "Мухой"

_setvideomode(_MRES256COLOR);

printf(" Brainy Fly - Q to Quit");

//основной игровой цикл

while(!done)

{

// очистка точек

_setcolor(0);

_setpixel(px,py);

_setpixel(ex,ey);

// перемещение игрока

if (kbhit()) {

// определяем направление движения

switch(getch()}

{

case 'u': // вверх

{

py-=2;

} break;

case 'n': // вниз

{

py+=2;

} break;

case 'j': // вправо

{

px+=2;

} break;

case 'h'': // влево

{

px-=2;

} break;

case 'q':

{ done=l;

} break;

} // конец оператора switch

}

// конец обработки нажатия клавиши

// теперь перемещаем противника

// начинается работа "мозга"

// определяем текущее состояние КА

switch(fly_state)

{

case STATE_CHASE:

{

_settextposition(24,2);

printf("current state:chase "};.

// реализуем Алгоритм Преследования

if (px>ex) ex++;

if (px<ex) ex--;

if (py>ey) ey++;

if (py<ey) ey--;

//не пора ли перейти к другому состоянию?

if (--clicks==0) select_state=l;

} break;

case STATE_RANDOM:

(

_settextposition(24,2};

printf("current state:random ");

// перемещаем "Муху" в случайном направлении

ex+=curr_xv;

ey+=curr_yv;

//не пора ли перейти к другому состоянию?

if (--clicks=0) select_state=l;

} break;

case STATE_EVADE:

{

_settextposition(24,2);

printf("current state:evade ");

// реализуем Алгоритм Уклонения

if (px>ex) ex--;

if (px<ex) ex++;

if (py>ey) ey—;

if (py<ey) ey++;

//не пора ли перейти к другому состоянию?

if (--clicks==0) select_state=l;

} break;

case STATE_PATTERN:

{

_settextposition(24,2);

printf("current state:pattern ");

// перемещаем "Муху", используя следующий

// элемент текущего шаблона

ex+=patterns_x[current_pattern][pattern_element];

ey+=patterns_y[current_pattern][pattern_element];

// обработка шаблона закончена?

if (++pattern element==20)

{

pattern_element = 0;

select_state=l;

} // конец проверки завершения шаблона

} break;

default;break;

} // конец обработки текущего состояния

// надо ли менять, состояние?

if (select_state==l)

{

// Выбор нового состояния основан на

// игровой ситуации и неявной логике.

// Для выбора используется расстояние до игрока

distance = sqrt(.5+fabs((рх-ех)*(рх-ех)+(ру-еу)*(ру-еу)));

if (distance>5&&distance<15&&rand()%2==1)

{

// выбираем новый шаблон

current_pattern = rand()%3;

// переводим "мозг" в состояние действий по шаблону

fly_state = STATE_PATTERN;

pattern_element = 0;

} // конец обработки ситуации "близко к игроку"

else if (distance<10) // слишком близко, убегаем!

clicks=20;

fly_state = STATE_EVADE;

} // конец обработки ситуации "слишком близко"

else

if (distance>25&sdistance<100&&rand()%3==1)

{

// преследуем игрока clicks=15;

fly_state = STATE_CHASE;

} // конец обработки ситуации Преследование

else

if (distance>30&&rand()%2==l)

{

clicks=10;

fly_State = STATE_RANDOM;

curr_xv = -5 + rand()%10; //от -5 до +5

curr_yv = -5 + rand()%10; //от -5 до +5

} // конец "неявной логики"

else

{

clicks=5;

fly_state = STATE_RANDOM;

curr_xv = -5 + rand()%10; //от -5 до +5

curr_yv = -5 + rand()%10; //от -5 до +5

} // конец оператора else // сбрасываем флаг смены состояния

select_state=0;

} // конец Алгоритма Смены Состояния

// Убеждаемся, что "Муха" находится в пределах экрана

if (ex>319) ех=0;

i£ (ex<0) ех=319;

if (ey>199) еу=0;

if (ey<0) еу=199;

// конец работы "мозга"

_setcolor(12);

_setpixel(ex,ey);

// Немного подождем...

Timer(1);

} // Конец цикла while

_setvideomode(_DEFAULTMODE);

} // Конец функции main

Запустив программу, вы наверняка обратите внимание на кажущуюся сложность поведения «Мухи». А ведь для получения такого результата использована весьма простая схема! Возможно, и вы заметите то, что увидел я - чуть ли не человеческую способность мыслить.

Управление приоритетным состоянием

Можно еще усовершенствовать наш КА, если ввести управление сменой состояний с помощью некоторых переменных и функций. На практике это означает возможность изменения текущего режима, не дожидаясь полного завершения программы, отвечающей за его выполнение.

В имитаторе движения «Мухи» каждое состояние выполнялось до полного завершения. Но если включить в программу проверку выполнения или невыполнения некоторых условий, это позволило бы КА «выпрыгнуть» из состояния, не дожидаясь окончания его «отработки».

Этим заканчивается наш разговор о конечных автоматах, которые могут быть использованы в наших играх для моделирования поведения существ и придания им видимости наличия интеллекта. Теперь к имеющейся у нас системе высокоуровневого управления не помешает добавить низкоуровневое функционирование.

Вероятностные автоматы

Наверное, вы уже поняли, как вероятность и случайные числа могут быть использованы для выбора направлений и состояний. Мы научились использовать случайные последовательности для конструирования «характера» персонажей. Я имею в виду, что «Муха» в нашем предыдущем примере могла самостоятельно выбирать различные состояния, основываясь на окружающей обстановке. Если несколько изменить метод выбора состояний, основанны на генерации случайных чисел (то есть, создать условия, при которых вход в опредёленное состояние стал бы легче или тяжелее), то, в конечном счете, нам удалось бы изменить "характер" «Мухи».

Скажем, нам захотелось иметь в игре две «мухи». Если одну и ту же программу использовать для создания траектории движения каждой «мухи», они бы действовали одинаково. Во многих случаях большего и не требуется. Однако гораздо интересней иметь много «мух» с небольшими различиями в поведении. Это можно было бы реализовать изменением диапазона случайных чисел-во всех строках программы, где выбираются состояния «мухи». Но такой подход будет очень грубым. Мы пойдем другим путем — путем создания общего метода управления характером персонажей, основанного на вероятности.

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

В видеоиграх мы могли бы иметь несколько противников, которые постоянно преследуют нас, пока другие в это время неподвижны и стреляют. Третьи трусливы и предпочитают убегать, а не сражаться. Анализируя ситуацию, мы видим, что имеется все тот же набор состояний, но вероятности перехода в них различны для каждого создания. Для моделирования этого процесса мы могли бы сослаться на «таблицу вероятностей» в той части программы, которая выбирает новое состояние. Эта таблица могла бы содержать различные степени вероятности переходов существ в то или иное состояние. К примеру, взгляните на таблицу 13.1, в которой перечислены соотношения вероятностей для трех различных существ в одной игре.

Таблица 13.1. Распределение вероятностей для трех существ в игре.


Дата добавления: 2015-07-12; просмотров: 102 | Нарушение авторских прав


<== предыдущая страница | следующая страница ==>
Листинг 13.3. Одинокая муха. (DFLY.C).| Состояние Существо 3: Хныкалка

mybiblioteka.su - 2015-2024 год. (0.014 сек.)