https://github.com/quantaris-live/quantaris-engine
Open source engine standard for Quantaris.live game
https://github.com/quantaris-live/quantaris-engine
ai-bot game game-engine open-source simultaneous turn-based-strategy
Last synced: 4 months ago
JSON representation
Open source engine standard for Quantaris.live game
- Host: GitHub
- URL: https://github.com/quantaris-live/quantaris-engine
- Owner: quantaris-live
- License: mit
- Created: 2025-12-17T08:35:49.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2025-12-29T15:59:15.000Z (5 months ago)
- Last Synced: 2026-01-01T20:17:48.561Z (5 months ago)
- Topics: ai-bot, game, game-engine, open-source, simultaneous, turn-based-strategy
- Language: TypeScript
- Homepage: https://quantaris.live
- Size: 11.8 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# @quantaris/engine
> Deterministic game logic for Quantaris — pure TypeScript, zero dependencies.
This is the canonical implementation of Quantaris game rules. The engine is 100% pure functions with no side effects, making it suitable for:
- Server-side turn resolution
- Client-side move preview
- Replay validation
- AI training and research
- Third-party tool development
## Installation
```bash
npm install @quantaris/engine
```
## Quick Start
```typescript
import {
createInitialState,
resolveTurn,
validatePlayerActions,
hashState,
ActionType,
Direction,
Player,
} from "@quantaris/engine";
// Create a new game
const state = createInitialState();
// Define player actions (use enums, never hardcoded strings!)
const actionsA = [
{ type: ActionType.Move, quantarId: "A1", direction: Direction.North },
{ type: ActionType.Pulse, quantarId: "A2", direction: Direction.North },
{ type: ActionType.Shield, quantarId: "A3" },
];
const actionsB = [
{ type: ActionType.Shield, quantarId: "B1" },
{ type: ActionType.Shield, quantarId: "B2" },
{ type: ActionType.Move, quantarId: "B3", direction: Direction.South },
];
// Validate before resolution
const validationA = validatePlayerActions(state, actionsA, Player.A);
const validationB = validatePlayerActions(state, actionsB, Player.B);
if (validationA.valid && validationB.valid) {
// Resolve the turn
const result = resolveTurn({ state, actionsA, actionsB });
console.log("New state:", result.state);
console.log("Turn log:", result.log);
console.log("State hash:", hashState(result.state));
}
```
## Core Concepts
### Entities
- **Quantar**: Active units controlled by players (3 per player, 2 HP each)
- **Core**: Passive objectives (1 per player, 5 HP, destroy to win)
### Actions
Each Quantar can perform exactly one action per turn:
- `MOVE`: Move one cell orthogonally (N/E/S/W)
- `PULSE`: Fire a beam in a direction (hits first entity, 1 damage)
- `SHIELD`: Reduce incoming damage by 1 this turn
### Turn Resolution
Turns are resolved in a deterministic order:
1. **MOVE phase** — All moves applied simultaneously
2. **SHIELD phase** — Shields activated
3. **PULSE phase** — Beams fired from post-move positions
4. **DAMAGE phase** — All damage applied simultaneously
5. **CLEANUP** — Remove destroyed entities, check win condition
## API Reference
### State Management
```typescript
// Create initial game state
createInitialState(): GameState
// Query helpers
getQuantar(state, id): Quantar | undefined
getPlayerQuantars(state, playerId): Quantar[]
getPlayerCore(state, playerId): Core
getEntityAt(state, position): Entity | null
```
### Validation
```typescript
// Validate a single action
validateAction(state, action, playerId): ValidationResult
// Validate all actions for a turn
validatePlayerActions(state, actions, playerId): ValidationResult
```
### Resolution
```typescript
// Resolve a turn (pure function)
resolveTurn({ state, actionsA, actionsB }): TurnResult
```
### Hashing
```typescript
// Hash state for comparison/verification
hashState(state): string
// Check if two states are identical
statesEqual(a, b): boolean
// Canonical string representation
canonicalizeState(state): string
```
## Types
```typescript
type PlayerId = "A" | "B";
type Direction = "N" | "E" | "S" | "W";
interface Position {
x: number; // 0-8
y: number; // 0-8
}
interface Quantar {
id: string;
owner: PlayerId;
position: Position;
hp: number;
}
interface Core {
owner: PlayerId;
position: Position;
hp: number;
}
interface GameState {
turn: number;
phase: GamePhase; // GamePhase.Playing | GamePhase.Ended
quantars: Quantar[];
cores: { A: Core; B: Core };
winner: PlayerId | null;
}
type Action = MoveAction | PulseAction | ShieldAction;
interface TurnResult {
state: GameState;
log: TurnLog;
}
```
## Enums (No Hardcoded Strings!)
**Always use these enums instead of string literals:**
```typescript
// Players
Player.A // "A"
Player.B // "B"
// Directions
Direction.North // "N"
Direction.East // "E"
Direction.South // "S"
Direction.West // "W"
// Action types
ActionType.Move // "MOVE"
ActionType.Pulse // "PULSE"
ActionType.Shield // "SHIELD"
// Game phases (engine-level only)
GamePhase.Playing // "playing"
GamePhase.Ended // "ended"
```
## Constants
```typescript
BOARD_SIZE = 9 // 9x9 grid
CORE_HP = 5 // Core hit points
QUANTAR_HP = 2 // Quantar hit points
PULSE_DAMAGE = 1 // Damage per pulse hit
SHIELD_REDUCTION = 1 // Damage reduction from shield
QUANTARS_PER_PLAYER = 3 // Quantars per side
```
## Design Principles
1. **Pure Functions**: No side effects, no mutations, no external state
2. **Deterministic**: Same inputs always produce same outputs
3. **Zero Dependencies**: Works anywhere TypeScript runs
4. **Immutable Data**: All state objects are readonly
## License
MIT
---
*May the quants be with us.* ⚛️