An AI-powered historical strategy game. The LLM plays advisors, generals, and NPC warlords. Players command with natural language. Supports two scenarios and two languages.
ScenarioSettingFactionsthree-kingdoms207 AD, Jian'an 12th year曹操军 (Cao Cao), 刘备军 (Liu Bei), 孙权军 (Sun Quan)rome-triumvirate44 BC, Ides of MarchOctavian, Antony, Cleopatra, Senate
Both English and Chinese (中文) are fully supported. Pass lang="en" or lang="zh" when creating a room:
python
# English game
room = Room.create("my-game", faction="cao", lang="en")
# Chinese game (default)
room = Room.create("my-game", faction="cao", lang="zh")
Use V1 engine for best narrative quality. V1 runs a single LLM call per turn with rich historical storytelling. V2 is deterministic (no LLM) for testing.
bash
export HISTRATEGY_ENGINE=v1
export DEEPSEEK_API_KEY="sk-..."
EngineDescriptionLLM CallsBest ForV1 (recommended)Single LLM simulation per turn1Narrative immersion, production playV2Pure deterministic formulas0Testing, offline play
bash
pip install histrategy-sdk
histrategy-sdk — Game SDK ( Room, MultiplayerRoom, DirectEngine)histrategy-engine — Auto-installed as dependencyhistrategy-agent — Optional: IM bot integration ( TurnProcessor, IM adapters)bash
git clone https://github.com/emergencescience/histrategy
cd histrategy
pip install -e histrategy-sdk/
bash
export DEEPSEEK_API_KEY="sk-..." # Recommended — best value
# or
export OPENAI_API_KEY="sk-..."
# or
export TONGYI_API_KEY="sk-..."
Without an API key, games run in offline rule-based mode (no LLM narrative).
python
from histrategy_sdk import Room
# Create an English Three Kingdoms game as Cao Cao
room = Room.create("my-campaign", faction="cao", lang="en")
# Get the intro scene
intro = room.intro()
print(intro["narrative"])
# Play a turn
result = room.play("Attack Xinye with 50,000 troops from Wancheng")
print(result["narrative"])
print(f"Morale: {result['faction_status']['morale']}")
# Resume after agent context reset
room = Room.load("my-campaign", lang="en")
result = room.play("Consolidate territories and lower taxes to 20%")
python
from histrategy_sdk import Room
room = Room.create("rome-campaign", faction="octavian", scenario="rome-triumvirate", lang="en")
result = room.play("Secure the Senate's support and isolate Antony politically")
Game state lives entirely on disk. Agent context resets don't lose progress:
text
~/.histrategy/rooms/
<room-name>/
world_state.json # Full game world state
turns.jsonl # Append-only turn log
metadata.json # Room metadata
Every turn: read state → execute → write back. Survives restarts.
MethodDescriptionRoom.create(name, faction, scenario, lang)Create new gameRoom.load(name, lang)Load from diskroom.play(decision)Execute turn → auto-saveroom.plan()Get advisor suggestionsroom.intro()Get opening sceneroom.status()Get resource snapshotroom.get_turn_history()Read all past turns
ParamTypeDefaultDescriptionname``strrequiredRoom name (unique ID)faction``str``"shu"Player factionscenario``str``"three-kingdoms"``"three-kingdoms" or "rome-triumvirate"``lang``str``"zh"``"zh" or "en"``llm_api_key``strautoOverride API keyllm_provider``strauto"deepseek", "openai", "tongyi"
Three Kingdoms: cao (曹操), shu (刘备), wu (孙权)
Rome Triumvirate: octavian, antony, cleopatra, senate
python
def format_turn(result: dict, lang: str = "en") -> str:
fs = result["faction_status"]
if lang == "en":
lines = [
f"## {result['year']} · {result['season']} | Turn {result['turn']}",
result["narrative"],
f"\n⚔️Troops:{fs['strength']} 🍚Food:{fs['food']} 💰Gold:{fs['treasury']} ❤️Morale:{fs['morale']}",
]
else:
lines = [
f"## {result['year']}年{result['season']} · 第{result['turn']}回合",
result["narrative"],
f"\n⚔️兵力:{fs['strength']} 🍚粮草:{fs['food']} 💰库金:{fs['treasury']} ❤️士气:{fs['morale']}",
]
if result.get("new_suggestions"):
label = "Advisor Suggestions" if lang == "en" else "谋士献策"
lines.append(f"\n**{label}**:")
for s in result["new_suggestions"][:3]:
lines.append(f" • {s}")
return "\n".join(lines)
IssueSolutionTurns are slow (60-90s)LLM generation. Show "Advisors are deliberating..."Progress lost after context resetNot possible. Room.load(name) restores from diskNo API keyAuto-falls back to offline rule-based modeChinese output when I want EnglishPass lang="en" to Room.create() or Room.load()MultiplayerUse MultiplayerRoom with a histrategy server