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 🙏

© 2026 – Pkg Stats / Ryan Hefner

civ6-roguelike-ai

v2.1.0

Published

Civilization Roguelike strategy game for AI agents. Full TypeScript source included - read, modify, and republish your own variant.

Readme

civ6-roguelike-ai

A hex-grid, turn-based strategy game designed for AI agents. Full TypeScript source included -- read it, modify it, republish your own variant.

Quick Start

npm install civ6-roguelike-ai
npx tsx play.ts

Or use it programmatically:

import { CivGame } from 'civ6-roguelike-ai';

const game = new CivGame('my-agent');

while (!game.isGameOver()) {
  const { actions, phase } = game.getValidActions();
  // Pick actions based on your strategy...
  game.endTurn();
}

console.log(game.getScore());

Game Rules

You manage a hex-grid city for 40 turns. Each turn:

  1. Shopping Phase - Buy terrain cards from the shop, place them on empty hexes
  2. Build - Construct improvements (farms, mines) or districts (campus, harbor) on placed tiles
  3. Workers - Assign population to tiles to harvest yields
  4. Tech Tree - Spend accumulated science/culture/faith to unlock upgrades
  5. End Turn - Collect yields, grow population, refresh shop

Resources

| Resource | Icon | Role | |----------|------|------| | Gold | gold | Buy cards, unlock hexes | | Production | production | Build improvements & districts | | Food | food | Feed population, surplus grows pop | | Science | science | Accumulates for tech tree + scoring | | Culture | culture | Accumulates for policy tree + scoring | | Faith | faith | Accumulates for faith tree + scoring |

Factions

Cards and tech nodes are tagged with one of 5 factions. As you pick tech nodes with faction boosts, the shop increasingly offers cards of that faction.

  • Maritime - Water, coast, ocean tiles
  • Highland - Mountains, hills, volcanic terrain
  • Pastoral - Grassland, farms, food-focused
  • Wilderness - Forests, tundra, natural terrain
  • Woodland - Vegetation, growth-focused

Victory

Default goal: maximize total score (science + culture + faith) in 40 turns. Configurable via IGameConfig.

Source Map

This package ships full TypeScript source. Here's what each file does:

src/data/ -- Game Data (Primary Modification Targets)

| File | What It Contains | Key Constants | |------|-----------------|---------------| | card-pool.ts | 36 terrain cards (T1/T2/T3), shop level configs, faction metadata | ALL_CARD_TEMPLATES, SHOP_LEVEL_CONFIGS, FACTION_META | | tech-trees.ts | 3 tech trees x 30 nodes = 90 nodes, 17 Eureka triggers | SCIENCE_TREE, POLICY_TREE, FAITH_TREE, EUREKA_DEFS | | improvements.ts | 17 improvements (farm, mine, trading post, ...) | IMPROVEMENT_REGISTRY, BASE_IMPROVEMENTS | | districts.ts | 11 districts (campus, harbor, holy site, ...) | DISTRICT_REGISTRY, BASE_DISTRICTS | | terrains.ts | 14 terrains, 11 features, 19 resources | TERRAIN_REGISTRY, FEATURE_REGISTRY, RESOURCE_REGISTRY |

src/core/ -- Types & Utilities

| File | What It Contains | |------|-----------------| | types.ts | All interfaces: IGameState, ITile, IYields, ITechNode, ICardTemplate, Faction, ... | | config.ts | IGameConfig with 15+ tunable parameters, DEFAULT_CONFIG, victory goal presets | | hex.ts | Hex math: hexNeighbors, hexDistance, hexRing, coordinate conversions | | yields.ts | Yield arithmetic: addYields, scaleYields, emptyYields |

src/game/ -- Game Engine (Rule Modification Targets)

| File | What It Contains | |------|-----------------| | engine.ts | Main game engine: turn flow, resource collection, building, tech, scoring (1100 lines) | | board.ts | Hex board: 61 tiles in 4 rings, adjacency, yield calculation, worker auto-assignment | | shop.ts | Card generation with tier weights and faction weighting | | tech-engine.ts | Tech node selection, effect compilation, Eureka system |

src/api/ -- AI Interface

| File | What It Contains | |------|-----------------| | sdk.ts | CivGame class - the main entry point for playing | | actions.ts | Action dispatcher: JSON action -> engine method call | | valid-actions.ts | Computes all legal actions for current state | | state-serializer.ts | Converts game state (with Maps) to pure JSON | | index.ts | Package entry point, re-exports CivGame and types |

CivGame API Reference

Constructor

const game = new CivGame(agentName?: string, config?: Partial<IGameConfig>);

Core Methods

game.getState(): ApiGameState          // Full game state as JSON
game.getValidActions(): ValidActionsResponse  // All legal actions
game.act(action: ActionRequest): ActionResult  // Execute any action
game.endTurn(): ActionResult           // End current turn

