There is no framework support (now) for AI/Bots, so it is all custom stuff.
What about "Can't Stop" Bot? Well it is the only game that has AI (without I) that is treated as separate player, admins won't reveal how it is done nor that is feasible to implement in other games.
Games
The following game have modes that support bots Conspiracy, Glow, Crew, Crew Deepsea, Tapestry.
NOTE: None of them currently is a real AI. Usually its implementation of "Automa" rules of the games, so you can play solo game.
Techniques
Testing bot
Testing bot is actually JavaScript bot that presses on buttons on behalf of player. Its handy for testing on Studio. Recommended way of doing it is add Studio only button (together with debug bar) "Run bot/Stop bot", when running it can react to state changes and press stuff. Example "Battleship" (this only appear on Studio as this is for testing only)
JavaScript AI
Currently I don't see how it is feasible, JS code requires real player connected to game and browser, so it cannot be run as AI engine
Server Bot as registered game Player
This would be ideal, but currently only Can't Stop does it and no other game can use this technique
Server Bot as game state action
This is the only feasible way in production. In addition to whatever game states are doing, it can handle fake players and simulate their moves
In some games Bot will take player color and whole player board similar to real player, and can even have resources. So it natural that Bot behaive like a player in a game. However you cannot add fake player into player table, so you cannot add any field in that table to track resources for examples. You cannot make fake player active or multiactive. How you do it then? See playerextra table below.
Bot Player ID
Reserve non-exising player id for bots (i.e. 1-6). If bot needs color and order see below.
Bot Color, Order and Resources
Create table similar player to track bots color, name, score, score_aux and possibly other stuff
CREATE TABLE IF NOT EXISTS `playerextra` ( `player_id` int(10) unsigned NOT NULL, `player_name` varchar(32) NOT NULL, `player_avatar` varchar(10) NOT NULL, `player_color` varchar(6) NOT NULL, `player_no` int(10) NOT NULL, `player_score` int(10) NOT NULL DEFAULT '0', `player_score_aux` int(10) NOT NULL DEFAULT '0', `player_ai` tinyint(1) NOT NULL DEFAULT '0' COMMENT '1 = player is an AI', PRIMARY KEY (`player_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
Bot Actions
- All actions that can be done by Bot have to have $player_id as argument and not use active player
- Separate code of ajax actions themselves and functional code, so function can be run from ajax action or from game state action
- If you using getPlayerNameById to send player_name in notification, you may have to override id (same for player color)
public function getPlayerNameById($player_id) { if ($player_id == PLAYER_AUTOMA) return ('Automa'); return parent::getPlayerNameById($player_id); }
- You may also create a function like loadPlayersBasicInfosWithBots which will return similar data as loadPlayersBasicInfos but with bots ids. Cache the result if using a lot
function loadPlayersBasicInfosWithBots() { $player_basic = $this->loadPlayersBasicInfos(); if ( !$this->isAutoma()) return $player_basic; if ( !isset($this->player_bots)) { $this->player_bots = $this->getCollectionFromDb("SELECT * FROM playerextra"); } return $this->player_bots + $player_basic; }
Bot Player Panel
If you want bot on player panel you have to add it manually. You can either create template similar to real one or use this hack. Below we get player_id and player from playerextra
var over = $('overall_player_board_' + player_id); if (!over) { let active_id = this.getActivePlayers()[0]; let active_name = gamedatas.players[active_id].name; var xclone = $('overall_player_board_' + active_id).outerHTML; xclone = xclone.replaceAll(String(active_id), player_id); xclone = xclone.replaceAll(active_name, player.name); xclone = xclone.replaceAll(gamedatas.players[active_id].color, player.color); var node = dojo.place(xclone, 'player_boards'); // tweak to change avatar status and such }
Bot Player Notifications
When you send notification with ${player_name} you also should send 'player_id' with you fake id. In additio getAllDatas() should contain record matching fake player id in players field, i.e if $player has data for fake player:
protected function getAllDatas() { $result = []; ... $result ['players'] [$player_id] ['id'] = $player['id']; $result ['players'] [$player_id] ['score'] = $player['score']; $result ['players'] [$player_id] ['color'] = $player['color']; $result ['players'] [$player_id] ['name'] = $player['name']; ... return $result; }