-
Notifications
You must be signed in to change notification settings - Fork 0
Getting Started
git clone https://github.com/killerboyyy777/Machine-Learning-mmo.git
cd Machine-Learning-mmo
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python3 server.pyStarts the world on ws://0.0.0.0:8765. Edit world.json to define your
own rooms, NPCs, and items before starting the server (loaded once at
startup). On Windows you can also just run start.bat — it starts the
engine, shows where to find the game and the dashboard, and turns on live
console logging.
Dungeons are instanced: a private, 50-floor staircase is created
per party the first time someone uses the enter doorway on the
graveyard — see Game-Systems Parties & the dungeon.
Any client is a WebSocket connection speaking JSON (see
Protocol for the full reference). Telnet and netcat cannot speak
WebSocket, so talk to the server with Python (websockets ships with
the requirements file) or straight from a browser console:
import asyncio, json, websockets
async def main():
async with websockets.connect("ws://localhost:8765") as ws:
await ws.send(json.dumps({"cmd": "login", "name": "YourName"}))
print(await ws.recv()) # stake message + welcome
await ws.send(json.dumps({"cmd": "look"}))
print(await ws.recv()) # room snapshot
# from here, send any command and print each reply:
# await ws.send(json.dumps({"cmd": "attack rat"}))
asyncio.run(main())// same, in a browser console (no install needed):
const ws = new WebSocket("ws://localhost:8765");
ws.onmessage = e => console.log(JSON.parse(e.data));
ws.onopen = () => ws.send(JSON.stringify({cmd: "login", name: "YourName"}));
// then: ws.send(JSON.stringify({cmd: "look"}))Type commands like look, north, attack rat, take sword,
equip sword — interactively in your own client or scripted directly.
See First-Session for a guided first ten minutes.
The server also runs a browser dashboard on port 8766 (stdlib only, no
extra dependencies). Start the engine, then open
http://localhost:8766/. See Dashboard for the panels.
Any client is just a WebSocket connection speaking JSON. Three steps:
1. Connect and log in.
import asyncio, json, websockets
async def main():
async with websockets.connect("ws://localhost:8765") as ws:
await ws.send(json.dumps({"cmd": "login", "name": "MyBot"}))
event = json.loads(await ws.recv()) # first message is always a room snapshot
print(event)2. Send commands, receive responses.
Every command is a JSON object with a "cmd" field. The server always
replies with a JSON object that has a "type" field. The most important
type is "room" — the full state of your current room (exits, NPCs,
items, other players), pushed after every move, look, login, and whenever
the room changes.
await ws.send(json.dumps({"cmd": "look"}))
event = json.loads(await ws.recv())
await ws.send(json.dumps({"cmd": "move", "dir": "north"}))
event = json.loads(await ws.recv())
await ws.send(json.dumps({"cmd": "attack", "target": "rat"}))
event = json.loads(await ws.recv())
await ws.send(json.dumps({"cmd": "take", "item": "sword"}))
event = json.loads(await ws.recv())3. Handle the main loop.
Read responses in a loop, update state from "room" and "stats"
events, and decide what to do next. On "error", send a "look" to
resync — never assume cached state is still valid after an error. On
"death" you respawned: look to re-orient.
async def main():
async with websockets.connect("ws://localhost:8765") as ws:
await ws.send(json.dumps({"cmd": "login", "name": "MyBot"}))
while True:
event = json.loads(await ws.recv())
t = event.get("type")
if t == "room":
print(f"In: {event['name']}")
elif t == "stats":
print(f"HP {event['hp']}/{event['max_hp']} Gold {event['gold']}")
elif t == "combat":
print(event["text"]) # pattern-match "dies" for kills
elif t == "error":
await ws.send(json.dumps({"cmd": "look"})) # resync
elif t == "death":
await ws.send(json.dumps({"cmd": "look"}))An LLM agent speaks the same WebSocket protocol as any other client. Give the LLM a system prompt describing the game and let it issue JSON commands directly:
You are a character in a text-based MMO. You communicate by sending JSON
commands over a WebSocket connection. The server responds with JSON messages.
Available commands (skeleton — full command list with quest, market,
party, and commission commands: see [[Protocol]]):
{"cmd": "login", "name": "YourName"}
{"cmd": "look"}
{"cmd": "move", "dir": "north"}
{"cmd": "attack", "target": "goblin"}
After each server response, decide your next action and send one JSON command.
Key messages: "room" (full state), "combat" (check "dies" for kills),
"stats" (HP/gold/score), "error" (look again to resync), "death" (respawned).
Quick-start Python bridge:
async def run_llm_agent(name="LLMAgent"):
async with websockets.connect("ws://localhost:8765") as ws:
await ws.send(json.dumps({"cmd": "login", "name": name}))
resp = json.loads(await ws.recv())
while True:
prompt = build_prompt(resp) # feed to your LLM
action = call_llm(prompt) # parse LLM output into a dict
await ws.send(json.dumps(action))
resp = json.loads(await ws.recv())The LLM sees the same snapshots, combat text, and errors as everyone
else. Treat error responses as a cue to look again and resync state.