Because nothing about quality-based narratives is actually simple.
SimpleQBN is a quality-based narrative (QBN) generic JavaScript library for use in browsers or Node.js-based projects. It provides state management and resolves expressions for checking openness (availability) based on states changes.
This project is based on another project Quis, which it uses to resolve expressions.
npm install simple-qbn
git clone https://github.com/videlais/simple-qbn.git
cd simple-qbn
npm install
// Original architecture
import State from 'simple-qbn/State';
import Card from 'simple-qbn/Card';
import Deck from 'simple-qbn/Deck';
// Or reactive architecture
import ReactiveState from 'simple-qbn/reactive/State';
import ReactiveCard from 'simple-qbn/reactive/Card';
import ReactiveDeck from 'simple-qbn/reactive/Deck';
Download the pre-built bundles from the build/ directory:
simpleqbn.bundle.js - Original architecture (~20KB minified)reactive-simpleqbn.bundle.js - Reactive architecture (~29KB minified)<!-- Original architecture -->
<script src="simpleqbn.bundle.js"></script>
<script>
const state = new SimpleQBN.State();
const deck = new SimpleQBN.Deck();
</script>
<!-- OR Reactive architecture -->
<script src="reactive-simpleqbn.bundle.js"></script>
<script>
const state = new ReactiveSimpleQBN.ReactiveState();
const deck = new ReactiveSimpleQBN.ReactiveDeck([], state);
</script>
SimpleQBN provides two distinct architectures for managing game state:
These two systems are incompatible and cannot be mixed within the same application.
The original architecture uses the State class along with Card, Deck, Expression, and QualitySet classes. This architecture requires manual state passing and explicit availability checking.
Key Classes: State, Card, Deck, Expression, QualitySet
Example:
import State from 'simple-qbn/State';
import Card from 'simple-qbn/Card';
import Deck from 'simple-qbn/Deck';
// Create game state
const gameState = new State();
gameState.set('health', 100);
gameState.set('hasKey', true);
// Create cards with quality requirements
const healingCard = new Card(
'Drink a healing potion',
['$health < 80']);
const doorCard = new Card(
'Open the locked door',
['$hasKey == true']);
// Create deck and add cards
const deck = new Deck();
deck.addCard(
healingCard.content,
healingCard.qualities);
deck.addCard(
doorCard.content,
doorCard.qualities);
// Check availability manually.
// Need to pass state each time.
const availableCards = deck.draw(gameState, 5);
console.log(`${availableCards.length} cards available`);
The reactive architecture uses ReactiveState with ReactiveCard, ReactiveDeck, ReactiveExpression, and ReactiveQualitySet. This architecture provides automatic updates and event-driven state management.
Key Classes: ReactiveState, ReactiveCard, ReactiveDeck, ReactiveExpression, ReactiveQualitySet
Example:
import ReactiveState from 'simple-qbn/reactive/State';
import ReactiveCard from 'simple-qbn/reactive/Card';
import ReactiveDeck from 'simple-qbn/reactive/Deck';
// Create reactive game state.
const gameState = new ReactiveState();
gameState.set('health', 100);
gameState.set('hasKey', true);
// Create reactive cards.
const healingCard = new ReactiveCard(
'Drink a healing potion',
['$health < 80']);
const doorCard = new ReactiveCard(
'Open the locked door',
['$hasKey == true']);
// Create reactive deck and bind to state.
const deck = new ReactiveDeck(
[healingCard, doorCard],
gameState);
// Subscribe to automatic updates.
deck.subscribe((availableCards) => {
console.log(`${availableCards.length} cards now available`);
});
// State changes trigger automatic updates.
gameState.set('health', 50);
Important: The two architectures are mutually exclusive:
Card, Deck, etc.) work only with StateReactiveCard, ReactiveDeck, etc.) work only with ReactiveStateState to reactive classes or a ReactiveState to original classesChoose one architecture for your entire application.
Starting with version 1.5.0, SimpleQBN uses Quis 1.3.6+ for expression evaluation with pure Quis syntax.
Previous versions used TinyQBN format and MongoDB query language compatibility, but as of 1.5.0, the library has been simplified to use only Quis string expressions to reduce dependencies and code size.
For full Quis expression syntax documentation, see the Quis documentation.
npm run build - Build the main bundlenpm run build:all - Build both original and reactive architecture bundlesnpm run build:original - Build only the original architecture bundlenpm run build:reactive - Build only the reactive architecture bundlenpm test - Run all tests with coveragenpm run test:browser - Run browser environment testsnpm run test:node - Run Node.js tests onlynpm run lint - Lint and fix source codenpm run docs - Build documentationnpm run all - Run complete build pipeline (compile, lint, test, build, docs)The project includes comprehensive test coverage (99.54%) with both Node.js and browser environment tests:
src/ # Source TypeScript files
├── Card.ts
├── Deck.ts
├── Expression.ts
├── QualitySet.ts
├── State.ts
└── reactive/ # Reactive architecture
test/ # Test files
├── Browser.test.js # Browser environment tests
└── reactive/ # Reactive architecture tests
build/ # Compiled bundles
dist/ # TypeScript compilation output
docs/ # Generated documentation
We welcome contributions! Please see our Contributing Guide for details.
For security vulnerabilities, please see our Security Policy.
See CHANGELOG.md for a history of changes to this project.
Jekyll is used to create a history and documentation of this project.