Долго размышлял, но всё таки взял себе игру Adventure Land — The Code MMORPG — игра, в которой, кроме всего прочего можно и нужно программировать поведение персонажа. Да ещё и не одного, а целых трёх боевых и одного торговца. А ведь игра появилась ещё где-то в 2017 году, вроде как…
Игра для программистов и как результат — я не мог пройти мимо неё.

В качестве языка программирования используется язык на основе JAVA. Что, в принципе, является и вариацией обучения программированию.

Из основных минусов — исключительно англофицированное сообщество и минимальная документация.
Из странных плюсов — возможность запуска клиента практически на любой технике (даже на вишенках). Так как клиент работает и в браузерах с поддержкой JAVA. Вот, например, в данный момент у меня запущен воин из STEAM библиотеки, а маг и хиллер из Google Chrome. Но тут же есть и минусы:
- При запуске из STEAM — клиент отжирает довольно не плохо ресурсы ПК
- При запуске из браузера — клиенты «тормозят», т.к. выделяет им ресурсы браузер из собственных соображений
Ещё один плюс, можно входить с разных устройств одновременно одним и тем же героем. Тогда все «новые» подключения становятся наблюдателями.
Первое впечатление — весьма положительное. И даже за пару ночей сумел сделать нечто похожее на автоматизированный фарм голды с ближних монстриков.

Естественно, команда из троих — воин, маг и хиллер. Всё в лучших традициях MMO RPG.
Относительно рабочий код прикладываю (в данный момент он и занимается фармом):
// true - будет атаковать
// false - не будет воевать
var attack_mode=true;
var myOwner = character.owner; //": "5728172030558208",
var TANK
var DAMAGER
var HEALER
var myType
function isType(character){
switch (character.type){
case "priest":
mType = "Healer";
break;
case "warrior":
case "paladin":
mType = "Tank";
break;
case "merchant": // ???
mType = "Merch";
break;
default:
mType = "Damager";
break;
}
return mType;
}
//game_log(get_characters());
//game_log(get_active_characters());
setInterval(function(){
// ДЛЯ ВСЕХ ПЕРСОНАЖЕЙ - НАЧАЛО
// перебор всех персонажей
//show_json(get_characters());
let obj = get_characters();
for(key in obj){
//log(key);
if(obj[key].online != 0){
tmp = isType(obj[key]);
if (obj[key].name == character.name){
myType = tmp;
}
if (tmp == "Tank"){
TANK = obj[key].name;
}
if (tmp == "Damager"){
DAMAGER = obj[key].name;
}
if (tmp == "Healer"){
HEALER = obj[key].name;
}
//show_json(obj[key]);
//log(obj[key].name + " is " + tmp);
}
}
//log("My type: " + myType);
// использовать зелья, когда нужно
if(character.hp<character.max_hp/3 || character.mp<character.max_mp/3){
use_hp_or_mp();
//game_log(character.name + " use POTION...");
}
// подобрать лут
loot();
// ДЛЯ КАЖДОГО ТИПА
switch (myType){
case "Tank":
// принять party от хиллера
x = get_party()
if (!x[HEALER]){
log("NOT IN PARTY");
accept_party_request(HEALER)
send_party_request(HEALER);
// show_json(get_party());
}
// выйти если не атакую или мёртв или двигается
if(!attack_mode || character.rip || is_moving(character)) return;
var target=get_targeted_monster();
if(!target)
{
target=get_nearest_monster({min_xp:100,max_att:120});
if(target){
change_target(target);
//log(get_target());
}
else
{
set_message("No Monsters");
return;
}
}
if(!is_in_range(target)) // вне дистанции атаки
{
move( // сокращение дистанции на половину
character.x+(target.x-character.x)/2,
character.y+(target.y-character.y)/2
);
}
else if(can_attack(target)) // могу атаковать?
{
set_message("Attacking");
attack(target);
}
break;
case "Damager":
// принять party от хиллера
x = get_party()
if (!x[HEALER]){
log("NOT IN PARTY");
//accept_party_request(HEALER);
accept_party_request(HEALER)
send_party_request(HEALER);
// show_json(get_party());
}
// выйти если не атакую или мёртв или двигается
if(!attack_mode || character.rip || is_moving(character)) return;
if(character.max_hp - character.hp > 200 ||
character.max_mp - character.mp > 300)
use_hp_or_mp();
// Party leader
var leader = get_player(TANK);
// Current target and target of leader.
var currentTarget = get_targeted_monster();
var leaderTarget = get_target_of(leader)
// Change the target.
if (!currentTarget || currentTarget != leaderTarget){
// Current target is empty or other than the leader's.
change_target(leaderTarget);
currentTarget = get_targeted_monster();
}
// Attack the target.
targetTarget = get_target_of(currentTarget)
if(currentTarget && can_attack(currentTarget) && targetTarget == leader){
// Current target isn't empty and attackable.
attack(currentTarget);
}
//Move to leader.
if(!character.moving){
if(!is_in_range(leader)) // вне дистанции атаки
{
move( // сокращение дистанции на половину
character.x+(leader.real_x-character.x)/2,
character.y+( leader.real_y-character.y)/2
);
}
}
break;
case "Healer":
// проверить у напарников здоровье и вылечить их
/* if (TANK){
targ = get_player(TANK)
if(!targ.rip && targ.hp < targ.max_hp / 2){
heal(targ);
};
};
if (DAMAGER){
targ = get_player(DAMAGER)
if(!targ.rip && targ.hp < targ.max_hp / 2){
heal(targ);
};
};
*/
let ob = get_party();
for(key in ob){
//log(key);
targ = get_player(key)
hp = targ.hp
mhp = targ.max_hp
if (hp< mhp/2){
heal(targ);
log("Heal: " + key + " " + hp + "/" + mhp)
}
}
//Move to leader.
// Party leader
var leader = get_player(TANK);
if(!character.moving){
if(!is_in_range(leader)) // вне дистанции атаки
{
move( // сокращение дистанции на половину
character.x+(leader.real_x-character.x)/2,
character.y+( leader.real_y-character.y)/2
);
}
}
// хиллер собирает команду
let obj = get_party();
//log (obj);
if( !obj[TANK] )
{
log("==TANK====================")
//log(obj[TANK])
send_party_request(TANK);
accept_party_request(TANK)
}
if( !obj[DAMAGER] )
{
log("==DAMAG===================")
//log(obj[DAMAGER])
send_party_request(DAMAGER);
accept_party_request(DAMAGER)
}
break;
default: // Healer
log("No logic for type: " + MyType);
break;
}
},1000/4); // повторяем каждые 1/4 секунды.
// событие после смерти
function handle_death()
{
setTimeout(respawn,25000);
return true;
// This ensures you keep on farming, yet, to retain your XP, do enhance the logic for defense
}
// Learn Javascript: https://www.codecademy.com/learn/introduction-to-javascript
// Write your own CODE: https://github.com/kaansoral/adventureland
Ну вот, как то такое моё первое знакомство с игрой.
Ссылочки:
Список функций — почти с описанием