npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@antogin/werewolf-engine

v1.0.5

Published

Event-sourced werewolf game engine

Readme

Werewolf Game Engine

Welcome to the Werewolf Game Engine, a sophisticated implementation of the classic social deduction game using Event Sourcing and Command Query Responsibility Segregation (CQRS) patterns. This document explains our architectural decisions and how they enable a robust, scalable, and maintainable game engine.

Core Architecture

Our Werewolf Game Engine is built on two fundamental architectural patterns: Event Sourcing and CQRS. Let's explore why we chose these patterns and how they benefit our implementation.

Event Sourcing: Capturing Game State

In traditional game implementations, you might store the current state of the game in a database. However, Werewolf is a game where the history of actions is crucial. Players need to know what happened during the night, who voted for whom, and how the game progressed. Event Sourcing addresses these needs perfectly by storing every game action as an immutable event.

Consider this example of how events tell the story of a game:

[
  { type: "GameCreated", timestamp: "2024-01-01T20:00:00Z", moderatorId: "mod1" },
  { type: "PlayerJoined", timestamp: "2024-01-01T20:01:00Z", playerId: "p1" },
  { type: "RoleAssigned", timestamp: "2024-01-01T20:05:00Z", playerId: "p1", role: "WEREWOLF" },
  { type: "NightPhaseStarted", timestamp: "2024-01-01T20:10:00Z", nightNumber: 1 }
]

This approach provides several benefits:

  1. Complete audit trail of the game
  2. Ability to reconstruct game state at any point
  3. Built-in support for game replay and spectator mode
  4. Natural handling of game saves and loading

CQRS: Separating Game Actions from Views

Werewolf is a game of hidden information. Werewolves know who other werewolves are, the Seer learns player roles gradually, and villagers operate with limited information. CQRS allows us to maintain these different views efficiently by separating how we handle game actions (commands) from how we present information to players (queries).

Our command side handles game actions:

  • Starting the game
  • Casting votes
  • Using special abilities
  • Making accusations

While our query side manages different views for:

  • Werewolf team members
  • Individual special roles (Seer, Witch)
  • Villagers
  • Spectators
  • Game moderators

Event Design Philosophy

Our events are designed around several key principles:

Complete Information

Every event contains all the information needed to understand what happened. For example, a WerewolfVoteCast event includes:

  • Who cast the vote (werewolfId)
  • Who was voted for (targetId)
  • When it happened (timestamp)
  • The game context (gameId)

Immutable History

Events are never modified or deleted. If a player changes their vote, we create a new VoteChanged event rather than modifying the original vote. This preserves the complete game history and allows for accurate replay.

Temporal Consistency

All events include timestamps and version numbers to maintain proper ordering. This is crucial for night actions where the Witch must act after the Werewolves, or for resolving simultaneous day phase votes.

State Management

The game state is managed through distinct phases, each with its own set of valid commands and resulting events:

Game Setup Phase

  • Player joining and role assignment
  • Game configuration and settings
  • Initial state validation

Night Phase

  • Sequential special role actions
  • Coordinated werewolf voting
  • Death and save resolutions

Day Phase

  • Discussion and accusation tracking
  • Village voting system
  • Execution resolution

Win Condition Checking

  • Team balance verification
  • Special win conditions
  • Game end state management

Handling Edge Cases

Our architecture specifically addresses common game challenges:

Disconnections

The event-sourced nature of our system means players can disconnect and reconnect seamlessly. Their game state is reconstructed from the event stream, ensuring they don't miss any information they're allowed to know.

Concurrent Actions

We handle multiple werewolves voting simultaneously through a two-phase voting system:

  1. Individual votes are recorded as WerewolfVoteCast events
  2. Once all votes are in, a WerewolfVoteCompleted event determines the final victim

Time Management

Game phases can have optional time limits, managed through:

  • Phase start events with duration
  • Timer events for phase progression
  • Forced resolution events for expired timers

Read Models

Our read models are tailored to different player roles and game phases:

Player-Specific Views

Each role gets a customized view of the game state. For example:

  • Werewolves see other werewolves but not the Seer's discoveries
  • The Seer accumulates knowledge of player roles over time
  • Villagers only see public information and voting results

Game Progress Views

  • Current game phase and timer status
  • Player alive/dead status
  • Vote tallies and results
  • Game history for spectators

Game Flow

Here is diagram of the game flow:

stateDiagram-v2
    [*] --> GameCreated: CreateGame
    GameCreated --> PlayersJoining: StartJoining
    
    state PlayersJoining {
        [*] --> WaitingForPlayers
        WaitingForPlayers --> EnoughPlayers: PlayerJoined
        EnoughPlayers --> [*]: AssignRoles
    }
    
    PlayersJoining --> NightPhase: GameStarted
    
    state NightPhase {
        [*] --> WerewolvesAction
        WerewolvesAction --> SeerAction: WerewolvesChoseVictim
        SeerAction --> WitchAction: SeerCheckedPlayer
        
        state WitchAction {
            [*] --> PotionChoice
            PotionChoice --> HealingChoice: WitchWakeCalled
            HealingChoice --> PoisonChoice: WitchHealingDecided
            PoisonChoice --> [*]: WitchPoisonDecided
        }
    }
    
    NightPhase --> DayPhase: NightResolved
    
    state DayPhase {
        [*] --> DeathAnnouncement
        DeathAnnouncement --> Discussion: DeathsAnnounced
        Discussion --> Voting: DiscussionEnded
        Voting --> VoteResolution: VotesCast
        VoteResolution --> [*]: VoteResolved
    }
    
    DayPhase --> WinCheck: DayResolved
    
    state WinCheck {
        [*] --> Counting
        Counting --> WerewolvesWin: WerewolvesReachedMajority
        Counting --> VillageWin: AllWerewolvesDead
        Counting --> GameContinues: NoWinCondition
    }
    
    WinCheck --> NightPhase: NextNightStarted
    WinCheck --> [*]: GameEnded

Testing Strategy

Our event-sourced architecture makes testing straightforward:

  1. Command Validation Tests

    • Verify that commands produce expected events
    • Check that invalid commands are rejected
  2. Event Application Tests

    • Ensure events properly update game state
    • Verify that event sequences maintain consistency
  3. Read Model Tests

    • Confirm that different roles see appropriate information
    • Check that game history is properly reconstructed

Getting Started

[Installation and setup instructions will go here]

Contributing

[Contribution guidelines will go here]

License

[License information will go here]