How the PHPDTS Bot Daemon Process Interacts with Game Logic

The PHPDTS bot daemon operates as a persistent PHP CLI process that continuously polls shared game state files, executing AI actions through the same core libraries (common.inc.php, game.func.php) used by the web frontend.

The amarillonmc/phpdts repository implements a real-time browser game where AI players require background processing to simulate human opponents. Understanding how this bot daemon process interacts with game logic reveals a tightly coupled architecture where the background service functions as a headless PHP client that directly reads and writes the same state files and data structures utilized by the web interface.

Entry Point and Daemon Boot Sequence

The bot_enable.sh Wrapper

The daemon lifecycle begins in bot/bot_enable.sh, a minimal Bash wrapper responsible for setting the correct working directory and launching the PHP service. This script ensures the daemon runs from the project root, allowing relative path resolution for all subsequent includes.


# bot/bot_enable.sh

cd ..                 # move to the game's root directory

php bot/revbotservice.php   # start the daemon

When executed, this script backgrounds the PHP process and returns control to the shell, enabling the daemon to persist independently of the terminal session.

Core Environment Initialization

Upon launch, bot/revbotservice.php bootstraps the exact same environment as the web frontend by requiring the core initialization files. This shared bootstrap ensures the daemon accesses identical global variables ($gamestate, $gamevars, $db) and configuration constants.

require_once $gameRoot.'include/common.inc.php';
require_once GAME_ROOT.'./include/game.func.php';
require_once GAME_ROOT.'./bot/revbot.func.php';

By loading include/common.inc.php and include/game.func.php, the daemon gains access to critical state management functions including load_gameinfo(), save_gameinfo(), and save_combatinfo(), ensuring perfect synchronization with the game's state machine.

State Synchronization and Lock Mechanisms

Loading Shared Game State

The daemon enters a perpetual loop that begins by refreshing its view of the game world. Each iteration calls load_gameinfo() to reload $gamestate, $gamevars, and current player data from disk. This polling mechanism guarantees the daemon always operates on the latest game state, preventing desynchronization with web-based player actions.

load_gameinfo();

Process Locking for Thread Safety

To prevent race conditions during bot initialization, the daemon implements a file-based locking system in the bot/lock/ directory. Before performing any initialization steps, it creates a process-specific lock file, ensuring only one daemon instance handles bot spawning at any given time.

// Creates lock file in bot/lock/1.lock
$lock_file = fopen('bot/lock/'.$process_id.'.lock', 'w');

When the game stops or restarts, the daemon detects the state change and jumps back to the preparation stage (goto bot_prepare_flag), recreating its lock file to re-establish safe synchronization with the game's own locking mechanisms.

Bot Lifecycle Management

Initialization Protocol

The daemon continuously monitors the $gamestate variable, waiting for the game to enter an active state ($gamestate > 10). When active, it checks $gamevars['botplayer'] to determine if pending bot slots require filling.

if($gamestate > 10 && $gamevars['botplayer'] > 0) {
    $id = bot_player_valid(1);
    $gamevars['botid'][] = $id;
    $gamevars['botplayer']--;
    save_gameinfo();
}

The function bot_player_valid(1), defined in bot/revbot.func.php, selects and validates an available player ID. The daemon then registers this ID in $gamevars['botid'] and decrements the pending counter, immediately persisting changes via save_gameinfo().

Action Execution and Respawn Logic

Once initialized, the daemon triggers bot behavior through bot_acts($id), which processes AI decisions for the specified player. After each action, the daemon evaluates the bot's survival status via the $flag return value.

If a bot dies ($flag == 0), the daemon applies the configurable $bot_respawn_chance to determine if the player should queue for reincarnation:

if ($flag == 0) {
    $roll = mt_rand(1,100);
    if($bot_respawn_chance > 0 && $roll <= $bot_respawn_chance) {
        $gamevars['botplayer'] = ($gamevars['botplayer'] ?? 0) + 1;
        echo "BOT:{$id} 已死亡;已加入重生队列。roll={$roll}, chance={$bot_respawn_chance}\n";
    }
    save_gameinfo();
    save_combatinfo();
}

This respawn mechanism ensures continuous AI population while respecting probability-based configuration. The daemon persists both general game state and combat information before continuing to the next iteration or exiting.

Key Interaction Points Between Daemon and Game Logic

The tight coupling between the background process and game engine manifests through several critical integration points:

  • include/common.inc.php: Provides the foundational $db connection and global variables ($now, $gamestate) required for all game operations.
  • include/game.func.php: Supplies state persistence functions (load_gameinfo(), save_gameinfo()) that synchronize daemon actions with the web frontend.
  • bot/revbot.func.php: Contains AI-specific logic including bot_player_valid() for ID selection and bot_acts() for behavior execution.
  • $gamevars array: Acts as the shared memory structure tracking active bot IDs ($gamevars['botid']) and pending initialization counts ($gamevars['botplayer']).
  • bot/lock/ directory: Implements mutual exclusion that coordinates daemon initialization with the game's internal state transitions.

Summary

  • The bot daemon is launched via bot/bot_enable.sh, which executes bot/revbotservice.php as a background PHP CLI process.
  • It initializes using the same core files as the web frontend (common.inc.php, game.func.php), ensuring access to identical game state and functions.
  • File-based locks in bot/lock/ prevent race conditions during bot initialization when multiple processes might compete for resources.
  • The daemon polls game state continuously via load_gameinfo(), executing bot actions only when $gamestate > 10 indicates an active game.
  • Bot respawn logic uses $bot_respawn_chance to probabilistically requeue deceased AI players, maintaining consistent opponent populations.
  • All state modifications are persisted immediately through save_gameinfo() and save_combatinfo(), keeping the daemon's changes visible to the web interface in real-time.

Frequently Asked Questions

How does bot_enable.sh start the daemon process?

The bot_enable.sh script performs two essential actions: it changes the working directory to the project root (cd ..) and then invokes the PHP interpreter to run bot/revbotservice.php. This ensures all relative includes resolve correctly and the daemon starts with the proper environment context. The script is typically executed with & to background the process, allowing it to run independently of the user's terminal session.

What prevents multiple daemon instances from corrupting game state?

The daemon implements a process-lock file mechanism within the bot/lock/ directory. Before initializing bots, it creates a unique lock file (e.g., 1.lock) that signals other potential instances to wait. Additionally, the daemon checks $gamestate to ensure it only acts during appropriate game phases, and it uses atomic file operations through save_gameinfo() to persist changes, minimizing collision risks with the web frontend.

How does the daemon know when to spawn or respawn bots?

The daemon monitors two key variables loaded via load_gameinfo(): $gamestate and $gamevars['botplayer']. When $gamestate > 10 (indicating an active game) and $gamevars['botplayer'] contains a positive value, the daemon calls bot_player_valid(1) to claim a player ID and decrement the counter. For respawns, after a bot dies ($flag == 0), it performs a random roll against $bot_respawn_chance; if successful, it increments $gamevars['botplayer'], effectively requeuing the slot for immediate reinitialization.

Why does the daemon use the same PHP includes as the web frontend?

By requiring common.inc.php and game.func.php, the daemon ensures it operates on the exact same data structures and business logic as the browser-based interface. This architectural choice eliminates API translation layers and allows the bot system to directly manipulate $gamevars, $gamestate, and database connections ($db) using proven, battle-tested functions like save_gameinfo(), guaranteeing consistency between AI actions and player actions.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →