[Tutorial] Автоматоны Pawn
#1

В языке Pawn есть механизм состояний(автоматон) - это такая система, которая позволяет определить несколько копий одной функции для использования в различных условиях. Я начну объяснять с примера, ибо так получится более наглядно, а ниже подробно опишу эту систему.

Пример

Допустим нам нужно сохранить данные игрока и данные гонок, а также сообщить об этом игрокам и гонщикам соответственно. При обычной реализации код выглядит грязновато:

Code:
#include 

forward data_Save(type);
forward message_Save(type);

enum {
	players,
	races
}

main() {
	data_Save(players);
	message_Save(players);
}

public data_Save(type)
{
	switch (type) {
		case players: {
			// saving
		}
		case races: {
			// saving
		}
	}
}
public message_Save(type)
{
	switch (type) {
		case players: {
			// send message to player
		}
		case races: {
			// send message to racers
		}
	}
}
А реализация с помощью автоматонов выглядит очень элегантно:

Code:
#include 

forward data_Save();
forward message_Save();

main() {
	state dataType:players;
	data_Save();
	message_Save();
}

public data_Save() 
{
	// saving
}

public data_Save() 
{
	// saving
}

public message_Save() 
{
	// send message to players
}

public message_Save() 
{
	// send message to racers
}
Плюсы этого метода

А если понадобится добавить в список выше что-нибудь ещё? Код без автоматонов превратиться в огромный switch! А если вы, например, захотите перенести код сохранения данных гонки в файл race/data.inc? Тогда вам придётся создавать дополнительную функцию и заносить её туда! Но с автоматонами это делается гораздо проще.

Ещё можно отметить то, что конструкция, выполненная с помощью автоматонов, работает немного быстрее, чем функция с большим switch.

Теория

state

Этим кодом мы устанавливаем для dataType состояние players

Code:
state dataType:players;
Для проверок, связанных с автоматонами, есть сокращённое написание, например этот код:

Code:
state (var == 1) dataType:races;
эквивалентен этому:

Code:
if (var == 1) {
	state dataType:races;
}
entry()

Для автоматонов зарезервирована специальная функция entry(), которая вызывается при установке состояния.


Пример:

Code:
#include 

main() {
	printf("Hello");
	state entryTest:message;
	printf("World!");
}

entry() 
{
	printf("Test");
}
Результатом выполнения этого кода будет:

Code:
Hello
Test
World
Функции

Вы можете объявлять функции с одним состоянием:

Code:
stock echo(msg[]) <exType:one>
{
	print(msg);
}
С несколькими:

Code:
stock echo(msg[]) <exType:one,exType:two>
{
	print(msg);
}
(эта функция будет вызвана при состоянии one или two).


И с любым другим состоянием:

Code:
stock echo(msg[]) <>
{
	print(msg);
}
(эта функция будет вызвана если не было вызвано ни одной функции со своим состоянием).

Источник
Reply
#2

Гуд. Где-то давно видел нечто подобное. + За разжёвывание.
Reply
#3

Спасибо, полезно. Можно ли их еще как-то применять (к переменным, например) ?
Reply
#4

Quote:
Originally Posted by stabker
View Post
Спасибо, полезно. Можно ли их еще как-то применять (к переменным, например) ?
К глобальным переменным можно, они будут доступны только в функциях своих состояний.
Reply
#5

Я на программиста не учился, поэтому след предложение может быть глупым...
Получается что можно сделать так:

PHP Code:
#include <a_samp>
main() {
    
state load:object;
    
state load:pickup;
}
entry() <load:object>
{
    
printf("loading");
}
entry() <load:pickup>
{
    
printf("loading");

И второй вариант:
PHP Code:
#include <a_samp>
main() {
    
state load:object;
    
Load();
    
state load:pickup;
    
Load();
}
public 
Load() <load:object>
{
    
printf("loading");
}
public 
Load() <load:pickup>
{
    
printf("loading");

Reply
#6

Quote:
Originally Posted by -Stranger-
View Post
Я на программиста не учился, поэтому след предложение может быть глупым...
Получается что можно сделать так:
Да, всё верно.
Reply
#7

Честно, не вижу разницы, или я не понял смысл. Мне куда проще и понятнее, на конкретном примере, сделать так:
PHP Code:
#include <a_samp> 
main() { 
    
Load_Object();  
    
Load_Pickup(); 

public 
Load_Object() 

    
printf("loading"); 

public 
Load_Pickup()

    
printf("loading"); 

Reply
#8

Во 2-ом примере сверху, ты наверно забыл объявить
PHP Code:
forward message_Save(type); 
Приведи пример с переменными в двух вариантах - как выглядит обычное использование и с автоматонами.
Reply
#9

Quote:
Originally Posted by Diman777
View Post
Во 2-ом примере сверху, ты наверно забыл объявить
PHP Code:
forward message_Save(type); 
Исправил, спасибо.

Quote:
Originally Posted by Diman777
View Post
Приведи пример с переменными в двух вариантах - как выглядит обычное использование и с автоматонами.
Не понял.
Reply
#10

Применить автоматоны можно к переменным? Если да, то приведи пример.
Reply
#11

Quote:
Originally Posted by Diman777
View Post
Применить автоматоны можно к переменным? Если да, то приведи пример.
Нельзя.
Reply
#12

В практике возможно применить "автомат" на авто вызываемые функции, например OnDialogResponse?

P.S. я думаю это не возможно
Reply
#13

Quote:
Originally Posted by pawnoholic
View Post
В практике возможно применить "автомат" на авто вызываемые функции, например OnDialogResponse?

P.S. я думаю это не возможно
Возможно, почему нет?
Reply
#14

Quote:
Originally Posted by pawnoholic
View Post
В практике возможно применить "автомат" на авто вызываемые функции, например OnDialogResponse?

P.S. я думаю это не возможно
Автоматоны - это тот же самый оператор switch с case и состоянием. Советую почитать вики: https://en.wikipedia.org/wiki/Automa...ed_programming
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)