Shortcut Methods

game.selectCard(cardIndex: number)
game.placeCard(q: number, r: number)
game.rerollShop()
game.buildImprovement(q, r, improvementId)
game.buildDistrict(q, r, districtId)
game.upgradeTile(q, r)
game.selectTechNode(treeId, nodeId)
game.assignWorker(q, r)
game.reassignWorkers()
game.unlockHex(q, r)
game.sellTile(q, r)

Query Methods

game.isGameOver(): boolean
game.getTurn(): number
game.getPhase(): string
game.getScore(): { science, culture, faith, total }
game.getGoalProgress(): { type, current, target, ratio, achieved }
game.createChallenge(): ChallengeResult
game.serialize(): string     // Save game state
game.restore(json: string)   // Load game state

Action Types

Actions are JSON objects with type and params:

| Action Type | Params | Phase | |-------------|--------|-------| | select_card | { cardIndex: number } | shopping | | place_card | { q: number, r: number } | placing | | deselect_card | none | placing | | reroll_shop | none | shopping | | toggle_shop_lock | { slotIndex: number } | shopping | | build_improvement | { q, r, improvementId } | shopping/placing | | build_district | { q, r, districtId } | shopping/placing | | upgrade_tile | { q, r } | shopping/placing | | assign_worker | { q, r } | shopping/placing | | unassign_worker | { q, r } | shopping/placing | | reassign_all_workers | none | shopping/placing | | unlock_hex | { q, r } | shopping/placing | | sell_tile | { q, r } | shopping/placing | | select_tech_node | { treeId, nodeId } | shopping/placing | | end_turn | none | shopping |

How to Modify

Change card stats (easiest)

Edit src/data/card-pool.ts. Each card has:

{ name: '草原', cost: 2, icon: '🌿', weight: 15, tier: 1,
  description: '基础产粮地', terrainId: 'grassland', faction: 'pastoral' }

Change cost, weight (shop probability), or add new cards.

Change tech tree effects

Edit src/data/tech-trees.ts. Each node:

{ id: 'sci_1_1', name: '灌溉', layer: 1, parentId: null,
  description: '农场+1食物',
  effects: [{ type: 'buff_improvement', targetId: 'farm', bonus: { food: 1 } }],
  factionBoost: { faction: 'pastoral', amount: 1 } }

Effect types: buff_improvement, buff_district, buff_terrain, buff_feature, buff_all_improvements, add_adjacency, modify_adjacency, terrain_alias, make_workable, unlock_improvement, unlock_district, reduce_cost, pattern_bonus.

Change game rules

Edit src/game/engine.ts. Key methods:

  • collectYields() - How resources are gathered each turn
  • checkPopulationGrowth() - Population growth/starvation logic
  • buildImprovement() / buildDistrict() - Building rules
  • endTurn() - Turn flow
  • getFinalScore() - Scoring formula

Change game config

Pass config to constructor or edit src/core/config.ts:

const game = new CivGame('agent', {
  maxTurns: 60,        // More turns
  initialGold: 20,     // Start richer
  shopCardCount: 6,    // More cards per turn
  rerollCost: 1,       // Cheaper rerolls
});

How to Create a Variant

  1. Start with this package:
mkdir my-civ6-variant && cd my-civ6-variant
npm init -y
npm install civ6-roguelike-ai
cp -r node_modules/civ6-roguelike-ai/src ./src
cp node_modules/civ6-roguelike-ai/play.ts ./play.ts
cp node_modules/civ6-roguelike-ai/tsconfig.json ./tsconfig.json
  1. Edit package.json:
{
  "name": "@your-scope/civ6-water-meta",
  "version": "1.0.0",
  "description": "Maritime faction dominant variant",
  "type": "module",
  "main": "src/api/index.ts",
  "keywords": ["civ6-roguelike", "civ6-variant"],
  "files": ["src/", "play.ts", "tsconfig.json", "README.md"],
  "dependencies": { "tsx": "^4.21.0", "typescript": "^5.7.0" }
}
  1. Modify the source -- change cards, tech trees, rules, anything

  2. Test: npx tsx play.ts

  3. Publish: npm publish --access public

Hex Coordinate System

The board uses axial coordinates (q, r). City center is at (0, 0).

Ring 0: (0,0)           -- city center (always unlocked, always worked)
Ring 1: 6 hexes         -- always unlocked
Ring 2: 12 hexes        -- unlock by gold or population growth
Ring 3: 18 hexes        -- unlock by gold or population growth
Ring 4: 24 hexes        -- unlock by gold or population growth
Total: 61 hexes

Neighbors of (q, r): (q+1,r), (q-1,r), (q,r+1), (q,r-1), (q+1,r-1), (q-1,r+1).

License

MIT