Guides

PvP (Player vs Player) with open-source tools

This guide outlines the technical implementation of a structured PvP framework for a MUD, focusing on state management, consent-based dueling, and automated ranking systems. It assumes an existing turn-based or round-based combat engine is already in place.

15-20 development hours6 steps
PvP (Player vs Player) with open-source tools hero illustration
1

Define PvP State and Room Flags

Modify the player data structure to include a 'pvp_status' enum (OFF, SEEKING, DUELING, AGGRESSIVE) and the room structure to include 'room_flags' (SAFE, ARENA, OPEN_PVP). This allows the combat engine to check legality before any damage packet is processed.

combat_util.c
typedef enum { PVP_NONE, PVP_CONSENT, PVP_OPEN } pvp_type_t;

bool is_combat_legal(char_data *ch, char_data *victim) {
    if (IS_SET(ch->in_room->room_flags, ROOM_SAFE)) return false;
    if (ch->pvp_status == PVP_NONE && !IS_SET(ch->in_room->room_flags, ROOM_ARENA)) return false;
    return true;
}

⚠ Common Pitfalls

  • Forgetting to check room flags during area-of-effect (AoE) spells, leading to accidental 'flagging' of peaceful players.
  • Inconsistent state when a player disconnects during an active PvP flag.
2

Implement the Duel Handshake Protocol

Create a command sequence that requires mutual consent to prevent griefing. The 'challenge' command should set a temporary 'pending_duel' pointer on the target, which expires after a set timeout (e.g., 60 seconds).

commands_pvp.py
def do_challenge(self, target_name):
    target = self.world.find_player(target_name)
    if not target:
        self.send("Player not found.")
        return
    target.pending_duel = self
    target.send(f"{self.name} has challenged you to a duel. Type 'accept {self.name}' to begin.")
    self.send(f"Challenge sent to {target.name}.")

⚠ Common Pitfalls

  • Allowing multiple pending challenges to stack, which can be used to spam a player's screen during combat.
3

Develop the ELO Ranking Logic

Integrate an ELO calculation post-combat. When a duel concludes, update the 'pvp_rating' field for both the winner and loser. Use a K-factor (typically 32) to determine the volatility of rating changes.

elo_system.js
function calculateElo(winnerRating, loserRating) {
    const K = 32;
    const expectedWinner = 1 / (1 + Math.pow(10, (loserRating - winnerRating) / 400));
    const ratingChange = Math.round(K * (1 - expectedWinner));
    return ratingChange;
}

⚠ Common Pitfalls

  • Rating inflation caused by 'farming' low-level alts. Implement a minimum level requirement or daily cap on rating gains from the same opponent.
4

Construct Combat Log Buffers

To facilitate balance and dispute resolution, implement a circular buffer that stores the last 50 combat events (damage, misses, spell effects) for every PvP encounter. This buffer should be dumpable to a file or a 'review' command upon combat conclusion.

⚠ Common Pitfalls

  • Memory leaks if buffers are not cleared when players log out.
  • Excessive disk I/O if logs are written to flat files for every single hit; use an in-memory buffer instead.
5

Apply Escape and Tether Restrictions

Prevent 'fleeing' or 'recalling' during active PvP. Implement a 'combat_timer' that resets every time a player deals or receives damage. While this timer is active, movement commands to exit the zone or teleportation spells should be disabled.

act_move.c
void do_flee(char_data *ch) {
    if (ch->pvp_timer > 0) {
        send_to_char("You are too focused on combat to flee properly!\n", ch);
        return;
    }
    // Standard flee logic here
}

⚠ Common Pitfalls

  • Players using 'quit' or 'force-close' to escape. Implement a 'ghost' system where the player character remains in the world for 30 seconds if they disconnect during PvP.
6

Automated Tournament Bracketing

Create a global controller that handles tournament registration. It should sort players by ELO, generate a power-of-two bracket, and automatically teleport pairs into 'ARENA' flagged rooms when their match is called.

⚠ Common Pitfalls

  • Handling 'no-shows' where one player enters the arena and the other is AFK. Implement a 2-minute disqualification timer.

What you built

A successful MUD PvP system requires strict state management to separate willing participants from roleplayers or questers. By implementing robust handshakes, ELO-based matchmaking, and anti-escape mechanics, developers can foster a competitive environment that minimizes toxicity and maximizes mechanical balance.